Skip to content

Commit 0e99cdd

Browse files
authored
feat: Added before breadcrumb callback (#78)
1 parent f985af0 commit 0e99cdd

File tree

3 files changed

+117
-8
lines changed

3 files changed

+117
-8
lines changed

src/client.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rand::random;
1010
use regex::Regex;
1111
use uuid::Uuid;
1212

13-
use api::protocol::{DebugMeta, Event, RepoReference};
13+
use api::protocol::{Breadcrumb, DebugMeta, Event, RepoReference};
1414
use api::Dsn;
1515
use backtrace_support::{function_starts_with, is_sys_function, trim_stacktrace};
1616
use constants::{SDK_INFO, USER_AGENT};
@@ -36,8 +36,8 @@ impl fmt::Debug for Client {
3636
}
3737
}
3838

39-
/// Type alias for before send handlers
40-
pub type BeforeSend = Box<Fn(Event<'static>) -> Option<Event<'static>> + Send + Sync>;
39+
/// Type alias for before event/breadcrumb handlers.
40+
pub type BeforeCallback<T> = Arc<Box<Fn(T) -> Option<T> + Send + Sync>>;
4141

4242
/// Configuration settings for the client.
4343
pub struct ClientOptions {
@@ -87,8 +87,10 @@ pub struct ClientOptions {
8787
pub attach_stacktrace: bool,
8888
/// If turned on some default PII informat is attached.
8989
pub send_default_pii: bool,
90-
/// Before send method.
91-
pub before_send: Option<Arc<BeforeSend>>,
90+
/// Before send callback.
91+
pub before_send: Option<BeforeCallback<Event<'static>>>,
92+
/// Before breadcrumb add callback.
93+
pub before_breadcrumb: Option<BeforeCallback<Breadcrumb>>,
9294
}
9395

9496
impl fmt::Debug for ClientOptions {
@@ -97,6 +99,8 @@ impl fmt::Debug for ClientOptions {
9799
struct TransportFactory;
98100
#[derive(Debug)]
99101
struct BeforeSendSet(bool);
102+
#[derive(Debug)]
103+
struct BeforeBreadcrumbSet(bool);
100104
f.debug_struct("ClientOptions")
101105
.field("dsn", &self.dsn)
102106
.field("transport", &TransportFactory)
@@ -117,6 +121,10 @@ impl fmt::Debug for ClientOptions {
117121
.field("attach_stacktrace", &self.attach_stacktrace)
118122
.field("send_default_pii", &self.send_default_pii)
119123
.field("before_send", &BeforeSendSet(self.before_send.is_some()))
124+
.field(
125+
"before_send",
126+
&BeforeBreadcrumbSet(self.before_breadcrumb.is_some()),
127+
)
120128
.finish()
121129
}
122130
}
@@ -143,6 +151,7 @@ impl Clone for ClientOptions {
143151
attach_stacktrace: self.attach_stacktrace,
144152
send_default_pii: self.send_default_pii,
145153
before_send: self.before_send.clone(),
154+
before_breadcrumb: self.before_breadcrumb.clone(),
146155
}
147156
}
148157
}
@@ -180,6 +189,7 @@ impl Default for ClientOptions {
180189
attach_stacktrace: false,
181190
send_default_pii: false,
182191
before_send: None,
192+
before_breadcrumb: None,
183193
}
184194
}
185195
}

src/hub.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,10 +379,16 @@ impl Hub {
379379
let top = stack.top_mut();
380380
if let Some(ref client) = top.client {
381381
let scope = Arc::make_mut(&mut top.scope);
382-
let limit = client.options().max_breadcrumbs;
382+
let options = client.options();
383383
for breadcrumb in breadcrumb.into_breadcrumbs() {
384-
scope.breadcrumbs.push_back(breadcrumb);
385-
while scope.breadcrumbs.len() > limit {
384+
let breadcrumb_opt = match options.before_breadcrumb {
385+
Some(ref callback) => callback(breadcrumb),
386+
None => Some(breadcrumb)
387+
};
388+
if let Some(breadcrumb) = breadcrumb_opt {
389+
scope.breadcrumbs.push_back(breadcrumb);
390+
}
391+
while scope.breadcrumbs.len() > options.max_breadcrumbs {
386392
scope.breadcrumbs.pop_front();
387393
}
388394
}

tests/test_processors.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
extern crate sentry;
22

3+
use std::sync::Arc;
4+
35
#[test]
46
fn test_event_processors() {
57
let events = sentry::test::with_captured_events(|| {
@@ -27,3 +29,94 @@ fn test_event_processors() {
2729
})
2830
);
2931
}
32+
33+
#[test]
34+
fn test_before_callbacks() {
35+
fn before_send(
36+
mut evt: sentry::protocol::Event<'static>,
37+
) -> Option<sentry::protocol::Event<'static>> {
38+
evt.logger = Some("muh_logger".into());
39+
Some(evt)
40+
}
41+
42+
fn before_breadcrumb(mut crumb: sentry::Breadcrumb) -> Option<sentry::Breadcrumb> {
43+
crumb.message = Some(format!("{} aha!", crumb.message.unwrap()));
44+
Some(crumb)
45+
}
46+
47+
let events = sentry::test::with_captured_events_options(
48+
|| {
49+
sentry::add_breadcrumb(sentry::Breadcrumb {
50+
message: Some("Testing".into()),
51+
..Default::default()
52+
});
53+
sentry::capture_message("Hello World!", sentry::Level::Warning);
54+
},
55+
sentry::ClientOptions {
56+
before_send: Some(Arc::new(Box::new(before_send))),
57+
before_breadcrumb: Some(Arc::new(Box::new(before_breadcrumb))),
58+
..Default::default()
59+
},
60+
);
61+
62+
assert_eq!(events.len(), 1);
63+
let event = &events[0];
64+
assert_eq!(event.logger.as_ref().unwrap(), "muh_logger");
65+
assert_eq!(
66+
event.breadcrumbs[0].message.as_ref().unwrap(),
67+
"Testing aha!"
68+
);
69+
}
70+
71+
#[test]
72+
fn test_before_event_callback_drop() {
73+
#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
74+
fn before_send(
75+
_evt: sentry::protocol::Event<'static>,
76+
) -> Option<sentry::protocol::Event<'static>> {
77+
None
78+
}
79+
80+
let events = sentry::test::with_captured_events_options(
81+
|| {
82+
sentry::add_breadcrumb(sentry::Breadcrumb {
83+
message: Some("Testing".into()),
84+
..Default::default()
85+
});
86+
sentry::capture_message("Hello World!", sentry::Level::Warning);
87+
},
88+
sentry::ClientOptions {
89+
before_send: Some(Arc::new(Box::new(before_send))),
90+
..Default::default()
91+
},
92+
);
93+
94+
assert_eq!(events.len(), 0);
95+
}
96+
97+
#[test]
98+
fn test_before_breadcrumb_callback_drop() {
99+
#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
100+
fn before_breadcrumb(_crumb: sentry::Breadcrumb) -> Option<sentry::Breadcrumb> {
101+
None
102+
}
103+
104+
let events = sentry::test::with_captured_events_options(
105+
|| {
106+
sentry::add_breadcrumb(sentry::Breadcrumb {
107+
message: Some("Testing".into()),
108+
..Default::default()
109+
});
110+
sentry::capture_message("Hello World!", sentry::Level::Warning);
111+
},
112+
sentry::ClientOptions {
113+
before_breadcrumb: Some(Arc::new(Box::new(before_breadcrumb))),
114+
..Default::default()
115+
},
116+
);
117+
118+
assert_eq!(events.len(), 1);
119+
let event = &events[0];
120+
assert_eq!(event.message.as_ref().unwrap(), "Hello World!");
121+
assert_eq!(event.breadcrumbs.len(), 0);
122+
}

0 commit comments

Comments
 (0)