mirror of
https://github.com/tokio-rs/tracing.git
synced 2025-10-01 15:00:33 +00:00
subscriber: forward Filtered::downcast_raw
to wrapped Layer (#1619)
## Motivation I'm trying to implement a `Layer` that has something very similar to tracing-error's [`WithContext`](66cd79f72a/tracing-error/src/layer.rs (L32)
) to support erasing types and getting access to the current span's state. To do that, I implement `Layer::downcast_raw` in [the same way that tracing-error does](66cd79f72a/tracing-error/src/layer.rs (L55-L63)
). This works great when the layer is not filtered. However, once I filter the layer ```rust let filter = tracing_subscriber::filter::Targets::new().with_default(tracing::Level::INFO); let layer = MyLayer::new(); tracing_subscriber::registry().with(layer.with_filter(filter)).init(); ``` I'm not able to get a `WithContext` instance anymore, because `Filtered` [handles `downcast_raw`, and doesn't forward it](66cd79f72a/tracing-subscriber/src/filter/layer_filters.rs (L379-L391)
) to `MyLayer::downcast_raw`. ## Solution If `Filtered::downcast_raw` does not know how to handle the given type, forward it to the wrapped layer's `Layer::downcast_raw` implementation. Fixes #1618
This commit is contained in:
parent
645f282eee
commit
29ffdbc2b2
@ -386,7 +386,7 @@ where
|
||||
id if id == TypeId::of::<MagicPlfDowncastMarker>() => {
|
||||
Some(&self.id as *const _ as *const ())
|
||||
}
|
||||
_ => None,
|
||||
_ => self.layer.downcast_raw(id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
68
tracing-subscriber/tests/layer_filters/downcast_raw.rs
Normal file
68
tracing-subscriber/tests/layer_filters/downcast_raw.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use tracing::Subscriber;
|
||||
use tracing_subscriber::filter::Targets;
|
||||
use tracing_subscriber::prelude::*;
|
||||
use tracing_subscriber::Layer;
|
||||
|
||||
#[test]
|
||||
fn downcast_ref_to_inner_layer_and_filter() {
|
||||
// Test that a filtered layer gives downcast_ref access to
|
||||
// both the layer and the filter.
|
||||
|
||||
struct WrappedLayer;
|
||||
|
||||
impl<S> Layer<S> for WrappedLayer
|
||||
where
|
||||
S: Subscriber,
|
||||
S: for<'lookup> tracing_subscriber::registry::LookupSpan<'lookup>,
|
||||
{
|
||||
}
|
||||
|
||||
let layer = WrappedLayer;
|
||||
let filter = Targets::new().with_default(tracing::Level::INFO);
|
||||
let registry = tracing_subscriber::registry().with(layer.with_filter(filter));
|
||||
let dispatch = tracing::dispatcher::Dispatch::new(registry);
|
||||
|
||||
// The filter is available
|
||||
assert!(dispatch.downcast_ref::<Targets>().is_some());
|
||||
// The wrapped layer is available
|
||||
assert!(dispatch.downcast_ref::<WrappedLayer>().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn forward_downcast_raw_to_layer() {
|
||||
// Test that a filtered layer still gives its wrapped layer a chance to
|
||||
// return a custom struct from downcast_raw.
|
||||
// https://github.com/tokio-rs/tracing/issues/1618
|
||||
|
||||
struct WrappedLayer {
|
||||
with_context: WithContext,
|
||||
}
|
||||
|
||||
struct WithContext;
|
||||
|
||||
impl<S> Layer<S> for WrappedLayer
|
||||
where
|
||||
S: Subscriber,
|
||||
S: for<'lookup> tracing_subscriber::registry::LookupSpan<'lookup>,
|
||||
{
|
||||
unsafe fn downcast_raw(&self, id: std::any::TypeId) -> Option<*const ()> {
|
||||
match id {
|
||||
id if id == std::any::TypeId::of::<Self>() => Some(self as *const _ as *const ()),
|
||||
id if id == std::any::TypeId::of::<WithContext>() => {
|
||||
Some(&self.with_context as *const _ as *const ())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let layer = WrappedLayer {
|
||||
with_context: WithContext,
|
||||
};
|
||||
let filter = Targets::new().with_default(tracing::Level::INFO);
|
||||
let registry = tracing_subscriber::registry().with(layer.with_filter(filter));
|
||||
let dispatch = tracing::dispatcher::Dispatch::new(registry);
|
||||
|
||||
// Types from a custom implementation of `downcast_raw` are available
|
||||
assert!(dispatch.downcast_ref::<WithContext>().is_some());
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
mod support;
|
||||
use self::support::*;
|
||||
mod boxed;
|
||||
mod downcast_raw;
|
||||
mod filter_scopes;
|
||||
mod targets;
|
||||
mod trees;
|
||||
|
Loading…
x
Reference in New Issue
Block a user