@@ -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,36 @@ 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+ (
248+ span,
249+ ( * * entries) . clone ( ) ,
250+ inner. context_flags . clone ( ) ,
251+ )
252+ } else {
253+ (
254+ span,
255+ EntryMap :: default ( ) ,
256+ inner. context_flags . clone ( ) ,
257+ )
258+ }
237259 } else {
238- let mut entries = EntryMap :: default ( ) ;
239- entries. insert ( TypeId :: of :: < T > ( ) , Arc :: new ( value) ) ;
240- Some ( Arc :: new ( entries) )
260+ ( None , EntryMap :: default ( ) , ContextFlags :: default ( ) )
241261 } ;
262+ entries. insert ( TypeId :: of :: < T > ( ) , Arc :: new ( value) ) ;
242263 Context {
243- entries,
244- #[ cfg( feature = "trace" ) ]
245- span : self . span . clone ( ) ,
246- suppress_telemetry : self . suppress_telemetry ,
264+ inner : Some ( Arc :: new ( InnerContext {
265+ #[ cfg( feature = "trace" ) ]
266+ span,
267+ entries : Some ( Arc :: new ( entries) ) ,
268+ context_flags,
269+ } ) ) ,
247270 }
248271 }
249272
@@ -333,16 +356,49 @@ impl Context {
333356 /// Returns whether telemetry is suppressed in this context.
334357 #[ inline]
335358 pub fn is_telemetry_suppressed ( & self ) -> bool {
336- self . suppress_telemetry
359+ if let Some ( inner) = & self . inner {
360+ inner. context_flags . suppress_telemetry ( )
361+ } else {
362+ false
363+ }
337364 }
338365
339366 /// Returns a new context with telemetry suppression enabled.
340367 pub fn with_telemetry_suppressed ( & self ) -> Self {
341- Context {
342- entries : self . entries . clone ( ) ,
368+ if self . is_telemetry_suppressed ( ) {
369+ return self . clone ( ) ;
370+ }
371+ let ( span, entries, context_flags) = if let Some ( inner) = & self . inner {
343372 #[ cfg( feature = "trace" ) ]
344- span : self . span . clone ( ) ,
345- suppress_telemetry : true ,
373+ {
374+ (
375+ inner. span . clone ( ) ,
376+ inner. entries . clone ( ) ,
377+ inner. context_flags . with_telemetry_suppressed ( ) ,
378+ )
379+ }
380+ #[ cfg( not( feature = "trace" ) ) ]
381+ {
382+ (
383+ Option :: < ( ) > :: None ,
384+ inner. entries . clone ( ) ,
385+ inner. context_flags . with_telemetry_suppressed ( ) ,
386+ )
387+ }
388+ } else {
389+ (
390+ None ,
391+ None ,
392+ ContextFlags :: default ( ) . with_telemetry_suppressed ( ) ,
393+ )
394+ } ;
395+ Context {
396+ inner : Some ( Arc :: new ( InnerContext {
397+ #[ cfg( feature = "trace" ) ]
398+ span,
399+ entries,
400+ context_flags,
401+ } ) ) ,
346402 }
347403 }
348404
@@ -408,30 +464,42 @@ impl Context {
408464
409465 #[ cfg( feature = "trace" ) ]
410466 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- } )
467+ Self :: map_current ( |cx| cx. with_synchronized_span ( value) )
416468 }
417469
418470 #[ cfg( feature = "trace" ) ]
419471 pub ( crate ) fn with_synchronized_span ( & self , value : SynchronizedSpan ) -> Self {
472+ let ( entries, context_flags) = if let Some ( inner) = & self . inner {
473+ ( inner. entries . clone ( ) , inner. context_flags . clone ( ) )
474+ } else {
475+ ( None , ContextFlags :: default ( ) )
476+ } ;
420477 Context {
421- span : Some ( Arc :: new ( value) ) ,
422- entries : self . entries . clone ( ) ,
423- suppress_telemetry : self . suppress_telemetry ,
478+ inner : Some ( Arc :: new ( InnerContext {
479+ span : Some ( Arc :: new ( value) ) ,
480+ entries,
481+ context_flags,
482+ } ) ) ,
424483 }
425484 }
426485}
427486
428487impl fmt:: Debug for Context {
429488 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
430489 let mut dbg = f. debug_struct ( "Context" ) ;
431- let mut entries = self . entries . as_ref ( ) . map_or ( 0 , |e| e. len ( ) ) ;
490+ let ( mut entries, suppress_telemetry) = self . inner . as_ref ( ) . map_or ( ( 0 , false ) , |inner| {
491+ (
492+ inner. entries . as_ref ( ) . map_or ( 0 , |e| e. len ( ) ) ,
493+ inner. context_flags . suppress_telemetry ( ) ,
494+ )
495+ } ) ;
432496 #[ cfg( feature = "trace" ) ]
433497 {
434- if let Some ( span) = & self . span {
498+ if let Some ( span) = self
499+ . inner
500+ . as_ref ( )
501+ . map_or ( None , |inner| inner. span . as_ref ( ) )
502+ {
435503 dbg. field ( "span" , & span. span_context ( ) ) ;
436504 entries += 1 ;
437505 } else {
@@ -440,7 +508,7 @@ impl fmt::Debug for Context {
440508 }
441509
442510 dbg. field ( "entries count" , & entries)
443- . field ( "suppress_telemetry" , & self . suppress_telemetry )
511+ . field ( "suppress_telemetry" , & suppress_telemetry)
444512 . finish ( )
445513 }
446514}
@@ -599,6 +667,23 @@ impl Default for ContextStack {
599667 }
600668}
601669
670+ #[ derive( Clone , Default ) ]
671+ struct ContextFlags ( u32 ) ;
672+
673+ impl ContextFlags {
674+ const SUPPRESS_TELEMETRY : u32 = 0b0000_0001 ;
675+
676+ #[ inline( always) ]
677+ fn suppress_telemetry ( & self ) -> bool {
678+ self . 0 & ContextFlags :: SUPPRESS_TELEMETRY != 0
679+ }
680+
681+ #[ inline( always) ]
682+ fn with_telemetry_suppressed ( & self ) -> Self {
683+ ContextFlags ( self . 0 | ContextFlags :: SUPPRESS_TELEMETRY )
684+ }
685+ }
686+
602687#[ cfg( test) ]
603688mod tests {
604689 use super :: * ;
0 commit comments