@@ -92,10 +92,15 @@ thread_local! {
9292/// ```
9393#[ derive( Clone , Default ) ]
9494pub struct Context {
95+ pub ( super ) inner : Option < Arc < InnerContext > > ,
96+ }
97+
98+ #[ derive( Clone , Default ) ]
99+ pub ( super ) struct InnerContext {
95100 #[ cfg( feature = "trace" ) ]
96101 pub ( crate ) span : Option < Arc < SynchronizedSpan > > ,
97102 entries : Option < Arc < EntryMap > > ,
98- suppress_telemetry : bool ,
103+ context_flags : ContextFlags ,
99104}
100105
101106type EntryMap = HashMap < TypeId , Arc < dyn Any + Sync + Send > , BuildHasherDefault < IdHasher > > ;
@@ -196,7 +201,9 @@ impl Context {
196201 /// assert_eq!(cx.get::<MyUser>(), None);
197202 /// ```
198203 pub fn get < T : ' static > ( & self ) -> Option < & T > {
199- self . entries
204+ self . inner
205+ . as_ref ( ) ?
206+ . entries
200207 . as_ref ( ) ?
201208 . get ( & TypeId :: of :: < T > ( ) ) ?
202209 . downcast_ref ( )
@@ -230,20 +237,28 @@ impl Context {
230237 /// assert_eq!(cx_with_a_and_b.get::<ValueB>(), Some(&ValueB(42)));
231238 /// ```
232239 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+ }
237251 } 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 ( ) )
241253 } ;
254+ entries. insert ( TypeId :: of :: < T > ( ) , Arc :: new ( value) ) ;
242255 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+ } ) ) ,
247262 }
248263 }
249264
@@ -333,16 +348,49 @@ impl Context {
333348 /// Returns whether telemetry is suppressed in this context.
334349 #[ inline]
335350 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+ }
337356 }
338357
339358 /// Returns a new context with telemetry suppression enabled.
340359 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 {
343364 #[ 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+ } ) ) ,
346394 }
347395 }
348396
@@ -408,30 +456,38 @@ impl Context {
408456
409457 #[ cfg( feature = "trace" ) ]
410458 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) )
416460 }
417461
418462 #[ cfg( feature = "trace" ) ]
419463 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+ } ;
420469 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+ } ) ) ,
424475 }
425476 }
426477}
427478
428479impl fmt:: Debug for Context {
429480 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
430481 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+ } ) ;
432488 #[ cfg( feature = "trace" ) ]
433489 {
434- if let Some ( span) = & self . span {
490+ if let Some ( span) = self . inner . as_ref ( ) . and_then ( |inner| inner . span . as_ref ( ) ) {
435491 dbg. field ( "span" , & span. span_context ( ) ) ;
436492 entries += 1 ;
437493 } else {
@@ -440,7 +496,7 @@ impl fmt::Debug for Context {
440496 }
441497
442498 dbg. field ( "entries count" , & entries)
443- . field ( "suppress_telemetry" , & self . suppress_telemetry )
499+ . field ( "suppress_telemetry" , & suppress_telemetry)
444500 . finish ( )
445501 }
446502}
@@ -599,6 +655,23 @@ impl Default for ContextStack {
599655 }
600656}
601657
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+
602675#[ cfg( test) ]
603676mod tests {
604677 use super :: * ;
0 commit comments