tracing_subscriber/filter/env/
mod.rs

1//! A `Layer` that enables or disables spans and events based on a set of
2//! filtering directives.
3
4// these are publicly re-exported, but the compiler doesn't realize
5// that for some reason.
6#[allow(unreachable_pub)]
7pub use self::{builder::Builder, directive::Directive, field::BadName as BadFieldName};
8mod builder;
9mod directive;
10mod field;
11
12use crate::{
13    filter::LevelFilter,
14    layer::{Context, Layer},
15    sync::RwLock,
16};
17use directive::ParseError;
18use std::{cell::RefCell, collections::HashMap, env, error::Error, fmt, str::FromStr};
19use thread_local::ThreadLocal;
20use tracing_core::{
21    callsite,
22    field::Field,
23    span,
24    subscriber::{Interest, Subscriber},
25    Metadata,
26};
27
28/// A [`Layer`] which filters spans and events based on a set of filter
29/// directives.
30///
31/// `EnvFilter` implements both the [`Layer`](#impl-Layer<S>) and [`Filter`] traits, so it may
32/// be used for both [global filtering][global] and [per-layer filtering][plf],
33/// respectively. See [the documentation on filtering with `Layer`s][filtering]
34/// for details.
35///
36/// The [`Targets`] type implements a similar form of filtering, but without the
37/// ability to dynamically enable events based on the current span context, and
38/// without filtering on field values. When these features are not required,
39/// [`Targets`] provides a lighter-weight alternative to [`EnvFilter`].
40///
41/// # Directives
42///
43/// A filter consists of one or more comma-separated directives which match on [`Span`]s and [`Event`]s.
44/// Each directive may have a corresponding maximum verbosity [`level`] which
45/// enables (e.g., _selects for_) spans and events that match. Like `log`,
46/// `tracing` considers less exclusive levels (like `trace` or `info`) to be more
47/// verbose than more exclusive levels (like `error` or `warn`).
48///
49/// The directive syntax is similar to that of [`env_logger`]'s. At a high level, the syntax for directives
50/// consists of several parts:
51///
52/// ```text
53/// target[span{field=value}]=level
54/// ```
55///
56/// Each component (`target`, `span`, `field`, `value`, and `level`) will be covered in turn.
57///
58/// - `target` matches the event or span's target. In general, this is the module path and/or crate name.
59///    Examples of targets `h2`, `tokio::net`, or `tide::server`. For more information on targets,
60///    please refer to [`Metadata`]'s documentation.
61/// - `span` matches on the span's name. If a `span` directive is provided alongside a `target`,
62///    the `span` directive will match on spans _within_ the `target`.
63/// - `field` matches on [fields] within spans. Field names can also be supplied without a `value`
64///    and will match on any [`Span`] or [`Event`] that has a field with that name.
65///    For example: `[span{field=\"value\"}]=debug`, `[{field}]=trace`.
66/// - `value` matches on the value of a span's field. If a value is a numeric literal or a bool,
67///    it will match _only_ on that value. Otherwise, this filter matches the
68///    [`std::fmt::Debug`] output from the value.
69/// - `level` sets a maximum verbosity level accepted by this directive.
70///
71/// When a field value directive (`[{<FIELD NAME>=<FIELD_VALUE>}]=...`) matches a
72/// value's [`std::fmt::Debug`] output (i.e., the field value in the directive
73/// is not a `bool`, `i64`, `u64`, or `f64` literal), the matched pattern may be
74/// interpreted as either a regular expression or as the precise expected
75/// output of the field's [`std::fmt::Debug`] implementation. By default, these
76/// filters are interpreted as regular expressions, but this can be disabled
77/// using the [`Builder::with_regex`] builder method to use precise matching
78/// instead.
79///
80/// When field value filters are interpreted as regular expressions, the
81/// [`regex-automata` crate's regular expression syntax][re-syntax] is
82/// supported.
83///
84/// **Note**: When filters are constructed from potentially untrusted inputs,
85/// [disabling regular expression matching](Builder::with_regex) is strongly
86/// recommended.
87///
88/// ## Usage Notes
89///
90/// - The portion of the directive which is included within the square brackets is `tracing`-specific.
91/// - Any portion of the directive can be omitted.
92///     - The sole exception are the `field` and `value` directives. If a `value` is provided,
93///       a `field` must _also_ be provided. However, the converse does not hold, as fields can
94///       be matched without a value.
95/// - If only a level is provided, it will set the maximum level for all `Span`s and `Event`s
96///   that are not enabled by other filters.
97/// - A directive without a level will enable anything that it matches. This is equivalent to `=trace`.
98/// - When a crate has a dash in its name, the default target for events will be the
99///   crate's module path as it appears in Rust. This means every dash will be replaced
100///   with an underscore.
101/// - A dash in a target will only appear when being specified explicitly:
102///   `tracing::info!(target: "target-name", ...);`
103///
104/// ## Example Syntax
105///
106/// - `tokio::net=info` will enable all spans or events that:
107///    - have the `tokio::net` target,
108///    - at the level `info` or above.
109/// - `warn,tokio::net=info` will enable all spans and events that:
110///    - are at the level `warn` or above, *or*
111///    - have the `tokio::net` target at the level `info` or above.
112/// - `my_crate[span_a]=trace` will enable all spans and events that:
113///    - are within the `span_a` span or named `span_a` _if_ `span_a` has the target `my_crate`,
114///    - at the level `trace` or above.
115/// - `[span_b{name=\"bob\"}]` will enable all spans or event that:
116///    - have _any_ target,
117///    - are inside a span named `span_b`,
118///    - which has a field named `name` with value `bob`,
119///    - at _any_ level.
120///
121/// # Examples
122///
123/// Parsing an `EnvFilter` from the [default environment
124/// variable](EnvFilter::from_default_env) (`RUST_LOG`):
125///
126/// ```
127/// use tracing_subscriber::{EnvFilter, fmt, prelude::*};
128///
129/// tracing_subscriber::registry()
130///     .with(fmt::layer())
131///     .with(EnvFilter::from_default_env())
132///     .init();
133/// ```
134///
135/// Parsing an `EnvFilter` [from a user-provided environment
136/// variable](EnvFilter::from_env):
137///
138/// ```
139/// use tracing_subscriber::{EnvFilter, fmt, prelude::*};
140///
141/// tracing_subscriber::registry()
142///     .with(fmt::layer())
143///     .with(EnvFilter::from_env("MYAPP_LOG"))
144///     .init();
145/// ```
146///
147/// Using `EnvFilter` as a [per-layer filter][plf] to filter only a single
148/// [`Layer`]:
149///
150/// ```
151/// use tracing_subscriber::{EnvFilter, fmt, prelude::*};
152///
153/// // Parse an `EnvFilter` configuration from the `RUST_LOG`
154/// // environment variable.
155/// let filter = EnvFilter::from_default_env();
156///
157/// // Apply the filter to this layer *only*.
158/// let filtered_layer = fmt::layer().with_filter(filter);
159///
160/// // Some other layer, whose output we don't want to filter.
161/// let unfiltered_layer = // ...
162///     # fmt::layer();
163///
164/// tracing_subscriber::registry()
165///     .with(filtered_layer)
166///     .with(unfiltered_layer)
167///     .init();
168/// ```
169/// # Constructing `EnvFilter`s
170///
171/// An `EnvFilter` is be constructed by parsing a string containing one or more
172/// directives. The [`EnvFilter::new`] constructor parses an `EnvFilter` from a
173/// string, ignoring any invalid directives, while [`EnvFilter::try_new`]
174/// returns an error if invalid directives are encountered. Similarly, the
175/// [`EnvFilter::from_env`] and [`EnvFilter::try_from_env`] constructors parse
176/// an `EnvFilter` from the value of the provided environment variable, with
177/// lossy and strict validation, respectively.
178///
179/// A [builder](EnvFilter::builder) interface is available to set additional
180/// configuration options prior to parsing an `EnvFilter`. See the [`Builder`
181/// type's documentation](Builder) for details on the options that can be
182/// configured using the builder.
183///
184/// [`Span`]: tracing_core::span
185/// [fields]: tracing_core::Field
186/// [`Event`]: tracing_core::Event
187/// [`level`]: tracing_core::Level
188/// [`Metadata`]: tracing_core::Metadata
189/// [`Targets`]: crate::filter::Targets
190/// [`env_logger`]: https://crates.io/crates/env_logger
191/// [`Filter`]: #impl-Filter<S>
192/// [global]: crate::layer#global-filtering
193/// [plf]: crate::layer#per-layer-filtering
194/// [filtering]: crate::layer#filtering-with-layers
195#[cfg_attr(docsrs, doc(cfg(all(feature = "env-filter", feature = "std"))))]
196#[derive(Debug)]
197pub struct EnvFilter {
198    statics: directive::Statics,
199    dynamics: directive::Dynamics,
200    has_dynamics: bool,
201    by_id: RwLock<HashMap<span::Id, directive::SpanMatcher>>,
202    by_cs: RwLock<HashMap<callsite::Identifier, directive::CallsiteMatcher>>,
203    scope: ThreadLocal<RefCell<Vec<LevelFilter>>>,
204    regex: bool,
205}
206
207type FieldMap<T> = HashMap<Field, T>;
208
209/// Indicates that an error occurred while parsing a `EnvFilter` from an
210/// environment variable.
211#[cfg_attr(docsrs, doc(cfg(all(feature = "env-filter", feature = "std"))))]
212#[derive(Debug)]
213pub struct FromEnvError {
214    kind: ErrorKind,
215}
216
217#[derive(Debug)]
218enum ErrorKind {
219    Parse(ParseError),
220    Env(env::VarError),
221}
222
223impl EnvFilter {
224    /// `RUST_LOG` is the default environment variable used by
225    /// [`EnvFilter::from_default_env`] and [`EnvFilter::try_from_default_env`].
226    ///
227    /// [`EnvFilter::from_default_env`]: EnvFilter::from_default_env()
228    /// [`EnvFilter::try_from_default_env`]: EnvFilter::try_from_default_env()
229    pub const DEFAULT_ENV: &'static str = "RUST_LOG";
230
231    // === constructors, etc ===
232
233    /// Returns a [builder] that can be used to configure a new [`EnvFilter`]
234    /// instance.
235    ///
236    /// The [`Builder`] type is used to set additional configurations, such as
237    /// [whether regular expressions are enabled](Builder::with_regex) or [the
238    /// default directive](Builder::with_default_directive) before parsing an
239    /// [`EnvFilter`] from a string or environment variable.
240    ///
241    /// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html
242    pub fn builder() -> Builder {
243        Builder::default()
244    }
245
246    /// Returns a new `EnvFilter` from the value of the `RUST_LOG` environment
247    /// variable, ignoring any invalid filter directives.
248    ///
249    /// If the environment variable is empty or not set, or if it contains only
250    /// invalid directives, a default directive enabling the [`ERROR`] level is
251    /// added.
252    ///
253    /// To set additional configuration options prior to parsing the filter, use
254    /// the [`Builder`] type instead.
255    ///
256    /// This function is equivalent to the following:
257    ///
258    /// ```rust
259    /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
260    ///
261    /// # fn docs() -> EnvFilter {
262    /// EnvFilter::builder()
263    ///     .with_default_directive(LevelFilter::ERROR.into())
264    ///     .from_env_lossy()
265    /// # }
266    /// ```
267    ///
268    /// [`ERROR`]: tracing::Level::ERROR
269    pub fn from_default_env() -> Self {
270        Self::builder()
271            .with_default_directive(LevelFilter::ERROR.into())
272            .from_env_lossy()
273    }
274
275    /// Returns a new `EnvFilter` from the value of the given environment
276    /// variable, ignoring any invalid filter directives.
277    ///
278    /// If the environment variable is empty or not set, or if it contains only
279    /// invalid directives, a default directive enabling the [`ERROR`] level is
280    /// added.
281    ///
282    /// To set additional configuration options prior to parsing the filter, use
283    /// the [`Builder`] type instead.
284    ///
285    /// This function is equivalent to the following:
286    ///
287    /// ```rust
288    /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
289    ///
290    /// # fn docs() -> EnvFilter {
291    /// # let env = "";
292    /// EnvFilter::builder()
293    ///     .with_default_directive(LevelFilter::ERROR.into())
294    ///     .with_env_var(env)
295    ///     .from_env_lossy()
296    /// # }
297    /// ```
298    ///
299    /// [`ERROR`]: tracing::Level::ERROR
300    pub fn from_env<A: AsRef<str>>(env: A) -> Self {
301        Self::builder()
302            .with_default_directive(LevelFilter::ERROR.into())
303            .with_env_var(env.as_ref())
304            .from_env_lossy()
305    }
306
307    /// Returns a new `EnvFilter` from the directives in the given string,
308    /// ignoring any that are invalid.
309    ///
310    /// If the string is empty or contains only invalid directives, a default
311    /// directive enabling the [`ERROR`] level is added.
312    ///
313    /// To set additional configuration options prior to parsing the filter, use
314    /// the [`Builder`] type instead.
315    ///
316    /// This function is equivalent to the following:
317    ///
318    /// ```rust
319    /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
320    ///
321    /// # fn docs() -> EnvFilter {
322    /// # let directives = "";
323    /// EnvFilter::builder()
324    ///     .with_default_directive(LevelFilter::ERROR.into())
325    ///     .parse_lossy(directives)
326    /// # }
327    /// ```
328    ///
329    /// [`ERROR`]: tracing::Level::ERROR
330    pub fn new<S: AsRef<str>>(directives: S) -> Self {
331        Self::builder()
332            .with_default_directive(LevelFilter::ERROR.into())
333            .parse_lossy(directives)
334    }
335
336    /// Returns a new `EnvFilter` from the directives in the given string,
337    /// or an error if any are invalid.
338    ///
339    /// If the string is empty, a default directive enabling the [`ERROR`] level
340    /// is added.
341    ///
342    /// To set additional configuration options prior to parsing the filter, use
343    /// the [`Builder`] type instead.
344    ///
345    /// This function is equivalent to the following:
346    ///
347    /// ```rust
348    /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
349    ///
350    /// # fn docs() -> Result<EnvFilter, tracing_subscriber::filter::ParseError> {
351    /// # let directives = "";
352    /// EnvFilter::builder()
353    ///     .with_default_directive(LevelFilter::ERROR.into())
354    ///     .parse(directives)
355    /// # }
356    /// ```
357    ///
358    /// [`ERROR`]: tracing::Level::ERROR
359    pub fn try_new<S: AsRef<str>>(dirs: S) -> Result<Self, directive::ParseError> {
360        Self::builder().parse(dirs)
361    }
362
363    /// Returns a new `EnvFilter` from the value of the `RUST_LOG` environment
364    /// variable, or an error if the environment variable is unset or contains
365    /// any invalid filter directives.
366    ///
367    /// To set additional configuration options prior to parsing the filter, use
368    /// the [`Builder`] type instead.
369    ///
370    /// This function is equivalent to the following:
371    ///
372    /// ```rust
373    /// use tracing_subscriber::EnvFilter;
374    ///
375    /// # fn docs() -> Result<EnvFilter, tracing_subscriber::filter::FromEnvError> {
376    /// EnvFilter::builder().try_from_env()
377    /// # }
378    /// ```
379    pub fn try_from_default_env() -> Result<Self, FromEnvError> {
380        Self::builder().try_from_env()
381    }
382
383    /// Returns a new `EnvFilter` from the value of the given environment
384    /// variable, or an error if the environment variable is unset or contains
385    /// any invalid filter directives.
386    ///
387    /// To set additional configuration options prior to parsing the filter, use
388    /// the [`Builder`] type instead.
389    ///
390    /// This function is equivalent to the following:
391    ///
392    /// ```rust
393    /// use tracing_subscriber::EnvFilter;
394    ///
395    /// # fn docs() -> Result<EnvFilter, tracing_subscriber::filter::FromEnvError> {
396    /// # let env = "";
397    /// EnvFilter::builder().with_env_var(env).try_from_env()
398    /// # }
399    /// ```
400    pub fn try_from_env<A: AsRef<str>>(env: A) -> Result<Self, FromEnvError> {
401        Self::builder().with_env_var(env.as_ref()).try_from_env()
402    }
403
404    /// Add a filtering directive to this `EnvFilter`.
405    ///
406    /// The added directive will be used in addition to any previously set
407    /// directives, either added using this method or provided when the filter
408    /// is constructed.
409    ///
410    /// Filters may be created from [`LevelFilter`] or [`Level`], which will
411    /// enable all traces at or below a certain verbosity level, or
412    /// parsed from a string specifying a directive.
413    ///
414    /// If a filter directive is inserted that matches exactly the same spans
415    /// and events as a previous filter, but sets a different level for those
416    /// spans and events, the previous directive is overwritten.
417    ///
418    /// [`LevelFilter`]: super::LevelFilter
419    /// [`Level`]: tracing_core::Level
420    ///
421    /// # Examples
422    ///
423    /// From [`LevelFilter`]:
424    ///
425    /// ```rust
426    /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
427    /// let mut filter = EnvFilter::from_default_env()
428    ///     .add_directive(LevelFilter::INFO.into());
429    /// ```
430    ///
431    /// Or from [`Level`]:
432    ///
433    /// ```rust
434    /// # use tracing_subscriber::filter::{EnvFilter, LevelFilter};
435    /// # use tracing::Level;
436    /// let mut filter = EnvFilter::from_default_env()
437    ///     .add_directive(Level::INFO.into());
438    /// ```
439    ///
440    /// Parsed from a string:
441    ///
442    /// ```rust
443    /// use tracing_subscriber::filter::{EnvFilter, Directive};
444    ///
445    /// # fn try_mk_filter() -> Result<(), Box<dyn ::std::error::Error>> {
446    /// let mut filter = EnvFilter::try_from_default_env()?
447    ///     .add_directive("my_crate::module=trace".parse()?)
448    ///     .add_directive("my_crate::my_other_module::something=info".parse()?);
449    /// # Ok(())
450    /// # }
451    /// ```
452    /// In the above example, substitute `my_crate`, `module`, etc. with the
453    /// name your target crate/module is imported with. This might be
454    /// different from the package name in Cargo.toml (`-` is replaced by `_`).
455    /// Example, if the package name in your Cargo.toml is `MY-FANCY-LIB`, then
456    /// the corresponding Rust identifier would be `MY_FANCY_LIB`:
457    pub fn add_directive(mut self, mut directive: Directive) -> Self {
458        if !self.regex {
459            directive.deregexify();
460        }
461        if let Some(stat) = directive.to_static() {
462            self.statics.add(stat)
463        } else {
464            self.has_dynamics = true;
465            self.dynamics.add(directive);
466        }
467        self
468    }
469
470    // === filtering methods ===
471
472    /// Returns `true` if this `EnvFilter` would enable the provided `metadata`
473    /// in the current context.
474    ///
475    /// This is equivalent to calling the [`Layer::enabled`] or
476    /// [`Filter::enabled`] methods on `EnvFilter`'s implementations of those
477    /// traits, but it does not require the trait to be in scope.
478    pub fn enabled<S>(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool {
479        let level = metadata.level();
480
481        // is it possible for a dynamic filter directive to enable this event?
482        // if not, we can avoid the thread local access + iterating over the
483        // spans in the current scope.
484        if self.has_dynamics && self.dynamics.max_level >= *level {
485            if metadata.is_span() {
486                // If the metadata is a span, see if we care about its callsite.
487                let enabled_by_cs = self
488                    .by_cs
489                    .read()
490                    .ok()
491                    .map(|by_cs| by_cs.contains_key(&metadata.callsite()))
492                    .unwrap_or(false);
493                if enabled_by_cs {
494                    return true;
495                }
496            }
497
498            let enabled_by_scope = {
499                let scope = self.scope.get_or_default().borrow();
500                for filter in &*scope {
501                    if filter >= level {
502                        return true;
503                    }
504                }
505                false
506            };
507            if enabled_by_scope {
508                return true;
509            }
510        }
511
512        // is it possible for a static filter directive to enable this event?
513        if self.statics.max_level >= *level {
514            // Otherwise, fall back to checking if the callsite is
515            // statically enabled.
516            return self.statics.enabled(metadata);
517        }
518
519        false
520    }
521
522    /// Returns an optional hint of the highest [verbosity level][level] that
523    /// this `EnvFilter` will enable.
524    ///
525    /// This is equivalent to calling the [`Layer::max_level_hint`] or
526    /// [`Filter::max_level_hint`] methods on `EnvFilter`'s implementations of those
527    /// traits, but it does not require the trait to be in scope.
528    ///
529    /// [level]: tracing_core::metadata::Level
530    pub fn max_level_hint(&self) -> Option<LevelFilter> {
531        if self.dynamics.has_value_filters() {
532            // If we perform any filtering on span field *values*, we will
533            // enable *all* spans, because their field values are not known
534            // until recording.
535            return Some(LevelFilter::TRACE);
536        }
537        std::cmp::max(
538            self.statics.max_level.into(),
539            self.dynamics.max_level.into(),
540        )
541    }
542
543    /// Informs the filter that a new span was created.
544    ///
545    /// This is equivalent to calling the [`Layer::on_new_span`] or
546    /// [`Filter::on_new_span`] methods on `EnvFilter`'s implementations of those
547    /// traits, but it does not require the trait to be in scope.
548    pub fn on_new_span<S>(&self, attrs: &span::Attributes<'_>, id: &span::Id, _: Context<'_, S>) {
549        let by_cs = try_lock!(self.by_cs.read());
550        if let Some(cs) = by_cs.get(&attrs.metadata().callsite()) {
551            let span = cs.to_span_match(attrs);
552            try_lock!(self.by_id.write()).insert(id.clone(), span);
553        }
554    }
555
556    /// Informs the filter that the span with the provided `id` was entered.
557    ///
558    /// This is equivalent to calling the [`Layer::on_enter`] or
559    /// [`Filter::on_enter`] methods on `EnvFilter`'s implementations of those
560    /// traits, but it does not require the trait to be in scope.
561    pub fn on_enter<S>(&self, id: &span::Id, _: Context<'_, S>) {
562        // XXX: This is where _we_ could push IDs to the stack instead, and use
563        // that to allow changing the filter while a span is already entered.
564        // But that might be much less efficient...
565        if let Some(span) = try_lock!(self.by_id.read()).get(id) {
566            self.scope.get_or_default().borrow_mut().push(span.level());
567        }
568    }
569
570    /// Informs the filter that the span with the provided `id` was exited.
571    ///
572    /// This is equivalent to calling the [`Layer::on_exit`] or
573    /// [`Filter::on_exit`] methods on `EnvFilter`'s implementations of those
574    /// traits, but it does not require the trait to be in scope.
575    pub fn on_exit<S>(&self, id: &span::Id, _: Context<'_, S>) {
576        if self.cares_about_span(id) {
577            self.scope.get_or_default().borrow_mut().pop();
578        }
579    }
580
581    /// Informs the filter that the span with the provided `id` was closed.
582    ///
583    /// This is equivalent to calling the [`Layer::on_close`] or
584    /// [`Filter::on_close`] methods on `EnvFilter`'s implementations of those
585    /// traits, but it does not require the trait to be in scope.
586    pub fn on_close<S>(&self, id: span::Id, _: Context<'_, S>) {
587        // If we don't need to acquire a write lock, avoid doing so.
588        if !self.cares_about_span(&id) {
589            return;
590        }
591
592        let mut spans = try_lock!(self.by_id.write());
593        spans.remove(&id);
594    }
595
596    /// Informs the filter that the span with the provided `id` recorded the
597    /// provided field `values`.
598    ///
599    /// This is equivalent to calling the [`Layer::on_record`] or
600    /// [`Filter::on_record`] methods on `EnvFilter`'s implementations of those
601    /// traits, but it does not require the trait to be in scope
602    pub fn on_record<S>(&self, id: &span::Id, values: &span::Record<'_>, _: Context<'_, S>) {
603        if let Some(span) = try_lock!(self.by_id.read()).get(id) {
604            span.record_update(values);
605        }
606    }
607
608    fn cares_about_span(&self, span: &span::Id) -> bool {
609        let spans = try_lock!(self.by_id.read(), else return false);
610        spans.contains_key(span)
611    }
612
613    fn base_interest(&self) -> Interest {
614        if self.has_dynamics {
615            Interest::sometimes()
616        } else {
617            Interest::never()
618        }
619    }
620
621    fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
622        if self.has_dynamics && metadata.is_span() {
623            // If this metadata describes a span, first, check if there is a
624            // dynamic filter that should be constructed for it. If so, it
625            // should always be enabled, since it influences filtering.
626            if let Some(matcher) = self.dynamics.matcher(metadata) {
627                let mut by_cs = try_lock!(self.by_cs.write(), else return self.base_interest());
628                by_cs.insert(metadata.callsite(), matcher);
629                return Interest::always();
630            }
631        }
632
633        // Otherwise, check if any of our static filters enable this metadata.
634        if self.statics.enabled(metadata) {
635            Interest::always()
636        } else {
637            self.base_interest()
638        }
639    }
640}
641
642impl<S: Subscriber> Layer<S> for EnvFilter {
643    #[inline]
644    fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
645        EnvFilter::register_callsite(self, metadata)
646    }
647
648    #[inline]
649    fn max_level_hint(&self) -> Option<LevelFilter> {
650        EnvFilter::max_level_hint(self)
651    }
652
653    #[inline]
654    fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool {
655        self.enabled(metadata, ctx)
656    }
657
658    #[inline]
659    fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) {
660        self.on_new_span(attrs, id, ctx)
661    }
662
663    #[inline]
664    fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) {
665        self.on_record(id, values, ctx);
666    }
667
668    #[inline]
669    fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
670        self.on_enter(id, ctx);
671    }
672
673    #[inline]
674    fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
675        self.on_exit(id, ctx);
676    }
677
678    #[inline]
679    fn on_close(&self, id: span::Id, ctx: Context<'_, S>) {
680        self.on_close(id, ctx);
681    }
682}
683
684feature! {
685    #![all(feature = "registry", feature = "std")]
686    use crate::layer::Filter;
687
688    impl<S> Filter<S> for EnvFilter {
689        #[inline]
690        fn enabled(&self, meta: &Metadata<'_>, ctx: &Context<'_, S>) -> bool {
691            self.enabled(meta, ctx.clone())
692        }
693
694        #[inline]
695        fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest {
696            self.register_callsite(meta)
697        }
698
699        #[inline]
700        fn max_level_hint(&self) -> Option<LevelFilter> {
701            EnvFilter::max_level_hint(self)
702        }
703
704        #[inline]
705        fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) {
706            self.on_new_span(attrs, id, ctx)
707        }
708
709        #[inline]
710        fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) {
711            self.on_record(id, values, ctx);
712        }
713
714        #[inline]
715        fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
716            self.on_enter(id, ctx);
717        }
718
719        #[inline]
720        fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
721            self.on_exit(id, ctx);
722        }
723
724        #[inline]
725        fn on_close(&self, id: span::Id, ctx: Context<'_, S>) {
726            self.on_close(id, ctx);
727        }
728    }
729}
730
731impl FromStr for EnvFilter {
732    type Err = directive::ParseError;
733
734    fn from_str(spec: &str) -> Result<Self, Self::Err> {
735        Self::try_new(spec)
736    }
737}
738
739impl<S> From<S> for EnvFilter
740where
741    S: AsRef<str>,
742{
743    fn from(s: S) -> Self {
744        Self::new(s)
745    }
746}
747
748impl Default for EnvFilter {
749    fn default() -> Self {
750        Builder::default().from_directives(std::iter::empty())
751    }
752}
753
754impl fmt::Display for EnvFilter {
755    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
756        let mut statics = self.statics.iter();
757        let wrote_statics = if let Some(next) = statics.next() {
758            fmt::Display::fmt(next, f)?;
759            for directive in statics {
760                write!(f, ",{}", directive)?;
761            }
762            true
763        } else {
764            false
765        };
766
767        let mut dynamics = self.dynamics.iter();
768        if let Some(next) = dynamics.next() {
769            if wrote_statics {
770                f.write_str(",")?;
771            }
772            fmt::Display::fmt(next, f)?;
773            for directive in dynamics {
774                write!(f, ",{}", directive)?;
775            }
776        }
777        Ok(())
778    }
779}
780
781// ===== impl FromEnvError =====
782
783impl From<directive::ParseError> for FromEnvError {
784    fn from(p: directive::ParseError) -> Self {
785        Self {
786            kind: ErrorKind::Parse(p),
787        }
788    }
789}
790
791impl From<env::VarError> for FromEnvError {
792    fn from(v: env::VarError) -> Self {
793        Self {
794            kind: ErrorKind::Env(v),
795        }
796    }
797}
798
799impl fmt::Display for FromEnvError {
800    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
801        match self.kind {
802            ErrorKind::Parse(ref p) => p.fmt(f),
803            ErrorKind::Env(ref e) => e.fmt(f),
804        }
805    }
806}
807
808impl Error for FromEnvError {
809    fn source(&self) -> Option<&(dyn Error + 'static)> {
810        match self.kind {
811            ErrorKind::Parse(ref p) => Some(p),
812            ErrorKind::Env(ref e) => Some(e),
813        }
814    }
815}
816
817#[cfg(test)]
818mod tests {
819    use super::*;
820    use tracing_core::field::FieldSet;
821    use tracing_core::*;
822
823    struct NoSubscriber;
824    impl Subscriber for NoSubscriber {
825        #[inline]
826        fn register_callsite(&self, _: &'static Metadata<'static>) -> subscriber::Interest {
827            subscriber::Interest::always()
828        }
829        fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
830            span::Id::from_u64(0xDEAD)
831        }
832        fn event(&self, _event: &Event<'_>) {}
833        fn record(&self, _span: &span::Id, _values: &span::Record<'_>) {}
834        fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
835
836        #[inline]
837        fn enabled(&self, _metadata: &Metadata<'_>) -> bool {
838            true
839        }
840        fn enter(&self, _span: &span::Id) {}
841        fn exit(&self, _span: &span::Id) {}
842    }
843
844    struct Cs;
845    impl Callsite for Cs {
846        fn set_interest(&self, _interest: Interest) {}
847        fn metadata(&self) -> &Metadata<'_> {
848            unimplemented!()
849        }
850    }
851
852    #[test]
853    fn callsite_enabled_no_span_directive() {
854        let filter = EnvFilter::new("app=debug").with_subscriber(NoSubscriber);
855        static META: &Metadata<'static> = &Metadata::new(
856            "mySpan",
857            "app",
858            Level::TRACE,
859            None,
860            None,
861            None,
862            FieldSet::new(&[], identify_callsite!(&Cs)),
863            Kind::SPAN,
864        );
865
866        let interest = filter.register_callsite(META);
867        assert!(interest.is_never());
868    }
869
870    #[test]
871    fn callsite_off() {
872        let filter = EnvFilter::new("app=off").with_subscriber(NoSubscriber);
873        static META: &Metadata<'static> = &Metadata::new(
874            "mySpan",
875            "app",
876            Level::ERROR,
877            None,
878            None,
879            None,
880            FieldSet::new(&[], identify_callsite!(&Cs)),
881            Kind::SPAN,
882        );
883
884        let interest = filter.register_callsite(META);
885        assert!(interest.is_never());
886    }
887
888    #[test]
889    fn callsite_enabled_includes_span_directive() {
890        let filter = EnvFilter::new("app[mySpan]=debug").with_subscriber(NoSubscriber);
891        static META: &Metadata<'static> = &Metadata::new(
892            "mySpan",
893            "app",
894            Level::TRACE,
895            None,
896            None,
897            None,
898            FieldSet::new(&[], identify_callsite!(&Cs)),
899            Kind::SPAN,
900        );
901
902        let interest = filter.register_callsite(META);
903        assert!(interest.is_always());
904    }
905
906    #[test]
907    fn callsite_enabled_includes_span_directive_field() {
908        let filter =
909            EnvFilter::new("app[mySpan{field=\"value\"}]=debug").with_subscriber(NoSubscriber);
910        static META: &Metadata<'static> = &Metadata::new(
911            "mySpan",
912            "app",
913            Level::TRACE,
914            None,
915            None,
916            None,
917            FieldSet::new(&["field"], identify_callsite!(&Cs)),
918            Kind::SPAN,
919        );
920
921        let interest = filter.register_callsite(META);
922        assert!(interest.is_always());
923    }
924
925    #[test]
926    fn callsite_enabled_includes_span_directive_multiple_fields() {
927        let filter = EnvFilter::new("app[mySpan{field=\"value\",field2=2}]=debug")
928            .with_subscriber(NoSubscriber);
929        static META: &Metadata<'static> = &Metadata::new(
930            "mySpan",
931            "app",
932            Level::TRACE,
933            None,
934            None,
935            None,
936            FieldSet::new(&["field"], identify_callsite!(&Cs)),
937            Kind::SPAN,
938        );
939
940        let interest = filter.register_callsite(META);
941        assert!(interest.is_never());
942    }
943
944    #[test]
945    fn roundtrip() {
946        let f1: EnvFilter =
947            "[span1{foo=1}]=error,[span2{bar=2 baz=false}],crate2[{quux=\"quuux\"}]=debug"
948                .parse()
949                .unwrap();
950        let f2: EnvFilter = format!("{}", f1).parse().unwrap();
951        assert_eq!(f1.statics, f2.statics);
952        assert_eq!(f1.dynamics, f2.dynamics);
953    }
954
955    #[test]
956    fn size_of_filters() {
957        fn print_sz(s: &str) {
958            let filter = s.parse::<EnvFilter>().expect("filter should parse");
959            println!(
960                "size_of_val({:?})\n -> {}B",
961                s,
962                std::mem::size_of_val(&filter)
963            );
964        }
965
966        print_sz("info");
967
968        print_sz("foo=debug");
969
970        print_sz(
971            "crate1::mod1=error,crate1::mod2=warn,crate1::mod2::mod3=info,\
972            crate2=debug,crate3=trace,crate3::mod2::mod1=off",
973        );
974
975        print_sz("[span1{foo=1}]=error,[span2{bar=2 baz=false}],crate2[{quux=\"quuux\"}]=debug");
976
977        print_sz(
978            "crate1::mod1=error,crate1::mod2=warn,crate1::mod2::mod3=info,\
979            crate2=debug,crate3=trace,crate3::mod2::mod1=off,[span1{foo=1}]=error,\
980            [span2{bar=2 baz=false}],crate2[{quux=\"quuux\"}]=debug",
981        );
982    }
983
984    #[test]
985    fn parse_empty_string() {
986        // There is no corresponding test for [`Builder::parse_lossy`] as failed
987        // parsing does not produce any observable side effects. If this test fails
988        // check that [`Builder::parse_lossy`] is behaving correctly as well.
989        assert!(EnvFilter::builder().parse("").is_ok());
990    }
991}