diff --git a/Cargo.toml b/Cargo.toml index adcf0b6..2d8a081 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ serde_json = "^1.0" # dates chrono = {version = "^0.4", default-features = false, features = ["serde", "clock"]} url = "2.5.0" +once_cell = "1.19.0" [dev-dependencies] actix-web = "4.0.1" diff --git a/src/subscriber.rs b/src/subscriber.rs index 867d685..5de70a0 100644 --- a/src/subscriber.rs +++ b/src/subscriber.rs @@ -84,7 +84,7 @@ pub struct Uninstall; impl Drop for Uninstall { fn drop(&mut self) { #[cfg(feature = "traces")] - opentelemetry::global::shutdown_tracer_provider(); + crate::telemetry::shutdown_tracer_provider(); } } /// Information about the current app context like name or environment diff --git a/src/telemetry.rs b/src/telemetry.rs index f280858..85bdc63 100644 --- a/src/telemetry.rs +++ b/src/telemetry.rs @@ -1,3 +1,4 @@ +use once_cell::sync::Lazy; use opentelemetry::global; use opentelemetry::trace::TracerProvider; use opentelemetry::KeyValue; @@ -6,6 +7,8 @@ use opentelemetry_sdk::{ trace::{self, Tracer}, Resource, }; +use std::mem; +use std::sync::Mutex; use crate::SubscriberConfig; @@ -64,7 +67,7 @@ pub fn configure(config: &SubscriberConfig) -> Tracer { .install_batch(runtime) .expect("Failed to configure the OpenTelemetry tracer provider"); - global::set_tracer_provider(tracer_provider.clone()); + set_tracer_provider(tracer_provider.clone()); tracer_provider .tracer_builder("prima-tracing") @@ -72,6 +75,32 @@ pub fn configure(config: &SubscriberConfig) -> Tracer { .build() } +static TRACER_PROVIDER: Lazy>> = + Lazy::new(Default::default); + +fn set_tracer_provider(new_provider: trace::TracerProvider) { + global::set_tracer_provider(new_provider.clone()); + + let mut tracer_provider = TRACER_PROVIDER + .lock() + .expect("OpenTelemetry tracer provider mutex poisoned"); + _ = mem::replace(&mut *tracer_provider, Some(new_provider)); +} + +pub(crate) fn shutdown_tracer_provider() { + global::shutdown_tracer_provider(); + + let tracer_provider = TRACER_PROVIDER + .lock() + .expect("OpenTelemetry tracer provider mutex poisoned") + .take() + .expect("OpenTelemetry tracer provider is missing, cannot shutdown"); + + if let Err(err) = tracer_provider.shutdown() { + eprintln!("Failed to shutdown the OpenTelemetry tracer provider: {err:?}"); + } +} + #[cfg(test)] mod test { use super::*;