Skip to content

Commit a349b8e

Browse files
committed
misc: Add support for bridge spans
These will use `bridge_trace_id` to map an exising client transaction/span to this one so they'll be displayed as a single one in Sentry. This is done through the `sentry.trace` field, which will be used by `sentry-tracing` to differentiate these kinds of special spans. The special fields need to be added on the Span creation, that's why we do it in the constructor instead of just using `span.record(...)` later.
1 parent ec44c74 commit a349b8e

2 files changed

Lines changed: 72 additions & 6 deletions

File tree

bindings/matrix-sdk-ffi/src/platform.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ use std::sync::OnceLock;
22
#[cfg(feature = "sentry")]
33
use std::sync::{atomic::AtomicBool, Arc};
44

5+
#[cfg(feature = "sentry")]
6+
use sentry::MaxRequestBodySize;
57
#[cfg(feature = "sentry")]
68
use tracing::warn;
79
use tracing_appender::rolling::{RollingFileAppender, Rotation};
10+
#[cfg(feature = "sentry")]
11+
use tracing_core::Level;
812
use tracing_core::Subscriber;
913
use tracing_subscriber::{
1014
field::RecordFields,
@@ -21,6 +25,8 @@ use tracing_subscriber::{
2125
EnvFilter, Layer, Registry,
2226
};
2327

28+
#[cfg(feature = "sentry")]
29+
use crate::tracing::BRIDGE_SPAN_NAME;
2430
use crate::{error::ClientError, tracing::LogLevel};
2531

2632
// Adjusted version of tracing_subscriber::fmt::Format
@@ -465,9 +471,17 @@ impl TracingConfiguration {
465471
let sentry_guard = sentry::init((
466472
sentry_dsn,
467473
sentry::ClientOptions {
468-
traces_sample_rate: 0.0,
474+
traces_sampler: Some(Arc::new(|ctx| {
475+
// Make sure bridge spans are always uploaded
476+
if ctx.name() == BRIDGE_SPAN_NAME {
477+
1.0
478+
} else {
479+
0.0
480+
}
481+
})),
469482
attach_stacktrace: true,
470483
release: Some(env!("VERGEN_GIT_SHA").into()),
484+
max_request_body_size: MaxRequestBodySize::None,
471485
..sentry::ClientOptions::default()
472486
},
473487
));
@@ -494,12 +508,16 @@ impl TracingConfiguration {
494508
}
495509
}
496510
})
511+
.enable_span_attributes()
497512
.span_filter({
498513
let enabled = sentry_enabled.clone();
499514

500515
move |metadata| {
501516
if enabled.load(std::sync::atomic::Ordering::SeqCst) {
502-
sentry_tracing::default_span_filter(metadata)
517+
matches!(
518+
metadata.level(),
519+
&Level::ERROR | &Level::WARN | &Level::INFO | &Level::DEBUG
520+
)
503521
} else {
504522
// Ignore, if sentry is globally disabled.
505523
false

bindings/matrix-sdk-ffi/src/tracing.rs

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
#[cfg(feature = "sentry")]
2+
use std::borrow::ToOwned;
13
use std::{
24
collections::BTreeMap,
35
sync::{Arc, Mutex},
46
};
57

68
use once_cell::sync::OnceCell;
7-
use tracing::{callsite::DefaultCallsite, field::FieldSet, Callsite};
9+
use tracing::{callsite::DefaultCallsite, debug, error, field::FieldSet, Callsite};
810
use tracing_core::{identify_callsite, metadata::Kind as MetadataKind};
911

1012
/// Log an event.
@@ -96,6 +98,8 @@ fn span_or_event_enabled(callsite: &'static DefaultCallsite) -> bool {
9698
#[derive(uniffi::Object)]
9799
pub struct Span(tracing::Span);
98100

101+
pub(crate) const BRIDGE_SPAN_NAME: &str = "<sdk_bridge_span>";
102+
99103
#[matrix_sdk_ffi_macros::export]
100104
impl Span {
101105
/// Create a span originating at the given callsite (file, line and column).
@@ -129,18 +133,41 @@ impl Span {
129133
level: LogLevel,
130134
target: String,
131135
name: String,
136+
bridge_trace_id: Option<String>,
132137
) -> Arc<Self> {
133138
static CALLSITES: Mutex<BTreeMap<MetadataId, &'static DefaultCallsite>> =
134139
Mutex::new(BTreeMap::new());
135140

136141
let loc = MetadataId { file, line, level, target, name: Some(name) };
137-
let callsite = get_or_init_metadata(&CALLSITES, loc, &[], MetadataKind::SPAN);
142+
143+
// If sentry isn't enabled, ignore bridge_trace_id's contents
144+
let bridge_trace_id = if cfg!(feature = "sentry") { bridge_trace_id } else { None };
145+
146+
let callsite = if cfg!(feature = "sentry") {
147+
get_or_init_metadata(&CALLSITES, loc, &["sentry", "sentry.trace"], MetadataKind::SPAN)
148+
} else {
149+
get_or_init_metadata(&CALLSITES, loc, &[], MetadataKind::SPAN)
150+
};
151+
138152
let metadata = callsite.metadata();
139153

140154
let span = if span_or_event_enabled(callsite) {
141155
// This function is hidden from docs, but we have to use it (see above).
142-
let values = metadata.fields().value_set(&[]);
143-
tracing::Span::new(metadata, &values)
156+
let fields = metadata.fields();
157+
158+
if let Some(parent_trace_id) = bridge_trace_id {
159+
debug!("Adding fields | sentry:true, sentry.trace={parent_trace_id}");
160+
let sentry_field = fields.field("sentry").unwrap();
161+
let sentry_trace_field = fields.field("sentry.trace").unwrap();
162+
#[allow(trivial_casts)] // The compiler is lying, it can't infer this cast
163+
let values = [
164+
(&sentry_field, Some(&true as &dyn tracing::Value)),
165+
(&sentry_trace_field, Some(&parent_trace_id as &dyn tracing::Value)),
166+
];
167+
tracing::Span::new(metadata, &fields.value_set(&values))
168+
} else {
169+
tracing::Span::new(metadata, &fields.value_set(&[]))
170+
}
144171
} else {
145172
tracing::Span::none()
146173
};
@@ -164,6 +191,27 @@ impl Span {
164191
fn is_none(&self) -> bool {
165192
self.0.is_none()
166193
}
194+
195+
/// Creates a [`Span`] that acts as a bridge between the client spans and
196+
/// the SDK ones, allowing them to be joined in Sentry. This function
197+
/// will only return a valid span if the `sentry` feature is enabled,
198+
/// otherwise it will return a noop span.
199+
#[uniffi::constructor]
200+
pub fn new_bridge_span(target: String, parent_trace_id: Option<String>) -> Arc<Self> {
201+
if cfg!(feature = "sentry") {
202+
Self::new(
203+
"Bridge".to_owned(),
204+
None,
205+
LogLevel::Info,
206+
target,
207+
BRIDGE_SPAN_NAME.to_owned(),
208+
parent_trace_id,
209+
)
210+
} else {
211+
error!("Sentry is not enabled!");
212+
Arc::new(Self(tracing::Span::none()))
213+
}
214+
}
167215
}
168216

169217
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, uniffi::Enum)]

0 commit comments

Comments
 (0)