diff --git a/Cargo.lock b/Cargo.lock index 388e3d46..9971c7df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3849,6 +3849,7 @@ dependencies = [ "sentry", "sentry-backtrace", "sentry-core", + "serde_json", "tokio", "tracing", "tracing-core", diff --git a/sentry-tracing/Cargo.toml b/sentry-tracing/Cargo.toml index fc146712..ded85262 100644 --- a/sentry-tracing/Cargo.toml +++ b/sentry-tracing/Cargo.toml @@ -32,6 +32,7 @@ sentry-backtrace = { version = "0.34.0", path = "../sentry-backtrace", optional [dev-dependencies] log = "0.4" sentry = { path = "../sentry", default-features = false, features = ["test"] } +serde_json = "1" tracing = "0.1" tracing-subscriber = { version = "0.3.1", features = ["fmt", "registry"] } tokio = { version = "1.8", features = ["rt-multi-thread", "macros", "time"] } diff --git a/sentry-tracing/src/converters.rs b/sentry-tracing/src/converters.rs index c71143be..acce1055 100644 --- a/sentry-tracing/src/converters.rs +++ b/sentry-tracing/src/converters.rs @@ -141,8 +141,14 @@ impl Visit for FieldVisitor { } /// Creates a [`Breadcrumb`] from a given [`tracing_core::Event`] -pub fn breadcrumb_from_event(event: &tracing_core::Event) -> Breadcrumb { - let (message, visitor) = extract_event_data(event); +pub fn breadcrumb_from_event<'context, S>( + event: &tracing_core::Event, + ctx: impl Into>>, +) -> Breadcrumb +where + S: Subscriber + for<'a> LookupSpan<'a>, +{ + let (message, visitor) = extract_event_data_with_context(event, ctx.into()); Breadcrumb { category: Some(event.metadata().target().to_owned()), ty: "log".into(), diff --git a/sentry-tracing/src/layer.rs b/sentry-tracing/src/layer.rs index 0540fe76..a2f94d17 100644 --- a/sentry-tracing/src/layer.rs +++ b/sentry-tracing/src/layer.rs @@ -214,7 +214,7 @@ where match (self.event_filter)(event.metadata()) { EventFilter::Ignore => EventMapping::Ignore, EventFilter::Breadcrumb => { - EventMapping::Breadcrumb(breadcrumb_from_event(event)) + EventMapping::Breadcrumb(breadcrumb_from_event(event, span_ctx)) } EventFilter::Event => EventMapping::Event(event_from_event(event, span_ctx)), EventFilter::Exception => { diff --git a/sentry-tracing/tests/README.md b/sentry-tracing/tests/README.md new file mode 100644 index 00000000..a5c57a9e --- /dev/null +++ b/sentry-tracing/tests/README.md @@ -0,0 +1,3 @@ +# Integration tests for `sentry-tracing` + +These tests are split up into 1 file per test to ensure they don't run concurrently. diff --git a/sentry-tracing/tests/breadcrumbs.rs b/sentry-tracing/tests/breadcrumbs.rs new file mode 100644 index 00000000..f62e13b6 --- /dev/null +++ b/sentry-tracing/tests/breadcrumbs.rs @@ -0,0 +1,34 @@ +mod shared; + +#[test] +fn breadcrumbs_should_capture_span_fields() { + let transport = shared::init_sentry(); + + foo(); + + let data = transport.fetch_and_clear_envelopes(); + assert_eq!(data.len(), 2); + + let event = data.first().expect("should have 1 event"); + let event = match event.items().next().unwrap() { + sentry::protocol::EnvelopeItem::Event(event) => event, + unexpected => panic!("Expected event, but got {:#?}", unexpected), + }; + + assert_eq!(event.breadcrumbs.len(), 1); + assert_eq!( + event.breadcrumbs[0].data["foo:contextual_value"], + serde_json::Value::from(42) + ); + assert_eq!( + event.breadcrumbs[0].message, + Some("executing foo".to_owned()) + ); +} + +#[tracing::instrument(fields(contextual_value = 42))] +fn foo() { + tracing::info!("executing foo"); + + tracing::error!("boom!"); +} diff --git a/sentry-tracing/tests/shared.rs b/sentry-tracing/tests/shared.rs new file mode 100644 index 00000000..9b4409ed --- /dev/null +++ b/sentry-tracing/tests/shared.rs @@ -0,0 +1,24 @@ +use sentry::{ClientOptions, Hub}; +use sentry_core::test::TestTransport; + +use std::sync::Arc; + +pub fn init_sentry() -> Arc { + use tracing_subscriber::prelude::*; + + let transport = TestTransport::new(); + let options = ClientOptions { + dsn: Some("https://test@sentry-tracing.com/test".parse().unwrap()), + transport: Some(Arc::new(transport.clone())), + sample_rate: 1.0, + traces_sample_rate: 1.0, + ..ClientOptions::default() + }; + Hub::current().bind_client(Some(Arc::new(options.into()))); + + let _ = tracing_subscriber::registry() + .with(sentry_tracing::layer().enable_span_attributes()) + .try_init(); + + transport +} diff --git a/sentry-tracing/tests/tracing.rs b/sentry-tracing/tests/smoke.rs similarity index 70% rename from sentry-tracing/tests/tracing.rs rename to sentry-tracing/tests/smoke.rs index c77183c3..05c3f9b5 100644 --- a/sentry-tracing/tests/tracing.rs +++ b/sentry-tracing/tests/smoke.rs @@ -1,27 +1,4 @@ -use sentry::{ClientOptions, Hub}; -use sentry_core::test::TestTransport; - -use std::sync::Arc; - -fn init_sentry() -> Arc { - use tracing_subscriber::prelude::*; - - let transport = TestTransport::new(); - let options = ClientOptions { - dsn: Some("https://test@sentry-tracing.com/test".parse().unwrap()), - transport: Some(Arc::new(transport.clone())), - sample_rate: 1.0, - traces_sample_rate: 1.0, - ..ClientOptions::default() - }; - Hub::current().bind_client(Some(Arc::new(options.into()))); - - let _ = tracing_subscriber::registry() - .with(sentry_tracing::layer().enable_span_attributes()) - .try_init(); - - transport -} +mod shared; #[tracing::instrument(fields(tags.tag = "key", not_tag = "value"))] fn function_with_tags(value: i32) { @@ -30,7 +7,7 @@ fn function_with_tags(value: i32) { #[test] fn should_instrument_function_with_event() { - let transport = init_sentry(); + let transport = shared::init_sentry(); function_with_tags(1);