11use 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
1011use crate :: {
1112 backends:: { pprof:: Pprof , Backend } ,
1213 error:: Result ,
1314 session:: { Session , SessionManager , SessionSignal } ,
14- timer:: Timer ,
15+ timer:: { Timer , TimerSignal } ,
1516} ;
1617
1718const 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 {
206254pub 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 }
0 commit comments