@@ -2,7 +2,7 @@ use super::{BatchLogProcessor, LogProcessor, SdkLogger, SimpleLogProcessor};
2
2
use crate :: error:: { OTelSdkError , OTelSdkResult } ;
3
3
use crate :: logs:: LogExporter ;
4
4
use crate :: Resource ;
5
- use opentelemetry:: { otel_debug, otel_info, InstrumentationScope } ;
5
+ use opentelemetry:: { otel_debug, otel_info, otel_warn , InstrumentationScope } ;
6
6
use std:: time:: Duration ;
7
7
use std:: {
8
8
borrow:: Cow ,
@@ -12,16 +12,32 @@ use std::{
12
12
} ,
13
13
} ;
14
14
15
- // a no nop logger provider used as placeholder when the provider is shutdown
15
+ // a no op logger provider used as placeholder when the provider is shutdown
16
16
// TODO - replace it with LazyLock once it is stable
17
- static NOOP_LOGGER_PROVIDER : OnceLock < SdkLoggerProvider > = OnceLock :: new ( ) ;
17
+ static SHUTDOWN_LOGGER_PROVIDER : OnceLock < SdkLoggerProvider > = OnceLock :: new ( ) ;
18
18
19
19
#[ inline]
20
- fn noop_logger_provider ( ) -> & ' static SdkLoggerProvider {
21
- NOOP_LOGGER_PROVIDER . get_or_init ( || SdkLoggerProvider {
20
+ fn shutdown_logger_provider ( ) -> & ' static SdkLoggerProvider {
21
+ SHUTDOWN_LOGGER_PROVIDER . get_or_init ( || SdkLoggerProvider {
22
22
inner : Arc :: new ( LoggerProviderInner {
23
23
processors : Vec :: new ( ) ,
24
24
is_shutdown : AtomicBool :: new ( true ) ,
25
+ is_disabled : false ,
26
+ } ) ,
27
+ } )
28
+ }
29
+ // a no op logger provider used as placeholder when sdk is disabled with
30
+ // help of environment variable `OTEL_SDK_DISABLED`
31
+ // TODO - replace it with LazyLock once it is stable
32
+ static DISABLED_LOGGER_PROVIDER : OnceLock < SdkLoggerProvider > = OnceLock :: new ( ) ;
33
+
34
+ #[ inline]
35
+ fn disabled_logger_provider ( ) -> & ' static SdkLoggerProvider {
36
+ DISABLED_LOGGER_PROVIDER . get_or_init ( || SdkLoggerProvider {
37
+ inner : Arc :: new ( LoggerProviderInner {
38
+ processors : Vec :: new ( ) ,
39
+ is_shutdown : AtomicBool :: new ( false ) ,
40
+ is_disabled : true ,
25
41
} ) ,
26
42
} )
27
43
}
@@ -53,13 +69,18 @@ impl opentelemetry::logs::LoggerProvider for SdkLoggerProvider {
53
69
}
54
70
55
71
fn logger_with_scope ( & self , scope : InstrumentationScope ) -> Self :: Logger {
56
- // If the provider is shutdown, new logger will refer a no-op logger provider.
72
+ // If the provider is shutdown, new logger will refer a shutdown no-op logger provider.
57
73
if self . inner . is_shutdown . load ( Ordering :: Relaxed ) {
58
74
otel_debug ! (
59
75
name: "LoggerProvider.NoOpLoggerReturned" ,
60
76
logger_name = scope. name( ) ,
61
77
) ;
62
- return SdkLogger :: new ( scope, noop_logger_provider ( ) . clone ( ) ) ;
78
+ return SdkLogger :: new ( scope, shutdown_logger_provider ( ) . clone ( ) ) ;
79
+ }
80
+ // If the provider is disabled, new logger will refer a disabled no-op logger provider.
81
+ if self . inner . is_disabled {
82
+ otel_warn ! ( name: "LoggerProvider.NoOpLoggerReturned" , message = "Returned NoOpLogger. SDK is disabled" ) ;
83
+ return SdkLogger :: new ( scope, disabled_logger_provider ( ) . clone ( ) ) ;
63
84
}
64
85
if scope. name ( ) . is_empty ( ) {
65
86
otel_info ! ( name: "LoggerNameEmpty" , message = "Logger name is empty; consider providing a meaningful name. Logger will function normally and the provided name will be used as-is." ) ;
@@ -135,6 +156,7 @@ impl SdkLoggerProvider {
135
156
struct LoggerProviderInner {
136
157
processors : Vec < Box < dyn LogProcessor > > ,
137
158
is_shutdown : AtomicBool ,
159
+ is_disabled : bool ,
138
160
}
139
161
140
162
impl LoggerProviderInner {
@@ -267,10 +289,18 @@ impl LoggerProviderBuilder {
267
289
processor. set_resource ( & resource) ;
268
290
}
269
291
292
+ let is_disabled =
293
+ std:: env:: var ( "OTEL_SDK_DISABLED" ) . is_ok_and ( |var| var. to_lowercase ( ) == "true" ) ;
294
+
295
+ if is_disabled {
296
+ otel_warn ! ( name: "LoggerProvider.Disabled" , message = "SDK is disabled through environment variable" ) ;
297
+ }
298
+
270
299
let logger_provider = SdkLoggerProvider {
271
300
inner : Arc :: new ( LoggerProviderInner {
272
301
processors,
273
302
is_shutdown : AtomicBool :: new ( false ) ,
303
+ is_disabled,
274
304
} ) ,
275
305
} ;
276
306
@@ -749,6 +779,7 @@ mod tests {
749
779
flush_called. clone( ) ,
750
780
) ) ] ,
751
781
is_shutdown : AtomicBool :: new ( false ) ,
782
+ is_disabled : false ,
752
783
} ) ;
753
784
754
785
{
@@ -777,6 +808,32 @@ mod tests {
777
808
assert ! ( !* flush_called. lock( ) . unwrap( ) ) ;
778
809
}
779
810
811
+ #[ test]
812
+ #[ ignore = "modifies OTEL_SDK_DISABLED env var which can affect other test" ]
813
+ fn otel_sdk_disabled_env ( ) {
814
+ temp_env:: with_var ( "OTEL_SDK_DISABLED" , Some ( "true" ) , || {
815
+ let exporter = InMemoryLogExporter :: default ( ) ;
816
+ let logger_provider = SdkLoggerProvider :: builder ( )
817
+ . with_simple_exporter ( exporter. clone ( ) )
818
+ . build ( ) ;
819
+ let logger = logger_provider. logger ( "noop" ) ;
820
+ let mut record = logger. create_log_record ( ) ;
821
+ record. set_body ( "Testing sdk disabled logger" . into ( ) ) ;
822
+ logger. emit ( record) ;
823
+ let mut record = logger. create_log_record ( ) ;
824
+ record. set_body ( "Testing sdk disabled logger" . into ( ) ) ;
825
+ logger. emit ( record) ;
826
+ let mut record = logger. create_log_record ( ) ;
827
+ record. set_body ( "Testing sdk disabled logger" . into ( ) ) ;
828
+ logger. emit ( record) ;
829
+ let emitted_logs = exporter. get_emitted_logs ( ) . unwrap ( ) ;
830
+ assert_eq ! ( emitted_logs. len( ) , 0 ) ;
831
+
832
+ assert ! ( logger. provider( ) . shutdown( ) . is_ok( ) ) ;
833
+ assert ! ( logger. provider( ) . shutdown( ) . is_err( ) ) ;
834
+ } ) ;
835
+ }
836
+
780
837
#[ test]
781
838
fn drop_after_shutdown_test_with_multiple_providers ( ) {
782
839
let shutdown_called = Arc :: new ( Mutex :: new ( 0 ) ) ; // Count the number of times shutdown is called
@@ -789,6 +846,7 @@ mod tests {
789
846
flush_called. clone( ) ,
790
847
) ) ] ,
791
848
is_shutdown : AtomicBool :: new ( false ) ,
849
+ is_disabled : false ,
792
850
} ) ;
793
851
794
852
// Create a scope to test behavior when providers are dropped
0 commit comments