diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:38 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:13:23 +0000 |
commit | 20431706a863f92cb37dc512fef6e48d192aaf2c (patch) | |
tree | 2867f13f5fd5437ba628c67d7f87309ccadcd286 /vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs | |
parent | Releasing progress-linux version 1.65.0+dfsg1-2~progress7.99u1. (diff) | |
download | rustc-20431706a863f92cb37dc512fef6e48d192aaf2c.tar.xz rustc-20431706a863f92cb37dc512fef6e48d192aaf2c.zip |
Merging upstream version 1.66.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs (renamed from vendor/tracing-subscriber/src/filter/env/mod.rs) | 677 |
1 files changed, 212 insertions, 465 deletions
diff --git a/vendor/tracing-subscriber/src/filter/env/mod.rs b/vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs index 81a9ae2bd..81fe0e62d 100644 --- a/vendor/tracing-subscriber/src/filter/env/mod.rs +++ b/vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs @@ -4,8 +4,7 @@ // these are publicly re-exported, but the compiler doesn't realize // that for some reason. #[allow(unreachable_pub)] -pub use self::{builder::Builder, directive::Directive, field::BadName as BadFieldName}; -mod builder; +pub use self::{directive::Directive, field::BadName as BadFieldName}; mod directive; mod field; @@ -16,7 +15,6 @@ use crate::{ }; use directive::ParseError; use std::{cell::RefCell, collections::HashMap, env, error::Error, fmt, str::FromStr}; -use thread_local::ThreadLocal; use tracing_core::{ callsite, field::Field, @@ -28,16 +26,6 @@ use tracing_core::{ /// A [`Layer`] which filters spans and events based on a set of filter /// directives. /// -/// `EnvFilter` implements both the [`Layer`](#impl-Layer<S>) and [`Filter`] traits, so it may -/// be used for both [global filtering][global] and [per-layer filtering][plf], -/// respectively. See [the documentation on filtering with `Layer`s][filtering] -/// for details. -/// -/// The [`Targets`] type implements a similar form of filtering, but without the -/// ability to dynamically enable events based on the current span context, and -/// without filtering on field values. When these features are not required, -/// [`Targets`] provides a lighter-weight alternative to [`EnvFilter`]. -/// /// # Directives /// /// A filter consists of one or more comma-separated directives which match on [`Span`]s and [`Event`]s. @@ -64,27 +52,10 @@ use tracing_core::{ /// and will match on any [`Span`] or [`Event`] that has a field with that name. /// For example: `[span{field=\"value\"}]=debug`, `[{field}]=trace`. /// - `value` matches on the value of a span's field. If a value is a numeric literal or a bool, -/// it will match _only_ on that value. Otherwise, this filter matches the -/// [`std::fmt::Debug`] output from the value. +/// it will match _only_ on that value. Otherwise, this filter acts as a regex on +/// the `std::fmt::Debug` output from the value. /// - `level` sets a maximum verbosity level accepted by this directive. /// -/// When a field value directive (`[{<FIELD NAME>=<FIELD_VALUE>}]=...`) matches a -/// value's [`std::fmt::Debug`] output (i.e., the field value in the directive -/// is not a `bool`, `i64`, `u64`, or `f64` literal), the matched pattern may be -/// interpreted as either a regular expression or as the precise expected -/// output of the field's [`std::fmt::Debug`] implementation. By default, these -/// filters are interpreted as regular expressions, but this can be disabled -/// using the [`Builder::with_regex`] builder method to use precise matching -/// instead. -/// -/// When field value filters are interpreted as regular expressions, the -/// [`regex-automata` crate's regular expression syntax][re-syntax] is -/// supported. -/// -/// **Note**: When filters are constructed from potentially untrusted inputs, -/// [disabling regular expression matching](Builder::with_regex) is strongly -/// recommended. -/// /// ## Usage Notes /// /// - The portion of the directive which is included within the square brackets is `tracing`-specific. @@ -101,7 +72,7 @@ use tracing_core::{ /// - A dash in a target will only appear when being specified explicitly: /// `tracing::info!(target: "target-name", ...);` /// -/// ## Example Syntax +/// ## Examples /// /// - `tokio::net=info` will enable all spans or events that: /// - have the `tokio::net` target, @@ -118,68 +89,10 @@ use tracing_core::{ /// - which has a field named `name` with value `bob`, /// - at _any_ level. /// -/// # Examples -/// -/// Parsing an `EnvFilter` from the [default environment -/// variable](EnvFilter::from_default_env) (`RUST_LOG`): -/// -/// ``` -/// use tracing_subscriber::{EnvFilter, fmt, prelude::*}; -/// -/// tracing_subscriber::registry() -/// .with(fmt::layer()) -/// .with(EnvFilter::from_default_env()) -/// .init(); -/// ``` -/// -/// Parsing an `EnvFilter` [from a user-provided environment -/// variable](EnvFilter::from_env): -/// -/// ``` -/// use tracing_subscriber::{EnvFilter, fmt, prelude::*}; -/// -/// tracing_subscriber::registry() -/// .with(fmt::layer()) -/// .with(EnvFilter::from_env("MYAPP_LOG")) -/// .init(); -/// ``` -/// -/// Using `EnvFilter` as a [per-layer filter][plf] to filter only a single -/// [`Layer`]: -/// -/// ``` -/// use tracing_subscriber::{EnvFilter, fmt, prelude::*}; -/// -/// // Parse an `EnvFilter` configuration from the `RUST_LOG` -/// // environment variable. -/// let filter = EnvFilter::from_default_env(); -/// -/// // Apply the filter to this layer *only*. -/// let filtered_layer = fmt::layer().with_filter(filter); -/// -/// // Some other layer, whose output we don't want to filter. -/// let unfiltered_layer = // ... -/// # fmt::layer(); -/// -/// tracing_subscriber::registry() -/// .with(filtered_layer) -/// .with(unfiltered_layer) -/// .init(); -/// ``` -/// # Constructing `EnvFilter`s -/// -/// An `EnvFilter` is be constructed by parsing a string containing one or more -/// directives. The [`EnvFilter::new`] constructor parses an `EnvFilter` from a -/// string, ignoring any invalid directives, while [`EnvFilter::try_new`] -/// returns an error if invalid directives are encountered. Similarly, the -/// [`EnvFilter::from_env`] and [`EnvFilter::try_from_env`] constructors parse -/// an `EnvFilter` from the value of the provided environment variable, with -/// lossy and strict validation, respectively. -/// -/// A [builder](EnvFilter::builder) interface is available to set additional -/// configuration options prior to parsing an `EnvFilter`. See the [`Builder` -/// type's documentation](Builder) for details on the options that can be -/// configured using the builder. +/// The [`Targets`] type implements a similar form of filtering, but without the +/// ability to dynamically enable events based on the current span context, and +/// without filtering on field values. When these features are not required, +/// [`Targets`] provides a lighter-weight alternative to [`EnvFilter`]. /// /// [`Span`]: tracing_core::span /// [fields]: tracing_core::Field @@ -187,11 +100,6 @@ use tracing_core::{ /// [`level`]: tracing_core::Level /// [`Metadata`]: tracing_core::Metadata /// [`Targets`]: crate::filter::Targets -/// [`env_logger`]: https://crates.io/crates/env_logger -/// [`Filter`]: #impl-Filter<S> -/// [global]: crate::layer#global-filtering -/// [plf]: crate::layer#per-layer-filtering -/// [filtering]: crate::layer#filtering-with-layers #[cfg_attr(docsrs, doc(cfg(all(feature = "env-filter", feature = "std"))))] #[derive(Debug)] pub struct EnvFilter { @@ -200,8 +108,10 @@ pub struct EnvFilter { has_dynamics: bool, by_id: RwLock<HashMap<span::Id, directive::SpanMatcher>>, by_cs: RwLock<HashMap<callsite::Identifier, directive::CallsiteMatcher>>, - scope: ThreadLocal<RefCell<Vec<LevelFilter>>>, - regex: bool, +} + +thread_local! { + static SCOPE: RefCell<Vec<LevelFilter>> = RefCell::new(Vec::new()); } type FieldMap<T> = HashMap<Field, T>; @@ -224,181 +134,58 @@ impl EnvFilter { /// `RUST_LOG` is the default environment variable used by /// [`EnvFilter::from_default_env`] and [`EnvFilter::try_from_default_env`]. /// - /// [`EnvFilter::from_default_env`]: EnvFilter::from_default_env() - /// [`EnvFilter::try_from_default_env`]: EnvFilter::try_from_default_env() + /// [`EnvFilter::from_default_env`]: #method.from_default_env + /// [`EnvFilter::try_from_default_env`]: #method.try_from_default_env pub const DEFAULT_ENV: &'static str = "RUST_LOG"; - // === constructors, etc === - - /// Returns a [builder] that can be used to configure a new [`EnvFilter`] - /// instance. - /// - /// The [`Builder`] type is used to set additional configurations, such as - /// [whether regular expressions are enabled](Builder::with_regex) or [the - /// default directive](Builder::with_default_directive) before parsing an - /// [`EnvFilter`] from a string or environment variable. - /// - /// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html - pub fn builder() -> Builder { - Builder::default() - } - /// Returns a new `EnvFilter` from the value of the `RUST_LOG` environment /// variable, ignoring any invalid filter directives. - /// - /// If the environment variable is empty or not set, or if it contains only - /// invalid directives, a default directive enabling the [`ERROR`] level is - /// added. - /// - /// To set additional configuration options prior to parsing the filter, use - /// the [`Builder`] type instead. - /// - /// This function is equivalent to the following: - /// - /// ```rust - /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// - /// # fn docs() -> EnvFilter { - /// EnvFilter::builder() - /// .with_default_directive(LevelFilter::ERROR.into()) - /// .from_env_lossy() - /// # } - /// ``` - /// - /// [`ERROR`]: tracing::Level::ERROR pub fn from_default_env() -> Self { - Self::builder() - .with_default_directive(LevelFilter::ERROR.into()) - .from_env_lossy() + Self::from_env(Self::DEFAULT_ENV) } /// Returns a new `EnvFilter` from the value of the given environment /// variable, ignoring any invalid filter directives. - /// - /// If the environment variable is empty or not set, or if it contains only - /// invalid directives, a default directive enabling the [`ERROR`] level is - /// added. - /// - /// To set additional configuration options prior to parsing the filter, use - /// the [`Builder`] type instead. - /// - /// This function is equivalent to the following: - /// - /// ```rust - /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// - /// # fn docs() -> EnvFilter { - /// # let env = ""; - /// EnvFilter::builder() - /// .with_default_directive(LevelFilter::ERROR.into()) - /// .with_env_var(env) - /// .from_env_lossy() - /// # } - /// ``` - /// - /// [`ERROR`]: tracing::Level::ERROR pub fn from_env<A: AsRef<str>>(env: A) -> Self { - Self::builder() - .with_default_directive(LevelFilter::ERROR.into()) - .with_env_var(env.as_ref()) - .from_env_lossy() + env::var(env.as_ref()).map(Self::new).unwrap_or_default() } /// Returns a new `EnvFilter` from the directives in the given string, /// ignoring any that are invalid. - /// - /// If the string is empty or contains only invalid directives, a default - /// directive enabling the [`ERROR`] level is added. - /// - /// To set additional configuration options prior to parsing the filter, use - /// the [`Builder`] type instead. - /// - /// This function is equivalent to the following: - /// - /// ```rust - /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// - /// # fn docs() -> EnvFilter { - /// # let directives = ""; - /// EnvFilter::builder() - /// .with_default_directive(LevelFilter::ERROR.into()) - /// .parse_lossy(directives) - /// # } - /// ``` - /// - /// [`ERROR`]: tracing::Level::ERROR - pub fn new<S: AsRef<str>>(directives: S) -> Self { - Self::builder() - .with_default_directive(LevelFilter::ERROR.into()) - .parse_lossy(directives) + pub fn new<S: AsRef<str>>(dirs: S) -> Self { + let directives = dirs.as_ref().split(',').filter_map(|s| match s.parse() { + Ok(d) => Some(d), + Err(err) => { + eprintln!("ignoring `{}`: {}", s, err); + None + } + }); + Self::from_directives(directives) } /// Returns a new `EnvFilter` from the directives in the given string, /// or an error if any are invalid. - /// - /// If the string is empty, a default directive enabling the [`ERROR`] level - /// is added. - /// - /// To set additional configuration options prior to parsing the filter, use - /// the [`Builder`] type instead. - /// - /// This function is equivalent to the following: - /// - /// ```rust - /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; - /// - /// # fn docs() -> Result<EnvFilter, tracing_subscriber::filter::ParseError> { - /// # let directives = ""; - /// EnvFilter::builder() - /// .with_default_directive(LevelFilter::ERROR.into()) - /// .parse(directives) - /// # } - /// ``` - /// - /// [`ERROR`]: tracing::Level::ERROR pub fn try_new<S: AsRef<str>>(dirs: S) -> Result<Self, directive::ParseError> { - Self::builder().parse(dirs) + let directives = dirs + .as_ref() + .split(',') + .map(|s| s.parse()) + .collect::<Result<Vec<_>, _>>()?; + Ok(Self::from_directives(directives)) } /// Returns a new `EnvFilter` from the value of the `RUST_LOG` environment - /// variable, or an error if the environment variable is unset or contains - /// any invalid filter directives. - /// - /// To set additional configuration options prior to parsing the filter, use - /// the [`Builder`] type instead. - /// - /// This function is equivalent to the following: - /// - /// ```rust - /// use tracing_subscriber::EnvFilter; - /// - /// # fn docs() -> Result<EnvFilter, tracing_subscriber::filter::FromEnvError> { - /// EnvFilter::builder().try_from_env() - /// # } - /// ``` + /// variable, or an error if the environment variable contains any invalid + /// filter directives. pub fn try_from_default_env() -> Result<Self, FromEnvError> { - Self::builder().try_from_env() + Self::try_from_env(Self::DEFAULT_ENV) } /// Returns a new `EnvFilter` from the value of the given environment /// variable, or an error if the environment variable is unset or contains /// any invalid filter directives. - /// - /// To set additional configuration options prior to parsing the filter, use - /// the [`Builder`] type instead. - /// - /// This function is equivalent to the following: - /// - /// ```rust - /// use tracing_subscriber::EnvFilter; - /// - /// # fn docs() -> Result<EnvFilter, tracing_subscriber::filter::FromEnvError> { - /// # let env = ""; - /// EnvFilter::builder().with_env_var(env).try_from_env() - /// # } - /// ``` pub fn try_from_env<A: AsRef<str>>(env: A) -> Result<Self, FromEnvError> { - Self::builder().with_env_var(env.as_ref()).try_from_env() + env::var(env.as_ref())?.parse().map_err(Into::into) } /// Add a filtering directive to this `EnvFilter`. @@ -415,13 +202,13 @@ impl EnvFilter { /// and events as a previous filter, but sets a different level for those /// spans and events, the previous directive is overwritten. /// - /// [`LevelFilter`]: super::LevelFilter - /// [`Level`]: tracing_core::Level + /// [`LevelFilter`]: ../filter/struct.LevelFilter.html + /// [`Level`]: https://docs.rs/tracing-core/latest/tracing_core/struct.Level.html /// /// # Examples /// /// From [`LevelFilter`]: - /// + //// /// ```rust /// use tracing_subscriber::filter::{EnvFilter, LevelFilter}; /// let mut filter = EnvFilter::from_default_env() @@ -436,9 +223,9 @@ impl EnvFilter { /// let mut filter = EnvFilter::from_default_env() /// .add_directive(Level::INFO.into()); /// ``` - /// + //// /// Parsed from a string: - /// + //// /// ```rust /// use tracing_subscriber::filter::{EnvFilter, Directive}; /// @@ -449,15 +236,7 @@ impl EnvFilter { /// # Ok(()) /// # } /// ``` - /// In the above example, substitute `my_crate`, `module`, etc. with the - /// name your target crate/module is imported with. This might be - /// different from the package name in Cargo.toml (`-` is replaced by `_`). - /// Example, if the package name in your Cargo.toml is `MY-FANCY-LIB`, then - /// the corresponding Rust identifier would be `MY_FANCY_LIB`: - pub fn add_directive(mut self, mut directive: Directive) -> Self { - if !self.regex { - directive.deregexify(); - } + pub fn add_directive(mut self, directive: Directive) -> Self { if let Some(stat) = directive.to_static() { self.statics.add(stat) } else { @@ -467,19 +246,165 @@ impl EnvFilter { self } - // === filtering methods === + fn from_directives(directives: impl IntoIterator<Item = Directive>) -> Self { + use tracing::level_filters::STATIC_MAX_LEVEL; + use tracing::Level; + + let directives: Vec<_> = directives.into_iter().collect(); + + let disabled: Vec<_> = directives + .iter() + .filter(|directive| directive.level > STATIC_MAX_LEVEL) + .collect(); + + if !disabled.is_empty() { + #[cfg(feature = "ansi_term")] + use ansi_term::{Color, Style}; + // NOTE: We can't use a configured `MakeWriter` because the EnvFilter + // has no knowledge of any underlying subscriber or subscriber, which + // may or may not use a `MakeWriter`. + let warn = |msg: &str| { + #[cfg(not(feature = "ansi_term"))] + let msg = format!("warning: {}", msg); + #[cfg(feature = "ansi_term")] + let msg = { + let bold = Style::new().bold(); + let mut warning = Color::Yellow.paint("warning"); + warning.style_ref_mut().is_bold = true; + format!("{}{} {}", warning, bold.paint(":"), bold.paint(msg)) + }; + eprintln!("{}", msg); + }; + let ctx_prefixed = |prefix: &str, msg: &str| { + #[cfg(not(feature = "ansi_term"))] + let msg = format!("note: {}", msg); + #[cfg(feature = "ansi_term")] + let msg = { + let mut equal = Color::Fixed(21).paint("="); // dark blue + equal.style_ref_mut().is_bold = true; + format!(" {} {} {}", equal, Style::new().bold().paint(prefix), msg) + }; + eprintln!("{}", msg); + }; + let ctx_help = |msg| ctx_prefixed("help:", msg); + let ctx_note = |msg| ctx_prefixed("note:", msg); + let ctx = |msg: &str| { + #[cfg(not(feature = "ansi_term"))] + let msg = format!("note: {}", msg); + #[cfg(feature = "ansi_term")] + let msg = { + let mut pipe = Color::Fixed(21).paint("|"); + pipe.style_ref_mut().is_bold = true; + format!(" {} {}", pipe, msg) + }; + eprintln!("{}", msg); + }; + warn("some trace filter directives would enable traces that are disabled statically"); + for directive in disabled { + let target = if let Some(target) = &directive.target { + format!("the `{}` target", target) + } else { + "all targets".into() + }; + let level = directive + .level + .into_level() + .expect("=off would not have enabled any filters"); + ctx(&format!( + "`{}` would enable the {} level for {}", + directive, level, target + )); + } + ctx_note(&format!("the static max level is `{}`", STATIC_MAX_LEVEL)); + let help_msg = || { + let (feature, filter) = match STATIC_MAX_LEVEL.into_level() { + Some(Level::TRACE) => unreachable!( + "if the max level is trace, no static filtering features are enabled" + ), + Some(Level::DEBUG) => ("max_level_debug", Level::TRACE), + Some(Level::INFO) => ("max_level_info", Level::DEBUG), + Some(Level::WARN) => ("max_level_warn", Level::INFO), + Some(Level::ERROR) => ("max_level_error", Level::WARN), + None => return ("max_level_off", String::new()), + }; + (feature, format!("{} ", filter)) + }; + let (feature, earlier_level) = help_msg(); + ctx_help(&format!( + "to enable {}logging, remove the `{}` feature", + earlier_level, feature + )); + } - /// Returns `true` if this `EnvFilter` would enable the provided `metadata` - /// in the current context. - /// - /// This is equivalent to calling the [`Layer::enabled`] or - /// [`Filter::enabled`] methods on `EnvFilter`'s implementations of those - /// traits, but it does not require the trait to be in scope. - pub fn enabled<S>(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool { + let (dynamics, mut statics) = Directive::make_tables(directives); + let has_dynamics = !dynamics.is_empty(); + + if statics.is_empty() && !has_dynamics { + statics.add(directive::StaticDirective::default()); + } + + Self { + statics, + dynamics, + has_dynamics, + by_id: RwLock::new(HashMap::new()), + by_cs: RwLock::new(HashMap::new()), + } + } + + fn cares_about_span(&self, span: &span::Id) -> bool { + let spans = try_lock!(self.by_id.read(), else return false); + spans.contains_key(span) + } + + fn base_interest(&self) -> Interest { + if self.has_dynamics { + Interest::sometimes() + } else { + Interest::never() + } + } +} + +impl<S: Subscriber> Layer<S> for EnvFilter { + fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { + if self.has_dynamics && metadata.is_span() { + // If this metadata describes a span, first, check if there is a + // dynamic filter that should be constructed for it. If so, it + // should always be enabled, since it influences filtering. + if let Some(matcher) = self.dynamics.matcher(metadata) { + let mut by_cs = try_lock!(self.by_cs.write(), else return self.base_interest()); + by_cs.insert(metadata.callsite(), matcher); + return Interest::always(); + } + } + + // Otherwise, check if any of our static filters enable this metadata. + if self.statics.enabled(metadata) { + Interest::always() + } else { + self.base_interest() + } + } + + fn max_level_hint(&self) -> Option<LevelFilter> { + if self.dynamics.has_value_filters() { + // If we perform any filtering on span field *values*, we will + // enable *all* spans, because their field values are not known + // until recording. + return Some(LevelFilter::TRACE); + } + std::cmp::max( + self.statics.max_level.into(), + self.dynamics.max_level.into(), + ) + } + + fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool { let level = metadata.level(); // is it possible for a dynamic filter directive to enable this event? - // if not, we can avoid the thread loca'l access + iterating over the + // if not, we can avoid the thread local access + iterating over the // spans in the current scope. if self.has_dynamics && self.dynamics.max_level >= *level { if metadata.is_span() { @@ -495,15 +420,14 @@ impl EnvFilter { } } - let enabled_by_scope = { - let scope = self.scope.get_or_default().borrow(); - for filter in &*scope { + let enabled_by_scope = SCOPE.with(|scope| { + for filter in scope.borrow().iter() { if filter >= level { return true; } } false - }; + }); if enabled_by_scope { return true; } @@ -519,33 +443,7 @@ impl EnvFilter { false } - /// Returns an optional hint of the highest [verbosity level][level] that - /// this `EnvFilter` will enable. - /// - /// This is equivalent to calling the [`Layer::max_level_hint`] or - /// [`Filter::max_level_hint`] methods on `EnvFilter`'s implementations of those - /// traits, but it does not require the trait to be in scope. - /// - /// [level]: tracing_core::metadata::Level - pub fn max_level_hint(&self) -> Option<LevelFilter> { - if self.dynamics.has_value_filters() { - // If we perform any filtering on span field *values*, we will - // enable *all* spans, because their field values are not known - // until recording. - return Some(LevelFilter::TRACE); - } - std::cmp::max( - self.statics.max_level.into(), - self.dynamics.max_level.into(), - ) - } - - /// Informs the filter that a new span was created. - /// - /// This is equivalent to calling the [`Layer::on_new_span`] or - /// [`Filter::on_new_span`] methods on `EnvFilter`'s implementations of those - /// traits, but it does not require the trait to be in scope. - pub fn on_new_span<S>(&self, attrs: &span::Attributes<'_>, id: &span::Id, _: Context<'_, S>) { + fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, _: Context<'_, S>) { let by_cs = try_lock!(self.by_cs.read()); if let Some(cs) = by_cs.get(&attrs.metadata().callsite()) { let span = cs.to_span_match(attrs); @@ -553,37 +451,28 @@ impl EnvFilter { } } - /// Informs the filter that the span with the provided `id` was entered. - /// - /// This is equivalent to calling the [`Layer::on_enter`] or - /// [`Filter::on_enter`] methods on `EnvFilter`'s implementations of those - /// traits, but it does not require the trait to be in scope. - pub fn on_enter<S>(&self, id: &span::Id, _: Context<'_, S>) { + fn on_record(&self, id: &span::Id, values: &span::Record<'_>, _: Context<'_, S>) { + if let Some(span) = try_lock!(self.by_id.read()).get(id) { + span.record_update(values); + } + } + + fn on_enter(&self, id: &span::Id, _: Context<'_, S>) { // XXX: This is where _we_ could push IDs to the stack instead, and use // that to allow changing the filter while a span is already entered. // But that might be much less efficient... if let Some(span) = try_lock!(self.by_id.read()).get(id) { - self.scope.get_or_default().borrow_mut().push(span.level()); + SCOPE.with(|scope| scope.borrow_mut().push(span.level())); } } - /// Informs the filter that the span with the provided `id` was exited. - /// - /// This is equivalent to calling the [`Layer::on_exit`] or - /// [`Filter::on_exit`] methods on `EnvFilter`'s implementations of those - /// traits, but it does not require the trait to be in scope. - pub fn on_exit<S>(&self, id: &span::Id, _: Context<'_, S>) { + fn on_exit(&self, id: &span::Id, _: Context<'_, S>) { if self.cares_about_span(id) { - self.scope.get_or_default().borrow_mut().pop(); + SCOPE.with(|scope| scope.borrow_mut().pop()); } } - /// Informs the filter that the span with the provided `id` was closed. - /// - /// This is equivalent to calling the [`Layer::on_close`] or - /// [`Filter::on_close`] methods on `EnvFilter`'s implementations of those - /// traits, but it does not require the trait to be in scope. - pub fn on_close<S>(&self, id: span::Id, _: Context<'_, S>) { + fn on_close(&self, id: span::Id, _: Context<'_, S>) { // If we don't need to acquire a write lock, avoid doing so. if !self.cares_about_span(&id) { return; @@ -592,140 +481,6 @@ impl EnvFilter { let mut spans = try_lock!(self.by_id.write()); spans.remove(&id); } - - /// Informs the filter that the span with the provided `id` recorded the - /// provided field `values`. - /// - /// This is equivalent to calling the [`Layer::on_record`] or - /// [`Filter::on_record`] methods on `EnvFilter`'s implementations of those - /// traits, but it does not require the trait to be in scope - pub fn on_record<S>(&self, id: &span::Id, values: &span::Record<'_>, _: Context<'_, S>) { - if let Some(span) = try_lock!(self.by_id.read()).get(id) { - span.record_update(values); - } - } - - fn cares_about_span(&self, span: &span::Id) -> bool { - let spans = try_lock!(self.by_id.read(), else return false); - spans.contains_key(span) - } - - fn base_interest(&self) -> Interest { - if self.has_dynamics { - Interest::sometimes() - } else { - Interest::never() - } - } - - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - if self.has_dynamics && metadata.is_span() { - // If this metadata describes a span, first, check if there is a - // dynamic filter that should be constructed for it. If so, it - // should always be enabled, since it influences filtering. - if let Some(matcher) = self.dynamics.matcher(metadata) { - let mut by_cs = try_lock!(self.by_cs.write(), else return self.base_interest()); - by_cs.insert(metadata.callsite(), matcher); - return Interest::always(); - } - } - - // Otherwise, check if any of our static filters enable this metadata. - if self.statics.enabled(metadata) { - Interest::always() - } else { - self.base_interest() - } - } -} - -impl<S: Subscriber> Layer<S> for EnvFilter { - #[inline] - fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { - EnvFilter::register_callsite(self, metadata) - } - - #[inline] - fn max_level_hint(&self) -> Option<LevelFilter> { - EnvFilter::max_level_hint(self) - } - - #[inline] - fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool { - self.enabled(metadata, ctx) - } - - #[inline] - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) { - self.on_new_span(attrs, id, ctx) - } - - #[inline] - fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) { - self.on_record(id, values, ctx); - } - - #[inline] - fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) { - self.on_enter(id, ctx); - } - - #[inline] - fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) { - self.on_exit(id, ctx); - } - - #[inline] - fn on_close(&self, id: span::Id, ctx: Context<'_, S>) { - self.on_close(id, ctx); - } -} - -feature! { - #![all(feature = "registry", feature = "std")] - use crate::layer::Filter; - - impl<S> Filter<S> for EnvFilter { - #[inline] - fn enabled(&self, meta: &Metadata<'_>, ctx: &Context<'_, S>) -> bool { - self.enabled(meta, ctx.clone()) - } - - #[inline] - fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { - self.register_callsite(meta) - } - - #[inline] - fn max_level_hint(&self) -> Option<LevelFilter> { - EnvFilter::max_level_hint(self) - } - - #[inline] - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) { - self.on_new_span(attrs, id, ctx) - } - - #[inline] - fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) { - self.on_record(id, values, ctx); - } - - #[inline] - fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) { - self.on_enter(id, ctx); - } - - #[inline] - fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) { - self.on_exit(id, ctx); - } - - #[inline] - fn on_close(&self, id: span::Id, ctx: Context<'_, S>) { - self.on_close(id, ctx); - } - } } impl FromStr for EnvFilter { @@ -747,7 +502,7 @@ where impl Default for EnvFilter { fn default() -> Self { - Builder::default().from_directives(std::iter::empty()) + Self::from_directives(std::iter::empty()) } } @@ -980,12 +735,4 @@ mod tests { [span2{bar=2 baz=false}],crate2[{quux=\"quuux\"}]=debug", ); } - - #[test] - fn parse_empty_string() { - // There is no corresponding test for [`Builder::parse_lossy`] as failed - // parsing does not produce any observable side effects. If this test fails - // check that [`Builder::parse_lossy`] is behaving correctly as well. - assert!(EnvFilter::builder().parse("").is_ok()); - } } |