Skip to content

Commit 9127303

Browse files
authored
Merge pull request #21 from drahnr/bernhard-acc-cycle
allow configurable accumulation_cycle
2 parents 37fa587 + 44fc28d commit 9127303

File tree

11 files changed

+219
-117
lines changed

11 files changed

+219
-117
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ libc = "^0.2.66"
2323
[dev-dependencies]
2424
tokio = { version = "1.13", features = ["full"] }
2525
pretty_env_logger = "0.4.0"
26+
assert_matches = "1"
2627

2728
[profile.dev]
2829
opt-level=0

examples/internals-timer.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
extern crate pyroscope;
22

3-
use std::sync::mpsc::channel;
4-
use std::sync::mpsc::{Receiver, Sender};
3+
use std::sync::mpsc;
54

65
use pyroscope::timer::Timer;
76

87
fn main() {
98
// Initialize the Timer
10-
let mut timer = Timer::default().initialize().unwrap();
9+
let mut timer = Timer::initialize(std::time::Duration::from_secs(10)).unwrap();
1110

1211
// Create a streaming channel
13-
let (tx, rx): (Sender<u64>, Receiver<u64>) = channel();
12+
let (tx, rx) = mpsc::channel();
1413

15-
let (tx2, rx2): (Sender<u64>, Receiver<u64>) = channel();
14+
let (tx2, rx2) = mpsc::channel();
1615

1716
// Attach tx to Timer
1817
timer.attach_listener(tx).unwrap();

src/error.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ pub enum PyroscopeError {
1515
AdHoc(String),
1616

1717
#[error("{msg}: {source:?}")]
18-
Compat{ msg: String, #[source] source: Box<dyn std::error::Error + Send + Sync + 'static> },
18+
Compat {
19+
msg: String,
20+
#[source]
21+
source: Box<dyn std::error::Error + Send + Sync + 'static>,
22+
},
1923

2024
#[error(transparent)]
2125
Reqwest(#[from] reqwest::Error),
@@ -37,7 +41,10 @@ impl PyroscopeError {
3741
}
3842

3943
/// Create a new instance of PyroscopeError with source
40-
pub fn new_with_source<E>(msg: &str, source: E) -> Self where E: std::error::Error + Send + Sync + 'static {
44+
pub fn new_with_source<E>(msg: &str, source: E) -> Self
45+
where
46+
E: std::error::Error + Send + Sync + 'static,
47+
{
4148
PyroscopeError::Compat {
4249
msg: msg.to_string(),
4350
source: Box::new(source),

src/pyroscope.rs

Lines changed: 82 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
use std::{
22
collections::HashMap,
33
sync::{
4-
mpsc::{channel, Receiver, Sender},
4+
mpsc::{self, Sender},
55
Arc, Condvar, Mutex,
66
},
77
thread::JoinHandle,
8+
time::Duration,
89
};
910

1011
use crate::{
1112
backends::{pprof::Pprof, Backend},
1213
error::Result,
1314
session::{Session, SessionManager, SessionSignal},
14-
timer::Timer,
15+
timer::{Timer, TimerSignal},
1516
};
1617

1718
const LOG_TAG: &str = "Pyroscope::Agent";
@@ -32,6 +33,8 @@ pub struct PyroscopeConfig {
3233
pub tags: HashMap<String, String>,
3334
/// Sample rate used in Hz
3435
pub sample_rate: i32,
36+
/// How long to accumulate data for before sending it upstream
37+
pub accumulation_cycle: Duration,
3538
// TODO
3639
// log_level
3740
// auth_token
@@ -52,6 +55,7 @@ impl PyroscopeConfig {
5255
application_name: application_name.as_ref().to_owned(),
5356
tags: HashMap::new(),
5457
sample_rate: 100i32,
58+
accumulation_cycle: Duration::from_secs(10),
5559
}
5660
}
5761

@@ -69,6 +73,27 @@ impl PyroscopeConfig {
6973
}
7074
}
7175

76+
/// Override the accumulation cycle.
77+
///
78+
/// # Example
79+
///
80+
/// ```
81+
/// use std::time::Duration;
82+
/// use pyroscope::pyroscope::PyroscopeConfig;
83+
/// # use pyroscope::PyroscopeError;
84+
/// # fn main() -> Result<(), PyroscopeError> {
85+
/// let config = PyroscopeConfig::new("http://localhost:8080", "my-app")
86+
/// .accumulation_cycle(Duration::from_millis(4587));
87+
/// # Ok(())
88+
/// # }
89+
/// ```
90+
pub fn accumulation_cycle(self, accumulation_cycle: Duration) -> Self {
91+
Self {
92+
accumulation_cycle,
93+
..self
94+
}
95+
}
96+
7297
/// Set the tags
7398
/// # Example
7499
/// ```ignore
@@ -147,7 +172,7 @@ impl PyroscopeAgentBuilder {
147172
/// # Example
148173
/// ```ignore
149174
/// let builder = PyroscopeAgentBuilder::new("http://localhost:8080", "my-app")
150-
/// .sample_rate(99)
175+
/// .sample_rate(113)
151176
/// .build()
152177
/// ?;
153178
/// ```
@@ -158,6 +183,29 @@ impl PyroscopeAgentBuilder {
158183
}
159184
}
160185

186+
/// Set the accumulation cycle. Default value is 10 seconds.
187+
///
188+
/// # Example
189+
///
190+
/// ```
191+
/// use pyroscope::pyroscope::PyroscopeAgentBuilder;
192+
/// use std::time::Duration;
193+
/// # use pyroscope::PyroscopeError;
194+
/// # fn main() -> Result<(), PyroscopeError> {
195+
///
196+
/// let builder = PyroscopeAgentBuilder::new("http://localhost:8080", "my-app")
197+
/// .accumulation_cycle(Duration::from_secs(3))
198+
/// .build()?;
199+
/// # Ok(())
200+
/// # }
201+
/// ```
202+
pub fn accumulation_cycle(self, acc_cycle: impl Into<Duration>) -> Self {
203+
Self {
204+
config: self.config.accumulation_cycle(acc_cycle.into()),
205+
..self
206+
}
207+
}
208+
161209
/// Set tags. Default is empty.
162210
/// # Example
163211
/// ```ignore
@@ -181,7 +229,7 @@ impl PyroscopeAgentBuilder {
181229
log::trace!(target: LOG_TAG, "Backend initialized");
182230

183231
// Start Timer
184-
let timer = Timer::default().initialize()?;
232+
let timer = Timer::initialize(self.config.accumulation_cycle.clone())?;
185233
log::trace!(target: LOG_TAG, "Timer initialized");
186234

187235
// Start the SessionManager
@@ -206,7 +254,7 @@ impl PyroscopeAgentBuilder {
206254
pub struct PyroscopeAgent {
207255
timer: Timer,
208256
session_manager: SessionManager,
209-
tx: Option<Sender<u64>>,
257+
tx: Option<Sender<TimerSignal>>,
210258
handle: Option<JoinHandle<Result<()>>>,
211259
running: Arc<(Mutex<bool>, Condvar)>,
212260

@@ -298,7 +346,7 @@ impl PyroscopeAgent {
298346
*running = true;
299347
drop(running);
300348

301-
let (tx, rx): (Sender<u64>, Receiver<u64>) = channel();
349+
let (tx, rx) = mpsc::channel();
302350
self.timer.attach_listener(tx.clone())?;
303351
self.tx = Some(tx);
304352

@@ -309,28 +357,31 @@ impl PyroscopeAgent {
309357
self.handle = Some(std::thread::spawn(move || {
310358
log::trace!(target: LOG_TAG, "Main Thread started");
311359

312-
while let Ok(until) = rx.recv() {
313-
log::trace!(target: LOG_TAG, "Sending session {}", until);
314-
315-
// Generate report from backend
316-
let report = backend.lock()?.report()?;
317-
318-
// Send new Session to SessionManager
319-
stx.send(SessionSignal::Session(Session::new(
320-
until,
321-
config.clone(),
322-
report,
323-
)?))?;
324-
325-
if until == 0 {
326-
log::trace!(target: LOG_TAG, "Session Killed");
327-
328-
let (lock, cvar) = &*pair;
329-
let mut running = lock.lock()?;
330-
*running = false;
331-
cvar.notify_one();
332-
333-
return Ok(());
360+
while let Ok(signal) = rx.recv() {
361+
match signal {
362+
TimerSignal::NextSnapshot(until) => {
363+
log::trace!(target: LOG_TAG, "Sending session {}", until);
364+
365+
// Generate report from backend
366+
let report = backend.lock()?.report()?;
367+
368+
// Send new Session to SessionManager
369+
stx.send(SessionSignal::Session(Session::new(
370+
until,
371+
config.clone(),
372+
report,
373+
)?))?
374+
}
375+
TimerSignal::Terminate => {
376+
log::trace!(target: LOG_TAG, "Session Killed");
377+
378+
let (lock, cvar) = &*pair;
379+
let mut running = lock.lock()?;
380+
*running = false;
381+
cvar.notify_one();
382+
383+
return Ok(());
384+
}
334385
}
335386
}
336387
Ok(())
@@ -351,7 +402,9 @@ impl PyroscopeAgent {
351402
log::debug!(target: LOG_TAG, "Stopping");
352403
// get tx and send termination signal
353404
if let Some(sender) = self.tx.take() {
354-
sender.send(0)?;
405+
// best effort
406+
let _ = sender.send(TimerSignal::NextSnapshot(0));
407+
sender.send(TimerSignal::Terminate)?;
355408
} else {
356409
log::error!("PyroscopeAgent - Missing sender")
357410
}

src/session.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{
22
sync::mpsc::{sync_channel, Receiver, SyncSender},
3-
thread,
4-
thread::JoinHandle,
3+
thread::{self, JoinHandle},
4+
time::Duration,
55
};
66

77
use crate::pyroscope::PyroscopeConfig;
@@ -84,7 +84,9 @@ impl SessionManager {
8484
pub struct Session {
8585
pub config: PyroscopeConfig,
8686
pub report: Vec<u8>,
87+
// unix time
8788
pub from: u64,
89+
// unix time
8890
pub until: u64,
8991
}
9092

@@ -122,7 +124,12 @@ impl Session {
122124
/// session.send()?;
123125
/// ```
124126
pub fn send(self) -> Result<()> {
125-
log::info!(target: LOG_TAG, "Sending Session: {} - {}", self.from, self.until);
127+
log::info!(
128+
target: LOG_TAG,
129+
"Sending Session: {} - {}",
130+
self.from,
131+
self.until
132+
);
126133

127134
// Check if the report is empty
128135
if self.report.is_empty() {
@@ -154,7 +161,7 @@ impl Session {
154161
("spyName", "pyroscope-rs"),
155162
])
156163
.body(self.report)
157-
.timeout(std::time::Duration::from_secs(10))
164+
.timeout(Duration::from_secs(10))
158165
.send()?;
159166

160167
Ok(())

0 commit comments

Comments
 (0)