summaryrefslogtreecommitdiffstats
path: root/vendor/tracing-subscriber/src/filter/layer_filters/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--vendor/tracing-subscriber/src/filter/layer_filters/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs)454
1 files changed, 422 insertions, 32 deletions
diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs b/vendor/tracing-subscriber/src/filter/layer_filters/mod.rs
index e77fd3751..e50ee6f00 100644
--- a/vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs
+++ b/vendor/tracing-subscriber/src/filter/layer_filters/mod.rs
@@ -37,14 +37,16 @@ use std::{
cell::{Cell, RefCell},
fmt,
marker::PhantomData,
+ ops::Deref,
sync::Arc,
thread_local,
};
use tracing_core::{
span,
subscriber::{Interest, Subscriber},
- Event, Metadata,
+ Dispatch, Event, Metadata,
};
+pub mod combinator;
/// A [`Layer`] that wraps an inner [`Layer`] and adds a [`Filter`] which
/// controls what spans and events are enabled for that layer.
@@ -158,7 +160,288 @@ thread_local! {
pub(crate) static FILTERING: FilterState = FilterState::new();
}
+/// Extension trait adding [combinators] for combining [`Filter`].
+///
+/// [combinators]: crate::filter::combinator
+/// [`Filter`]: crate::layer::Filter
+pub trait FilterExt<S>: layer::Filter<S> {
+ /// Combines this [`Filter`] with another [`Filter`] s so that spans and
+ /// events are enabled if and only if *both* filters return `true`.
+ ///
+ /// # Examples
+ ///
+ /// Enabling spans or events if they have both a particular target *and* are
+ /// above a certain level:
+ ///
+ /// ```
+ /// use tracing_subscriber::{
+ /// filter::{filter_fn, LevelFilter, FilterExt},
+ /// prelude::*,
+ /// };
+ ///
+ /// // Enables spans and events with targets starting with `interesting_target`:
+ /// let target_filter = filter_fn(|meta| {
+ /// meta.target().starts_with("interesting_target")
+ /// });
+ ///
+ /// // Enables spans and events with levels `INFO` and below:
+ /// let level_filter = LevelFilter::INFO;
+ ///
+ /// // Combine the two filters together, returning a filter that only enables
+ /// // spans and events that *both* filters will enable:
+ /// let filter = target_filter.and(level_filter);
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(tracing_subscriber::fmt::layer().with_filter(filter))
+ /// .init();
+ ///
+ /// // This event will *not* be enabled:
+ /// tracing::info!("an event with an uninteresting target");
+ ///
+ /// // This event *will* be enabled:
+ /// tracing::info!(target: "interesting_target", "a very interesting event");
+ ///
+ /// // This event will *not* be enabled:
+ /// tracing::debug!(target: "interesting_target", "interesting debug event...");
+ /// ```
+ ///
+ /// [`Filter`]: crate::layer::Filter
+ fn and<B>(self, other: B) -> combinator::And<Self, B, S>
+ where
+ Self: Sized,
+ B: layer::Filter<S>,
+ {
+ combinator::And::new(self, other)
+ }
+
+ /// Combines two [`Filter`]s so that spans and events are enabled if *either* filter
+ /// returns `true`.
+ ///
+ /// # Examples
+ ///
+ /// Enabling spans and events at the `INFO` level and above, and all spans
+ /// and events with a particular target:
+ /// ```
+ /// use tracing_subscriber::{
+ /// filter::{filter_fn, LevelFilter, FilterExt},
+ /// prelude::*,
+ /// };
+ ///
+ /// // Enables spans and events with targets starting with `interesting_target`:
+ /// let target_filter = filter_fn(|meta| {
+ /// meta.target().starts_with("interesting_target")
+ /// });
+ ///
+ /// // Enables spans and events with levels `INFO` and below:
+ /// let level_filter = LevelFilter::INFO;
+ ///
+ /// // Combine the two filters together so that a span or event is enabled
+ /// // if it is at INFO or lower, or if it has a target starting with
+ /// // `interesting_target`.
+ /// let filter = level_filter.or(target_filter);
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(tracing_subscriber::fmt::layer().with_filter(filter))
+ /// .init();
+ ///
+ /// // This event will *not* be enabled:
+ /// tracing::debug!("an uninteresting event");
+ ///
+ /// // This event *will* be enabled:
+ /// tracing::info!("an uninteresting INFO event");
+ ///
+ /// // This event *will* be enabled:
+ /// tracing::info!(target: "interesting_target", "a very interesting event");
+ ///
+ /// // This event *will* be enabled:
+ /// tracing::debug!(target: "interesting_target", "interesting debug event...");
+ /// ```
+ ///
+ /// Enabling a higher level for a particular target by using `or` in
+ /// conjunction with the [`and`] combinator:
+ ///
+ /// ```
+ /// use tracing_subscriber::{
+ /// filter::{filter_fn, LevelFilter, FilterExt},
+ /// prelude::*,
+ /// };
+ ///
+ /// // This filter will enable spans and events with targets beginning with
+ /// // `my_crate`:
+ /// let my_crate = filter_fn(|meta| {
+ /// meta.target().starts_with("my_crate")
+ /// });
+ ///
+ /// let filter = my_crate
+ /// // Combine the `my_crate` filter with a `LevelFilter` to produce a
+ /// // filter that will enable the `INFO` level and lower for spans and
+ /// // events with `my_crate` targets:
+ /// .and(LevelFilter::INFO)
+ /// // If a span or event *doesn't* have a target beginning with
+ /// // `my_crate`, enable it if it has the `WARN` level or lower:
+ /// .or(LevelFilter::WARN);
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(tracing_subscriber::fmt::layer().with_filter(filter))
+ /// .init();
+ /// ```
+ ///
+ /// [`Filter`]: crate::layer::Filter
+ /// [`and`]: FilterExt::and
+ fn or<B>(self, other: B) -> combinator::Or<Self, B, S>
+ where
+ Self: Sized,
+ B: layer::Filter<S>,
+ {
+ combinator::Or::new(self, other)
+ }
+
+ /// Inverts `self`, returning a filter that enables spans and events only if
+ /// `self` would *not* enable them.
+ ///
+ /// This inverts the values returned by the [`enabled`] and [`callsite_enabled`]
+ /// methods on the wrapped filter; it does *not* invert [`event_enabled`], as
+ /// filters which do not implement filtering on event field values will return
+ /// the default `true` even for events that their [`enabled`] method disables.
+ ///
+ /// Consider a normal filter defined as:
+ ///
+ /// ```ignore (pseudo-code)
+ /// // for spans
+ /// match callsite_enabled() {
+ /// ALWAYS => on_span(),
+ /// SOMETIMES => if enabled() { on_span() },
+ /// NEVER => (),
+ /// }
+ /// // for events
+ /// match callsite_enabled() {
+ /// ALWAYS => on_event(),
+ /// SOMETIMES => if enabled() && event_enabled() { on_event() },
+ /// NEVER => (),
+ /// }
+ /// ```
+ ///
+ /// and an inverted filter defined as:
+ ///
+ /// ```ignore (pseudo-code)
+ /// // for spans
+ /// match callsite_enabled() {
+ /// ALWAYS => (),
+ /// SOMETIMES => if !enabled() { on_span() },
+ /// NEVER => on_span(),
+ /// }
+ /// // for events
+ /// match callsite_enabled() {
+ /// ALWAYS => (),
+ /// SOMETIMES => if !enabled() { on_event() },
+ /// NEVER => on_event(),
+ /// }
+ /// ```
+ ///
+ /// A proper inversion would do `!(enabled() && event_enabled())` (or
+ /// `!enabled() || !event_enabled()`), but because of the implicit `&&`
+ /// relation between `enabled` and `event_enabled`, it is difficult to
+ /// short circuit and not call the wrapped `event_enabled`.
+ ///
+ /// A combinator which remembers the result of `enabled` in order to call
+ /// `event_enabled` only when `enabled() == true` is possible, but requires
+ /// additional thread-local mutable state to support a very niche use case.
+ //
+ // Also, it'd mean the wrapped layer's `enabled()` always gets called and
+ // globally applied to events where it doesn't today, since we can't know
+ // what `event_enabled` will say until we have the event to call it with.
+ ///
+ /// [`Filter`]: crate::subscribe::Filter
+ /// [`enabled`]: crate::subscribe::Filter::enabled
+ /// [`event_enabled`]: crate::subscribe::Filter::event_enabled
+ /// [`callsite_enabled`]: crate::subscribe::Filter::callsite_enabled
+ fn not(self) -> combinator::Not<Self, S>
+ where
+ Self: Sized,
+ {
+ combinator::Not::new(self)
+ }
+
+ /// [Boxes] `self`, erasing its concrete type.
+ ///
+ /// This is equivalent to calling [`Box::new`], but in method form, so that
+ /// it can be used when chaining combinator methods.
+ ///
+ /// # Examples
+ ///
+ /// When different combinations of filters are used conditionally, they may
+ /// have different types. For example, the following code won't compile,
+ /// since the `if` and `else` clause produce filters of different types:
+ ///
+ /// ```compile_fail
+ /// use tracing_subscriber::{
+ /// filter::{filter_fn, LevelFilter, FilterExt},
+ /// prelude::*,
+ /// };
+ ///
+ /// let enable_bar_target: bool = // ...
+ /// # false;
+ ///
+ /// let filter = if enable_bar_target {
+ /// filter_fn(|meta| meta.target().starts_with("foo"))
+ /// // If `enable_bar_target` is true, add a `filter_fn` enabling
+ /// // spans and events with the target `bar`:
+ /// .or(filter_fn(|meta| meta.target().starts_with("bar")))
+ /// .and(LevelFilter::INFO)
+ /// } else {
+ /// filter_fn(|meta| meta.target().starts_with("foo"))
+ /// .and(LevelFilter::INFO)
+ /// };
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(tracing_subscriber::fmt::layer().with_filter(filter))
+ /// .init();
+ /// ```
+ ///
+ /// By using `boxed`, the types of the two different branches can be erased,
+ /// so the assignment to the `filter` variable is valid (as both branches
+ /// have the type `Box<dyn Filter<S> + Send + Sync + 'static>`). The
+ /// following code *does* compile:
+ ///
+ /// ```
+ /// use tracing_subscriber::{
+ /// filter::{filter_fn, LevelFilter, FilterExt},
+ /// prelude::*,
+ /// };
+ ///
+ /// let enable_bar_target: bool = // ...
+ /// # false;
+ ///
+ /// let filter = if enable_bar_target {
+ /// filter_fn(|meta| meta.target().starts_with("foo"))
+ /// .or(filter_fn(|meta| meta.target().starts_with("bar")))
+ /// .and(LevelFilter::INFO)
+ /// // Boxing the filter erases its type, so both branches now
+ /// // have the same type.
+ /// .boxed()
+ /// } else {
+ /// filter_fn(|meta| meta.target().starts_with("foo"))
+ /// .and(LevelFilter::INFO)
+ /// .boxed()
+ /// };
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(tracing_subscriber::fmt::layer().with_filter(filter))
+ /// .init();
+ /// ```
+ ///
+ /// [Boxes]: std::boxed
+ /// [`Box::new`]: std::boxed::Box::new
+ fn boxed(self) -> Box<dyn layer::Filter<S> + Send + Sync + 'static>
+ where
+ Self: Sized + Send + Sync + 'static,
+ {
+ Box::new(self)
+ }
+}
+
// === impl Filter ===
+
#[cfg(feature = "registry")]
#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
impl<S> layer::Filter<S> for LevelFilter {
@@ -179,38 +462,35 @@ impl<S> layer::Filter<S> for LevelFilter {
}
}
-impl<S> layer::Filter<S> for Arc<dyn layer::Filter<S> + Send + Sync + 'static> {
- #[inline]
- fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool {
- (**self).enabled(meta, cx)
- }
+macro_rules! filter_impl_body {
+ () => {
+ #[inline]
+ fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool {
+ self.deref().enabled(meta, cx)
+ }
- #[inline]
- fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest {
- (**self).callsite_enabled(meta)
- }
+ #[inline]
+ fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest {
+ self.deref().callsite_enabled(meta)
+ }
- #[inline]
- fn max_level_hint(&self) -> Option<LevelFilter> {
- (**self).max_level_hint()
- }
+ #[inline]
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ self.deref().max_level_hint()
+ }
+ };
}
-impl<S> layer::Filter<S> for Box<dyn layer::Filter<S> + Send + Sync + 'static> {
- #[inline]
- fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool {
- (**self).enabled(meta, cx)
- }
-
- #[inline]
- fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest {
- (**self).callsite_enabled(meta)
- }
+#[cfg(feature = "registry")]
+#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
+impl<S> layer::Filter<S> for Arc<dyn layer::Filter<S> + Send + Sync + 'static> {
+ filter_impl_body!();
+}
- #[inline]
- fn max_level_hint(&self) -> Option<LevelFilter> {
- (**self).max_level_hint()
- }
+#[cfg(feature = "registry")]
+#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
+impl<S> layer::Filter<S> for Box<dyn layer::Filter<S> + Send + Sync + 'static> {
+ filter_impl_body!();
}
// === impl Filtered ===
@@ -247,6 +527,78 @@ impl<L, F, S> Filtered<L, F, S> {
fn did_enable(&self, f: impl FnOnce()) {
FILTERING.with(|filtering| filtering.did_enable(self.id(), f))
}
+
+ /// Borrows the [`Filter`](crate::layer::Filter) used by this layer.
+ pub fn filter(&self) -> &F {
+ &self.filter
+ }
+
+ /// Mutably borrows the [`Filter`](crate::layer::Filter) used by this layer.
+ ///
+ /// When this layer can be mutably borrowed, this may be used to mutate the filter.
+ /// Generally, this will primarily be used with the
+ /// [`reload::Handle::modify`](crate::reload::Handle::modify) method.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use tracing::info;
+ /// # use tracing_subscriber::{filter,fmt,reload,Registry,prelude::*};
+ /// # fn main() {
+ /// let filtered_layer = fmt::Layer::default().with_filter(filter::LevelFilter::WARN);
+ /// let (filtered_layer, reload_handle) = reload::Layer::new(filtered_layer);
+ /// #
+ /// # // specifying the Registry type is required
+ /// # let _: &reload::Handle<filter::Filtered<fmt::Layer<Registry>,
+ /// # filter::LevelFilter, Registry>,Registry>
+ /// # = &reload_handle;
+ /// #
+ /// info!("This will be ignored");
+ /// reload_handle.modify(|layer| *layer.filter_mut() = filter::LevelFilter::INFO);
+ /// info!("This will be logged");
+ /// # }
+ /// ```
+ pub fn filter_mut(&mut self) -> &mut F {
+ &mut self.filter
+ }
+
+ /// Borrows the inner [`Layer`] wrapped by this `Filtered` layer.
+ pub fn inner(&self) -> &L {
+ &self.layer
+ }
+
+ /// Mutably borrows the inner [`Layer`] wrapped by this `Filtered` layer.
+ ///
+ /// This method is primarily expected to be used with the
+ /// [`reload::Handle::modify`](crate::reload::Handle::modify) method.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use tracing::info;
+ /// # use tracing_subscriber::{filter,fmt,reload,Registry,prelude::*};
+ /// # fn non_blocking<T: std::io::Write>(writer: T) -> (fn() -> std::io::Stdout) {
+ /// # std::io::stdout
+ /// # }
+ /// # fn main() {
+ /// let filtered_layer = fmt::layer().with_writer(non_blocking(std::io::stderr())).with_filter(filter::LevelFilter::INFO);
+ /// let (filtered_layer, reload_handle) = reload::Layer::new(filtered_layer);
+ /// #
+ /// # // specifying the Registry type is required
+ /// # let _: &reload::Handle<filter::Filtered<fmt::Layer<Registry, _, _, fn() -> std::io::Stdout>,
+ /// # filter::LevelFilter, Registry>, Registry>
+ /// # = &reload_handle;
+ /// #
+ /// info!("This will be logged to stderr");
+ /// reload_handle.modify(|layer| *layer.inner_mut().writer_mut() = non_blocking(std::io::stdout()));
+ /// info!("This will be logged to stdout");
+ /// # }
+ /// ```
+ ///
+ /// [subscriber]: Subscribe
+ pub fn inner_mut(&mut self) -> &mut L {
+ &mut self.layer
+ }
}
impl<S, L, F> Layer<S> for Filtered<L, F, S>
@@ -255,6 +607,10 @@ where
F: layer::Filter<S> + 'static,
L: Layer<S>,
{
+ fn on_register_dispatch(&self, collector: &Dispatch) {
+ self.layer.on_register_dispatch(collector);
+ }
+
fn on_layer(&mut self, subscriber: &mut S) {
self.id = MagicPlfDowncastMarker(subscriber.register_filter());
self.layer.on_layer(subscriber);
@@ -322,7 +678,9 @@ where
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()));
+ let cx = cx.with_filter(self.id());
+ self.filter.on_new_span(attrs, id, cx.clone());
+ self.layer.on_new_span(attrs, id, cx);
})
}
@@ -333,6 +691,7 @@ where
fn on_record(&self, span: &span::Id, values: &span::Record<'_>, cx: Context<'_, S>) {
if let Some(cx) = cx.if_enabled_for(span, self.id()) {
+ self.filter.on_record(span, values, cx.clone());
self.layer.on_record(span, values, cx)
}
}
@@ -345,6 +704,22 @@ where
}
}
+ fn event_enabled(&self, event: &Event<'_>, cx: Context<'_, S>) -> bool {
+ let cx = cx.with_filter(self.id());
+ let enabled = FILTERING
+ .with(|filtering| filtering.and(self.id(), || self.filter.event_enabled(event, &cx)));
+
+ if enabled {
+ // If the filter enabled this event, ask the wrapped subscriber if
+ // _it_ wants it --- it might have a global filter.
+ self.layer.event_enabled(event, cx)
+ } else {
+ // Otherwise, return `true`. See the comment in `enabled` for why this
+ // is necessary.
+ true
+ }
+ }
+
fn on_event(&self, event: &Event<'_>, cx: Context<'_, S>) {
self.did_enable(|| {
self.layer.on_event(event, cx.with_filter(self.id()));
@@ -353,19 +728,22 @@ where
fn on_enter(&self, id: &span::Id, cx: Context<'_, S>) {
if let Some(cx) = cx.if_enabled_for(id, self.id()) {
- self.layer.on_enter(id, cx)
+ self.filter.on_enter(id, cx.clone());
+ self.layer.on_enter(id, cx);
}
}
fn on_exit(&self, id: &span::Id, cx: Context<'_, S>) {
if let Some(cx) = cx.if_enabled_for(id, self.id()) {
- self.layer.on_exit(id, cx)
+ self.filter.on_exit(id, cx.clone());
+ self.layer.on_exit(id, cx);
}
}
fn on_close(&self, id: span::Id, cx: Context<'_, S>) {
if let Some(cx) = cx.if_enabled_for(&id, self.id()) {
- self.layer.on_close(id, cx)
+ self.filter.on_close(id.clone(), cx.clone());
+ self.layer.on_close(id, cx);
}
}
@@ -544,6 +922,10 @@ impl fmt::Binary for FilterId {
}
}
+// === impl FilterExt ===
+
+impl<F, S> FilterExt<S> for F where F: layer::Filter<S> {}
+
// === impl FilterMap ===
impl FilterMap {
@@ -709,6 +1091,14 @@ impl FilterState {
}
}
+ /// Run a second filtering pass, e.g. for Subscribe::event_enabled.
+ fn and(&self, filter: FilterId, f: impl FnOnce() -> bool) -> bool {
+ let map = self.enabled.get();
+ let enabled = map.is_enabled(filter) && f();
+ self.enabled.set(map.set(filter, enabled));
+ enabled
+ }
+
/// Clears the current in-progress filter state.
///
/// This resets the [`FilterMap`] and current [`Interest`] as well as