Skip to content

Commit b02aa89

Browse files
authored
Merge pull request #6 from omarabid/main
Error update
2 parents 335196b + e1e007c commit b02aa89

File tree

4 files changed

+126
-56
lines changed

4 files changed

+126
-56
lines changed

examples/error.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2021 Developers of Pyroscope.
2+
3+
// Licensed under the Apache License, Version 2.0 <LICENSE or
4+
// https://www.apache.org/licenses/LICENSE-2.0>. This file may not be copied, modified, or distributed
5+
// except according to those terms.
6+
7+
extern crate pyroscope;
8+
9+
use pyroscope::{PyroscopeAgent, Result};
10+
11+
fn fibonacci(n: u64) -> u64 {
12+
match n {
13+
0 | 1 => 1,
14+
n => fibonacci(n - 1) + fibonacci(n - 2),
15+
}
16+
}
17+
18+
fn main() -> Result<()> {
19+
// Force rustc to display the log messages in the console.
20+
std::env::set_var("RUST_LOG", "trace");
21+
22+
// Initialize the logger.
23+
pretty_env_logger::init_timed();
24+
25+
// This example should fail and return an error.
26+
println!("This example should fail and return an error.");
27+
println!("Run this with: RUST_BACKTRACE=1 cargo run --example error");
28+
29+
let mut agent = PyroscopeAgent::builder("http://invalid_url", "example.error")
30+
.build()?;
31+
// Start Agent
32+
agent.start()?;
33+
34+
let _result = fibonacci(47);
35+
36+
// Stop Agent
37+
agent.stop()?;
38+
39+
drop(agent);
40+
41+
Ok(())
42+
}

src/backends/pprof.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use pprof::{ProfilerGuard, ProfilerGuardBuilder, Report};
88

99
use crate::backends::Backend;
1010
use crate::backends::State;
11+
use crate::PyroscopeError;
1112
use crate::Result;
1213

1314
#[derive(Default)]
@@ -31,9 +32,7 @@ impl Backend for Pprof<'_> {
3132
fn initialize(&mut self, sample_rate: i32) -> Result<()> {
3233
// Check if Backend is Uninitialized
3334
if self.state != State::Uninitialized {
34-
return Err(crate::error::PyroscopeError {
35-
msg: String::from("Pprof Backend is already Initialized"),
36-
});
35+
return Err(PyroscopeError::new("Pprof Backend is already Initialized"));
3736
}
3837

3938
// Construct a ProfilerGuardBuilder
@@ -50,9 +49,7 @@ impl Backend for Pprof<'_> {
5049
fn start(&mut self) -> Result<()> {
5150
// Check if Backend is Ready
5251
if self.state != State::Ready {
53-
return Err(crate::error::PyroscopeError {
54-
msg: String::from("Pprof Backend is not Ready"),
55-
});
52+
return Err(PyroscopeError::new("Pprof Backend is not Ready"));
5653
}
5754

5855
self.guard = Some(self.inner_builder.as_ref().unwrap().clone().build()?);
@@ -66,9 +63,7 @@ impl Backend for Pprof<'_> {
6663
fn stop(&mut self) -> Result<()> {
6764
// Check if Backend is Running
6865
if self.state != State::Running {
69-
return Err(crate::error::PyroscopeError {
70-
msg: String::from("Pprof Backend is not Running"),
71-
});
66+
return Err(PyroscopeError::new("Pprof Backend is not Running"));
7267
}
7368

7469
// drop the guard
@@ -83,9 +78,7 @@ impl Backend for Pprof<'_> {
8378
fn report(&mut self) -> Result<Vec<u8>> {
8479
// Check if Backend is Running
8580
if self.state != State::Running {
86-
return Err(crate::error::PyroscopeError {
87-
msg: String::from("Pprof Backend is not Running"),
88-
});
81+
return Err(PyroscopeError::new("Pprof Backend is not Running"));
8982
}
9083

9184
let mut buffer = Vec::new();
@@ -102,7 +95,9 @@ impl Backend for Pprof<'_> {
10295

10396
// Copyright: https://github.com/YangKeao
10497
fn fold<W>(report: &Report, with_thread_name: bool, mut writer: W) -> Result<()>
105-
where W: std::io::Write {
98+
where
99+
W: std::io::Write,
100+
{
106101
for (key, value) in report.data.iter() {
107102
if with_thread_name {
108103
if !key.thread_name.is_empty() {

src/error.rs

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ use thiserror::Error;
1111
pub type Result<T> = std::result::Result<T, PyroscopeError>;
1212

1313
/// Error type of Pyroscope
14-
#[derive(Error, Debug, PartialEq)]
14+
#[derive(Error, Debug)]
1515
pub struct PyroscopeError {
1616
pub msg: String,
17+
source: Option<Box<dyn std::error::Error + Send + Sync>>,
1718
}
1819

1920
impl fmt::Display for PyroscopeError {
@@ -22,50 +23,83 @@ impl fmt::Display for PyroscopeError {
2223
}
2324
}
2425

26+
impl Default for PyroscopeError {
27+
fn default() -> Self {
28+
PyroscopeError {
29+
msg: "".to_string(),
30+
source: None,
31+
}
32+
}
33+
}
34+
35+
impl PyroscopeError {
36+
/// Create a new instance of PyroscopeError
37+
pub fn new(msg: &str) -> Self {
38+
PyroscopeError {
39+
msg: msg.to_string(),
40+
source: None,
41+
}
42+
}
43+
44+
/// Create a new instance of PyroscopeError with source
45+
pub fn new_with_source(msg: &str, source: Box<dyn std::error::Error + Send + Sync>) -> Self {
46+
PyroscopeError {
47+
msg: msg.to_string(),
48+
source: Some(source),
49+
}
50+
}
51+
}
52+
2553
impl From<reqwest::Error> for PyroscopeError {
26-
fn from(_err: reqwest::Error) -> Self {
54+
fn from(err: reqwest::Error) -> Self {
2755
PyroscopeError {
2856
msg: String::from("reqwest Error"),
57+
source: Some(Box::new(err)),
2958
}
3059
}
3160
}
3261

3362
impl From<pprof::Error> for PyroscopeError {
34-
fn from(_err: pprof::Error) -> Self {
63+
fn from(err: pprof::Error) -> Self {
3564
PyroscopeError {
3665
msg: String::from("pprof Error"),
66+
source: Some(Box::new(err)),
3767
}
3868
}
3969
}
4070

4171
impl From<std::time::SystemTimeError> for PyroscopeError {
42-
fn from(_err: std::time::SystemTimeError) -> Self {
72+
fn from(err: std::time::SystemTimeError) -> Self {
4373
PyroscopeError {
4474
msg: String::from("SystemTime Error"),
75+
source: Some(Box::new(err)),
4576
}
4677
}
4778
}
4879

4980
impl From<std::io::Error> for PyroscopeError {
50-
fn from(_err: std::io::Error) -> Self {
81+
fn from(err: std::io::Error) -> Self {
5182
PyroscopeError {
5283
msg: String::from("IO Error"),
84+
source: Some(Box::new(err)),
5385
}
5486
}
5587
}
5688

5789
impl<T> From<std::sync::PoisonError<T>> for PyroscopeError {
5890
fn from(_err: std::sync::PoisonError<T>) -> Self {
5991
PyroscopeError {
60-
msg: String::from("Poison/Mutex Error"),
92+
msg: String::from("Poison Error"),
93+
source: None,
6194
}
6295
}
6396
}
6497

65-
impl<T> From<std::sync::mpsc::SendError<T>> for PyroscopeError {
66-
fn from(_err: std::sync::mpsc::SendError<T>) -> Self {
98+
impl<T: 'static + Send + Sync> From<std::sync::mpsc::SendError<T>> for PyroscopeError {
99+
fn from(err: std::sync::mpsc::SendError<T>) -> Self {
67100
PyroscopeError {
68-
msg: String::from("mpsc Send Error"),
101+
msg: String::from("SendError Error"),
102+
source: Some(Box::new(err)),
69103
}
70104
}
71105
}

src/session.rs

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ impl SessionManager {
5454
}
5555
SessionSignal::Kill => {
5656
// Kill the session manager
57-
return Ok(());
5857
log::trace!("SessionManager - Kill signal received");
58+
return Ok(());
5959
}
6060
}
6161
}
@@ -89,7 +89,7 @@ pub struct Session {
8989

9090
impl Session {
9191
/// Create a new Session
92-
/// # Example
92+
/// # Example
9393
/// ```ignore
9494
/// let config = PyroscopeConfig::new("https://localhost:8080", "my-app");
9595
/// let report = vec![1, 2, 3];
@@ -131,39 +131,38 @@ impl Session {
131131
pub fn send(self) -> Result<()> {
132132
log::info!("Session - Sending Session");
133133

134-
let _handle: JoinHandle<Result<()>> = thread::spawn(move || {
135-
if self.report.is_empty() {
136-
return Ok(());
137-
}
138-
139-
let client = reqwest::blocking::Client::new();
140-
// TODO: handle the error of this request
141-
142-
// Clone URL
143-
let url = self.config.url.clone();
144-
145-
// Merge application name with Tags
146-
let application_name = merge_tags_with_app_name(
147-
self.config.application_name.clone(),
148-
self.config.tags.clone(),
149-
)?;
150-
151-
client
152-
.post(format!("{}/ingest", url))
153-
.header("Content-Type", "binary/octet-stream")
154-
.query(&[
155-
("name", application_name.as_str()),
156-
("from", &format!("{}", self.from)),
157-
("until", &format!("{}", self.until)),
158-
("format", "folded"),
159-
("sampleRate", &format!("{}", self.config.sample_rate)),
160-
("spyName", "pprof-rs"),
161-
])
162-
.body(self.report)
163-
.send()?;
164-
134+
// Check if the report is empty
135+
if self.report.is_empty() {
165136
return Ok(());
166-
});
137+
}
138+
139+
// Create a new client
140+
let client = reqwest::blocking::Client::new();
141+
142+
// Clone URL
143+
let url = self.config.url.clone();
144+
145+
// Merge application name with Tags
146+
let application_name = merge_tags_with_app_name(
147+
self.config.application_name.clone(),
148+
self.config.tags.clone(),
149+
)?;
150+
151+
// Create and send the request
152+
client
153+
.post(format!("{}/ingest", url))
154+
.header("Content-Type", "binary/octet-stream")
155+
.query(&[
156+
("name", application_name.as_str()),
157+
("from", &format!("{}", self.from)),
158+
("until", &format!("{}", self.until)),
159+
("format", "folded"),
160+
("sampleRate", &format!("{}", self.config.sample_rate)),
161+
("spyName", "pyroscope-rs"),
162+
])
163+
.body(self.report)
164+
.timeout(std::time::Duration::from_secs(10))
165+
.send()?;
167166

168167
Ok(())
169168
}

0 commit comments

Comments
 (0)