@@ -97,7 +97,6 @@ pub struct Context {
97
97
#[ cfg( feature = "trace" ) ]
98
98
pub ( crate ) span : Option < Arc < SynchronizedSpan > > ,
99
99
entries : Option < Arc < EntryMap > > ,
100
- suppress_telemetry : bool ,
101
100
}
102
101
103
102
type EntryMap = HashMap < TypeId , Arc < dyn Any + Sync + Send > , BuildHasherDefault < IdHasher > > ;
@@ -245,7 +244,6 @@ impl Context {
245
244
entries,
246
245
#[ cfg( feature = "trace" ) ]
247
246
span : self . span . clone ( ) ,
248
- suppress_telemetry : self . suppress_telemetry ,
249
247
}
250
248
}
251
249
@@ -332,97 +330,19 @@ impl Context {
332
330
}
333
331
}
334
332
335
- /// Returns whether telemetry is suppressed in this context.
336
- #[ inline]
337
- pub fn is_telemetry_suppressed ( & self ) -> bool {
338
- self . suppress_telemetry
339
- }
340
-
341
- /// Returns a new context with telemetry suppression enabled.
342
- pub fn with_telemetry_suppressed ( & self ) -> Self {
343
- Context {
344
- entries : self . entries . clone ( ) ,
345
- #[ cfg( feature = "trace" ) ]
346
- span : self . span . clone ( ) ,
347
- suppress_telemetry : true ,
348
- }
349
- }
350
-
351
- /// Enters a scope where telemetry is suppressed.
352
- ///
353
- /// This method is specifically designed for OpenTelemetry components (like Exporters,
354
- /// Processors etc.) to prevent generating recursive or self-referential
355
- /// telemetry data when performing their own operations.
356
- ///
357
- /// Without suppression, we have a telemetry-induced-telemetry situation
358
- /// where, operations like exporting telemetry could generate new telemetry
359
- /// about the export process itself, potentially causing:
360
- /// - Infinite telemetry feedback loops
361
- /// - Excessive resource consumption
362
- ///
363
- /// This method:
364
- /// 1. Takes the current context
365
- /// 2. Creates a new context from current, with `suppress_telemetry` set to `true`
366
- /// 3. Attaches it to the current thread
367
- /// 4. Returns a guard that restores the previous context when dropped
368
- ///
369
- /// OTel SDK components would check `is_current_telemetry_suppressed()` before
370
- /// generating new telemetry, but not end users.
371
- ///
372
- /// # Examples
373
- ///
374
- /// ```
375
- /// use opentelemetry::Context;
376
- ///
377
- /// // Example: Inside an exporter's implementation
378
- /// fn example_export_function() {
379
- /// // Prevent telemetry-generating operations from creating more telemetry
380
- /// let _guard = Context::enter_telemetry_suppressed_scope();
381
- ///
382
- /// // Verify suppression is active
383
- /// assert_eq!(Context::is_current_telemetry_suppressed(), true);
384
- ///
385
- /// // Here you would normally perform operations that might generate telemetry
386
- /// // but now they won't because the context has suppression enabled
387
- /// }
388
- ///
389
- /// // Demonstrate the function
390
- /// example_export_function();
391
- /// ```
392
- pub fn enter_telemetry_suppressed_scope ( ) -> ContextGuard {
393
- Self :: map_current ( |cx| cx. with_telemetry_suppressed ( ) ) . attach ( )
394
- }
395
-
396
- /// Returns whether telemetry is suppressed in the current context.
397
- ///
398
- /// This method is used by OpenTelemetry components to determine whether they should
399
- /// generate new telemetry in the current execution context. It provides a performant
400
- /// way to check the suppression state.
401
- ///
402
- /// End-users generally should not use this method directly, as it is primarily intended for
403
- /// OpenTelemetry SDK components.
404
- ///
405
- ///
406
- #[ inline]
407
- pub fn is_current_telemetry_suppressed ( ) -> bool {
408
- Self :: map_current ( |cx| cx. is_telemetry_suppressed ( ) )
409
- }
410
-
411
333
#[ cfg( feature = "trace" ) ]
412
334
pub ( crate ) fn current_with_synchronized_span ( value : SynchronizedSpan ) -> Self {
413
- Self :: map_current ( |cx| Context {
335
+ Context {
414
336
span : Some ( Arc :: new ( value) ) ,
415
- entries : cx. entries . clone ( ) ,
416
- suppress_telemetry : cx. suppress_telemetry ,
417
- } )
337
+ entries : Context :: map_current ( |cx| cx. entries . clone ( ) ) ,
338
+ }
418
339
}
419
340
420
341
#[ cfg( feature = "trace" ) ]
421
342
pub ( crate ) fn with_synchronized_span ( & self , value : SynchronizedSpan ) -> Self {
422
343
Context {
423
344
span : Some ( Arc :: new ( value) ) ,
424
345
entries : self . entries . clone ( ) ,
425
- suppress_telemetry : self . suppress_telemetry ,
426
346
}
427
347
}
428
348
}
@@ -445,9 +365,7 @@ impl fmt::Debug for Context {
445
365
#[ cfg( not( feature = "trace" ) ) ]
446
366
let entries = self . entries . as_ref ( ) . map_or ( 0 , |e| e. len ( ) ) ;
447
367
448
- dbg. field ( "entries count" , & entries)
449
- . field ( "suppress_telemetry" , & self . suppress_telemetry )
450
- . finish ( )
368
+ dbg. field ( "entries count" , & entries) . finish ( )
451
369
}
452
370
}
453
371
@@ -985,158 +903,4 @@ mod tests {
985
903
assert_eq ! ( Context :: current( ) . get:: <ValueA >( ) , None ) ;
986
904
assert_eq ! ( Context :: current( ) . get:: <ValueB >( ) , None ) ;
987
905
}
988
-
989
- #[ test]
990
- fn test_is_telemetry_suppressed ( ) {
991
- // Default context has suppression disabled
992
- let cx = Context :: new ( ) ;
993
- assert ! ( !cx. is_telemetry_suppressed( ) ) ;
994
-
995
- // With suppression enabled
996
- let suppressed = cx. with_telemetry_suppressed ( ) ;
997
- assert ! ( suppressed. is_telemetry_suppressed( ) ) ;
998
- }
999
-
1000
- #[ test]
1001
- fn test_with_telemetry_suppressed ( ) {
1002
- // Start with a normal context
1003
- let cx = Context :: new ( ) ;
1004
- assert ! ( !cx. is_telemetry_suppressed( ) ) ;
1005
-
1006
- // Create a suppressed context
1007
- let suppressed = cx. with_telemetry_suppressed ( ) ;
1008
-
1009
- // Original should remain unchanged
1010
- assert ! ( !cx. is_telemetry_suppressed( ) ) ;
1011
-
1012
- // New context should be suppressed
1013
- assert ! ( suppressed. is_telemetry_suppressed( ) ) ;
1014
-
1015
- // Test with values to ensure they're preserved
1016
- let cx_with_value = cx. with_value ( ValueA ( 42 ) ) ;
1017
- let suppressed_with_value = cx_with_value. with_telemetry_suppressed ( ) ;
1018
-
1019
- assert ! ( !cx_with_value. is_telemetry_suppressed( ) ) ;
1020
- assert ! ( suppressed_with_value. is_telemetry_suppressed( ) ) ;
1021
- assert_eq ! ( suppressed_with_value. get:: <ValueA >( ) , Some ( & ValueA ( 42 ) ) ) ;
1022
- }
1023
-
1024
- #[ test]
1025
- fn test_enter_telemetry_suppressed_scope ( ) {
1026
- // Ensure we start with a clean context
1027
- let _reset_guard = Context :: new ( ) . attach ( ) ;
1028
-
1029
- // Default context should not be suppressed
1030
- assert ! ( !Context :: is_current_telemetry_suppressed( ) ) ;
1031
-
1032
- // Add an entry to the current context
1033
- let cx_with_value = Context :: current ( ) . with_value ( ValueA ( 42 ) ) ;
1034
- let _guard_with_value = cx_with_value. attach ( ) ;
1035
-
1036
- // Verify the entry is present and context is not suppressed
1037
- assert_eq ! ( Context :: current( ) . get:: <ValueA >( ) , Some ( & ValueA ( 42 ) ) ) ;
1038
- assert ! ( !Context :: is_current_telemetry_suppressed( ) ) ;
1039
-
1040
- // Enter a suppressed scope
1041
- {
1042
- let _guard = Context :: enter_telemetry_suppressed_scope ( ) ;
1043
-
1044
- // Verify suppression is active and the entry is still present
1045
- assert ! ( Context :: is_current_telemetry_suppressed( ) ) ;
1046
- assert ! ( Context :: current( ) . is_telemetry_suppressed( ) ) ;
1047
- assert_eq ! ( Context :: current( ) . get:: <ValueA >( ) , Some ( & ValueA ( 42 ) ) ) ;
1048
- }
1049
-
1050
- // After guard is dropped, should be back to unsuppressed and entry should still be present
1051
- assert ! ( !Context :: is_current_telemetry_suppressed( ) ) ;
1052
- assert ! ( !Context :: current( ) . is_telemetry_suppressed( ) ) ;
1053
- assert_eq ! ( Context :: current( ) . get:: <ValueA >( ) , Some ( & ValueA ( 42 ) ) ) ;
1054
- }
1055
-
1056
- #[ test]
1057
- fn test_nested_suppression_scopes ( ) {
1058
- // Ensure we start with a clean context
1059
- let _reset_guard = Context :: new ( ) . attach ( ) ;
1060
-
1061
- // Default context should not be suppressed
1062
- assert ! ( !Context :: is_current_telemetry_suppressed( ) ) ;
1063
-
1064
- // First level suppression
1065
- {
1066
- let _outer = Context :: enter_telemetry_suppressed_scope ( ) ;
1067
- assert ! ( Context :: is_current_telemetry_suppressed( ) ) ;
1068
-
1069
- // Second level. This component is unaware of Suppression,
1070
- // and just attaches a new context. Since it is from current,
1071
- // it'll already have suppression enabled.
1072
- {
1073
- let _inner = Context :: current ( ) . with_value ( ValueA ( 1 ) ) . attach ( ) ;
1074
- assert ! ( Context :: is_current_telemetry_suppressed( ) ) ;
1075
- assert_eq ! ( Context :: current( ) . get:: <ValueA >( ) , Some ( & ValueA ( 1 ) ) ) ;
1076
- }
1077
-
1078
- // Another scenario. This component is unaware of Suppression,
1079
- // and just attaches a new context, not from Current. Since it is
1080
- // not from current it will not have suppression enabled.
1081
- {
1082
- let _inner = Context :: new ( ) . with_value ( ValueA ( 1 ) ) . attach ( ) ;
1083
- assert ! ( !Context :: is_current_telemetry_suppressed( ) ) ;
1084
- assert_eq ! ( Context :: current( ) . get:: <ValueA >( ) , Some ( & ValueA ( 1 ) ) ) ;
1085
- }
1086
-
1087
- // Still suppressed after inner scope
1088
- assert ! ( Context :: is_current_telemetry_suppressed( ) ) ;
1089
- }
1090
-
1091
- // Back to unsuppressed
1092
- assert ! ( !Context :: is_current_telemetry_suppressed( ) ) ;
1093
- }
1094
-
1095
- #[ tokio:: test( flavor = "multi_thread" , worker_threads = 4 ) ]
1096
- async fn test_async_suppression ( ) {
1097
- async fn nested_operation ( ) {
1098
- assert ! ( Context :: is_current_telemetry_suppressed( ) ) ;
1099
-
1100
- let cx_with_additional_value = Context :: current ( ) . with_value ( ValueB ( 24 ) ) ;
1101
-
1102
- async {
1103
- assert_eq ! (
1104
- Context :: current( ) . get:: <ValueB >( ) ,
1105
- Some ( & ValueB ( 24 ) ) ,
1106
- "Parent value should still be available after adding new value"
1107
- ) ;
1108
- assert ! ( Context :: is_current_telemetry_suppressed( ) ) ;
1109
-
1110
- // Do some async work to simulate real-world scenario
1111
- sleep ( Duration :: from_millis ( 10 ) ) . await ;
1112
-
1113
- // Values should still be available after async work
1114
- assert_eq ! (
1115
- Context :: current( ) . get:: <ValueB >( ) ,
1116
- Some ( & ValueB ( 24 ) ) ,
1117
- "Parent value should still be available after adding new value"
1118
- ) ;
1119
- assert ! ( Context :: is_current_telemetry_suppressed( ) ) ;
1120
- }
1121
- . with_context ( cx_with_additional_value)
1122
- . await ;
1123
- }
1124
-
1125
- // Set up suppressed context, but don't attach it to current
1126
- let suppressed_parent = Context :: new ( ) . with_telemetry_suppressed ( ) ;
1127
- // Current should not be suppressed as we haven't attached it
1128
- assert ! ( !Context :: is_current_telemetry_suppressed( ) ) ;
1129
-
1130
- // Create and run async operation with the suppressed context explicitly propagated
1131
- nested_operation ( )
1132
- . with_context ( suppressed_parent. clone ( ) )
1133
- . await ;
1134
-
1135
- // After async operation completes:
1136
- // Suppression should be active
1137
- assert ! ( suppressed_parent. is_telemetry_suppressed( ) ) ;
1138
-
1139
- // Current should still be not suppressed
1140
- assert ! ( !Context :: is_current_telemetry_suppressed( ) ) ;
1141
- }
1142
906
}
0 commit comments