diff --git a/examples/self-diagnostics/src/main.rs b/examples/self-diagnostics/src/main.rs index e34ed5f67b..02ea356b0d 100644 --- a/examples/self-diagnostics/src/main.rs +++ b/examples/self-diagnostics/src/main.rs @@ -26,7 +26,7 @@ async fn main() -> Result<(), Box> { // OpenTelemetry uses `tracing` crate for its internal logging. Unless a // tracing subscriber is set, the logs will be discarded. In this example, // we configure a `tracing` subscriber to: - // 1. Print logs of level INFO or higher to stdout. + // 1. Print logs of level INFO or higher to stdout using tracing's fmt layer. // 2. Filter logs from OpenTelemetry's dependencies (like tonic, hyper, // reqwest etc. which are commonly used by the OTLP exporter) to only print // ERROR-level logs. This filtering helps reduce repetitive log messages @@ -35,7 +35,7 @@ async fn main() -> Result<(), Box> { // https://github.com/open-telemetry/opentelemetry-rust/issues/761 is // resolved. - // Target name used by OpenTelemetry always start with "opentelemetry". + // Target names used by all OpenTelemetry official crates always start with "opentelemetry". // Hence, one may use "add_directive("opentelemetry=off".parse().unwrap())" // to turn off all logs from OpenTelemetry. diff --git a/opentelemetry-sdk/CHANGELOG.md b/opentelemetry-sdk/CHANGELOG.md index cf0543b76c..8002a34ca1 100644 --- a/opentelemetry-sdk/CHANGELOG.md +++ b/opentelemetry-sdk/CHANGELOG.md @@ -18,6 +18,7 @@ .with_resource(Resource::empty()) .build(); ``` + - `logs::LogData` struct is deprecated, and scheduled to be removed from public API in `v0.28.0`. ## 0.27.0 diff --git a/opentelemetry-sdk/src/logs/log_emitter.rs b/opentelemetry-sdk/src/logs/log_emitter.rs index 0f4cbfc53c..b2e0c5452b 100644 --- a/opentelemetry-sdk/src/logs/log_emitter.rs +++ b/opentelemetry-sdk/src/logs/log_emitter.rs @@ -1,6 +1,7 @@ use super::{BatchLogProcessor, LogProcessor, LogRecord, SimpleLogProcessor, TraceContext}; use crate::{export::logs::LogExporter, runtime::RuntimeChannel, Resource}; use crate::{logs::LogError, logs::LogResult}; +use opentelemetry::otel_info; use opentelemetry::{otel_debug, trace::TraceContextExt, Context, InstrumentationScope}; #[cfg(feature = "spec_unstable_logs_enabled")] @@ -154,10 +155,15 @@ impl LoggerProviderInner { impl Drop for LoggerProviderInner { fn drop(&mut self) { if !self.is_shutdown.load(Ordering::Relaxed) { + otel_info!( + name: "LoggerProvider.Drop", + message = "Last reference of LoggerProvider dropped, initiating shutdown." + ); let _ = self.shutdown(); // errors are handled within shutdown } else { otel_debug!( - name: "LoggerProvider.Drop.AlreadyShutdown" + name: "LoggerProvider.Drop.AlreadyShutdown", + message = "LoggerProvider was already shut down; drop will not attempt shutdown again." ); } } diff --git a/opentelemetry-sdk/src/logs/log_processor.rs b/opentelemetry-sdk/src/logs/log_processor.rs index d4f5e53f40..7e384d2147 100644 --- a/opentelemetry-sdk/src/logs/log_processor.rs +++ b/opentelemetry-sdk/src/logs/log_processor.rs @@ -45,14 +45,14 @@ const OTEL_BLRP_MAX_EXPORT_BATCH_SIZE_DEFAULT: usize = 512; pub trait LogProcessor: Send + Sync + Debug { /// Called when a log record is ready to processed and exported. /// - /// This method receives a mutable reference to `LogData`. If the processor + /// This method receives a mutable reference to `LogRecord`. If the processor /// needs to handle the export asynchronously, it should clone the data to /// ensure it can be safely processed without lifetime issues. Any changes /// made to the log data in this method will be reflected in the next log /// processor in the chain. /// /// # Parameters - /// - `record`: A mutable reference to `LogData` representing the log record. + /// - `record`: A mutable reference to `LogRecord` representing the log record. /// - `instrumentation`: The instrumentation scope associated with the log record. fn emit(&self, data: &mut LogRecord, instrumentation: &InstrumentationScope); /// Force the logs lying in the cache to be exported. diff --git a/opentelemetry-sdk/src/logs/mod.rs b/opentelemetry-sdk/src/logs/mod.rs index 2dba806056..f4f55cd390 100644 --- a/opentelemetry-sdk/src/logs/mod.rs +++ b/opentelemetry-sdk/src/logs/mod.rs @@ -13,6 +13,10 @@ pub use log_processor::{ use opentelemetry::InstrumentationScope; pub use record::{LogRecord, TraceContext}; +#[deprecated( + since = "0.27.1", + note = "The struct is not used anywhere in the SDK and will be removed in the next major release." +)] /// `LogData` represents a single log event without resource context. #[derive(Clone, Debug)] pub struct LogData { diff --git a/opentelemetry-sdk/src/metrics/meter_provider.rs b/opentelemetry-sdk/src/metrics/meter_provider.rs index 44504ae9c0..fd55df4c49 100644 --- a/opentelemetry-sdk/src/metrics/meter_provider.rs +++ b/opentelemetry-sdk/src/metrics/meter_provider.rs @@ -9,7 +9,7 @@ use std::{ use opentelemetry::{ metrics::{Meter, MeterProvider}, - otel_debug, otel_error, InstrumentationScope, + otel_debug, otel_error, otel_info, InstrumentationScope, }; use crate::metrics::{MetricError, MetricResult}; @@ -109,6 +109,10 @@ impl SdkMeterProvider { /// There is no guaranteed that all telemetry be flushed or all resources have /// been released on error. pub fn shutdown(&self) -> MetricResult<()> { + otel_info!( + name: "MeterProvider.Shutdown", + message = "User initiated shutdown of MeterProvider." + ); self.inner.shutdown() } } @@ -139,15 +143,25 @@ impl Drop for SdkMeterProviderInner { // shutdown(), then we don't need to call shutdown again. if self.is_shutdown.load(Ordering::Relaxed) { otel_debug!( - name: "MeterProvider.AlreadyShutdown", - message = "Meter provider was already shut down; drop will not attempt shutdown again." + name: "MeterProvider.Drop.AlreadyShutdown", + message = "MeterProvider was already shut down; drop will not attempt shutdown again." ); - } else if let Err(err) = self.shutdown() { - otel_error!( - name: "MeterProvider.ShutdownFailed", - message = "Shutdown attempt failed during drop of MeterProvider.", - reason = format!("{}", err) + } else { + otel_info!( + name: "MeterProvider.Drop", + message = "Last reference of MeterProvider dropped, initiating shutdown." ); + if let Err(err) = self.shutdown() { + otel_error!( + name: "MeterProvider.Drop.ShutdownFailed", + message = "Shutdown attempt failed during drop of MeterProvider.", + reason = format!("{}", err) + ); + } else { + otel_info!( + name: "MeterProvider.Drop.ShutdownCompleted", + ); + } } } } @@ -231,7 +245,7 @@ impl MeterProviderBuilder { /// Construct a new [MeterProvider] with this configuration. pub fn build(self) -> SdkMeterProvider { - SdkMeterProvider { + let meter_provider = SdkMeterProvider { inner: Arc::new(SdkMeterProviderInner { pipes: Arc::new(Pipelines::new( self.resource.unwrap_or_default(), @@ -241,7 +255,12 @@ impl MeterProviderBuilder { meters: Default::default(), is_shutdown: AtomicBool::new(false), }), - } + }; + + otel_info!( + name: "MeterProvider.Built", + ); + meter_provider } } diff --git a/opentelemetry-sdk/src/metrics/periodic_reader.rs b/opentelemetry-sdk/src/metrics/periodic_reader.rs index 7a00e3978a..c0a40b5f8c 100644 --- a/opentelemetry-sdk/src/metrics/periodic_reader.rs +++ b/opentelemetry-sdk/src/metrics/periodic_reader.rs @@ -234,10 +234,18 @@ impl PeriodicReaderWorker { async fn collect_and_export(&mut self) -> MetricResult<()> { self.reader.collect(&mut self.rm)?; if self.rm.scope_metrics.is_empty() { + otel_debug!( + name: "PeriodicReaderWorker.NoMetricsToExport", + ); // No metrics to export. return Ok(()); } + otel_debug!( + name: "PeriodicReaderWorker.InvokeExporter", + message = "Calling exporter's export method with collected metrics.", + count = self.rm.scope_metrics.len(), + ); let export = self.reader.exporter.export(&mut self.rm); let timeout = self.runtime.delay(self.timeout); pin_mut!(export); diff --git a/opentelemetry-sdk/src/testing/logs/in_memory_exporter.rs b/opentelemetry-sdk/src/testing/logs/in_memory_exporter.rs index cac026c663..daafd47fc0 100644 --- a/opentelemetry-sdk/src/testing/logs/in_memory_exporter.rs +++ b/opentelemetry-sdk/src/testing/logs/in_memory_exporter.rs @@ -10,7 +10,7 @@ use std::sync::{Arc, Mutex}; /// An in-memory logs exporter that stores logs data in memory.. /// /// This exporter is useful for testing and debugging purposes. -/// It stores logs in a `Vec`. Logs can be retrieved using +/// It stores logs in a `Vec`. Logs can be retrieved using /// `get_emitted_logs` method. /// /// # Example @@ -65,9 +65,9 @@ pub struct OwnedLogData { pub struct LogDataWithResource { /// Log record pub record: LogRecord, - /// Instrumentation details for the emitter who produced this `LogData`. + /// Instrumentation details for the emitter who produced this `LogRecord`. pub instrumentation: InstrumentationScope, - /// Resource for the emitter who produced this `LogData`. + /// Resource for the emitter who produced this `LogRecord`. pub resource: Cow<'static, Resource>, } @@ -137,7 +137,7 @@ impl InMemoryLogExporterBuilder { } impl InMemoryLogExporter { - /// Returns the logs emitted via Logger as a vector of `LogData`. + /// Returns the logs emitted via Logger as a vector of `LogDataWithResource`. /// /// # Example /// diff --git a/opentelemetry/Cargo.toml b/opentelemetry/Cargo.toml index 89e2592a5c..cb47d8da3e 100644 --- a/opentelemetry/Cargo.toml +++ b/opentelemetry/Cargo.toml @@ -21,11 +21,10 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] -futures-core = { workspace = true } -futures-sink = "0.3" -once_cell = { workspace = true } +futures-core = { workspace = true, optional = true } +futures-sink = { version = "0.3", optional = true } pin-project-lite = { workspace = true, optional = true } -thiserror = { workspace = true } +thiserror = { workspace = true, optional = true} tracing = {workspace = true, optional = true} # optional for opentelemetry internal logging [target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dependencies] @@ -33,7 +32,7 @@ js-sys = "0.3.63" [features] default = ["trace", "metrics", "logs"] -trace = ["pin-project-lite"] +trace = ["pin-project-lite", "futures-sink", "futures-core", "thiserror"] metrics = [] testing = ["trace", "metrics"] logs = [] diff --git a/opentelemetry/src/baggage.rs b/opentelemetry/src/baggage.rs index 37ba28e682..279613a287 100644 --- a/opentelemetry/src/baggage.rs +++ b/opentelemetry/src/baggage.rs @@ -15,16 +15,22 @@ //! //! [W3C Baggage]: https://w3c.github.io/baggage use crate::{Context, Key, KeyValue, Value}; -use once_cell::sync::Lazy; use std::collections::{hash_map, HashMap}; use std::fmt; +use std::sync::OnceLock; -static DEFAULT_BAGGAGE: Lazy = Lazy::new(Baggage::default); +static DEFAULT_BAGGAGE: OnceLock = OnceLock::new(); const MAX_KEY_VALUE_PAIRS: usize = 180; const MAX_BYTES_FOR_ONE_PAIR: usize = 4096; const MAX_LEN_OF_ALL_PAIRS: usize = 8192; +/// Returns the default baggage, ensuring it is initialized only once. +#[inline] +fn get_default_baggage() -> &'static Baggage { + DEFAULT_BAGGAGE.get_or_init(Baggage::default) +} + /// A set of name/value pairs describing user-defined properties. /// /// ### Baggage Names @@ -399,7 +405,7 @@ impl BaggageExt for Context { } fn baggage(&self) -> &Baggage { - self.get::().unwrap_or(&DEFAULT_BAGGAGE) + self.get::().unwrap_or(get_default_baggage()) } } diff --git a/opentelemetry/src/global/metrics.rs b/opentelemetry/src/global/metrics.rs index 142a5c2f69..810212a00d 100644 --- a/opentelemetry/src/global/metrics.rs +++ b/opentelemetry/src/global/metrics.rs @@ -1,13 +1,17 @@ use crate::metrics::{self, Meter, MeterProvider}; use crate::InstrumentationScope; -use once_cell::sync::Lazy; -use std::sync::{Arc, RwLock}; +use std::sync::{Arc, OnceLock, RwLock}; type GlobalMeterProvider = Arc; /// The global `MeterProvider` singleton. -static GLOBAL_METER_PROVIDER: Lazy> = - Lazy::new(|| RwLock::new(Arc::new(crate::metrics::noop::NoopMeterProvider::new()))); +static GLOBAL_METER_PROVIDER: OnceLock> = OnceLock::new(); + +#[inline] +fn global_meter_provider() -> &'static RwLock { + GLOBAL_METER_PROVIDER + .get_or_init(|| RwLock::new(Arc::new(crate::metrics::noop::NoopMeterProvider::new()))) +} /// Sets the given [`MeterProvider`] instance as the current global meter /// provider. @@ -15,7 +19,7 @@ pub fn set_meter_provider

(new_provider: P) where P: metrics::MeterProvider + Send + Sync + 'static, { - let mut global_provider = GLOBAL_METER_PROVIDER + let mut global_provider = global_meter_provider() .write() .expect("GLOBAL_METER_PROVIDER RwLock poisoned"); *global_provider = Arc::new(new_provider); @@ -23,7 +27,7 @@ where /// Returns an instance of the currently configured global [`MeterProvider`]. pub fn meter_provider() -> GlobalMeterProvider { - GLOBAL_METER_PROVIDER + global_meter_provider() .read() .expect("GLOBAL_METER_PROVIDER RwLock poisoned") .clone() diff --git a/opentelemetry/src/global/propagation.rs b/opentelemetry/src/global/propagation.rs index 30d5b8f86b..4a8a296820 100644 --- a/opentelemetry/src/global/propagation.rs +++ b/opentelemetry/src/global/propagation.rs @@ -1,19 +1,29 @@ use crate::propagation::TextMapPropagator; use crate::trace::noop::NoopTextMapPropagator; -use once_cell::sync::Lazy; -use std::sync::RwLock; +use std::sync::{OnceLock, RwLock}; /// The current global `TextMapPropagator` propagator. -static GLOBAL_TEXT_MAP_PROPAGATOR: Lazy>> = - Lazy::new(|| RwLock::new(Box::new(NoopTextMapPropagator::new()))); +static GLOBAL_TEXT_MAP_PROPAGATOR: OnceLock>> = + OnceLock::new(); /// The global default `TextMapPropagator` propagator. -static DEFAULT_TEXT_MAP_PROPAGATOR: Lazy = - Lazy::new(NoopTextMapPropagator::new); +static DEFAULT_TEXT_MAP_PROPAGATOR: OnceLock = OnceLock::new(); + +/// Ensures the `GLOBAL_TEXT_MAP_PROPAGATOR` is initialized with a `NoopTextMapPropagator`. +#[inline] +fn global_text_map_propagator() -> &'static RwLock> { + GLOBAL_TEXT_MAP_PROPAGATOR.get_or_init(|| RwLock::new(Box::new(NoopTextMapPropagator::new()))) +} + +/// Ensures the `DEFAULT_TEXT_MAP_PROPAGATOR` is initialized. +#[inline] +fn default_text_map_propagator() -> &'static NoopTextMapPropagator { + DEFAULT_TEXT_MAP_PROPAGATOR.get_or_init(NoopTextMapPropagator::new) +} /// Sets the given [`TextMapPropagator`] propagator as the current global propagator. pub fn set_text_map_propagator(propagator: P) { - let _lock = GLOBAL_TEXT_MAP_PROPAGATOR + let _lock = global_text_map_propagator() .write() .map(|mut global_propagator| *global_propagator = Box::new(propagator)); } @@ -23,8 +33,11 @@ pub fn get_text_map_propagator(mut f: F) -> T where F: FnMut(&dyn TextMapPropagator) -> T, { - GLOBAL_TEXT_MAP_PROPAGATOR + global_text_map_propagator() .read() .map(|propagator| f(&**propagator)) - .unwrap_or_else(|_| f(&*DEFAULT_TEXT_MAP_PROPAGATOR as &dyn TextMapPropagator)) + .unwrap_or_else(|_| { + let default_propagator = default_text_map_propagator(); + f(default_propagator as &dyn TextMapPropagator) + }) } diff --git a/opentelemetry/src/global/trace.rs b/opentelemetry/src/global/trace.rs index bb9100bd15..68e7813a05 100644 --- a/opentelemetry/src/global/trace.rs +++ b/opentelemetry/src/global/trace.rs @@ -1,11 +1,10 @@ use crate::trace::{noop::NoopTracerProvider, SpanContext, Status}; use crate::InstrumentationScope; use crate::{trace, trace::TracerProvider, Context, KeyValue}; -use once_cell::sync::Lazy; use std::borrow::Cow; use std::fmt; use std::mem; -use std::sync::{Arc, RwLock}; +use std::sync::{Arc, OnceLock, RwLock}; use std::time::SystemTime; /// Allows a specific [`crate::trace::Span`] to be used generically by [`BoxedSpan`] @@ -360,11 +359,13 @@ impl trace::TracerProvider for GlobalTracerProvider { } /// The global `Tracer` provider singleton. -static GLOBAL_TRACER_PROVIDER: Lazy> = Lazy::new(|| { - RwLock::new(GlobalTracerProvider::new( - trace::noop::NoopTracerProvider::new(), - )) -}); +static GLOBAL_TRACER_PROVIDER: OnceLock> = OnceLock::new(); + +#[inline] +fn global_tracer_provider() -> &'static RwLock { + GLOBAL_TRACER_PROVIDER + .get_or_init(|| RwLock::new(GlobalTracerProvider::new(NoopTracerProvider::new()))) +} /// Returns an instance of the currently configured global [`TracerProvider`] through /// [`GlobalTracerProvider`]. @@ -372,7 +373,7 @@ static GLOBAL_TRACER_PROVIDER: Lazy> = Lazy::new(|| /// [`TracerProvider`]: crate::trace::TracerProvider /// [`GlobalTracerProvider`]: crate::global::GlobalTracerProvider pub fn tracer_provider() -> GlobalTracerProvider { - GLOBAL_TRACER_PROVIDER + global_tracer_provider() .read() .expect("GLOBAL_TRACER_PROVIDER RwLock poisoned") .clone() @@ -428,7 +429,7 @@ where T: trace::Tracer + Send + Sync + 'static, P: trace::TracerProvider + Send + Sync + 'static, { - let mut tracer_provider = GLOBAL_TRACER_PROVIDER + let mut tracer_provider = global_tracer_provider() .write() .expect("GLOBAL_TRACER_PROVIDER RwLock poisoned"); mem::replace( @@ -440,7 +441,7 @@ where /// Shut down the current tracer provider. This will invoke the shutdown method on all span processors. /// span processors should export remaining spans before return pub fn shutdown_tracer_provider() { - let mut tracer_provider = GLOBAL_TRACER_PROVIDER + let mut tracer_provider = global_tracer_provider() .write() .expect("GLOBAL_TRACER_PROVIDER RwLock poisoned"); diff --git a/scripts/patch_dependencies.sh b/scripts/patch_dependencies.sh index 1bd1f05ceb..7f3e4d9af1 100755 --- a/scripts/patch_dependencies.sh +++ b/scripts/patch_dependencies.sh @@ -7,3 +7,5 @@ function patch_version() { } patch_version url 2.5.2 #https://github.com/servo/rust-url/issues/992 +patch_version rustls-native-certs 0.8.0 #0.8.1 needs rustc 1.71 or newer +patch_version rustls 0.23.17 #0.23.18 needs rustc 1.71 or newer