Description
Version
tracing 0.1.41
tracing-subscriber 0.3.19
Platform
I'm pretty sure all of them, but definitely verified on Linux 6.12.9-arch1-1
Description
Using with_subscriber will trigger a panic if the async block creates a span & enters it on a different thread that will target the default subscriber. I believe both the with_subscriber AND the enter off-thread scenario are idiomatic. The reason for the crash is that the span.enter() try's recording the span exit into the default subscriber which isn't aware of it since it's registered by the scoped subscriber.
I encountered this with hyper which in GaiResolver has a block like:
fn call(&mut self, name: Name) -> Self::Future {
let span = debug_span!("resolve", host = %name.host);
let blocking = tokio::task::spawn_blocking(move || {
let _enter = span.enter();
(&*name.host, 0)
.to_socket_addrs()
.map(|i| SocketAddrs { iter: i })
});
GaiFuture { inner: blocking }
}
This pattern seems pretty idiomatic: https://docs.rs/tracing/0.1.41/tracing/struct.Span.html#method.or_current
A simple repro on Linux (which uses GaiResolver) is:
#[tokio::main]
async fn main() {
tracing_subscriber::registry()
.with(tracing_subscriber::fmt::layer())
.init();
let override_default_registry =
tracing_subscriber::Registry::default().with(tracing_subscriber::fmt::layer());
async move {
tracing::info!("Starting request");
reqwest::Client::new()
.post("http://localhost:8787/ping")
.body("")
.send()
.await
.expect("HTTP request failed");
tracing::info!("Finished request");
}
.with_subscriber(override_default_registry)
.await;
}
Tried filing upstream but the author there confirmed it's likely an issue in this crate: hyperium/hyper#3848 (comment)
Either with_subscriber
has a fatal flaw or the idiomatic pattern needs to be clarified on how to actually make it safe for the above snippet.