Skip to content

Commit df694a4

Browse files
authored
ref: Rewrite tracing integration in terms of manual API (NATIVE-312) (#400)
Instead of hand-rolling all the transaction/span manipulation, rather implement it on top of the manual performance monitoring API.
1 parent afcac66 commit df694a4

File tree

5 files changed

+141
-357
lines changed

5 files changed

+141
-357
lines changed

sentry-core/src/performance.rs

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ impl TransactionContext {
112112
)
113113
}
114114
TransactionOrSpan::Span(span) => {
115-
(span.span.trace_id, span.span.span_id, Some(span.sampled))
115+
let sampled = span.sampled;
116+
let span = span.span.lock().unwrap();
117+
(span.trace_id, span.span_id, Some(sampled))
116118
}
117119
};
118120

@@ -158,6 +160,14 @@ impl From<Span> for TransactionOrSpan {
158160
}
159161

160162
impl TransactionOrSpan {
163+
/// Set some extra information to be sent with this Transaction/Span.
164+
pub fn set_data(&self, key: &str, value: protocol::Value) {
165+
match self {
166+
TransactionOrSpan::Transaction(transaction) => transaction.set_data(key, value),
167+
TransactionOrSpan::Span(span) => span.set_data(key, value),
168+
}
169+
}
170+
161171
/// Returns the headers needed for distributed tracing.
162172
pub fn iter_headers(&self) -> TraceHeadersIter {
163173
match self {
@@ -187,11 +197,14 @@ impl TransactionOrSpan {
187197
TransactionOrSpan::Transaction(transaction) => {
188198
transaction.inner.lock().unwrap().context.clone()
189199
}
190-
TransactionOrSpan::Span(span) => protocol::TraceContext {
191-
span_id: span.span.span_id,
192-
trace_id: span.span.trace_id,
193-
..Default::default()
194-
},
200+
TransactionOrSpan::Span(span) => {
201+
let span = span.span.lock().unwrap();
202+
protocol::TraceContext {
203+
span_id: span.span_id,
204+
trace_id: span.trace_id,
205+
..Default::default()
206+
}
207+
}
195208
};
196209
event.contexts.insert("trace".into(), context.into());
197210
}
@@ -266,6 +279,14 @@ impl Transaction {
266279
}
267280
}
268281

282+
/// Set some extra information to be sent with this Transaction.
283+
pub fn set_data(&self, key: &str, value: protocol::Value) {
284+
let mut inner = self.inner.lock().unwrap();
285+
if let Some(transaction) = inner.transaction.as_mut() {
286+
transaction.data.insert(key.into(), value);
287+
}
288+
}
289+
269290
/// Returns the headers needed for distributed tracing.
270291
pub fn iter_headers(&self) -> TraceHeadersIter {
271292
let inner = self.inner.lock().unwrap();
@@ -326,7 +347,7 @@ impl Transaction {
326347
Span {
327348
transaction: Arc::clone(&self.inner),
328349
sampled: inner.sampled,
329-
span,
350+
span: Arc::new(Mutex::new(span)),
330351
}
331352
}
332353
}
@@ -339,13 +360,22 @@ impl Transaction {
339360
pub struct Span {
340361
transaction: TransactionArc,
341362
sampled: bool,
342-
span: protocol::Span,
363+
span: SpanArc,
343364
}
344365

366+
type SpanArc = Arc<Mutex<protocol::Span>>;
367+
345368
impl Span {
369+
/// Set some extra information to be sent with this Transaction.
370+
pub fn set_data(&self, key: &str, value: protocol::Value) {
371+
let mut span = self.span.lock().unwrap();
372+
span.data.insert(key.into(), value);
373+
}
374+
346375
/// Returns the headers needed for distributed tracing.
347376
pub fn iter_headers(&self) -> TraceHeadersIter {
348-
let trace = SentryTrace(self.span.trace_id, self.span.span_id, Some(self.sampled));
377+
let span = self.span.lock().unwrap();
378+
let trace = SentryTrace(span.trace_id, span.span_id, Some(self.sampled));
349379
TraceHeadersIter {
350380
sentry_trace: Some(trace.to_string()),
351381
}
@@ -355,12 +385,17 @@ impl Span {
355385
///
356386
/// This will record the end timestamp and add the span to the transaction
357387
/// in which it was started.
358-
pub fn finish(mut self) {
359-
self.span.finish();
388+
pub fn finish(self) {
389+
let mut span = self.span.lock().unwrap();
390+
if span.timestamp.is_some() {
391+
// the span was already finished
392+
return;
393+
}
394+
span.finish();
360395
let mut inner = self.transaction.lock().unwrap();
361396
if let Some(transaction) = inner.transaction.as_mut() {
362397
if transaction.spans.len() <= MAX_SPANS {
363-
transaction.spans.push(self.span);
398+
transaction.spans.push(span.clone());
364399
}
365400
}
366401
}
@@ -370,9 +405,10 @@ impl Span {
370405
/// The span must be explicitly finished via [`Span::finish`].
371406
#[must_use = "a span must be explicitly closed via `finish()`"]
372407
pub fn start_child(&self, op: &str, description: &str) -> Span {
408+
let span = self.span.lock().unwrap();
373409
let span = protocol::Span {
374-
trace_id: self.span.trace_id,
375-
parent_span_id: Some(self.span.span_id),
410+
trace_id: span.trace_id,
411+
parent_span_id: Some(span.span_id),
376412
op: Some(op.into()),
377413
description: if description.is_empty() {
378414
None
@@ -384,7 +420,7 @@ impl Span {
384420
Span {
385421
transaction: self.transaction.clone(),
386422
sampled: self.sampled,
387-
span,
423+
span: Arc::new(Mutex::new(span)),
388424
}
389425
}
390426
}

sentry-tracing/src/converters.rs

Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
use std::collections::BTreeMap;
22

3-
use sentry_core::protocol::{self, Event, TraceContext, Value};
3+
use sentry_core::protocol::{Event, Value};
44
use sentry_core::{Breadcrumb, Level};
5-
use tracing_core::{
6-
field::{Field, Visit},
7-
span, Subscriber,
8-
};
5+
use tracing_core::field::{Field, Visit};
6+
use tracing_core::{span, Subscriber};
97
use tracing_subscriber::layer::Context;
108
use tracing_subscriber::registry::LookupSpan;
119

12-
use crate::Trace;
13-
1410
/// Converts a [`tracing_core::Level`] to a Sentry [`Level`]
1511
pub fn convert_tracing_level(level: &tracing_core::Level) -> Level {
1612
match level {
@@ -94,46 +90,19 @@ pub fn breadcrumb_from_event(event: &tracing_core::Event) -> Breadcrumb {
9490
}
9591

9692
/// Creates an [`Event`] from a given [`tracing_core::Event`]
97-
pub fn event_from_event<S>(event: &tracing_core::Event, ctx: Context<S>) -> Event<'static>
93+
pub fn event_from_event<S>(event: &tracing_core::Event, _ctx: Context<S>) -> Event<'static>
9894
where
9995
S: Subscriber + for<'a> LookupSpan<'a>,
10096
{
10197
let (message, extra) = extract_event_data(event);
10298

103-
let mut result = Event {
99+
Event {
104100
logger: Some(event.metadata().target().to_owned()),
105101
level: convert_tracing_level(event.metadata().level()),
106102
message,
107103
extra,
108104
..Default::default()
109-
};
110-
111-
let parent = event
112-
.parent()
113-
.and_then(|id| ctx.span(id))
114-
.or_else(|| ctx.lookup_current());
115-
116-
if let Some(parent) = parent {
117-
let extensions = parent.extensions();
118-
if let Some(trace) = extensions.get::<Trace>() {
119-
let context = protocol::Context::from(TraceContext {
120-
span_id: trace.span.span_id,
121-
trace_id: trace.span.trace_id,
122-
..TraceContext::default()
123-
});
124-
125-
result.contexts.insert(String::from("trace"), context);
126-
127-
result.transaction = parent
128-
.parent()
129-
.into_iter()
130-
.flat_map(|span| span.scope())
131-
.last()
132-
.map(|root| root.name().into());
133-
}
134105
}
135-
136-
result
137106
}
138107

139108
/// Creates an exception [`Event`] from a given [`tracing_core::Event`]

0 commit comments

Comments
 (0)