Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rand::random;
use regex::Regex;
use uuid::Uuid;

use api::protocol::{DebugMeta, Event, RepoReference};
use api::protocol::{Breadcrumb, DebugMeta, Event, RepoReference};
use api::Dsn;
use backtrace_support::{function_starts_with, is_sys_function, trim_stacktrace};
use constants::{SDK_INFO, USER_AGENT};
Expand All @@ -36,8 +36,8 @@ impl fmt::Debug for Client {
}
}

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

/// Configuration settings for the client.
pub struct ClientOptions {
Expand Down Expand Up @@ -87,8 +87,10 @@ pub struct ClientOptions {
pub attach_stacktrace: bool,
/// If turned on some default PII informat is attached.
pub send_default_pii: bool,
/// Before send method.
pub before_send: Option<Arc<BeforeSend>>,
/// Before send callback.
pub before_send: Option<BeforeCallback<Event<'static>>>,
/// Before breadcrumb add callback.
pub before_breadcrumb: Option<BeforeCallback<Breadcrumb>>,
}

impl fmt::Debug for ClientOptions {
Expand All @@ -97,6 +99,8 @@ impl fmt::Debug for ClientOptions {
struct TransportFactory;
#[derive(Debug)]
struct BeforeSendSet(bool);
#[derive(Debug)]
struct BeforeBreadcrumbSet(bool);
f.debug_struct("ClientOptions")
.field("dsn", &self.dsn)
.field("transport", &TransportFactory)
Expand All @@ -117,6 +121,10 @@ impl fmt::Debug for ClientOptions {
.field("attach_stacktrace", &self.attach_stacktrace)
.field("send_default_pii", &self.send_default_pii)
.field("before_send", &BeforeSendSet(self.before_send.is_some()))
.field(
"before_send",
&BeforeBreadcrumbSet(self.before_breadcrumb.is_some()),
)
.finish()
}
}
Expand All @@ -143,6 +151,7 @@ impl Clone for ClientOptions {
attach_stacktrace: self.attach_stacktrace,
send_default_pii: self.send_default_pii,
before_send: self.before_send.clone(),
before_breadcrumb: self.before_breadcrumb.clone(),
}
}
}
Expand Down Expand Up @@ -180,6 +189,7 @@ impl Default for ClientOptions {
attach_stacktrace: false,
send_default_pii: false,
before_send: None,
before_breadcrumb: None,
}
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/hub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,10 +370,16 @@ impl Hub {
let top = stack.top_mut();
if let Some(ref client) = top.client {
let scope = Arc::make_mut(&mut top.scope);
let limit = client.options().max_breadcrumbs;
let options = client.options();
for breadcrumb in breadcrumb.into_breadcrumbs() {
scope.breadcrumbs.push_back(breadcrumb);
while scope.breadcrumbs.len() > limit {
let breadcrumb_opt = match options.before_breadcrumb {
Some(ref callback) => callback(breadcrumb),
None => Some(breadcrumb)
};
if let Some(breadcrumb) = breadcrumb_opt {
scope.breadcrumbs.push_back(breadcrumb);
}
while scope.breadcrumbs.len() > options.max_breadcrumbs {
scope.breadcrumbs.pop_front();
}
}
Expand Down
93 changes: 93 additions & 0 deletions tests/test_processors.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
extern crate sentry;

use std::sync::Arc;

#[test]
fn test_event_processors() {
let events = sentry::test::with_captured_events(|| {
Expand Down Expand Up @@ -27,3 +29,94 @@ fn test_event_processors() {
})
);
}

#[test]
fn test_before_callbacks() {
fn before_send(
mut evt: sentry::protocol::Event<'static>,
) -> Option<sentry::protocol::Event<'static>> {
evt.logger = Some("muh_logger".into());
Some(evt)
}

fn before_breadcrumb(mut crumb: sentry::Breadcrumb) -> Option<sentry::Breadcrumb> {
crumb.message = Some(format!("{} aha!", crumb.message.unwrap()));
Some(crumb)
}

let events = sentry::test::with_captured_events_options(
|| {
sentry::add_breadcrumb(sentry::Breadcrumb {
message: Some("Testing".into()),
..Default::default()
});
sentry::capture_message("Hello World!", sentry::Level::Warning);
},
sentry::ClientOptions {
before_send: Some(Arc::new(Box::new(before_send))),
before_breadcrumb: Some(Arc::new(Box::new(before_breadcrumb))),
..Default::default()
},
);

assert_eq!(events.len(), 1);
let event = &events[0];
assert_eq!(event.logger.as_ref().unwrap(), "muh_logger");
assert_eq!(
event.breadcrumbs[0].message.as_ref().unwrap(),
"Testing aha!"
);
}

#[test]
fn test_before_event_callback_drop() {
#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
fn before_send(
_evt: sentry::protocol::Event<'static>,
) -> Option<sentry::protocol::Event<'static>> {
None
}

let events = sentry::test::with_captured_events_options(
|| {
sentry::add_breadcrumb(sentry::Breadcrumb {
message: Some("Testing".into()),
..Default::default()
});
sentry::capture_message("Hello World!", sentry::Level::Warning);
},
sentry::ClientOptions {
before_send: Some(Arc::new(Box::new(before_send))),
..Default::default()
},
);

assert_eq!(events.len(), 0);
}

#[test]
fn test_before_breadcrumb_callback_drop() {
#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
fn before_breadcrumb(_crumb: sentry::Breadcrumb) -> Option<sentry::Breadcrumb> {
None
}

let events = sentry::test::with_captured_events_options(
|| {
sentry::add_breadcrumb(sentry::Breadcrumb {
message: Some("Testing".into()),
..Default::default()
});
sentry::capture_message("Hello World!", sentry::Level::Warning);
},
sentry::ClientOptions {
before_breadcrumb: Some(Arc::new(Box::new(before_breadcrumb))),
..Default::default()
},
);

assert_eq!(events.len(), 1);
let event = &events[0];
assert_eq!(event.message.as_ref().unwrap(), "Hello World!");
assert_eq!(event.breadcrumbs.len(), 0);
}