diff --git a/tracing-core/src/dispatcher.rs b/tracing-core/src/dispatcher.rs index a52ea8fae8..ab4a3605c0 100644 --- a/tracing-core/src/dispatcher.rs +++ b/tracing-core/src/dispatcher.rs @@ -504,6 +504,12 @@ impl Dispatch { self.subscriber.enabled(metadata) } + #[inline] + #[doc(hidden)] + pub fn fully_enabled(&self, metadata: &Metadata<'_>) -> bool { + self.subscriber.fully_enabled(metadata) + } + /// Records that an [`Event`] has occurred. /// /// This calls the [`event`] function on the [`Subscriber`] that this diff --git a/tracing-core/src/subscriber.rs b/tracing-core/src/subscriber.rs index 11695e5382..f55f26d09f 100644 --- a/tracing-core/src/subscriber.rs +++ b/tracing-core/src/subscriber.rs @@ -171,6 +171,11 @@ pub trait Subscriber: 'static { /// [`register_callsite`]: #method.register_callsite fn enabled(&self, metadata: &Metadata<'_>) -> bool; + #[doc(hidden)] + fn fully_enabled(&self, metadata: &Metadata<'_>) -> bool { + self.enabled(metadata) + } + /// Returns the highest [verbosity level][level] that this `Subscriber` will /// enable, or `None`, if the subscriber does not implement level-based /// filtering or chooses not to implement this method. @@ -606,6 +611,11 @@ impl Subscriber for Box { self.as_ref().enabled(metadata) } + #[inline] + fn fully_enabled(&self, metadata: &Metadata<'_>) -> bool { + self.as_ref().fully_enabled(metadata) + } + #[inline] fn max_level_hint(&self) -> Option { self.as_ref().max_level_hint() @@ -683,6 +693,11 @@ impl Subscriber for Arc { self.as_ref().enabled(metadata) } + #[inline] + fn fully_enabled(&self, metadata: &Metadata<'_>) -> bool { + self.as_ref().fully_enabled(metadata) + } + #[inline] fn max_level_hint(&self) -> Option { self.as_ref().max_level_hint() diff --git a/tracing-subscriber/src/filter/layer_filters/mod.rs b/tracing-subscriber/src/filter/layer_filters/mod.rs index d391d31b22..86c4016131 100644 --- a/tracing-subscriber/src/filter/layer_filters/mod.rs +++ b/tracing-subscriber/src/filter/layer_filters/mod.rs @@ -543,6 +543,22 @@ where } } + fn fully_enabled(&self, metadata: &Metadata<'_>, cx: Context<'_, S>) -> bool { + let cx = cx.with_filter(self.id()); + let enabled = self.filter.enabled(metadata, &cx); + FILTERING.with(|filtering| filtering.set(self.id(), enabled)); + + println!("GUS: {}", enabled); + if enabled { + // If the filter enabled this metadata, ask the wrapped layer if + // _it_ wants it --- it might have a global filter. + self.layer.fully_enabled(metadata, cx) + } else { + // ORDERED + false + } + } + fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, cx: Context<'_, S>) { self.did_enable(|| { self.layer.on_new_span(attrs, id, cx.with_filter(self.id())); diff --git a/tracing-subscriber/src/layer/layered.rs b/tracing-subscriber/src/layer/layered.rs index c690764add..ba07ac32cf 100644 --- a/tracing-subscriber/src/layer/layered.rs +++ b/tracing-subscriber/src/layer/layered.rs @@ -91,6 +91,25 @@ where } } + #[doc(hidden)] + fn fully_enabled(&self, metadata: &Metadata<'_>) -> bool { + println!("Layered::Subscriber::fully_enabled"); + if self.layer.fully_enabled(metadata, self.ctx()) { + // if the outer layer enables the callsite metadata, ask the subscriber. + self.inner.fully_enabled(metadata) + } else { + // otherwise, the callsite is disabled by the layer + + // If per-layer filters are in use, and we are short-circuiting + // (rather than calling into the inner type), clear the current + // per-layer filter `enabled` state. + #[cfg(feature = "registry")] + filter::FilterState::clear_enabled(); + + false + } + } + fn max_level_hint(&self) -> Option { self.pick_level_hint(self.layer.max_level_hint(), self.inner.max_level_hint()) } @@ -228,6 +247,18 @@ where } } + #[doc(hidden)] + fn fully_enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool { + println!("Layered::Layer::fully_enabled"); + if self.layer.fully_enabled(metadata, ctx.clone()) { + // if the outer subscriber enables the callsite metadata, ask the inner layer. + self.inner.fully_enabled(metadata, ctx) + } else { + // otherwise, the callsite is disabled by this layer + false + } + } + fn max_level_hint(&self) -> Option { self.pick_level_hint(self.layer.max_level_hint(), self.inner.max_level_hint()) } diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index d041d7f78c..c477fec298 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -648,6 +648,11 @@ where true } + #[doc(hidden)] + fn fully_enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool { + self.enabled(metadata, ctx) + } + /// Notifies this layer that a new span was constructed with the given /// `Attributes` and `Id`. fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) { diff --git a/tracing-subscriber/tests/layer_filters/combinators.rs b/tracing-subscriber/tests/layer_filters/combinators.rs index 6052a2d00c..5921d71cbb 100644 --- a/tracing-subscriber/tests/layer_filters/combinators.rs +++ b/tracing-subscriber/tests/layer_filters/combinators.rs @@ -1,6 +1,6 @@ use super::*; use tracing_subscriber::{ - filter::{filter_fn, FilterExt, LevelFilter}, + filter::{FilterExt, LevelFilter}, prelude::*, }; diff --git a/tracing-subscriber/tests/layer_filters/main.rs b/tracing-subscriber/tests/layer_filters/main.rs index 2359584d72..c79fb9dacf 100644 --- a/tracing-subscriber/tests/layer_filters/main.rs +++ b/tracing-subscriber/tests/layer_filters/main.rs @@ -3,8 +3,10 @@ mod support; use self::support::*; mod boxed; +mod combinators; mod downcast_raw; mod filter_scopes; +mod fully_enabled; mod targets; mod trees; diff --git a/tracing/src/macros.rs b/tracing/src/macros.rs index 55fc881e8b..67e8c26c82 100644 --- a/tracing/src/macros.rs +++ b/tracing/src/macros.rs @@ -868,32 +868,9 @@ macro_rules! event { /// #[macro_export] macro_rules! enabled { - (target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ({ - if $crate::level_enabled!($lvl) { - use $crate::__macro_support::Callsite as _; - static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { - name: concat!( - "enabled ", - file!(), - ":", - line!() - ), - kind: $crate::metadata::Kind::HINT, - target: $target, - level: $lvl, - fields: $($fields)* - }; - let interest = CALLSITE.interest(); - if !interest.is_never() && CALLSITE.is_enabled(interest) { - let meta = CALLSITE.metadata(); - $crate::dispatcher::get_default(|current| current.enabled(meta)) - } else { - false - } - } else { - false - } - }); + (target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ( + $crate::_enabled!(enabled, target: $target, $lvl, { $($fields:tt)* } ) + ); // Just target and level (target: $target:expr, $lvl:expr ) => ( $crate::enabled!(target: $target, $lvl, { }) @@ -921,6 +898,71 @@ macro_rules! enabled { ); } +/// TODO +#[macro_export] +macro_rules! fully_enabled { + (target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ( + $crate::_enabled!(fully_enabled, target: $target, $lvl, { $($fields:tt)* } ) + ); + // Just target and level + (target: $target:expr, $lvl:expr ) => ( + $crate::fully_enabled!(target: $target, $lvl, { }) + ); + + // These two cases handle fields with no values + (target: $target:expr, $lvl:expr, $($field:tt)*) => ( + $crate::fully_enabled!( + target: $target, + $lvl, + { $($field)*} + ) + ); + ($lvl:expr, $($field:tt)*) => ( + $crate::fully_enabled!( + target: module_path!(), + $lvl, + { $($field)*} + ) + ); + + // Simplest `enabled!` case + ( $lvl:expr ) => ( + $crate::fully_enabled!(target: module_path!(), $lvl, { }) + ); +} + +/// TODO +#[doc(hidden)] +#[macro_export] +macro_rules! _enabled { + ($style:tt, target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ({ + if $crate::level_enabled!($lvl) { + use $crate::__macro_support::Callsite as _; + static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { + name: concat!( + "enabled ", + file!(), + ":", + line!() + ), + kind: $crate::metadata::Kind::HINT, + target: $target, + level: $lvl, + fields: $($fields)* + }; + let interest = CALLSITE.interest(); + if !interest.is_never() && CALLSITE.is_enabled(interest) { + let meta = CALLSITE.metadata(); + $crate::dispatcher::get_default(|current| current.$style(meta)) + } else { + false + } + } else { + false + } + }); +} + /// Constructs an event at the trace level. /// /// This functions similarly to the [`event!`] macro. See [the top-level