Skip to content

Commit 02ed62d

Browse files
committed
refactor(code): various code refactoring
1 parent f10a71c commit 02ed62d

File tree

10 files changed

+161
-47
lines changed

10 files changed

+161
-47
lines changed

Cargo.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
[package]
22
name = "pyroscope"
33
description = """
4-
Pyroscope Profiler
4+
Pyroscope Profiler Agent for continuous profiling of Rust, Python and Ruby applications.
55
"""
6-
keywords = ["pyroscope", "profiler"]
6+
keywords = ["pyroscope", "profiler", "profiling", "pprof"]
77
authors = ["Abid Omar <[email protected]>"]
8-
version = "0.4.0"
8+
version = "0.5.0"
99
edition = "2021"
1010
license = "Apache-2.0"
11-
homepage = "https://pyroscope.io"
11+
homepage = "https://pyroscope.io/docs/rust"
1212
documentation = "https://docs.rs/pyroscope"
1313
repository = "https://github.com/pyroscope-io/pyroscope-rs"
1414
readme = "README.md"
@@ -54,10 +54,10 @@ path = "examples/internal/rbspy-connect.rs"
5454
thiserror ="1.0"
5555
log = "0.4"
5656
reqwest = { version = "0.11", features = ["blocking"]}
57-
libc = "^0.2.66"
57+
libc = "^0.2.124"
5858

5959
[dev-dependencies]
60-
tokio = { version = "1.13", features = ["full"] }
60+
tokio = { version = "1.18", features = ["full"] }
6161
pretty_env_logger = "0.4.0"
6262
assert_matches = "1"
6363
pyroscope_pprofrs = { path = "pyroscope_backends/pyroscope_pprofrs" }

SECURITY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
| Version | Supported |
66
| ------- | ------------------ |
7+
| 0.5.x | :white_check_mark: |
78
| 0.4.x | :white_check_mark: |
89
| 0.3.x | :white_check_mark: |
910
| < 3.0 | :x: |

src/backend/types.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ use crate::error::Result;
88
/// Pyroscope Tag
99
#[derive(Debug, PartialOrd, Ord, Eq, PartialEq, Hash, Clone)]
1010
pub struct Tag {
11+
/// Tag key
1112
pub key: String,
13+
/// Tag value
1214
pub value: String,
1315
}
1416

@@ -28,6 +30,7 @@ impl std::fmt::Display for Tag {
2830
/// Stack buffer
2931
#[derive(Debug, Default, Clone)]
3032
pub struct StackBuffer {
33+
/// Buffer data bucket
3134
pub data: HashMap<StackTrace, usize>,
3235
}
3336

src/lib.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22
//!
33
//! # Quick Start
44
//!
5-
//! ## Add Pyroscope and pprof-rs backend to Cargo.toml
5+
//! ## Add the Pyroscope Library and the pprof-rs backend to Cargo.toml
66
//!
77
//! ```toml
88
//! [dependencies]
99
//! pyroscope = "0.5"
10-
//! pyroscope-pprofrs = "0.1"
10+
//! pyroscope-pprofrs = "0.2"
1111
//! ```
1212
//!
1313
//! ## Configure a Pyroscope Agent
1414
//!
1515
//! ```ignore
16-
//! let mut agent =
16+
//! let agent =
1717
//! PyroscopeAgent::builder("http://localhost:4040", "myapp")
1818
//! .backend(Pprof::new(PprofConfig::new().sample_rate(100)))
1919
//! .build()?;
@@ -24,13 +24,19 @@
2424
//! To start profiling code and sending data.
2525
//!
2626
//! ```ignore
27-
//! agent.start();
27+
//! let agent_running = agent.start()?;
2828
//! ```
2929
//!
3030
//! To stop profiling code. You can restart the profiling at a later point.
3131
//!
3232
//! ```ignore
33-
//! agent.stop();
33+
//! let agent_ready = agent.stop()?;
34+
//! ```
35+
//!
36+
//! Before you drop the variable, make sure to shutdown the agent.
37+
//!
38+
//! ```ignore
39+
//! agent_ready.shutdown();
3440
//! ```
3541
3642
// Re-exports structs

src/pyroscope.rs

Lines changed: 82 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ use crate::{
1414
session::{Session, SessionManager, SessionSignal},
1515
timer::{Timer, TimerSignal},
1616
utils::get_time_range,
17+
PyroscopeError,
1718
};
1819

1920
use crate::backend::BackendImpl;
2021

2122
const LOG_TAG: &str = "Pyroscope::Agent";
2223

2324
/// Pyroscope Agent Configuration. This is the configuration that is passed to the agent.
25+
///
2426
/// # Example
2527
/// ```
2628
/// use pyroscope::pyroscope::PyroscopeConfig;
@@ -43,6 +45,7 @@ pub struct PyroscopeConfig {
4345
impl PyroscopeConfig {
4446
/// Create a new PyroscopeConfig object. url and application_name are required.
4547
/// tags and sample_rate are optional. If sample_rate is not specified, it will default to 100.
48+
///
4649
/// # Example
4750
/// ```ignore
4851
/// let config = PyroscopeConfig::new("http://localhost:8080", "my-app");
@@ -70,7 +73,8 @@ impl PyroscopeConfig {
7073
Self { spy_name, ..self }
7174
}
7275

73-
/// Set the tags
76+
/// Set the tags.
77+
///
7478
/// # Example
7579
/// ```ignore
7680
/// use pyroscope::pyroscope::PyroscopeConfig;
@@ -126,11 +130,12 @@ impl PyroscopeAgentBuilder {
126130
}
127131
}
128132

129-
/// Set the agent backend. Default is pprof.
133+
/// Set the agent backend. Default is void-backend.
134+
///
130135
/// # Example
131136
/// ```ignore
132137
/// let builder = PyroscopeAgentBuilder::new("http://localhost:8080", "my-app")
133-
/// .backend(Pprof::default())
138+
/// .backend(PprofConfig::new().sample_rate(100))
134139
/// .build()
135140
/// ?;
136141
/// ```
@@ -139,6 +144,7 @@ impl PyroscopeAgentBuilder {
139144
}
140145

141146
/// Set tags. Default is empty.
147+
///
142148
/// # Example
143149
/// ```ignore
144150
/// let builder = PyroscopeAgentBuilder::new("http://localhost:8080", "my-app")
@@ -152,30 +158,28 @@ impl PyroscopeAgentBuilder {
152158
}
153159
}
154160

155-
/// Initialize the backend, timer and return a PyroscopeAgent object.
161+
/// Initialize the backend, timer and return a PyroscopeAgent with Ready
162+
/// state. While you can call this method, you should call it through the
163+
/// `PyroscopeAgent.build()` method.
156164
pub fn build(self) -> Result<PyroscopeAgent<PyroscopeAgentReady>> {
157-
// Get the backend
158-
//let backend = Arc::clone(&self.backend);
159-
160165
// Set Spy Name and Sample Rate from the Backend
161166
let config = self.config.sample_rate(self.backend.sample_rate()?);
162167
let config = config.spy_name(self.backend.spy_name()?);
163168

164169
// Set Global Tags
165-
for (k, v) in config.tags.iter() {
170+
for (key, value) in config.tags.iter() {
166171
self.backend
167172
.add_rule(crate::backend::Rule::GlobalTag(Tag::new(
168-
k.to_owned(),
169-
v.to_owned(),
173+
key.to_owned(),
174+
value.to_owned(),
170175
)))?;
171176
}
172177

173-
// Initialize the backend
178+
// Initialize the Backend
174179
let backend_ready = self.backend.initialize()?;
175-
176180
log::trace!(target: LOG_TAG, "Backend initialized");
177181

178-
// Start Timer
182+
// Start the Timer
179183
let timer = Timer::initialize(std::time::Duration::from_secs(10))?;
180184
log::trace!(target: LOG_TAG, "Timer initialized");
181185

@@ -201,9 +205,13 @@ impl PyroscopeAgentBuilder {
201205
}
202206
}
203207

208+
/// This trait is used to encode the state of the agent.
204209
pub trait PyroscopeAgentState {}
210+
/// Marker struct for an Uninitialized state.
205211
pub struct PyroscopeAgentBare;
212+
/// Marker struct for a Ready state.
206213
pub struct PyroscopeAgentReady;
214+
/// Marker struct for a Running state.
207215
pub struct PyroscopeAgentRunning;
208216
impl PyroscopeAgentState for PyroscopeAgentBare {}
209217
impl PyroscopeAgentState for PyroscopeAgentReady {}
@@ -307,11 +315,12 @@ impl PyroscopeAgent<PyroscopeAgentBare> {
307315
}
308316

309317
impl PyroscopeAgent<PyroscopeAgentReady> {
310-
/// Start profiling and sending data. The agent will keep running until stopped. The agent will send data to the server every 10s secondy.
318+
/// Start profiling and sending data. The agent will keep running until stopped. The agent will send data to the server every 10s seconds.
319+
///
311320
/// # Example
312321
/// ```ignore
313322
/// let agent = PyroscopeAgent::builder("http://localhost:8080", "my-app").build()?;
314-
/// agent.start()?;
323+
/// let agent_running = agent.start()?;
315324
/// ```
316325
pub fn start(mut self) -> Result<PyroscopeAgent<PyroscopeAgentRunning>> {
317326
log::debug!(target: LOG_TAG, "Starting");
@@ -327,12 +336,14 @@ impl PyroscopeAgent<PyroscopeAgentReady> {
327336
*running = true;
328337
drop(running);
329338

339+
// Create a channel to listen for timer signals
330340
let (tx, rx) = mpsc::channel();
331341
self.timer.attach_listener(tx.clone())?;
332342
self.tx = Some(tx);
333343

334344
let config = self.config.clone();
335345

346+
// Clone SessionManager Sender
336347
let stx = self.session_manager.tx.clone();
337348

338349
self.handle = Some(std::thread::spawn(move || {
@@ -344,7 +355,15 @@ impl PyroscopeAgent<PyroscopeAgentReady> {
344355
log::trace!(target: LOG_TAG, "Sending session {}", until);
345356

346357
// Generate report from backend
347-
let report = backend.lock()?.as_mut().unwrap().report()?;
358+
let report = backend
359+
.lock()?
360+
.as_mut()
361+
.ok_or_else(|| {
362+
PyroscopeError::AdHoc(
363+
"PyroscopeAgent - Failed to unwrap backend".to_string(),
364+
)
365+
})?
366+
.report()?;
348367

349368
// Send new Session to SessionManager
350369
stx.send(SessionSignal::Session(Session::new(
@@ -356,40 +375,32 @@ impl PyroscopeAgent<PyroscopeAgentReady> {
356375
TimerSignal::Terminate => {
357376
log::trace!(target: LOG_TAG, "Session Killed");
358377

378+
// Notify the Stop function
359379
let (lock, cvar) = &*pair;
360380
let mut running = lock.lock()?;
361381
*running = false;
362382
cvar.notify_one();
363383

384+
// Kill the internal thread
364385
return Ok(());
365386
}
366387
}
367388
}
368389
Ok(())
369390
}));
370391

371-
//let agent_running = PyroscopeAgent {
372-
//timer: self.timer,
373-
//session_manager: self.session_manager,
374-
//tx: self.tx,
375-
//handle: self.handle,
376-
//running: self.running,
377-
//backend: self.backend,
378-
//config: self.config,
379-
//_state: PhantomData,
380-
//};
381-
382392
Ok(self.transition())
383393
}
384394
}
385395
impl PyroscopeAgent<PyroscopeAgentRunning> {
386396
/// Stop the agent. The agent will stop profiling and send a last report to the server.
397+
///
387398
/// # Example
388399
/// ```ignore
389400
/// let agent = PyroscopeAgent::builder("http://localhost:8080", "my-app").build()?;
390-
/// agent.start()?;
401+
/// let agent_running = agent.start()?;
391402
/// // Expensive operation
392-
/// agent.stop();
403+
/// let agent_ready = agent_running.stop();
393404
/// ```
394405
pub fn stop(mut self) -> Result<PyroscopeAgent<PyroscopeAgentReady>> {
395406
log::debug!(target: LOG_TAG, "Stopping");
@@ -411,6 +422,24 @@ impl PyroscopeAgent<PyroscopeAgentRunning> {
411422
Ok(self.transition())
412423
}
413424

425+
/// Return a tuple of functions to add and remove tags to the agent across
426+
/// thread boundaries. This function can be called multiple times.
427+
///
428+
/// # Example
429+
/// ```ignore
430+
/// let agent = PyroscopeAgent::builder("http://localhost:8080", "my-app").build()?;
431+
/// let agent_running = agent.start()?;
432+
/// let (add_tag, remove_tag) = agent_running.tag_wrapper();
433+
/// ```
434+
///
435+
/// The functions can be later called from any thread.
436+
///
437+
/// # Example
438+
/// ```ignore
439+
/// add_tag("key".to_string(), "value".to_string());
440+
/// // some computation
441+
/// remove_tag("key".to_string(), "value".to_string());
442+
/// ```
414443
pub fn tag_wrapper(
415444
&self,
416445
) -> (
@@ -425,42 +454,64 @@ impl PyroscopeAgent<PyroscopeAgentRunning> {
425454
let thread_id = crate::utils::pthread_self()?;
426455
let rule = Rule::ThreadTag(thread_id, Tag::new(key, value));
427456
let backend = backend_add.lock()?;
428-
backend.as_ref().unwrap().add_rule(rule)?;
457+
backend
458+
.as_ref()
459+
.ok_or_else(|| {
460+
PyroscopeError::AdHoc(
461+
"PyroscopeAgent - Failed to unwrap backend".to_string(),
462+
)
463+
})?
464+
.add_rule(rule)?;
429465

430466
Ok(())
431467
},
432468
move |key, value| {
433469
let thread_id = crate::utils::pthread_self()?;
434470
let rule = Rule::ThreadTag(thread_id, Tag::new(key, value));
435471
let backend = backend_remove.lock()?;
436-
backend.as_ref().unwrap().remove_rule(rule)?;
472+
backend
473+
.as_ref()
474+
.ok_or_else(|| {
475+
PyroscopeError::AdHoc(
476+
"PyroscopeAgent - Failed to unwrap backend".to_string(),
477+
)
478+
})?
479+
.remove_rule(rule)?;
437480

438481
Ok(())
439482
},
440483
)
441484
}
442485

486+
/// Add a global Tag rule to the backend Ruleset. For tagging, it's
487+
/// recommended to use the `tag_wrapper` function.
443488
pub fn add_global_tag(&self, tag: Tag) -> Result<()> {
444489
let rule = Rule::GlobalTag(tag);
445490
self.backend.add_rule(rule)?;
446491

447492
Ok(())
448493
}
449494

495+
/// Remove a global Tag rule from the backend Ruleset. For tagging, it's
496+
/// recommended to use the `tag_wrapper` function.
450497
pub fn remove_global_tag(&self, tag: Tag) -> Result<()> {
451498
let rule = Rule::GlobalTag(tag);
452499
self.backend.remove_rule(rule)?;
453500

454501
Ok(())
455502
}
456503

504+
/// Add a thread Tag rule to the backend Ruleset. For tagging, it's
505+
/// recommended to use the `tag_wrapper` function.
457506
pub fn add_thread_tag(&self, thread_id: u64, tag: Tag) -> Result<()> {
458507
let rule = Rule::ThreadTag(thread_id, tag);
459508
self.backend.add_rule(rule)?;
460509

461510
Ok(())
462511
}
463512

513+
/// Remove a thread Tag rule from the backend Ruleset. For tagging, it's
514+
/// recommended to use the `tag_wrapper` function.
464515
pub fn remove_thread_tag(&self, thread_id: u64, tag: Tag) -> Result<()> {
465516
let rule = Rule::ThreadTag(thread_id, tag);
466517
self.backend.remove_rule(rule)?;

0 commit comments

Comments
 (0)