1
- use opentelemetry :: api :: { Context as OtelContext , IdGenerator , TraceContextExt } ;
2
- use opentelemetry:: { api, sdk } ;
1
+ use crate :: PreSampledTracer ;
2
+ use opentelemetry:: api:: { self , Context as OtelContext , TraceContextExt } ;
3
3
use std:: any:: TypeId ;
4
4
use std:: fmt;
5
5
use std:: marker;
@@ -20,10 +20,8 @@ static SPAN_KIND_FIELD: &str = "otel.kind";
20
20
///
21
21
/// [OpenTelemetry]: https://opentelemetry.io
22
22
/// [tracing]: https://github.com/tokio-rs/tracing
23
- pub struct OpenTelemetryLayer < S , T : api :: Tracer > {
23
+ pub struct OpenTelemetryLayer < S , T > {
24
24
tracer : T ,
25
- sampler : Box < dyn sdk:: ShouldSample > ,
26
- id_generator : sdk:: IdGenerator ,
27
25
28
26
get_context : WithContext ,
29
27
_registry : marker:: PhantomData < S > ,
34
32
S : Subscriber + for < ' span > LookupSpan < ' span > ,
35
33
{
36
34
fn default ( ) -> Self {
37
- OpenTelemetryLayer :: new ( api:: NoopTracer { } , sdk :: Sampler :: AlwaysOn )
35
+ OpenTelemetryLayer :: new ( api:: NoopTracer { } )
38
36
}
39
37
}
40
38
50
48
///
51
49
/// // Use the tracing subscriber `Registry`, or any other subscriber
52
50
/// // that impls `LookupSpan`
53
- /// let subscriber = Registry::default()
54
- /// .with(tracing_opentelemetry::layer());
51
+ /// let subscriber = Registry::default().with(tracing_opentelemetry::layer());
55
52
/// # drop(subscriber);
56
53
/// ```
57
54
pub fn layer < S > ( ) -> OpenTelemetryLayer < S , api:: NoopTracer >
@@ -70,7 +67,7 @@ pub(crate) struct WithContext(
70
67
fn (
71
68
& tracing:: Dispatch ,
72
69
& span:: Id ,
73
- f : & mut dyn FnMut ( & mut api:: SpanBuilder , & dyn sdk :: ShouldSample ) ,
70
+ f : & mut dyn FnMut ( & mut api:: SpanBuilder , & dyn PreSampledTracer ) ,
74
71
) ,
75
72
) ;
76
73
@@ -81,63 +78,12 @@ impl WithContext {
81
78
& self ,
82
79
dispatch : & ' a tracing:: Dispatch ,
83
80
id : & span:: Id ,
84
- mut f : impl FnMut ( & mut api:: SpanBuilder , & dyn sdk :: ShouldSample ) ,
81
+ mut f : impl FnMut ( & mut api:: SpanBuilder , & dyn PreSampledTracer ) ,
85
82
) {
86
83
( self . 0 ) ( dispatch, id, & mut f)
87
84
}
88
85
}
89
86
90
- pub ( crate ) fn build_span_context (
91
- builder : & mut api:: SpanBuilder ,
92
- sampler : & dyn sdk:: ShouldSample ,
93
- ) -> api:: SpanContext {
94
- let span_id = builder. span_id . expect ( "Builders must have id" ) ;
95
- let ( trace_id, trace_flags) = builder
96
- . parent_context
97
- . as_ref ( )
98
- . filter ( |parent_context| parent_context. is_valid ( ) )
99
- . map ( |parent_context| ( parent_context. trace_id ( ) , parent_context. trace_flags ( ) ) )
100
- . unwrap_or_else ( || {
101
- let trace_id = builder. trace_id . expect ( "trace_id should exist" ) ;
102
-
103
- // ensure sampling decision is recorded so all span contexts have consistent flags
104
- let sampling_decision = if let Some ( result) = builder. sampling_result . as_ref ( ) {
105
- result. decision . clone ( )
106
- } else {
107
- let mut result = sampler. should_sample (
108
- builder. parent_context . as_ref ( ) ,
109
- trace_id,
110
- & builder. name ,
111
- builder
112
- . span_kind
113
- . as_ref ( )
114
- . unwrap_or ( & api:: SpanKind :: Internal ) ,
115
- builder. attributes . as_ref ( ) . unwrap_or ( & Vec :: new ( ) ) ,
116
- builder. links . as_ref ( ) . unwrap_or ( & Vec :: new ( ) ) ,
117
- ) ;
118
-
119
- // Record additional attributes resulting from sampling
120
- if let Some ( attributes) = & mut builder. attributes {
121
- attributes. append ( & mut result. attributes )
122
- } else {
123
- builder. attributes = Some ( result. attributes ) ;
124
- }
125
-
126
- result. decision
127
- } ;
128
-
129
- let trace_flags = if sampling_decision == sdk:: SamplingDecision :: RecordAndSampled {
130
- api:: TRACE_FLAG_SAMPLED
131
- } else {
132
- 0
133
- } ;
134
-
135
- ( trace_id, trace_flags)
136
- } ) ;
137
-
138
- api:: SpanContext :: new ( trace_id, span_id, trace_flags, false )
139
- }
140
-
141
87
fn str_to_span_kind ( s : & str ) -> Option < api:: SpanKind > {
142
88
if s. eq_ignore_ascii_case ( "SERVER" ) {
143
89
Some ( api:: SpanKind :: Server )
@@ -235,13 +181,12 @@ impl<'a> field::Visit for SpanAttributeVisitor<'a> {
235
181
impl < S , T > OpenTelemetryLayer < S , T >
236
182
where
237
183
S : Subscriber + for < ' span > LookupSpan < ' span > ,
238
- T : api:: Tracer + ' static ,
184
+ T : api:: Tracer + PreSampledTracer + ' static ,
239
185
{
240
- /// Set the [`Tracer`] and [`Sampler`] that this layer will use to produce and
241
- /// track OpenTelemetry [`Span`]s.
186
+ /// Set the [`Tracer`] that this layer will use to produce and track
187
+ /// OpenTelemetry [`Span`]s.
242
188
///
243
189
/// [`Tracer`]: https://docs.rs/opentelemetry/latest/opentelemetry/api/trace/tracer/trait.Tracer.html
244
- /// [`Sampler`]: https://docs.rs/opentelemetry/latest/opentelemetry/api/trace/sampler/trait.Sampler.html
245
190
/// [`Span`]: https://docs.rs/opentelemetry/latest/opentelemetry/api/trace/span/trait.Span.html
246
191
///
247
192
/// # Examples
@@ -273,26 +218,17 @@ where
273
218
/// // Get a tracer from the provider for a component
274
219
/// let tracer = provider.get_tracer("component-name");
275
220
///
276
- /// // The probability sampler can be used to export a percentage of spans
277
- /// let sampler = sdk::Sampler::Probability(0.33);
278
- ///
279
221
/// // Create a layer with the configured tracer
280
- /// let otel_layer = OpenTelemetryLayer::new(tracer, sampler );
222
+ /// let otel_layer = OpenTelemetryLayer::new(tracer);
281
223
///
282
224
/// // Use the tracing subscriber `Registry`, or any other subscriber
283
225
/// // that impls `LookupSpan`
284
- /// let subscriber = Registry::default()
285
- /// .with(otel_layer);
226
+ /// let subscriber = Registry::default().with(otel_layer);
286
227
/// # drop(subscriber);
287
228
/// ```
288
- pub fn new < Sampler > ( tracer : T , sampler : Sampler ) -> Self
289
- where
290
- Sampler : sdk:: ShouldSample + ' static ,
291
- {
229
+ pub fn new ( tracer : T ) -> Self {
292
230
OpenTelemetryLayer {
293
231
tracer,
294
- sampler : Box :: new ( sampler) ,
295
- id_generator : sdk:: IdGenerator :: default ( ) ,
296
232
get_context : WithContext ( Self :: get_context) ,
297
233
_registry : marker:: PhantomData ,
298
234
}
@@ -343,52 +279,15 @@ where
343
279
/// ```
344
280
pub fn with_tracer < Tracer > ( self , tracer : Tracer ) -> OpenTelemetryLayer < S , Tracer >
345
281
where
346
- Tracer : api:: Tracer + ' static ,
282
+ Tracer : api:: Tracer + PreSampledTracer + ' static ,
347
283
{
348
284
OpenTelemetryLayer {
349
285
tracer,
350
- sampler : self . sampler ,
351
- id_generator : self . id_generator ,
352
286
get_context : WithContext ( OpenTelemetryLayer :: < S , Tracer > :: get_context) ,
353
287
_registry : self . _registry ,
354
288
}
355
289
}
356
290
357
- /// Set the [`Sampler`] to configure the logic around which [`Span`]s are
358
- /// exported.
359
- ///
360
- /// [`Sampler`]: https://docs.rs/opentelemetry/latest/opentelemetry/api/trace/sampler/trait.Sampler.html
361
- /// [`Span`]: https://docs.rs/opentelemetry/latest/opentelemetry/api/trace/span/trait.Span.html
362
- ///
363
- /// # Examples
364
- ///
365
- /// ```rust,no_run
366
- /// use opentelemetry::sdk;
367
- /// use tracing_subscriber::layer::SubscriberExt;
368
- /// use tracing_subscriber::Registry;
369
- ///
370
- /// // The probability sampler can be used to export a percentage of spans
371
- /// let sampler = sdk::Sampler::Probability(0.33);
372
- ///
373
- /// // Create a layer with the configured sampler
374
- /// let otel_layer = tracing_opentelemetry::layer().with_sampler(sampler);
375
- ///
376
- /// // Use the tracing subscriber `Registry`, or any other subscriber
377
- /// // that impls `LookupSpan`
378
- /// let subscriber = Registry::default()
379
- /// .with(otel_layer);
380
- /// # drop(subscriber);
381
- /// ```
382
- pub fn with_sampler < Sampler > ( self , sampler : Sampler ) -> Self
383
- where
384
- Sampler : sdk:: ShouldSample + ' static ,
385
- {
386
- OpenTelemetryLayer {
387
- sampler : Box :: new ( sampler) ,
388
- ..self
389
- }
390
- }
391
-
392
291
/// Retrieve the parent OpenTelemetry [`SpanContext`] from the current
393
292
/// tracing [`span`] through the [`Registry`]. This [`SpanContext`]
394
293
/// links spans to their parent for proper hierarchical visualization.
@@ -407,14 +306,14 @@ where
407
306
let mut extensions = span. extensions_mut ( ) ;
408
307
extensions
409
308
. get_mut :: < api:: SpanBuilder > ( )
410
- . map ( |builder| build_span_context ( builder , self . sampler . as_ref ( ) ) )
309
+ . map ( |builder| self . tracer . sampled_span_context ( builder ) )
411
310
// Else if the span is inferred from context, look up any available current span.
412
311
} else if attrs. is_contextual ( ) {
413
312
ctx. lookup_current ( ) . and_then ( |span| {
414
313
let mut extensions = span. extensions_mut ( ) ;
415
314
extensions
416
315
. get_mut :: < api:: SpanBuilder > ( )
417
- . map ( |builder| build_span_context ( builder , self . sampler . as_ref ( ) ) )
316
+ . map ( |builder| self . tracer . sampled_span_context ( builder ) )
418
317
} )
419
318
// Explicit root spans should have no parent context.
420
319
} else {
@@ -425,7 +324,7 @@ where
425
324
fn get_context (
426
325
dispatch : & tracing:: Dispatch ,
427
326
id : & span:: Id ,
428
- f : & mut dyn FnMut ( & mut api:: SpanBuilder , & dyn sdk :: ShouldSample ) ,
327
+ f : & mut dyn FnMut ( & mut api:: SpanBuilder , & dyn PreSampledTracer ) ,
429
328
) {
430
329
let subscriber = dispatch
431
330
. downcast_ref :: < S > ( )
@@ -439,15 +338,15 @@ where
439
338
440
339
let mut extensions = span. extensions_mut ( ) ;
441
340
if let Some ( builder) = extensions. get_mut :: < api:: SpanBuilder > ( ) {
442
- f ( builder, layer. sampler . as_ref ( ) ) ;
341
+ f ( builder, & layer. tracer ) ;
443
342
}
444
343
}
445
344
}
446
345
447
346
impl < S , T > Layer < S > for OpenTelemetryLayer < S , T >
448
347
where
449
348
S : Subscriber + for < ' span > LookupSpan < ' span > ,
450
- T : api:: Tracer + ' static ,
349
+ T : api:: Tracer + PreSampledTracer + ' static ,
451
350
{
452
351
/// Creates an [OpenTelemetry `Span`] for the corresponding [tracing `Span`].
453
352
///
@@ -462,7 +361,7 @@ where
462
361
. span_builder ( attrs. metadata ( ) . name ( ) )
463
362
. with_start_time ( SystemTime :: now ( ) )
464
363
// Eagerly assign span id so children have stable parent id
465
- . with_span_id ( self . id_generator . new_span_id ( ) ) ;
364
+ . with_span_id ( self . tracer . new_span_id ( ) ) ;
466
365
467
366
// Set optional parent span context from attrs
468
367
builder. parent_context = self . parent_span_context ( attrs, & ctx) ;
@@ -473,7 +372,7 @@ where
473
372
if existing_otel_span_context. is_valid ( ) {
474
373
builder. trace_id = Some ( existing_otel_span_context. trace_id ( ) ) ;
475
374
} else {
476
- builder. trace_id = Some ( self . id_generator . new_trace_id ( ) ) ;
375
+ builder. trace_id = Some ( self . tracer . new_trace_id ( ) ) ;
477
376
}
478
377
}
479
378
@@ -507,7 +406,7 @@ where
507
406
. get_mut :: < api:: SpanBuilder > ( )
508
407
. expect ( "Missing SpanBuilder span extensions" ) ;
509
408
510
- let follows_context = build_span_context ( follows_builder , self . sampler . as_ref ( ) ) ;
409
+ let follows_context = self . tracer . sampled_span_context ( follows_builder ) ;
511
410
let follows_link = api:: Link :: new ( follows_context, Vec :: new ( ) ) ;
512
411
if let Some ( ref mut links) = builder. links {
513
412
links. push ( follows_link) ;
@@ -613,6 +512,18 @@ mod tests {
613
512
}
614
513
}
615
514
515
+ impl PreSampledTracer for TestTracer {
516
+ fn sampled_span_context ( & self , _builder : & mut api:: SpanBuilder ) -> api:: SpanContext {
517
+ api:: SpanContext :: empty_context ( )
518
+ }
519
+ fn new_trace_id ( & self ) -> api:: TraceId {
520
+ api:: TraceId :: invalid ( )
521
+ }
522
+ fn new_span_id ( & self ) -> api:: SpanId {
523
+ api:: SpanId :: invalid ( )
524
+ }
525
+ }
526
+
616
527
#[ derive( Debug , Clone ) ]
617
528
struct TestSpan ( api:: SpanContext ) ;
618
529
impl api:: Span for TestSpan {
0 commit comments