#![expect(clippy::unwrap_used, reason = "This file needs a bit more cleanup.")]
use std::{ptr, sync::atomic::Ordering};
use tracing_core::{
Event,
LevelFilter,
Metadata,
span,
subscriber::{Interest, Subscriber},
};
use tracing_subscriber::{layer, registry::LookupSpan};
use crate::{Layer, ReloadRouting, subscriber::ReloadSubscriber};
impl<L, S> tracing_subscriber::Layer<S> for Layer<L, S>
where
S: Subscriber + for<'lookup> LookupSpan<'lookup>,
L: tracing_subscriber::Layer<ReloadSubscriber<S>>,
{
fn on_layer(&mut self, subscriber: &mut S) {
let mut filters = try_lock!(self.inner.filters.lock());
filters.backup = subscriber.register_filter();
for _ in 1..crate::MAX_FILTER_COUNT.get() {
filters.free.push(subscriber.register_filter());
}
let inner_subscriber = unsafe { std::mem::transmute::<&'_ S, &'static S>(&*subscriber) };
let mut fake_subscriber = ReloadSubscriber::new(inner_subscriber, filters.clone());
unsafe {
#[expect(clippy::unwrap_used, reason = "There is always at least one layer.")]
try_lock!(self.inner.layers.write())
.last_mut()
.unwrap()
.as_mut()
.get_unchecked_mut()
.on_layer(&mut fake_subscriber);
}
}
fn on_register_dispatch(&self, subscriber: &tracing_core::Dispatch) {
#[expect(
clippy::expect_used,
reason = "Panicking here might prevent worse bugs. This should only be called during \
startup."
)]
self.inner
.dispatch
.set(subscriber.downgrade())
.expect("on_register_dispatch should be called only once");
<L as layer::Layer<ReloadSubscriber<S>>>::on_register_dispatch(
#[expect(clippy::unwrap_used, reason = "There is always at least one layer.")]
try_lock!(self.inner.layers.read()).last().unwrap(),
subscriber,
);
}
#[inline]
fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
<L as layer::Layer<ReloadSubscriber<S>>>::register_callsite(
#[expect(clippy::unwrap_used, reason = "There is always at least one layer.")]
try_lock!(self.inner.layers.read(), else return Interest::sometimes())
.last()
.unwrap(),
metadata,
)
}
#[inline]
fn enabled(&self, metadata: &Metadata<'_>, _ctx: layer::Context<'_, S>) -> bool {
#[expect(
clippy::expect_used,
reason = "TODO when can this happen and is sentinel return value better than \
panicking."
)]
self.with_ctx(move |ctx| {
#[expect(clippy::unwrap_used, reason = "There is always at least one layer.")]
try_lock!(self.inner.layers.read(), else return false)
.last()
.unwrap()
.enabled(metadata, ctx)
})
.expect("could not get value for enabled")
}
#[inline]
fn event_enabled(&self, event: &Event<'_>, _ctx: layer::Context<'_, S>) -> bool {
#[expect(
clippy::expect_used,
reason = "TODO when can this happen and is sentinel return value better than \
panicking."
)]
self.with_ctx(move |ctx| {
#[expect(clippy::unwrap_used, reason = "There is always at least one layer.")]
try_lock!(self.inner.layers.read(), else return false)
.last()
.unwrap()
.event_enabled(event, ctx)
})
.expect("could not get value for event_enabled")
}
#[inline]
fn max_level_hint(&self) -> Option<LevelFilter> {
<L as layer::Layer<ReloadSubscriber<S>>>::max_level_hint(
#[expect(clippy::unwrap_used, reason = "There is always at least one layer.")]
try_lock!(self.inner.layers.read(), else return None)
.last()
.unwrap(),
)
}
#[inline]
fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: layer::Context<'_, S>) {
let index = {
let layers = try_lock!(self.inner.layers.read());
let index = match self.span_routing {
ReloadRouting::NewSpanToLatestLayer => layers.len() - 1,
ReloadRouting::NewSpanToParentLayer => {
let parent_id = attrs.parent().cloned().or_else(|| {
attrs
.is_contextual()
.then_some(ctx.current_span().id().cloned())
.flatten()
});
parent_id
.and_then(|parent_id| {
let span_map = try_lock!(self.inner.span_map.read(), else return None);
span_map.get(&parent_id).copied()
})
.unwrap_or(layers.len() - 1)
},
};
self.with_ctx(move |ctx| {
layers.get(index).unwrap().on_new_span(attrs, id, ctx);
})
.unwrap();
index
};
let mut span_map = try_lock!(self.inner.span_map.write());
span_map.insert(id.clone(), index);
}
#[inline]
fn on_record(&self, span: &span::Id, values: &span::Record<'_>, _ctx: layer::Context<'_, S>) {
self.with_span(span, |layer| {
self.with_ctx(move |ctx| layer.on_record(span, values, ctx))
});
}
#[inline]
fn on_follows_from(&self, span: &span::Id, follows: &span::Id, _ctx: layer::Context<'_, S>) {
let idx = {
let span_map = try_lock!(self.inner.span_map.read());
span_map.get(span).copied()
};
if let Some(idx) = idx {
let current = try_lock!(self.inner.layers.read());
if let Some(layer) = current.get(idx) {
self.with_ctx(move |ctx| {
layer.on_follows_from(span, follows, ctx);
});
}
}
}
#[inline]
fn on_event(&self, event: &Event<'_>, ctx: layer::Context<'_, S>) {
let span_id = event
.parent()
.cloned()
.or_else(|| ctx.current_span().id().cloned());
if let Some(span_id) = span_id {
self.with_span(&span_id, |layer| {
self.with_ctx(move |ctx| layer.on_event(event, ctx))
});
} else {
self.with_ctx(move |ctx| {
#[expect(clippy::unwrap_used, reason = "There is always at least one layer.")]
try_lock!(self.inner.layers.read())
.last()
.unwrap()
.on_event(event, ctx);
});
}
}
#[inline]
fn on_enter(&self, id: &span::Id, _ctx: layer::Context<'_, S>) {
self.with_span(id, |layer| {
self.with_ctx(move |ctx| layer.on_enter(id, ctx))
});
}
#[inline]
fn on_exit(&self, id: &span::Id, _ctx: layer::Context<'_, S>) {
self.with_span(id, |layer| self.with_ctx(move |ctx| layer.on_exit(id, ctx)));
}
#[inline]
fn on_close(&self, id: span::Id, _ctx: layer::Context<'_, S>) {
let index = {
let mut span_map = try_lock!(self.inner.span_map.write());
span_map.remove(&id).unwrap()
};
self.with_ctx(move |ctx| {
try_lock!(self.inner.layers.read())
.get(index)
.unwrap()
.on_close(id, ctx);
});
}
#[inline]
fn on_id_change(&self, old: &span::Id, new: &span::Id, _ctx: layer::Context<'_, S>) {
let index = {
let mut span_map = try_lock!(self.inner.span_map.write());
let index = span_map.remove(old).unwrap();
span_map.insert(new.clone(), index);
index
};
self.with_ctx(move |ctx| {
try_lock!(self.inner.layers.read())
.get(index)
.unwrap()
.on_id_change(old, new, ctx);
});
}
#[doc(hidden)]
unsafe fn downcast_raw(&self, id: core::any::TypeId) -> Option<*const ()> {
if id == core::any::TypeId::of::<Self>() {
return Some(ptr::from_ref(self).cast::<()>());
}
if id == core::any::TypeId::of::<ReloadSubscriber<S>>() {
let dispatch = self.inner.dispatch.get()?.upgrade()?;
if !self.inner.dispatch_leaked.swap(true, Ordering::Relaxed) {
std::mem::forget(dispatch.clone());
}
let subscriber = dispatch.downcast_ref::<S>()?;
let static_subscriber = unsafe { std::mem::transmute::<&'_ S, &'static S>(subscriber) };
return Some(
try_lock!(self.subscriber_cache.lock(), else return None)
.get(id, static_subscriber),
);
}
let current = try_lock!(self.inner.layers.read(), else return None);
current.last().and_then(|layer| unsafe {
<L as layer::Layer<ReloadSubscriber<S>>>::downcast_raw(layer, id)
})
}
}