• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use criterion::{criterion_group, criterion_main, Criterion};
2 use opentelemetry::{
3     sdk::trace::{Tracer, TracerProvider},
4     trace::{SpanBuilder, Tracer as _, TracerProvider as _},
5     Context,
6 };
7 use std::time::SystemTime;
8 use tracing::trace_span;
9 use tracing_subscriber::prelude::*;
10 
many_children(c: &mut Criterion)11 fn many_children(c: &mut Criterion) {
12     let mut group = c.benchmark_group("otel_many_children");
13 
14     group.bench_function("spec_baseline", |b| {
15         let provider = TracerProvider::default();
16         let tracer = provider.tracer("bench");
17         b.iter(|| {
18             fn dummy(tracer: &Tracer, cx: &Context) {
19                 for _ in 0..99 {
20                     tracer.start_with_context("child", cx);
21                 }
22             }
23 
24             tracer.in_span("parent", |cx| dummy(&tracer, &cx));
25         });
26     });
27 
28     {
29         let _subscriber = tracing_subscriber::registry()
30             .with(RegistryAccessLayer)
31             .set_default();
32         group.bench_function("no_data_baseline", |b| b.iter(tracing_harness));
33     }
34 
35     {
36         let _subscriber = tracing_subscriber::registry()
37             .with(OtelDataLayer)
38             .set_default();
39         group.bench_function("data_only_baseline", |b| b.iter(tracing_harness));
40     }
41 
42     {
43         let provider = TracerProvider::default();
44         let tracer = provider.tracer("bench");
45         let otel_layer = tracing_opentelemetry::layer()
46             .with_tracer(tracer)
47             .with_tracked_inactivity(false);
48         let _subscriber = tracing_subscriber::registry()
49             .with(otel_layer)
50             .set_default();
51 
52         group.bench_function("full", |b| b.iter(tracing_harness));
53     }
54 }
55 
56 struct NoDataSpan;
57 struct RegistryAccessLayer;
58 
59 impl<S> tracing_subscriber::Layer<S> for RegistryAccessLayer
60 where
61     S: tracing_core::Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span>,
62 {
on_new_span( &self, _attrs: &tracing_core::span::Attributes<'_>, id: &tracing::span::Id, ctx: tracing_subscriber::layer::Context<'_, S>, )63     fn on_new_span(
64         &self,
65         _attrs: &tracing_core::span::Attributes<'_>,
66         id: &tracing::span::Id,
67         ctx: tracing_subscriber::layer::Context<'_, S>,
68     ) {
69         let span = ctx.span(id).expect("Span not found, this is a bug");
70         let mut extensions = span.extensions_mut();
71         extensions.insert(NoDataSpan);
72     }
73 
on_close(&self, id: tracing::span::Id, ctx: tracing_subscriber::layer::Context<'_, S>)74     fn on_close(&self, id: tracing::span::Id, ctx: tracing_subscriber::layer::Context<'_, S>) {
75         let span = ctx.span(&id).expect("Span not found, this is a bug");
76         let mut extensions = span.extensions_mut();
77 
78         extensions.remove::<NoDataSpan>();
79     }
80 }
81 
82 struct OtelDataLayer;
83 
84 impl<S> tracing_subscriber::Layer<S> for OtelDataLayer
85 where
86     S: tracing_core::Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span>,
87 {
on_new_span( &self, attrs: &tracing_core::span::Attributes<'_>, id: &tracing::span::Id, ctx: tracing_subscriber::layer::Context<'_, S>, )88     fn on_new_span(
89         &self,
90         attrs: &tracing_core::span::Attributes<'_>,
91         id: &tracing::span::Id,
92         ctx: tracing_subscriber::layer::Context<'_, S>,
93     ) {
94         let span = ctx.span(id).expect("Span not found, this is a bug");
95         let mut extensions = span.extensions_mut();
96         extensions.insert(
97             SpanBuilder::from_name(attrs.metadata().name()).with_start_time(SystemTime::now()),
98         );
99     }
100 
on_close(&self, id: tracing::span::Id, ctx: tracing_subscriber::layer::Context<'_, S>)101     fn on_close(&self, id: tracing::span::Id, ctx: tracing_subscriber::layer::Context<'_, S>) {
102         let span = ctx.span(&id).expect("Span not found, this is a bug");
103         let mut extensions = span.extensions_mut();
104 
105         if let Some(builder) = extensions.remove::<SpanBuilder>() {
106             builder.with_end_time(SystemTime::now());
107         }
108     }
109 }
110 
tracing_harness()111 fn tracing_harness() {
112     fn dummy() {
113         for _ in 0..99 {
114             let child = trace_span!("child");
115             let _enter = child.enter();
116         }
117     }
118 
119     let parent = trace_span!("parent");
120     let _enter = parent.enter();
121 
122     dummy();
123 }
124 
125 criterion_group!(benches, many_children);
126 criterion_main!(benches);
127