Skip to content

Commit 6dffee7

Browse files
feat: add support for OTEL_SDK_DISABLED environment variable
Signed-off-by: Saurav Sharma <appdroiddeveloper@gmail.com>
1 parent 74cb6f3 commit 6dffee7

9 files changed

Lines changed: 469 additions & 17 deletions

File tree

opentelemetry-sdk/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
`queue_full` and `already_shutdown`, enabling operators to distinguish
1818
successful processing from drops due to full queue or post-shutdown emits.
1919
([#3514](https://github.com/open-telemetry/opentelemetry-rust/pull/3514))
20+
- **Feature**: Add support for `OTEL_SDK_DISABLED` environment variable [#3088][3088]
21+
22+
[3088]: https://github.com/open-telemetry/opentelemetry-rust/pull/3088
2023

2124
## 0.32.1
2225

opentelemetry-sdk/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ name = "bound_instruments"
129129
harness = false
130130
required-features = ["metrics", "experimental_metrics_custom_reader", "experimental_metrics_bound_instruments", "spec_unstable_metrics_views"]
131131

132+
[[bench]]
133+
name = "sdk_disabled"
134+
harness = false
135+
required-features = ["trace", "logs", "metrics"]
136+
132137
[lib]
133138
bench = false
134139

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
/*
2+
The benchmark results:
3+
criterion = "0.5.1"
4+
rustc 1.98.0-nightly (8b6558a02 2026-06-20)
5+
OS: macOS 26.5.1 (arm64)
6+
Hardware: Apple M1
7+
8+
| Test | api-only | sdk-disabled | sdk-shutdown | sdk-enabled |
9+
|---------|----------|--------------|--------------|-------------|
10+
| trace | 20.4 ns | 38.9 ns | 38.5 ns | 178 ns |
11+
| log | 0.32 ns | 1.28 ns | 1.27 ns | 37 ns |
12+
| metrics | 6.11 ns | 6.11 ns | 6.10 ns | 66 ns |
13+
*/
14+
15+
use criterion::{criterion_group, criterion_main, Criterion};
16+
use opentelemetry::InstrumentationScope;
17+
use opentelemetry::{
18+
logs::{LogRecord, Logger, LoggerProvider, Severity},
19+
metrics::{Counter, MeterProvider},
20+
trace::{Span, Tracer, TracerProvider},
21+
KeyValue,
22+
};
23+
use opentelemetry_sdk::{
24+
error::OTelSdkResult,
25+
logs::{LogProcessor, SdkLogRecord, SdkLoggerProvider},
26+
metrics::{
27+
data::ResourceMetrics, exporter::PushMetricExporter, PeriodicReader, SdkMeterProvider,
28+
Temporality,
29+
},
30+
trace::{Sampler, SdkTracerProvider, SpanData, SpanExporter},
31+
};
32+
use std::time::Duration;
33+
34+
// Run the given closure with the `OTEL_SDK_DISABLED` environment variable set to "true".
35+
fn with_sdk_disabled<T>(f: impl FnOnce() -> T) -> T {
36+
temp_env::with_var("OTEL_SDK_DISABLED", Some("true"), f)
37+
}
38+
39+
#[derive(Debug)]
40+
struct NoOpSpanExporter;
41+
42+
impl SpanExporter for NoOpSpanExporter {
43+
async fn export(&self, _spans: Vec<SpanData>) -> OTelSdkResult {
44+
Ok(())
45+
}
46+
}
47+
48+
#[derive(Debug)]
49+
struct NoOpLogProcessor;
50+
51+
impl LogProcessor for NoOpLogProcessor {
52+
fn emit(&self, _data: &mut SdkLogRecord, _scope: &InstrumentationScope) {}
53+
54+
fn force_flush(&self) -> OTelSdkResult {
55+
Ok(())
56+
}
57+
58+
fn shutdown_with_timeout(&self, _timeout: Duration) -> OTelSdkResult {
59+
Ok(())
60+
}
61+
}
62+
63+
#[derive(Debug)]
64+
struct NoOpMetricExporter;
65+
66+
impl PushMetricExporter for NoOpMetricExporter {
67+
async fn export(&self, _metrics: &ResourceMetrics) -> OTelSdkResult {
68+
Ok(())
69+
}
70+
71+
fn force_flush(&self) -> OTelSdkResult {
72+
Ok(())
73+
}
74+
75+
fn shutdown_with_timeout(&self, _timeout: Duration) -> OTelSdkResult {
76+
Ok(())
77+
}
78+
79+
fn temporality(&self) -> Temporality {
80+
Temporality::Cumulative
81+
}
82+
}
83+
84+
fn emit_span<T: Tracer>(tracer: &T) {
85+
let mut span = tracer.start("span-name");
86+
if span.is_recording() {
87+
span.set_attribute(KeyValue::new("key1", "value1"));
88+
span.set_attribute(KeyValue::new("key2", 123));
89+
}
90+
span.end();
91+
}
92+
93+
fn emit_log<L: Logger>(logger: &L) {
94+
if logger.event_enabled(Severity::Info, "benchmark", None) {
95+
let mut record = logger.create_log_record();
96+
record.set_body("a log message".into());
97+
record.set_severity_number(Severity::Info);
98+
record.add_attribute("key1", "value1");
99+
record.add_attribute("key2", 123);
100+
logger.emit(record);
101+
}
102+
}
103+
104+
fn add_to_counter(counter: &Counter<u64>) {
105+
counter.add(
106+
1,
107+
&[KeyValue::new("key1", "value1"), KeyValue::new("key2", 123)],
108+
);
109+
}
110+
111+
fn trace_benchmark(c: &mut Criterion) {
112+
let mut group = c.benchmark_group("trace");
113+
114+
group.bench_function("api-only", |b| {
115+
let provider = opentelemetry::trace::noop::NoopTracerProvider::new();
116+
let tracer = provider.tracer("bench");
117+
b.iter(|| emit_span(&tracer));
118+
});
119+
120+
group.bench_function("sdk-disabled", |b| {
121+
let provider = with_sdk_disabled(|| {
122+
SdkTracerProvider::builder()
123+
.with_sampler(Sampler::AlwaysOn)
124+
.build()
125+
});
126+
let tracer = provider.tracer("bench");
127+
b.iter(|| emit_span(&tracer));
128+
});
129+
130+
group.bench_function("sdk-shutdown", |b| {
131+
let provider = SdkTracerProvider::builder()
132+
.with_sampler(Sampler::AlwaysOn)
133+
.with_simple_exporter(NoOpSpanExporter)
134+
.build();
135+
let _ = provider.shutdown();
136+
let tracer = provider.tracer("bench");
137+
b.iter(|| emit_span(&tracer));
138+
});
139+
140+
group.bench_function("sdk-enabled", |b| {
141+
let provider = SdkTracerProvider::builder()
142+
.with_sampler(Sampler::AlwaysOn)
143+
.with_simple_exporter(NoOpSpanExporter)
144+
.build();
145+
let tracer = provider.tracer("bench");
146+
b.iter(|| emit_span(&tracer));
147+
});
148+
149+
group.finish();
150+
}
151+
152+
fn log_benchmark(c: &mut Criterion) {
153+
let mut group = c.benchmark_group("log");
154+
155+
group.bench_function("api-only", |b| {
156+
let provider = opentelemetry::logs::NoopLoggerProvider::new();
157+
let logger = provider.logger("bench");
158+
b.iter(|| emit_log(&logger));
159+
});
160+
161+
group.bench_function("sdk-disabled", |b| {
162+
let provider = with_sdk_disabled(|| {
163+
SdkLoggerProvider::builder()
164+
.with_log_processor(NoOpLogProcessor)
165+
.build()
166+
});
167+
let logger = provider.logger("bench");
168+
b.iter(|| emit_log(&logger));
169+
});
170+
171+
group.bench_function("sdk-shutdown", |b| {
172+
let provider = SdkLoggerProvider::builder()
173+
.with_log_processor(NoOpLogProcessor)
174+
.build();
175+
let _ = provider.shutdown();
176+
let logger = provider.logger("bench");
177+
b.iter(|| emit_log(&logger));
178+
});
179+
180+
group.bench_function("sdk-enabled", |b| {
181+
let provider = SdkLoggerProvider::builder()
182+
.with_log_processor(NoOpLogProcessor)
183+
.build();
184+
let logger = provider.logger("bench");
185+
b.iter(|| emit_log(&logger));
186+
});
187+
188+
group.finish();
189+
}
190+
191+
fn metrics_benchmark(c: &mut Criterion) {
192+
let mut group = c.benchmark_group("metrics");
193+
194+
group.bench_function("api-only", |b| {
195+
let provider = opentelemetry::metrics::NoopMeterProvider::new();
196+
let counter = provider.meter("bench").u64_counter("counter").build();
197+
b.iter(|| add_to_counter(&counter));
198+
});
199+
200+
group.bench_function("sdk-disabled", |b| {
201+
let provider = with_sdk_disabled(|| SdkMeterProvider::builder().build());
202+
let counter = provider.meter("bench").u64_counter("counter").build();
203+
b.iter(|| add_to_counter(&counter));
204+
});
205+
206+
group.bench_function("sdk-shutdown", |b| {
207+
let provider = SdkMeterProvider::builder()
208+
.with_reader(PeriodicReader::builder(NoOpMetricExporter).build())
209+
.build();
210+
let _ = provider.shutdown();
211+
let counter = provider.meter("bench").u64_counter("counter").build();
212+
b.iter(|| add_to_counter(&counter));
213+
});
214+
215+
group.bench_function("sdk-enabled", |b| {
216+
let provider = SdkMeterProvider::builder()
217+
.with_reader(PeriodicReader::builder(NoOpMetricExporter).build())
218+
.build();
219+
let counter = provider.meter("bench").u64_counter("counter").build();
220+
b.iter(|| add_to_counter(&counter));
221+
});
222+
223+
group.finish();
224+
}
225+
226+
fn criterion_benchmark(c: &mut Criterion) {
227+
trace_benchmark(c);
228+
log_benchmark(c);
229+
metrics_benchmark(c);
230+
}
231+
232+
criterion_group! {
233+
name = benches;
234+
config = Criterion::default()
235+
.warm_up_time(std::time::Duration::from_secs(1))
236+
.measurement_time(std::time::Duration::from_secs(2));
237+
targets = criterion_benchmark
238+
}
239+
criterion_main!(benches);

opentelemetry-sdk/src/logs/logger.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ impl SdkLogger {
2121
pub(crate) fn new(scope: InstrumentationScope, provider: SdkLoggerProvider) -> Self {
2222
SdkLogger { scope, provider }
2323
}
24+
25+
#[cfg(test)]
26+
pub(crate) fn provider(&self) -> &SdkLoggerProvider {
27+
&self.provider
28+
}
2429
}
2530

2631
impl opentelemetry::logs::Logger for SdkLogger {
@@ -58,13 +63,16 @@ impl opentelemetry::logs::Logger for SdkLogger {
5863

5964
#[inline]
6065
fn event_enabled(&self, level: Severity, target: &str, name: Option<&str>) -> bool {
66+
let processors = self.provider.log_processors();
67+
// Early return if there are no processors
68+
if processors.is_empty() {
69+
return false;
70+
}
6171
if Context::is_current_telemetry_suppressed() {
6272
return false;
6373
}
64-
// Returns false if there are no log processors.
6574
// Returns true if at least one processor returns true.
66-
self.provider
67-
.log_processors()
75+
processors
6876
.iter()
6977
.any(|processor| processor.event_enabled(level, target, name))
7078
}

0 commit comments

Comments
 (0)