Skip to content

Commit d29550d

Browse files
committed
perf(context): move active span to flag and make invalid spans none
1 parent 5723d7c commit d29550d

File tree

3 files changed

+97
-53
lines changed

3 files changed

+97
-53
lines changed

opentelemetry/src/context.rs

Lines changed: 56 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -425,47 +425,44 @@ impl Context {
425425
}
426426

427427
#[cfg(feature = "trace")]
428-
pub(crate) fn current_with_synchronized_span(value: SynchronizedSpan) -> Self {
429-
Self::map_current(|cx| {
430-
if let Some(inner) = &cx.inner {
428+
pub(crate) fn current_with_synchronized_span(span: Option<Arc<SynchronizedSpan>>) -> Self {
429+
Self::map_current(|cx| cx.with_synchronized_span(span))
430+
}
431+
432+
#[cfg(feature = "trace")]
433+
pub(crate) fn with_synchronized_span(&self, span: Option<Arc<SynchronizedSpan>>) -> Self {
434+
let active = span.is_some();
435+
if let Some(inner) = &self.inner {
436+
if span.is_none() && inner.span.is_none() {
437+
self.clone()
438+
} else {
431439
Context {
432440
inner: Some(Arc::new(InnerContext {
433-
span: Some(Arc::new(value)),
441+
span,
434442
entries: inner.entries.clone(),
435443
})),
436-
flags: cx.flags,
444+
flags: self.flags.with_active_span(active),
437445
}
446+
}
447+
} else {
448+
if span.is_none() {
449+
self.clone()
438450
} else {
439451
Context {
440452
inner: Some(Arc::new(InnerContext {
441-
span: Some(Arc::new(value)),
453+
span,
442454
entries: None,
443455
})),
444-
flags: ContextFlags::new(),
456+
flags: self.flags.with_active_span(active),
445457
}
446458
}
447-
})
459+
}
448460
}
449461

450462
#[cfg(feature = "trace")]
451-
pub(crate) fn with_synchronized_span(&self, value: SynchronizedSpan) -> Self {
452-
if let Some(inner) = &self.inner {
453-
Context {
454-
inner: Some(Arc::new(InnerContext {
455-
span: Some(Arc::new(value)),
456-
entries: inner.entries.clone(),
457-
})),
458-
flags: self.flags,
459-
}
460-
} else {
461-
Context {
462-
inner: Some(Arc::new(InnerContext {
463-
span: Some(Arc::new(value)),
464-
entries: None,
465-
})),
466-
flags: ContextFlags::new(),
467-
}
468-
}
463+
#[inline(always)]
464+
pub(crate) const fn has_active_span_flag(&self) -> bool {
465+
self.flags.is_span_active()
469466
}
470467
}
471468

@@ -505,12 +502,8 @@ struct ContextFlags(u16);
505502

506503
impl ContextFlags {
507504
const SUPPRESS_TELEMETRY: u16 = 1 << 0;
508-
509-
/// Creates a new ContextFlags with all flags cleared.
510-
#[inline(always)]
511-
const fn new() -> Self {
512-
ContextFlags(0)
513-
}
505+
#[cfg(feature = "trace")]
506+
const ACTIVE_SPAN: u16 = 1 << 1;
514507

515508
/// Returns true if telemetry suppression is enabled.
516509
#[inline(always)]
@@ -523,13 +516,44 @@ impl ContextFlags {
523516
const fn with_telemetry_suppressed(self) -> Self {
524517
ContextFlags(self.0 | Self::SUPPRESS_TELEMETRY)
525518
}
519+
520+
/// Returns true if the active span flag is set.
521+
#[cfg(feature = "trace")]
522+
#[inline(always)]
523+
const fn is_span_active(self) -> bool {
524+
(self.0 & Self::ACTIVE_SPAN) != 0
525+
}
526+
527+
/// Returns a new ContextFlags with the active span flag set.
528+
#[cfg(feature = "trace")]
529+
#[inline(always)]
530+
const fn with_active_span(self, active: bool) -> Self {
531+
if active {
532+
ContextFlags(self.0 | Self::ACTIVE_SPAN)
533+
} else {
534+
ContextFlags(self.0 & !Self::ACTIVE_SPAN)
535+
}
536+
}
526537
}
527538

528539
impl fmt::Debug for ContextFlags {
529540
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
541+
#[cfg(feature = "trace")]
542+
let mut comma = false;
530543
f.write_str("ContextFlags(")?;
531544
if self.is_telemetry_suppressed() {
532545
f.write_str("TELEMETRY_SUPPRESSED")?;
546+
#[cfg(feature = "trace")]
547+
{
548+
comma = true;
549+
}
550+
}
551+
#[cfg(feature = "trace")]
552+
if self.is_span_active() {
553+
if comma {
554+
f.write_str(", ")?;
555+
}
556+
f.write_str("ACTIVE_SPAN")?;
533557
}
534558
f.write_str(")")
535559
}

opentelemetry/src/trace/context.rs

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ use crate::{
44
trace::{Span, SpanContext, Status},
55
Context, ContextGuard, KeyValue,
66
};
7-
use std::{borrow::Cow, error::Error, sync::Mutex};
7+
use std::{
8+
borrow::Cow,
9+
error::Error,
10+
sync::{Arc, Mutex},
11+
};
812

913
// Re-export for compatability. This used to be contained here.
1014
pub use crate::context::{FutureExt, WithContext};
@@ -30,22 +34,29 @@ impl SynchronizedSpan {
3034
pub(crate) fn span_context(&self) -> &SpanContext {
3135
&self.span_context
3236
}
33-
}
3437

35-
impl From<SpanContext> for SynchronizedSpan {
36-
fn from(value: SpanContext) -> Self {
37-
Self {
38-
span_context: value,
39-
inner: None,
38+
fn maybe_from_span<T>(value: T) -> Option<Arc<SynchronizedSpan>>
39+
where
40+
T: Span + Send + Sync + 'static,
41+
{
42+
if !value.span_context().is_valid() {
43+
None
44+
} else {
45+
Some(Arc::new(SynchronizedSpan {
46+
span_context: value.span_context().clone(),
47+
inner: Some(Mutex::new(global::BoxedSpan::new(value))),
48+
}))
4049
}
4150
}
42-
}
4351

44-
impl<T: Span + Send + Sync + 'static> From<T> for SynchronizedSpan {
45-
fn from(value: T) -> Self {
46-
Self {
47-
span_context: value.span_context().clone(),
48-
inner: Some(Mutex::new(global::BoxedSpan::new(value))),
52+
fn maybe_from_span_context(value: SpanContext) -> Option<Arc<SynchronizedSpan>> {
53+
if !value.is_valid() {
54+
None
55+
} else {
56+
Some(Arc::new(SynchronizedSpan {
57+
span_context: value,
58+
inner: None,
59+
}))
4960
}
5061
}
5162
}
@@ -300,11 +311,11 @@ pub trait TraceContextExt {
300311

301312
impl TraceContextExt for Context {
302313
fn current_with_span<T: crate::trace::Span + Send + Sync + 'static>(span: T) -> Self {
303-
Context::current_with_synchronized_span(span.into())
314+
Context::current_with_synchronized_span(SynchronizedSpan::maybe_from_span(span))
304315
}
305316

306317
fn with_span<T: crate::trace::Span + Send + Sync + 'static>(&self, span: T) -> Self {
307-
self.with_synchronized_span(span.into())
318+
self.with_synchronized_span(SynchronizedSpan::maybe_from_span(span))
308319
}
309320

310321
fn span(&self) -> SpanRef<'_> {
@@ -316,11 +327,11 @@ impl TraceContextExt for Context {
316327
}
317328

318329
fn has_active_span(&self) -> bool {
319-
self.inner.as_ref().map_or(false, |i| i.span.is_some())
330+
self.has_active_span_flag()
320331
}
321332

322333
fn with_remote_span_context(&self, span_context: crate::trace::SpanContext) -> Self {
323-
self.with_synchronized_span(span_context.into())
334+
self.with_synchronized_span(SynchronizedSpan::maybe_from_span_context(span_context))
324335
}
325336
}
326337

opentelemetry/src/trace/span_context.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -446,18 +446,27 @@ mod tests {
446446
format!("{cx:?}"),
447447
"Context { span: \"None\", entries count: 0, flags: ContextFlags() }"
448448
);
449-
let cx = Context::current().with_remote_span_context(SpanContext::NONE).with_telemetry_suppressed();
449+
let remote_span_cx = SpanContext::new(
450+
0x123456789abcdef0123456789abcdef0.into(),
451+
0x876543210fedcba0.into(),
452+
TraceFlags::NOT_SAMPLED,
453+
false,
454+
TraceState::NONE,
455+
);
456+
let cx = Context::current()
457+
.with_remote_span_context(remote_span_cx)
458+
.with_telemetry_suppressed();
450459
assert_eq!(
451460
format!("{cx:?}"),
452461
"Context { \
453462
span: SpanContext { \
454-
trace_id: 00000000000000000000000000000000, \
455-
span_id: 0000000000000000, \
463+
trace_id: 123456789abcdef0123456789abcdef0, \
464+
span_id: 876543210fedcba0, \
456465
trace_flags: TraceFlags(0), \
457466
is_remote: false, \
458467
trace_state: TraceState(None) \
459468
}, \
460-
entries count: 1, flags: ContextFlags(TELEMETRY_SUPPRESSED) \
469+
entries count: 1, flags: ContextFlags(TELEMETRY_SUPPRESSED, ACTIVE_SPAN) \
461470
}"
462471
);
463472
}

0 commit comments

Comments
 (0)