@@ -92,10 +92,15 @@ thread_local! {
92
92
/// ```
93
93
#[ derive( Clone , Default ) ]
94
94
pub struct Context {
95
+ pub ( super ) inner : Option < Arc < InnerContext > > ,
96
+ }
97
+
98
+ #[ derive( Clone , Default ) ]
99
+ pub ( super ) struct InnerContext {
95
100
#[ cfg( feature = "trace" ) ]
96
101
pub ( crate ) span : Option < Arc < SynchronizedSpan > > ,
97
102
entries : Option < Arc < EntryMap > > ,
98
- suppress_telemetry : bool ,
103
+ context_flags : ContextFlags ,
99
104
}
100
105
101
106
type EntryMap = HashMap < TypeId , Arc < dyn Any + Sync + Send > , BuildHasherDefault < IdHasher > > ;
@@ -196,7 +201,9 @@ impl Context {
196
201
/// assert_eq!(cx.get::<MyUser>(), None);
197
202
/// ```
198
203
pub fn get < T : ' static > ( & self ) -> Option < & T > {
199
- self . entries
204
+ self . inner
205
+ . as_ref ( ) ?
206
+ . entries
200
207
. as_ref ( ) ?
201
208
. get ( & TypeId :: of :: < T > ( ) ) ?
202
209
. downcast_ref ( )
@@ -230,20 +237,28 @@ impl Context {
230
237
/// assert_eq!(cx_with_a_and_b.get::<ValueB>(), Some(&ValueB(42)));
231
238
/// ```
232
239
pub fn with_value < T : ' static + Send + Sync > ( & self , value : T ) -> Self {
233
- let entries = if let Some ( current_entries) = & self . entries {
234
- let mut inner_entries = ( * * current_entries) . clone ( ) ;
235
- inner_entries. insert ( TypeId :: of :: < T > ( ) , Arc :: new ( value) ) ;
236
- Some ( Arc :: new ( inner_entries) )
240
+ let ( span, mut entries, context_flags) = if let Some ( inner) = & self . inner {
241
+ #[ cfg( feature = "trace" ) ]
242
+ let span = inner. span . clone ( ) ;
243
+ #[ cfg( not( feature = "trace" ) ) ]
244
+ let span: Option < ( ) > = None ;
245
+
246
+ if let Some ( entries) = & inner. entries {
247
+ ( span, ( * * entries) . clone ( ) , inner. context_flags . clone ( ) )
248
+ } else {
249
+ ( span, EntryMap :: default ( ) , inner. context_flags . clone ( ) )
250
+ }
237
251
} else {
238
- let mut entries = EntryMap :: default ( ) ;
239
- entries. insert ( TypeId :: of :: < T > ( ) , Arc :: new ( value) ) ;
240
- Some ( Arc :: new ( entries) )
252
+ ( None , EntryMap :: default ( ) , ContextFlags :: default ( ) )
241
253
} ;
254
+ entries. insert ( TypeId :: of :: < T > ( ) , Arc :: new ( value) ) ;
242
255
Context {
243
- entries,
244
- #[ cfg( feature = "trace" ) ]
245
- span : self . span . clone ( ) ,
246
- suppress_telemetry : self . suppress_telemetry ,
256
+ inner : Some ( Arc :: new ( InnerContext {
257
+ #[ cfg( feature = "trace" ) ]
258
+ span,
259
+ entries : Some ( Arc :: new ( entries) ) ,
260
+ context_flags,
261
+ } ) ) ,
247
262
}
248
263
}
249
264
@@ -333,16 +348,49 @@ impl Context {
333
348
/// Returns whether telemetry is suppressed in this context.
334
349
#[ inline]
335
350
pub fn is_telemetry_suppressed ( & self ) -> bool {
336
- self . suppress_telemetry
351
+ if let Some ( inner) = & self . inner {
352
+ inner. context_flags . suppress_telemetry ( )
353
+ } else {
354
+ false
355
+ }
337
356
}
338
357
339
358
/// Returns a new context with telemetry suppression enabled.
340
359
pub fn with_telemetry_suppressed ( & self ) -> Self {
341
- Context {
342
- entries : self . entries . clone ( ) ,
360
+ if self . is_telemetry_suppressed ( ) {
361
+ return self . clone ( ) ;
362
+ }
363
+ let ( span, entries, context_flags) = if let Some ( inner) = & self . inner {
343
364
#[ cfg( feature = "trace" ) ]
344
- span : self . span . clone ( ) ,
345
- suppress_telemetry : true ,
365
+ {
366
+ (
367
+ inner. span . clone ( ) ,
368
+ inner. entries . clone ( ) ,
369
+ inner. context_flags . with_telemetry_suppressed ( ) ,
370
+ )
371
+ }
372
+ #[ cfg( not( feature = "trace" ) ) ]
373
+ {
374
+ (
375
+ Option :: < ( ) > :: None ,
376
+ inner. entries . clone ( ) ,
377
+ inner. context_flags . with_telemetry_suppressed ( ) ,
378
+ )
379
+ }
380
+ } else {
381
+ (
382
+ None ,
383
+ None ,
384
+ ContextFlags :: default ( ) . with_telemetry_suppressed ( ) ,
385
+ )
386
+ } ;
387
+ Context {
388
+ inner : Some ( Arc :: new ( InnerContext {
389
+ #[ cfg( feature = "trace" ) ]
390
+ span,
391
+ entries,
392
+ context_flags,
393
+ } ) ) ,
346
394
}
347
395
}
348
396
@@ -408,30 +456,38 @@ impl Context {
408
456
409
457
#[ cfg( feature = "trace" ) ]
410
458
pub ( crate ) fn current_with_synchronized_span ( value : SynchronizedSpan ) -> Self {
411
- Self :: map_current ( |cx| Context {
412
- span : Some ( Arc :: new ( value) ) ,
413
- entries : cx. entries . clone ( ) ,
414
- suppress_telemetry : cx. suppress_telemetry ,
415
- } )
459
+ Self :: map_current ( |cx| cx. with_synchronized_span ( value) )
416
460
}
417
461
418
462
#[ cfg( feature = "trace" ) ]
419
463
pub ( crate ) fn with_synchronized_span ( & self , value : SynchronizedSpan ) -> Self {
464
+ let ( entries, context_flags) = if let Some ( inner) = & self . inner {
465
+ ( inner. entries . clone ( ) , inner. context_flags . clone ( ) )
466
+ } else {
467
+ ( None , ContextFlags :: default ( ) )
468
+ } ;
420
469
Context {
421
- span : Some ( Arc :: new ( value) ) ,
422
- entries : self . entries . clone ( ) ,
423
- suppress_telemetry : self . suppress_telemetry ,
470
+ inner : Some ( Arc :: new ( InnerContext {
471
+ span : Some ( Arc :: new ( value) ) ,
472
+ entries,
473
+ context_flags,
474
+ } ) ) ,
424
475
}
425
476
}
426
477
}
427
478
428
479
impl fmt:: Debug for Context {
429
480
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
430
481
let mut dbg = f. debug_struct ( "Context" ) ;
431
- let mut entries = self . entries . as_ref ( ) . map_or ( 0 , |e| e. len ( ) ) ;
482
+ let ( mut entries, suppress_telemetry) = self . inner . as_ref ( ) . map_or ( ( 0 , false ) , |inner| {
483
+ (
484
+ inner. entries . as_ref ( ) . map_or ( 0 , |e| e. len ( ) ) ,
485
+ inner. context_flags . suppress_telemetry ( ) ,
486
+ )
487
+ } ) ;
432
488
#[ cfg( feature = "trace" ) ]
433
489
{
434
- if let Some ( span) = & self . span {
490
+ if let Some ( span) = self . inner . as_ref ( ) . and_then ( |inner| inner . span . as_ref ( ) ) {
435
491
dbg. field ( "span" , & span. span_context ( ) ) ;
436
492
entries += 1 ;
437
493
} else {
@@ -440,7 +496,7 @@ impl fmt::Debug for Context {
440
496
}
441
497
442
498
dbg. field ( "entries count" , & entries)
443
- . field ( "suppress_telemetry" , & self . suppress_telemetry )
499
+ . field ( "suppress_telemetry" , & suppress_telemetry)
444
500
. finish ( )
445
501
}
446
502
}
@@ -599,6 +655,23 @@ impl Default for ContextStack {
599
655
}
600
656
}
601
657
658
+ #[ derive( Clone , Default ) ]
659
+ struct ContextFlags ( u32 ) ;
660
+
661
+ impl ContextFlags {
662
+ const SUPPRESS_TELEMETRY : u32 = 0b0000_0001 ;
663
+
664
+ #[ inline( always) ]
665
+ fn suppress_telemetry ( & self ) -> bool {
666
+ self . 0 & ContextFlags :: SUPPRESS_TELEMETRY != 0
667
+ }
668
+
669
+ #[ inline( always) ]
670
+ fn with_telemetry_suppressed ( & self ) -> Self {
671
+ ContextFlags ( self . 0 | ContextFlags :: SUPPRESS_TELEMETRY )
672
+ }
673
+ }
674
+
602
675
#[ cfg( test) ]
603
676
mod tests {
604
677
use super :: * ;
0 commit comments