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