Skip to content

Commit e9d9696

Browse files
authored
Merge pull request #30 from pyroscope-io/0.5.2
0.5.2
2 parents d9a6015 + c435509 commit e9d9696

File tree

9 files changed

+208
-11
lines changed

9 files changed

+208
-11
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
# v0.5.2
2+
## New features
3+
- Authentication Token support
4+
5+
## API Changes
6+
- use rust-tls instead of openssl
7+
8+
# v0.5.1
9+
## API Changes
10+
- Backend shutdown bug
11+
- Docs update
12+
13+
# v0.5.0
14+
## API Changes
15+
- New API for building, starting and stopping the profiling agent.
16+
- Backend supports reporting multiple threads.
17+
- Tagging within local thread-scope
18+
119
# v0.4.0
220
## API Changes
321
- Backend now support passing a configuration struct.

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Pyroscope Profiler Agent for continuous profiling of Rust, Python and Ruby appli
55
"""
66
keywords = ["pyroscope", "profiler", "profiling", "pprof"]
77
authors = ["Abid Omar <[email protected]>"]
8-
version = "0.5.1"
8+
version = "0.5.2"
99
edition = "2021"
1010
license = "Apache-2.0"
1111
homepage = "https://pyroscope.io/docs/rust"
@@ -53,7 +53,8 @@ path = "examples/internal/rbspy-connect.rs"
5353
[dependencies]
5454
thiserror ="1.0"
5555
log = "0.4"
56-
reqwest = { version = "0.11", features = ["blocking"]}
56+
names = "0.13.0"
57+
reqwest = { version = "0.11", features = ["blocking", "rustls-tls-native-roots"]}
5758
libc = "^0.2.124"
5859

5960
[dev-dependencies]

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Add this to your `Cargo.toml`:
3232

3333
```toml
3434
[dependencies]
35-
pyroscope = "0.5.0"
35+
pyroscope = "0.5.2"
3636
pyroscope_pprofrs = "0.2"
3737
```
3838

@@ -83,8 +83,7 @@ The Pyroscope Agent doesn't do any profiling. The agent role is to orchasrate a
8383
### Limitations
8484

8585
- **Backend**: The Pyroscope Agent uses [pprof-rs](https://github.com/tikv/pprof-rs) as a backend. As a result, the [limitations](https://github.com/tikv/pprof-rs#why-not-) for pprof-rs also applies.
86-
- **Tagging**: ~~Adding or removing tags is not possible within threads. In general, the [Pyroscope Agent](https://docs.rs/pyroscope/latest/pyroscope/pyroscope/struct.PyroscopeAgent.html) is not Sync; and as a result a reference cannot be shared between threads. A multi-threaded program could be profiled but the agent is not thread-aware and a particular thread cannot be tagged.~~
87-
As of 0.5.0, the Pyroscope Agent support tagging within threads. Check the [Tags](examples/tags.rs) and [Multi-Thread](examples/multi-thread.rs) examples for usage.
86+
- **Tagging**: As of 0.5.0, the Pyroscope Agent support tagging within threads. Check the [Tags](examples/tags.rs) and [Multi-Thread](examples/multi-thread.rs) examples for usage.
8887
- **Timer**: epoll (for Linux) and kqueue (for macOS) are required for a more precise timer.
8988
- **Shutdown**: The Pyroscope Agent might take some time (usually less than 10 seconds) to shutdown properly and drop its threads. For a proper shutdown, it's recommended that you run the `shutdown` function before dropping the Agent.
9089

examples/auth.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
extern crate pyroscope;
2+
3+
use pyroscope::{PyroscopeAgent, Result};
4+
use pyroscope_pprofrs::{pprof_backend, PprofConfig};
5+
use std::hash::{Hash, Hasher};
6+
7+
fn hash_rounds(n: u64) -> u64 {
8+
let hash_str = "Some string to hash";
9+
let mut default_hasher = std::collections::hash_map::DefaultHasher::new();
10+
11+
for _ in 0..n {
12+
for _ in 0..1000 {
13+
default_hasher.write(hash_str.as_bytes());
14+
}
15+
hash_str.hash(&mut default_hasher);
16+
}
17+
18+
n
19+
}
20+
21+
fn main() -> Result<()> {
22+
// TODO: Change this token to your own.
23+
let token = String::from("<your-token>");
24+
25+
let agent = PyroscopeAgent::builder("http://localhost:4040", "example.basic")
26+
.backend(pprof_backend(PprofConfig::new().sample_rate(100)))
27+
.auth_token(token)
28+
.tags([("TagA", "ValueA"), ("TagB", "ValueB")].to_vec())
29+
.build()?;
30+
31+
// Show start time
32+
let start = std::time::SystemTime::now()
33+
.duration_since(std::time::UNIX_EPOCH)
34+
.unwrap()
35+
.as_secs();
36+
println!("Start Time: {}", start);
37+
38+
// Start Agent
39+
let agent_running = agent.start()?;
40+
41+
let _result = hash_rounds(300_000);
42+
43+
// Show stop time
44+
let stop = std::time::SystemTime::now()
45+
.duration_since(std::time::UNIX_EPOCH)
46+
.unwrap()
47+
.as_secs();
48+
println!("Stop Time: {}", stop);
49+
50+
// Stop Agent
51+
let agent_ready = agent_running.stop()?;
52+
53+
// Shutdown the Agent
54+
agent_ready.shutdown();
55+
56+
// Show program exit time
57+
let exit = std::time::SystemTime::now()
58+
.duration_since(std::time::UNIX_EPOCH)
59+
.unwrap()
60+
.as_secs();
61+
println!("Exit Time: {}", exit);
62+
63+
Ok(())
64+
}

pyroscope_cli/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/pyroscope.rs

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,24 @@ pub struct PyroscopeConfig {
4040
pub sample_rate: u32,
4141
/// Spy Name
4242
pub spy_name: String,
43+
/// Authentication Token
44+
pub auth_token: Option<String>,
45+
}
46+
47+
impl Default for PyroscopeConfig {
48+
fn default() -> Self {
49+
Self {
50+
url: "http://localhost:4040".to_string(),
51+
application_name: names::Generator::default()
52+
.next()
53+
.unwrap_or_else(|| "unassigned.app".to_string())
54+
.replace('-', "."),
55+
tags: HashMap::new(),
56+
sample_rate: 100u32,
57+
spy_name: "undefined".to_string(),
58+
auth_token: None,
59+
}
60+
}
4361
}
4462

4563
impl PyroscopeConfig {
@@ -57,6 +75,23 @@ impl PyroscopeConfig {
5775
tags: HashMap::new(), // Empty tags
5876
sample_rate: 100u32, // Default sample rate
5977
spy_name: String::from("undefined"), // Spy Name should be set by the backend
78+
auth_token: None, // No authentication token
79+
}
80+
}
81+
82+
// Set the Pyroscope Server URL
83+
pub fn url(self, url: impl AsRef<str>) -> Self {
84+
Self {
85+
url: url.as_ref().to_owned(),
86+
..self
87+
}
88+
}
89+
90+
// Set the Application Name
91+
pub fn application_name(self, application_name: impl AsRef<str>) -> Self {
92+
Self {
93+
application_name: application_name.as_ref().to_owned(),
94+
..self
6095
}
6196
}
6297

@@ -73,6 +108,14 @@ impl PyroscopeConfig {
73108
Self { spy_name, ..self }
74109
}
75110

111+
/// Set the Authentication Token.
112+
pub fn auth_token(self, auth_token: String) -> Self {
113+
Self {
114+
auth_token: Some(auth_token),
115+
..self
116+
}
117+
}
118+
76119
/// Set the tags.
77120
///
78121
/// # Example
@@ -115,6 +158,15 @@ pub struct PyroscopeAgentBuilder {
115158
config: PyroscopeConfig,
116159
}
117160

161+
impl Default for PyroscopeAgentBuilder {
162+
fn default() -> Self {
163+
Self {
164+
backend: void_backend(VoidConfig::default()),
165+
config: PyroscopeConfig::default(),
166+
}
167+
}
168+
}
169+
118170
impl PyroscopeAgentBuilder {
119171
/// Create a new PyroscopeAgentBuilder object. url and application_name are required.
120172
/// tags and sample_rate are optional.
@@ -130,19 +182,67 @@ impl PyroscopeAgentBuilder {
130182
}
131183
}
132184

185+
/// Set the Pyroscope Server URL. This can be used if the Builder was initialized with the default
186+
/// trait. Default is "http://localhost:4040".
187+
///
188+
/// # Example
189+
/// ```ignore
190+
/// let builder = PyroscopeAgentBuilder::default()
191+
/// .url("http://localhost:8080")
192+
/// .build()?;
193+
/// ```
194+
pub fn url(self, url: impl AsRef<str>) -> Self {
195+
Self {
196+
config: self.config.url(url),
197+
..self
198+
}
199+
}
200+
201+
/// Set the Application Name. This can be used if the Builder was initialized with the default
202+
/// trait. Default is a randomly generated name.
203+
///
204+
/// # Example
205+
/// ```ignore
206+
/// let builder = PyroscopeAgentBuilder::default()
207+
/// .application_name("my-app")
208+
/// .build()?;
209+
/// ```
210+
pub fn application_name(self, application_name: impl AsRef<str>) -> Self {
211+
Self {
212+
config: self.config.application_name(application_name),
213+
..self
214+
}
215+
}
216+
133217
/// Set the agent backend. Default is void-backend.
134218
///
135219
/// # Example
136220
/// ```ignore
137221
/// let builder = PyroscopeAgentBuilder::new("http://localhost:8080", "my-app")
138222
/// .backend(PprofConfig::new().sample_rate(100))
139-
/// .build()
140-
/// ?;
223+
/// .build()?;
141224
/// ```
142225
pub fn backend(self, backend: BackendImpl<BackendUninitialized>) -> Self {
143226
Self { backend, ..self }
144227
}
145228

229+
/// Set JWT authentication token.
230+
/// This is optional. If not set, the agent will not send any authentication token.
231+
///
232+
/// #Example
233+
/// ```ignore
234+
/// let builder = PyroscopeAgentBuilder::new("http://localhost:8080", "my-app")
235+
/// .auth_token("my-token")
236+
/// .build()
237+
/// ?;
238+
/// ```
239+
pub fn auth_token(self, auth_token: impl AsRef<str>) -> Self {
240+
Self {
241+
config: self.config.auth_token(auth_token.as_ref().to_owned()),
242+
..self
243+
}
244+
}
245+
146246
/// Set tags. Default is empty.
147247
///
148248
/// # Example

src/session.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,22 @@ impl Session {
168168
report.metadata.tags.clone().into_iter().collect(),
169169
)?;
170170

171-
// Create and send the request
172-
client
171+
// Create Reqwest builder
172+
let mut req_builder = client
173173
.post(format!("{}/ingest", url))
174-
.header("Content-Type", "binary/octet-stream")
174+
.header("Content-Type", "binary/octet-stream");
175+
176+
// Set authentication token
177+
//if self.config.auth_token.is_some() {
178+
//req_builder = req_builder.bearer_auth(self.config.auth_token.clone().unwrap());
179+
//}
180+
// rewrite with let some
181+
if let Some(auth_token) = self.config.auth_token.clone() {
182+
req_builder = req_builder.bearer_auth(auth_token);
183+
}
184+
185+
// Send the request
186+
req_builder
175187
.query(&[
176188
("name", application_name.as_str()),
177189
("from", &format!("{}", self.from)),

src/timer/kqueue.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ impl Timer {
157157
};
158158

159159
// add loop event
160-
let ke = kevent(
160+
let _ke = kevent(
161161
kqueue,
162162
[loop_event].as_ptr() as *const libc::kevent,
163163
1,

tests/session.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ fn test_session_new() {
2626
tags: HashMap::new(),
2727
sample_rate: 100u32,
2828
spy_name: "test-rs".to_string(),
29+
..Default::default()
2930
};
3031

3132
let report = vec![Report::new(HashMap::new())];
@@ -44,6 +45,7 @@ fn test_session_send_error() {
4445
tags: HashMap::new(),
4546
sample_rate: 100u32,
4647
spy_name: "test-rs".to_string(),
48+
..Default::default()
4749
};
4850

4951
let report = vec![Report::new(HashMap::new())];

0 commit comments

Comments
 (0)