Skip to content

Commit c990dd7

Browse files
feat: add support for OTEL_SDK_DISABLED environment variable
Signed-off-by: Saurav Sharma <appdroiddeveloper@gmail.com>
1 parent 42139cb commit c990dd7

File tree

6 files changed

+182
-14
lines changed

6 files changed

+182
-14
lines changed

opentelemetry-sdk/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
- *Fix* SpanProcessor::on_start is no longer called on non recording spans
77
- **Fix**: Restore true parallel exports in the async-native `BatchSpanProcessor` by honoring `OTEL_BSP_MAX_CONCURRENT_EXPORTS` ([#2959](https://github.com/open-telemetry/opentelemetry-rust/pull/3028)). A regression in [#2685](https://github.com/open-telemetry/opentelemetry-rust/pull/2685) inadvertently awaited the `export()` future directly in `opentelemetry-sdk/src/trace/span_processor_with_async_runtime.rs` instead of spawning it on the runtime, forcing all exports to run sequentially.
88
- **Feature**: Added `Clone` implementation to `SdkLogger` for API consistency with `SdkTracer` ([#3058](https://github.com/open-telemetry/opentelemetry-rust/issues/3058)).
9+
- **Feature**: Add support for `OTEL_SDK_DISABLED` environment variable ([#3088](https://github.com/open-telemetry/opentelemetry-rust/pull/3088))
10+
911

1012
## 0.30.0
1113

opentelemetry-sdk/src/logs/logger.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ impl SdkLogger {
1818
pub(crate) fn new(scope: InstrumentationScope, provider: SdkLoggerProvider) -> Self {
1919
SdkLogger { scope, provider }
2020
}
21+
22+
#[cfg(test)]
23+
pub(crate) fn provider(&self) -> &SdkLoggerProvider {
24+
&self.provider
25+
}
2126
}
2227

2328
impl opentelemetry::logs::Logger for SdkLogger {

opentelemetry-sdk/src/logs/logger_provider.rs

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::{BatchLogProcessor, LogProcessor, SdkLogger, SimpleLogProcessor};
22
use crate::error::{OTelSdkError, OTelSdkResult};
33
use crate::logs::LogExporter;
44
use crate::Resource;
5-
use opentelemetry::{otel_debug, otel_info, InstrumentationScope};
5+
use opentelemetry::{otel_debug, otel_info, otel_warn, InstrumentationScope};
66
use std::time::Duration;
77
use std::{
88
borrow::Cow,
@@ -12,16 +12,32 @@ use std::{
1212
},
1313
};
1414

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
1616
// 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();
1818

1919
#[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 {
2222
inner: Arc::new(LoggerProviderInner {
2323
processors: Vec::new(),
2424
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,
2541
}),
2642
})
2743
}
@@ -53,13 +69,18 @@ impl opentelemetry::logs::LoggerProvider for SdkLoggerProvider {
5369
}
5470

5571
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.
5773
if self.inner.is_shutdown.load(Ordering::Relaxed) {
5874
otel_debug!(
5975
name: "LoggerProvider.NoOpLoggerReturned",
6076
logger_name = scope.name(),
6177
);
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());
6384
}
6485
if scope.name().is_empty() {
6586
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 {
135156
struct LoggerProviderInner {
136157
processors: Vec<Box<dyn LogProcessor>>,
137158
is_shutdown: AtomicBool,
159+
is_disabled: bool,
138160
}
139161

140162
impl LoggerProviderInner {
@@ -267,10 +289,18 @@ impl LoggerProviderBuilder {
267289
processor.set_resource(&resource);
268290
}
269291

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+
270299
let logger_provider = SdkLoggerProvider {
271300
inner: Arc::new(LoggerProviderInner {
272301
processors,
273302
is_shutdown: AtomicBool::new(false),
303+
is_disabled,
274304
}),
275305
};
276306

@@ -745,6 +775,7 @@ mod tests {
745775
flush_called.clone(),
746776
))],
747777
is_shutdown: AtomicBool::new(false),
778+
is_disabled: false,
748779
});
749780

750781
{
@@ -773,6 +804,32 @@ mod tests {
773804
assert!(!*flush_called.lock().unwrap());
774805
}
775806

807+
#[test]
808+
#[ignore = "modifies OTEL_SDK_DISABLED env var which can affect other test"]
809+
fn otel_sdk_disabled_env() {
810+
temp_env::with_var("OTEL_SDK_DISABLED", Some("true"), || {
811+
let exporter = InMemoryLogExporter::default();
812+
let logger_provider = SdkLoggerProvider::builder()
813+
.with_simple_exporter(exporter.clone())
814+
.build();
815+
let logger = logger_provider.logger("noop");
816+
let mut record = logger.create_log_record();
817+
record.set_body("Testing sdk disabled logger".into());
818+
logger.emit(record);
819+
let mut record = logger.create_log_record();
820+
record.set_body("Testing sdk disabled logger".into());
821+
logger.emit(record);
822+
let mut record = logger.create_log_record();
823+
record.set_body("Testing sdk disabled logger".into());
824+
logger.emit(record);
825+
let emitted_logs = exporter.get_emitted_logs().unwrap();
826+
assert_eq!(emitted_logs.len(), 0);
827+
828+
assert!(logger.provider().shutdown().is_ok());
829+
assert!(logger.provider().shutdown().is_err());
830+
});
831+
}
832+
776833
#[test]
777834
fn drop_after_shutdown_test_with_multiple_providers() {
778835
let shutdown_called = Arc::new(Mutex::new(0)); // Count the number of times shutdown is called
@@ -785,6 +842,7 @@ mod tests {
785842
flush_called.clone(),
786843
))],
787844
is_shutdown: AtomicBool::new(false),
845+
is_disabled: false,
788846
});
789847

790848
// Create a scope to test behavior when providers are dropped

opentelemetry-sdk/src/metrics/meter_provider.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use core::fmt;
22
use opentelemetry::{
33
metrics::{Meter, MeterProvider},
4-
otel_debug, otel_error, otel_info, InstrumentationScope,
4+
otel_debug, otel_error, otel_info, otel_warn, InstrumentationScope,
55
};
66
use std::time::Duration;
77
use std::{
@@ -41,6 +41,7 @@ struct SdkMeterProviderInner {
4141
pipes: Arc<Pipelines>,
4242
meters: Mutex<HashMap<InstrumentationScope, Arc<SdkMeter>>>,
4343
shutdown_invoked: AtomicBool,
44+
is_disabled: bool,
4445
}
4546

4647
impl Default for SdkMeterProvider {
@@ -196,6 +197,10 @@ impl MeterProvider for SdkMeterProvider {
196197
);
197198
return Meter::new(Arc::new(NoopMeter::new()));
198199
}
200+
if self.inner.is_disabled {
201+
otel_warn!(name: "MeterProvider.NoOpMeterReturned", message = "Returned NoOpMeter. SDK is disabled");
202+
return Meter::new(Arc::new(NoopMeter::new()));
203+
}
199204

200205
if scope.name().is_empty() {
201206
otel_info!(name: "MeterNameEmpty", message = "Meter name is empty; consider providing a meaningful name. Meter will function normally and the provided name will be used as-is.");
@@ -379,6 +384,13 @@ impl MeterProviderBuilder {
379384
builder = format!("{:?}", &self),
380385
);
381386

387+
let is_disabled =
388+
std::env::var("OTEL_SDK_DISABLED").is_ok_and(|var| var.to_lowercase() == "true");
389+
390+
if is_disabled {
391+
otel_warn!(name: "MeterProvider.Disabled", message = "SDK is disabled through environment variable");
392+
}
393+
382394
let meter_provider = SdkMeterProvider {
383395
inner: Arc::new(SdkMeterProviderInner {
384396
pipes: Arc::new(Pipelines::new(
@@ -388,6 +400,7 @@ impl MeterProviderBuilder {
388400
)),
389401
meters: Default::default(),
390402
shutdown_invoked: AtomicBool::new(false),
403+
is_disabled,
391404
}),
392405
};
393406

@@ -729,4 +742,21 @@ mod tests {
729742
);
730743
assert_eq!(resource.schema_url(), Some("http://example.com"));
731744
}
745+
746+
#[test]
747+
#[ignore = "modifies OTEL_SDK_DISABLED env var which can affect other test"]
748+
fn otel_sdk_disabled_env() {
749+
temp_env::with_var("OTEL_SDK_DISABLED", Some("true"), || {
750+
let meter_provider = super::SdkMeterProvider::builder().build();
751+
let _ = meter_provider.meter("noop1");
752+
let _ = meter_provider.meter("noop2");
753+
let _ = meter_provider.meter("noop3");
754+
let _ = meter_provider.meter("noop4");
755+
let _ = meter_provider.meter("noop5");
756+
757+
assert_eq!(meter_provider.inner.meters.lock().unwrap().len(), 0);
758+
assert!(meter_provider.shutdown().is_ok());
759+
assert!(meter_provider.shutdown().is_err());
760+
});
761+
}
732762
}

0 commit comments

Comments
 (0)