diff --git a/src/layer.rs b/src/layer.rs index acf423b..d9570af 100644 --- a/src/layer.rs +++ b/src/layer.rs @@ -13,6 +13,7 @@ use std::time::Instant; use std::{any::TypeId, borrow::Cow}; use std::{fmt, vec}; use std::{marker, mem::take}; +use tracing::Dispatch; use tracing_core::span::{self, Attributes, Id, Record}; use tracing_core::{field, Event, Subscriber}; #[cfg(feature = "tracing-log")] @@ -1079,10 +1080,16 @@ where status, } = take(&mut otel_data.state) { - let mut span = builder.start_with_context(&self.tracer, &parent_cx); - span.set_status(status); - let current_cx = parent_cx.with_span(span); - otel_data.state = OtelDataState::Context { current_cx }; + // We purposefully disable all tracing inside this call. Whoever called this is most + // likely holding `ExtensionsMut` so if anything inside any of the opentelemetry + // functions tries to log anything and any layer (including this one) tries to get the + // extensions again, we get a deadlock. + tracing::dispatcher::with_default(&Dispatch::none(), || { + let mut span = builder.start_with_context(&self.tracer, &parent_cx); + span.set_status(status); + let current_cx = parent_cx.with_span(span); + otel_data.state = OtelDataState::Context { current_cx }; + }); } } @@ -1477,7 +1484,9 @@ where parent_cx, status, } => { - // Don't create the context here just to get a SpanRef since it's costly + // We're not holding the extensions lock here so it's fine to just call to + // opentelemetry and let it log whatever it wants. If we had a lock, we'd have + // to set the default `Dispatch` to none to prevent deadlocks. let mut span = builder.start_with_context(&self.tracer, &parent_cx); if let Some(timings) = timings { span.set_attributes(timings)