Skip to content

Commit a138e3c

Browse files
committed
fix(sentry-tracing): switch sentry spans on enter and exit
1 parent 96b35c7 commit a138e3c

File tree

4 files changed

+101
-21
lines changed

4 files changed

+101
-21
lines changed

Cargo.lock

Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sentry-core/src/performance.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,24 @@ impl TransactionOrSpan {
322322
}
323323
}
324324

325+
#[doc(hidden)]
326+
#[must_use = "a span must be explicitly closed via `finish()`"]
327+
pub fn start_child_with_span_id(
328+
&self,
329+
op: &str,
330+
description: &str,
331+
span_id: protocol::SpanId,
332+
) -> Span {
333+
match self {
334+
TransactionOrSpan::Transaction(transaction) => {
335+
transaction.start_child_with_span_id(op, description, span_id)
336+
}
337+
TransactionOrSpan::Span(span) => {
338+
span.start_child_with_span_id(op, description, span_id)
339+
}
340+
}
341+
}
342+
325343
#[cfg(feature = "client")]
326344
pub(crate) fn apply_to_event(&self, event: &mut protocol::Event<'_>) {
327345
if event.contexts.contains_key("trace") {
@@ -587,10 +605,22 @@ impl Transaction {
587605
/// The span must be explicitly finished via [`Span::finish`].
588606
#[must_use = "a span must be explicitly closed via `finish()`"]
589607
pub fn start_child(&self, op: &str, description: &str) -> Span {
608+
self.start_child_with_span_id(op, description, Default::default())
609+
}
610+
611+
#[doc(hidden)]
612+
#[must_use = "a span must be explicitly closed via `finish()`"]
613+
pub fn start_child_with_span_id(
614+
&self,
615+
op: &str,
616+
description: &str,
617+
span_id: protocol::SpanId,
618+
) -> Span {
590619
let inner = self.inner.lock().unwrap();
591620
let span = protocol::Span {
592621
trace_id: inner.context.trace_id,
593622
parent_span_id: Some(inner.context.span_id),
623+
span_id,
594624
op: Some(op.into()),
595625
description: if description.is_empty() {
596626
None
@@ -754,10 +784,22 @@ impl Span {
754784
/// The span must be explicitly finished via [`Span::finish`].
755785
#[must_use = "a span must be explicitly closed via `finish()`"]
756786
pub fn start_child(&self, op: &str, description: &str) -> Span {
787+
self.start_child_with_span_id(op, description, Default::default())
788+
}
789+
790+
#[doc(hidden)]
791+
#[must_use = "a span must be explicitly closed via `finish()`"]
792+
pub fn start_child_with_span_id(
793+
&self,
794+
op: &str,
795+
description: &str,
796+
span_id: protocol::SpanId,
797+
) -> Span {
757798
let span = self.span.lock().unwrap();
758799
let span = protocol::Span {
759800
trace_id: span.trace_id,
760801
parent_span_id: Some(span.span_id),
802+
span_id,
761803
op: Some(op.into()),
762804
description: if description.is_empty() {
763805
None

sentry-tracing/src/layer.rs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,11 @@ where
208208
});
209209

210210
let parent_sentry_span = sentry_core::configure_scope(|s| s.get_span());
211+
let span_id = sentry_core::protocol::SpanId::from(id.into_u64().to_ne_bytes());
211212
let sentry_span: sentry_core::TransactionOrSpan = match &parent_sentry_span {
212-
Some(parent) => parent.start_child(op, &description).into(),
213+
Some(parent) => parent
214+
.start_child_with_span_id(op, &description, span_id)
215+
.into(),
213216
None => {
214217
let ctx = sentry_core::TransactionContext::new(&description, op);
215218
sentry_core::start_transaction(ctx).into()
@@ -221,15 +224,48 @@ where
221224
sentry_span.set_data(key, value);
222225
}
223226

224-
sentry_core::configure_scope(|scope| scope.set_span(Some(sentry_span.clone())));
225-
226227
let mut extensions = span.extensions_mut();
227228
extensions.insert(SentrySpanData {
228229
sentry_span,
229230
parent_sentry_span,
230231
});
231232
}
232233

234+
/// Sets entered span as *current* sentry span. A tracing span can be
235+
/// entered and existed multiple times, for example, when using a `tracing::Instrumented` future.
236+
fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
237+
let span = match ctx.span(&id) {
238+
Some(span) => span,
239+
None => return,
240+
};
241+
242+
let extensions = span.extensions();
243+
let SentrySpanData { sentry_span, .. } = match extensions.get::<SentrySpanData>() {
244+
Some(data) => data,
245+
None => return,
246+
};
247+
248+
sentry_core::configure_scope(|scope| scope.set_span(Some(sentry_span.clone())));
249+
}
250+
251+
/// Set exited span's parent as *current* sentry span.
252+
fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
253+
let span = match ctx.span(&id) {
254+
Some(span) => span,
255+
None => return,
256+
};
257+
258+
let extensions = span.extensions();
259+
let SentrySpanData {
260+
parent_sentry_span, ..
261+
} = match extensions.get::<SentrySpanData>() {
262+
Some(data) => data,
263+
None => return,
264+
};
265+
266+
sentry_core::configure_scope(|scope| scope.set_span(parent_sentry_span.clone()));
267+
}
268+
233269
/// When a span gets closed, finish the underlying sentry span, and set back
234270
/// its parent as the *current* sentry span.
235271
fn on_close(&self, id: span::Id, ctx: Context<'_, S>) {
@@ -239,16 +275,12 @@ where
239275
};
240276

241277
let mut extensions = span.extensions_mut();
242-
let SentrySpanData {
243-
sentry_span,
244-
parent_sentry_span,
245-
} = match extensions.remove::<SentrySpanData>() {
278+
let SentrySpanData { sentry_span, .. } = match extensions.remove::<SentrySpanData>() {
246279
Some(data) => data,
247280
None => return,
248281
};
249282

250283
sentry_span.finish();
251-
sentry_core::configure_scope(|scope| scope.set_span(parent_sentry_span));
252284
}
253285

254286
/// Implement the writing of extra data to span

sentry-types/src/protocol/v7.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,6 +1355,12 @@ impl From<SpanId> for String {
13551355
}
13561356
}
13571357

1358+
impl From<[u8; 8]> for SpanId {
1359+
fn from(span_id: [u8; 8]) -> Self {
1360+
Self(span_id)
1361+
}
1362+
}
1363+
13581364
impl str::FromStr for SpanId {
13591365
type Err = hex::FromHexError;
13601366

0 commit comments

Comments
 (0)