Skip to content

Commit 1aaaba1

Browse files
committed
imp(pprof): add multi-thread tagging support for pprof-rs
1 parent bb8e88c commit 1aaaba1

File tree

2 files changed

+87
-30
lines changed

2 files changed

+87
-30
lines changed

examples/tags.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
extern crate pyroscope;
22

3-
use pyroscope::{PyroscopeAgent, Result};
3+
use pyroscope::{backend::Tag, PyroscopeAgent, Result};
44
use pyroscope_pprofrs::{pprof_backend, PprofConfig};
55
use std::hash::{Hash, Hasher};
66

@@ -27,15 +27,33 @@ fn main() -> Result<()> {
2727
// Start Agent
2828
agent.start()?;
2929

30+
// Show start time
31+
let start = std::time::SystemTime::now()
32+
.duration_since(std::time::UNIX_EPOCH)
33+
.unwrap()
34+
.as_secs();
35+
println!("Start Time: {}", start);
36+
37+
// Add Tags
38+
agent.add_global_tag(Tag::new("series".to_string(), "Number 1".to_string()))?;
39+
3040
// Make some calculation
3141
let _result = hash_rounds(300_000);
3242

3343
// Add Tags
34-
agent.add_tags(&[("series", "Number 2")])?;
44+
agent.remove_global_tag(Tag::new("series".to_string(), "Number 1".to_string()))?;
45+
agent.add_global_tag(Tag::new("series".to_string(), "Number 2".to_string()))?;
3546

3647
// Do more calculation
3748
let _result = hash_rounds(500_000);
3849

50+
// Show stop time
51+
let stop = std::time::SystemTime::now()
52+
.duration_since(std::time::UNIX_EPOCH)
53+
.unwrap()
54+
.as_secs();
55+
println!("Stop Time: {}", stop);
56+
3957
// Stop Agent
4058
agent.stop()?;
4159

pyroscope_backends/pyroscope_pprofrs/src/lib.rs

Lines changed: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ use pyroscope::{
66
},
77
error::{PyroscopeError, Result},
88
};
9-
use std::{collections::HashMap, ffi::OsStr};
9+
use std::{
10+
collections::HashMap,
11+
ffi::OsStr,
12+
ops::Deref,
13+
sync::{Arc, Mutex},
14+
};
1015

1116
pub fn pprof_backend(config: PprofConfig) -> BackendImpl<BackendUninitialized> {
1217
BackendImpl::new(Box::new(Pprof::new(config)))
@@ -37,9 +42,15 @@ impl PprofConfig {
3742
/// Pprof Backend
3843
#[derive(Default)]
3944
pub struct Pprof<'a> {
45+
/// Profling buffer
46+
buffer: Arc<Mutex<StackBuffer>>,
47+
/// pprof-rs Configuration
4048
config: PprofConfig,
41-
inner_builder: Option<ProfilerGuardBuilder>,
42-
guard: Option<ProfilerGuard<'a>>,
49+
/// pprof-rs profiler Guard Builder
50+
inner_builder: Arc<Mutex<Option<ProfilerGuardBuilder>>>,
51+
/// pprof-rs profiler Guard
52+
guard: Arc<Mutex<Option<ProfilerGuard<'a>>>>,
53+
/// Ruleset
4354
ruleset: Ruleset,
4455
}
4556

@@ -52,9 +63,10 @@ impl std::fmt::Debug for Pprof<'_> {
5263
impl<'a> Pprof<'a> {
5364
pub fn new(config: PprofConfig) -> Self {
5465
Pprof {
66+
buffer: Arc::new(Mutex::new(StackBuffer::default())),
5567
config,
56-
inner_builder: None,
57-
guard: None,
68+
inner_builder: Arc::new(Mutex::new(None)),
69+
guard: Arc::new(Mutex::new(None)),
5870
ruleset: Ruleset::default(),
5971
}
6072
}
@@ -78,11 +90,13 @@ impl Backend for Pprof<'_> {
7890
fn initialize(&mut self) -> Result<()> {
7991
// Construct a ProfilerGuardBuilder
8092
let profiler = ProfilerGuardBuilder::default().frequency(self.config.sample_rate as i32);
93+
8194
// Set inner_builder field
82-
self.inner_builder = Some(profiler);
95+
*self.inner_builder.lock()? = Some(profiler);
8396

84-
self.guard = Some(
97+
*self.guard.lock()? = Some(
8598
self.inner_builder
99+
.lock()?
86100
.as_ref()
87101
.ok_or_else(|| PyroscopeError::new("pprof-rs: ProfilerGuardBuilder error"))?
88102
.clone()
@@ -94,8 +108,44 @@ impl Backend for Pprof<'_> {
94108
}
95109

96110
fn report(&mut self) -> Result<Vec<Report>> {
111+
self.dump_report()?;
112+
113+
let buffer = self.buffer.clone();
114+
115+
let report: StackBuffer = buffer.lock()?.deref().to_owned();
116+
117+
let reports: Vec<Report> = report.into();
118+
119+
buffer.lock()?.clear();
120+
121+
Ok(reports)
122+
}
123+
124+
fn add_rule(&self, rule: Rule) -> Result<()> {
125+
if self.guard.lock()?.as_ref().is_some() {
126+
self.dump_report()?;
127+
}
128+
129+
self.ruleset.add_rule(rule)?;
130+
131+
Ok(())
132+
}
133+
fn remove_rule(&self, rule: Rule) -> Result<()> {
134+
if self.guard.lock()?.as_ref().is_some() {
135+
self.dump_report()?;
136+
}
137+
138+
self.ruleset.remove_rule(rule)?;
139+
140+
Ok(())
141+
}
142+
}
143+
144+
impl Pprof<'_> {
145+
pub fn dump_report(&self) -> Result<()> {
97146
let report = self
98147
.guard
148+
.lock()?
99149
.as_ref()
100150
.ok_or_else(|| PyroscopeError::new("pprof-rs: ProfilerGuard report error"))?
101151
.report()
@@ -105,43 +155,32 @@ impl Backend for Pprof<'_> {
105155
let stack_buffer = Into::<StackBuffer>::into(Into::<StackBufferWrapper>::into(report));
106156

107157
// apply ruleset to stack_buffer
108-
let data = stack_buffer
158+
let data: HashMap<StackTrace, usize> = stack_buffer
109159
.data
110160
.iter()
111161
.map(|(stacktrace, ss)| {
112162
let stacktrace = stacktrace.to_owned() + &self.ruleset;
113163
(stacktrace, ss.to_owned())
114164
})
115165
.collect();
116-
let stack_buffer = StackBuffer::new(data);
117166

118-
let reports = stack_buffer.into();
119-
//let new_report = Into::<Report>::into(Into::<ReportWrapper>::into(report));
120-
//let reports = vec![new_report];
121-
122-
self.reset()?;
123-
124-
Ok(reports)
125-
}
167+
let buffer = self.buffer.clone();
126168

127-
fn add_rule(&self, rule: Rule) -> Result<()> {
128-
self.ruleset.add_rule(rule)?;
169+
for (stacktrace, count) in data {
170+
buffer.lock()?.record_with_count(stacktrace, count)?;
171+
}
129172

130-
Ok(())
131-
}
132-
fn remove_rule(&self, rule: Rule) -> Result<()> {
133-
self.ruleset.remove_rule(rule)?;
173+
self.reset()?;
134174

135175
Ok(())
136176
}
137-
}
138177

139-
impl Pprof<'_> {
140-
pub fn reset(&mut self) -> Result<()> {
141-
drop(self.guard.take());
178+
pub fn reset(&self) -> Result<()> {
179+
drop(self.guard.lock()?.take());
142180

143-
self.guard = Some(
181+
*self.guard.lock()? = Some(
144182
self.inner_builder
183+
.lock()?
145184
.as_ref()
146185
.ok_or_else(|| PyroscopeError::new("pprof-rs: ProfilerGuardBuilder error"))?
147186
.clone()

0 commit comments

Comments
 (0)