1
1
use criterion:: { criterion_group, criterion_main, Criterion } ;
2
2
use opentelemetry:: {
3
- trace:: { SpanBuilder , Tracer as _, TracerProvider as _} ,
3
+ trace:: { Span , SpanBuilder , Tracer as _, TracerProvider as _} ,
4
4
Context ,
5
5
} ;
6
- use opentelemetry_sdk:: trace:: { Tracer , TracerProvider } ;
6
+ use opentelemetry_sdk:: trace:: { Config , SpanLimits , Tracer , TracerProvider } ;
7
7
#[ cfg( not( target_os = "windows" ) ) ]
8
8
use pprof:: criterion:: { Output , PProfProfiler } ;
9
9
use std:: time:: SystemTime ;
10
- use tracing:: trace_span;
10
+ use tracing:: { trace , trace_span} ;
11
11
use tracing_subscriber:: prelude:: * ;
12
12
13
13
fn many_children ( c : & mut Criterion ) {
@@ -55,6 +55,73 @@ fn many_children(c: &mut Criterion) {
55
55
}
56
56
}
57
57
58
+ fn many_events ( c : & mut Criterion ) {
59
+ let mut group = c. benchmark_group ( "otel_many_events" ) ;
60
+
61
+ group. bench_function ( "spec_baseline" , |b| {
62
+ let provider = TracerProvider :: default ( ) ;
63
+ let tracer = provider. tracer ( "bench" ) ;
64
+ b. iter ( || {
65
+ fn dummy ( tracer : & Tracer , cx : & Context ) {
66
+ let mut span = tracer. start_with_context ( "child" , cx) ;
67
+ for _ in 0 ..1000 {
68
+ span. add_event ( "name" , Vec :: new ( ) ) ;
69
+ }
70
+ }
71
+
72
+ tracer. in_span ( "parent" , |cx| dummy ( & tracer, & cx) ) ;
73
+ } ) ;
74
+ } ) ;
75
+
76
+ {
77
+ let _subscriber = tracing_subscriber:: registry ( )
78
+ . with ( RegistryAccessLayer )
79
+ . set_default ( ) ;
80
+ group. bench_function ( "no_data_baseline" , |b| b. iter ( events_harness) ) ;
81
+ }
82
+
83
+ {
84
+ let _subscriber = tracing_subscriber:: registry ( )
85
+ . with ( OtelDataLayer )
86
+ . set_default ( ) ;
87
+ group. bench_function ( "data_only_baseline" , |b| b. iter ( events_harness) ) ;
88
+ }
89
+
90
+ {
91
+ let provider = TracerProvider :: default ( ) ;
92
+ let tracer = provider. tracer ( "bench" ) ;
93
+ let otel_layer = tracing_opentelemetry:: layer ( )
94
+ . with_tracer ( tracer)
95
+ . with_tracked_inactivity ( false ) ;
96
+ let _subscriber = tracing_subscriber:: registry ( )
97
+ . with ( otel_layer)
98
+ . set_default ( ) ;
99
+
100
+ group. bench_function ( "full_filtered" , |b| b. iter ( events_harness) ) ;
101
+ }
102
+
103
+ {
104
+ let provider = TracerProvider :: builder ( )
105
+ . with_config ( Config {
106
+ span_limits : SpanLimits {
107
+ max_events_per_span : 1000 ,
108
+ ..SpanLimits :: default ( )
109
+ } ,
110
+ ..Config :: default ( )
111
+ } )
112
+ . build ( ) ;
113
+ let tracer = provider. tracer ( "bench" ) ;
114
+ let otel_layer = tracing_opentelemetry:: layer ( )
115
+ . with_tracer ( tracer)
116
+ . with_tracked_inactivity ( false ) ;
117
+ let _subscriber = tracing_subscriber:: registry ( )
118
+ . with ( otel_layer)
119
+ . set_default ( ) ;
120
+
121
+ group. bench_function ( "full_not_filtered" , |b| b. iter ( events_harness) ) ;
122
+ }
123
+ }
124
+
58
125
struct NoDataSpan ;
59
126
struct RegistryAccessLayer ;
60
127
@@ -73,6 +140,23 @@ where
73
140
extensions. insert ( NoDataSpan ) ;
74
141
}
75
142
143
+ fn on_event (
144
+ & self ,
145
+ event : & tracing_core:: Event < ' _ > ,
146
+ ctx : tracing_subscriber:: layer:: Context < ' _ , S > ,
147
+ ) {
148
+ let Some ( parent) = event. parent ( ) . and_then ( |id| ctx. span ( id) ) . or_else ( || {
149
+ event
150
+ . is_contextual ( )
151
+ . then ( || ctx. lookup_current ( ) )
152
+ . flatten ( )
153
+ } ) else {
154
+ return ;
155
+ } ;
156
+ let mut extensions = parent. extensions_mut ( ) ;
157
+ extensions. get_mut :: < NoDataSpan > ( ) ;
158
+ }
159
+
76
160
fn on_close ( & self , id : tracing:: span:: Id , ctx : tracing_subscriber:: layer:: Context < ' _ , S > ) {
77
161
let span = ctx. span ( & id) . expect ( "Span not found, this is a bug" ) ;
78
162
let mut extensions = span. extensions_mut ( ) ;
@@ -100,6 +184,29 @@ where
100
184
) ;
101
185
}
102
186
187
+ fn on_event (
188
+ & self ,
189
+ event : & tracing_core:: Event < ' _ > ,
190
+ ctx : tracing_subscriber:: layer:: Context < ' _ , S > ,
191
+ ) {
192
+ let Some ( parent) = event. parent ( ) . and_then ( |id| ctx. span ( id) ) . or_else ( || {
193
+ event
194
+ . is_contextual ( )
195
+ . then ( || ctx. lookup_current ( ) )
196
+ . flatten ( )
197
+ } ) else {
198
+ return ;
199
+ } ;
200
+ let mut extensions = parent. extensions_mut ( ) ;
201
+ let builder = extensions
202
+ . get_mut :: < SpanBuilder > ( )
203
+ . expect ( "Builder not found in span, this is a bug" ) ;
204
+ let events = builder. events . get_or_insert_with ( Vec :: new) ;
205
+ let otel_event =
206
+ opentelemetry:: trace:: Event :: new ( String :: new ( ) , SystemTime :: now ( ) , Vec :: new ( ) , 0 ) ;
207
+ events. push ( otel_event) ;
208
+ }
209
+
103
210
fn on_close ( & self , id : tracing:: span:: Id , ctx : tracing_subscriber:: layer:: Context < ' _ , S > ) {
104
211
let span = ctx. span ( & id) . expect ( "Span not found, this is a bug" ) ;
105
212
let mut extensions = span. extensions_mut ( ) ;
@@ -124,16 +231,30 @@ fn tracing_harness() {
124
231
dummy ( ) ;
125
232
}
126
233
234
+ fn events_harness ( ) {
235
+ fn dummy ( ) {
236
+ let _child = trace_span ! ( "child" ) . entered ( ) ;
237
+ for _ in 0 ..1000 {
238
+ trace ! ( "event" ) ;
239
+ }
240
+ }
241
+
242
+ let parent = trace_span ! ( "parent" ) ;
243
+ let _enter = parent. enter ( ) ;
244
+
245
+ dummy ( ) ;
246
+ }
247
+
127
248
#[ cfg( not( target_os = "windows" ) ) ]
128
249
criterion_group ! {
129
250
name = benches;
130
251
config = Criterion :: default ( ) . with_profiler( PProfProfiler :: new( 100 , Output :: Flamegraph ( None ) ) ) ;
131
- targets = many_children
252
+ targets = many_children, many_events
132
253
}
133
254
#[ cfg( target_os = "windows" ) ]
134
255
criterion_group ! {
135
256
name = benches;
136
257
config = Criterion :: default ( ) ;
137
- targets = many_children
258
+ targets = many_children, many_events
138
259
}
139
260
criterion_main ! ( benches) ;
0 commit comments