From 34f8be85ce5862d2c32220a0c69b508cd25ba1b4 Mon Sep 17 00:00:00 2001 From: Cijo Thomas Date: Fri, 25 Jul 2025 09:23:23 -0700 Subject: [PATCH 1/2] Fix: Explore how to achieve telemetry suppression with OTLP --- .../examples/basic-otlp/src/main.rs | 57 ++++++++++--------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/opentelemetry-otlp/examples/basic-otlp/src/main.rs b/opentelemetry-otlp/examples/basic-otlp/src/main.rs index 1e657863e0..0923deaac9 100644 --- a/opentelemetry-otlp/examples/basic-otlp/src/main.rs +++ b/opentelemetry-otlp/examples/basic-otlp/src/main.rs @@ -1,12 +1,13 @@ use opentelemetry::trace::{TraceContextExt, Tracer}; -use opentelemetry::KeyValue; use opentelemetry::{global, InstrumentationScope}; +use opentelemetry::{Context, KeyValue}; use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge; use opentelemetry_otlp::{LogExporter, MetricExporter, SpanExporter}; use opentelemetry_sdk::logs::SdkLoggerProvider; use opentelemetry_sdk::metrics::SdkMeterProvider; use opentelemetry_sdk::trace::SdkTracerProvider; use opentelemetry_sdk::Resource; +use std::cell::RefCell; use std::error::Error; use std::sync::OnceLock; use tracing::info; @@ -59,33 +60,37 @@ fn init_logs() -> SdkLoggerProvider { .build() } -#[tokio::main] -async fn main() -> Result<(), Box> { - let logger_provider = init_logs(); +thread_local! { + static SUPPRESS_GUARD: RefCell> = RefCell::new(None); +} + +// #[tokio::main] +fn main() -> Result<(), Box> { + let rt = tokio::runtime::Builder::new_multi_thread() + .worker_threads(1) // Don't think this matters as no matter how many threads + // are created, we intercept the thread start to set suppress guard. + .enable_all() + .on_thread_start(|| { + let suppress_guard = Context::enter_telemetry_suppressed_scope(); + SUPPRESS_GUARD.with(|guard| { + *guard.borrow_mut() = Some(suppress_guard); + }); + }) + .on_thread_stop(|| { + // Cleanup thread-local resources + SUPPRESS_GUARD.with(|guard| { + if let Some(suppress_guard) = guard.borrow_mut().take() { + drop(suppress_guard); + } + }); + }) + .build() + .expect("Failed to create tokio runtime"); + let logger_provider = rt.block_on(async { init_logs() }); // Create a new OpenTelemetryTracingBridge using the above LoggerProvider. let otel_layer = OpenTelemetryTracingBridge::new(&logger_provider); - // To prevent a telemetry-induced-telemetry loop, OpenTelemetry's own internal - // logging is properly suppressed. However, logs emitted by external components - // (such as reqwest, tonic, etc.) are not suppressed as they do not propagate - // OpenTelemetry context. Until this issue is addressed - // (https://github.com/open-telemetry/opentelemetry-rust/issues/2877), - // filtering like this is the best way to suppress such logs. - // - // The filter levels are set as follows: - // - Allow `info` level and above by default. - // - Completely restrict logs from `hyper`, `tonic`, `h2`, and `reqwest`. - // - // Note: This filtering will also drop logs from these components even when - // they are used outside of the OTLP Exporter. - let filter_otel = EnvFilter::new("info") - .add_directive("hyper=off".parse().unwrap()) - .add_directive("tonic=off".parse().unwrap()) - .add_directive("h2=off".parse().unwrap()) - .add_directive("reqwest=off".parse().unwrap()); - let otel_layer = otel_layer.with_filter(filter_otel); - // Create a new tracing::Fmt layer to print the logs to stdout. It has a // default filter of `info` level and above, and `debug` and above for logs // from OpenTelemetry crates. The filter levels can be customized as needed. @@ -104,7 +109,7 @@ async fn main() -> Result<(), Box> { // At this point Logs (OTel Logs and Fmt Logs) are initialized, which will // allow internal-logs from Tracing/Metrics initializer to be captured. - let tracer_provider = init_traces(); + let tracer_provider = rt.block_on(async { init_traces() }); // Set the global tracer provider using a clone of the tracer_provider. // Setting global tracer provider is required if other parts of the application // uses global::tracer() or global::tracer_with_version() to get a tracer. @@ -113,7 +118,7 @@ async fn main() -> Result<(), Box> { // shutdown on it when application ends. global::set_tracer_provider(tracer_provider.clone()); - let meter_provider = init_metrics(); + let meter_provider = rt.block_on(async { init_metrics() }); // Set the global meter provider using a clone of the meter_provider. // Setting global meter provider is required if other parts of the application // uses global::meter() or global::meter_with_version() to get a meter. From 54e05d5919cba9ec637685a3871140183328cbb1 Mon Sep 17 00:00:00 2001 From: Cijo Thomas Date: Fri, 25 Jul 2025 09:39:45 -0700 Subject: [PATCH 2/2] clippy --- opentelemetry-otlp/examples/basic-otlp/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-otlp/examples/basic-otlp/src/main.rs b/opentelemetry-otlp/examples/basic-otlp/src/main.rs index 0923deaac9..0b93a7dd34 100644 --- a/opentelemetry-otlp/examples/basic-otlp/src/main.rs +++ b/opentelemetry-otlp/examples/basic-otlp/src/main.rs @@ -61,7 +61,7 @@ fn init_logs() -> SdkLoggerProvider { } thread_local! { - static SUPPRESS_GUARD: RefCell> = RefCell::new(None); + static SUPPRESS_GUARD: RefCell> = const { RefCell::new(None) }; } // #[tokio::main]