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 alloc::{fmt, str::FromStr, vec::Vec};
18use core::cell::RefCell;
19use directive::ParseError;
20use std::{collections::HashMap, env, error::Error};
21use thread_local::ThreadLocal;
22use tracing_core::{
23    callsite,
24    field::Field,
25    span,
26    subscriber::{Interest, Subscriber},
27    Metadata,
28};
29
30/// A [`Layer`] which filters spans and events based on a set of filter
31/// directives.
32///
33/// `EnvFilter` implements both the [`Layer`](#impl-Layer<S>) and [`Filter`] traits, so it may
34/// be used for both [global filtering][global] and [per-layer filtering][plf],
35/// respectively. See [the documentation on filtering with `Layer`s][filtering]
36/// for details.
37///
38/// The [`Targets`] type implements a similar form of filtering, but without the
39/// ability to dynamically enable events based on the current span context, and
40/// without filtering on field values. When these features are not required,
41/// [`Targets`] provides a lighter-weight alternative to [`EnvFilter`].
42///
43/// # Directives
44///
45/// A filter consists of one or more comma-separated directives which match on [`Span`]s and [`Event`]s.
46/// Each directive may have a corresponding maximum verbosity [`level`] which
47/// enables (e.g., _selects for_) spans and events that match. Like `log`,
48/// `tracing` considers less exclusive levels (like `trace` or `info`) to be more
49/// verbose than more exclusive levels (like `error` or `warn`).
50///
51/// The directive syntax is similar to that of [`env_logger`]'s. At a high level, the syntax for directives
52/// consists of several parts:
53///
54/// ```text
55/// target[span{field=value}]=level
56/// ```
57///
58/// Each component (`target`, `span`, `field`, `value`, and `level`) will be covered in turn.
59///
60/// - `target` matches the event or span's target. In general, this is the module path and/or crate name.
61///   Examples of targets `h2`, `tokio::net`, or `tide::server`. For more information on targets,
62///   please refer to [`Metadata`]'s documentation.
63/// - `span` matches on the span's name. If a `span` directive is provided alongside a `target`,
64///   the `span` directive will match on spans _within_ the `target`.
65/// - `field` matches on [fields] within spans. Field names can also be supplied without a `value`
66///   and will match on any [`Span`] or [`Event`] that has a field with that name.
67///   For example: `[span{field=\"value\"}]=debug`, `[{field}]=trace`.
68/// - `value` matches on the value of a span's field. If a value is a numeric literal or a bool,
69///   it will match _only_ on that value. Otherwise, this filter matches the
70///   [`std::fmt::Debug`] output from the value.
71/// - `level` sets a maximum verbosity level accepted by this directive.
72///
73/// When a field value directive (`[{<FIELD NAME>=<FIELD_VALUE>}]=...`) matches a
74/// value's [`std::fmt::Debug`] output (i.e., the field value in the directive
75/// is not a `bool`, `i64`, `u64`, or `f64` literal), the matched pattern may be
76/// interpreted as either a regular expression or as the precise expected
77/// output of the field's [`std::fmt::Debug`] implementation. By default, these
78/// filters are interpreted as regular expressions, but this can be disabled
79/// using the [`Builder::with_regex`] builder method to use precise matching
80/// instead.
81///
82/// When field value filters are interpreted as regular expressions, the
83/// [`regex` crate's regular expression syntax][re-syntax] is supported.
84///
85/// **Note**: When filters are constructed from potentially untrusted inputs,
86/// [disabling regular expression matching](Builder::with_regex) is strongly
87/// recommended.
88///
89/// ## Usage Notes
90///
91/// - The portion of the directive which is included within the square brackets is `tracing`-specific.
92/// - Any portion of the directive can be omitted.
93///     - The sole exception are the `field` and `value` directives. If a `value` is provided,
94///       a `field` must _also_ be provided. However, the converse does not hold, as fields can
95///       be matched without a value.
96/// - If only a level is provided, it will set the maximum level for all `Span`s and `Event`s
97///   that are not enabled by other filters.
98/// - A directive without a level will enable anything that it matches. This is equivalent to `=trace`.
99/// - When a crate has a dash in its name, the default target for events will be the
100///   crate's module path as it appears in Rust. This means every dash will be replaced
101///   with an underscore.
102/// - A dash in a target will only appear when being specified explicitly:
103///   `tracing::info!(target: "target-name", ...);`
104///
105/// ## Example Syntax
106///
107/// - `tokio::net=info` will enable all spans or events that:
108///    - have the `tokio::net` target,
109///    - at the level `info` or above.
110/// - `warn,tokio::net=info` will enable all spans and events that:
111///    - are at the level `warn` or above, *or*
112///    - have the `tokio::net` target at the level `info` or above.
113/// - `my_crate[span_a]=trace` will enable all spans and events that:
114///    - are within the `span_a` span or named `span_a` _if_ `span_a` has the target `my_crate`,
115///    - at the level `trace` or above.
116/// - `[span_b{name=\"bob\"}]` will enable all spans or event that:
117///    - have _any_ target,
118///    - are inside a span named `span_b`,
119///    - which has a field named `name` with value `bob`,
120///    - at _any_ level.
121///
122/// # Examples
123///
124/// Parsing an `EnvFilter` from the [default environment
125/// variable](EnvFilter::from_default_env) (`RUST_LOG`):
126///
127/// ```
128/// use tracing_subscriber::{EnvFilter, fmt, prelude::*};
129///
130/// tracing_subscriber::registry()
131///     .with(fmt::layer())
132///     .with(EnvFilter::from_default_env())
133///     .init();
134/// ```
135///
136/// Parsing an `EnvFilter` [from a user-provided environment
137/// variable](EnvFilter::from_env):
138///
139/// ```
140/// use tracing_subscriber::{EnvFilter, fmt, prelude::*};
141///
142/// tracing_subscriber::registry()
143///     .with(fmt::layer())
144///     .with(EnvFilter::from_env("MYAPP_LOG"))
145///     .init();
146/// ```
147///
148/// Using `EnvFilter` as a [per-layer filter][plf] to filter only a single
149/// [`Layer`]:
150///
151/// ```
152/// use tracing_subscriber::{EnvFilter, fmt, prelude::*};
153///
154/// // Parse an `EnvFilter` configuration from the `RUST_LOG`
155/// // environment variable.
156/// let filter = EnvFilter::from_default_env();
157///
158/// // Apply the filter to this layer *only*.
159/// let filtered_layer = fmt::layer().with_filter(filter);
160///
161/// // Some other layer, whose output we don't want to filter.
162/// let unfiltered_layer = // ...
163///     # fmt::layer();
164///
165/// tracing_subscriber::registry()
166///     .with(filtered_layer)
167///     .with(unfiltered_layer)
168///     .init();
169/// ```
170/// # Constructing `EnvFilter`s
171///
172/// An `EnvFilter` is be constructed by parsing a string containing one or more
173/// directives. The [`EnvFilter::new`] constructor parses an `EnvFilter` from a
174/// string, ignoring any invalid directives, while [`EnvFilter::try_new`]
175/// returns an error if invalid directives are encountered. Similarly, the
176/// [`EnvFilter::from_env`] and [`EnvFilter::try_from_env`] constructors parse
177/// an `EnvFilter` from the value of the provided environment variable, with
178/// lossy and strict validation, respectively.
179///
180/// A [builder](EnvFilter::builder) interface is available to set additional
181/// configuration options prior to parsing an `EnvFilter`. See the [`Builder`
182/// type's documentation](Builder) for details on the options that can be
183/// configured using the builder.
184///
185/// [`Span`]: tracing_core::span
186/// [fields]: tracing_core::Field
187/// [`Event`]: tracing_core::Event
188/// [`level`]: tracing_core::Level
189/// [`Metadata`]: tracing_core::Metadata
190/// [`Targets`]: crate::filter::Targets
191/// [`env_logger`]: https://crates.io/crates/env_logger
192/// [`Filter`]: #impl-Filter<S>
193/// [global]: crate::layer#global-filtering
194/// [plf]: crate::layer#per-layer-filtering
195/// [filtering]: crate::layer#filtering-with-layers
196/// [re-syntax]: https://docs.rs/regex/1.11.1/regex/#syntax
197#[cfg_attr(docsrs, doc(cfg(all(feature = "env-filter", feature = "std"))))]
198#[derive(Debug)]
199pub struct EnvFilter {
200    statics: directive::Statics,
201    dynamics: directive::Dynamics,
202    has_dynamics: bool,
203    by_id: RwLock<HashMap<span::Id, directive::SpanMatcher>>,
204    by_cs: RwLock<HashMap<callsite::Identifier, directive::CallsiteMatcher>>,
205    scope: ThreadLocal<RefCell<Vec<LevelFilter>>>,
206    regex: bool,
207}
208
209/// Creates an [`EnvFilter`] with the same directives as `self`.
210///
211/// This does *not* clone any of the dynamic state that [`EnvFilter`] acquires while attached to a
212/// subscriber.
213impl Clone for EnvFilter {
214    fn clone(&self) -> EnvFilter {
215        EnvFilter {
216            statics: self.statics.clone(),
217            dynamics: self.dynamics.clone(),
218            has_dynamics: self.has_dynamics,
219            by_id: RwLock::default(),
220            by_cs: RwLock::default(),
221            scope: ThreadLocal::new(),
222            regex: self.regex,
223        }
224    }
225}
226
227type FieldMap<T> = HashMap<Field, T>;
228
229/// Indicates that an error occurred while parsing a `EnvFilter` from an
230/// environment variable.
231#[cfg_attr(docsrs, doc(cfg(all(feature = "env-filter", feature = "std"))))]
232#[derive(Debug)]
233pub struct FromEnvError {
234    kind: ErrorKind,
235}
236
237#[derive(Debug)]
238enum ErrorKind {
239    Parse(ParseError),
240    Env(env::VarError),
241}
242
243impl EnvFilter {
244    /// `RUST_LOG` is the default environment variable used by
245    /// [`EnvFilter::from_default_env`] and [`EnvFilter::try_from_default_env`].
246    ///
247    /// [`EnvFilter::from_default_env`]: EnvFilter::from_default_env()
248    /// [`EnvFilter::try_from_default_env`]: EnvFilter::try_from_default_env()
249    pub const DEFAULT_ENV: &'static str = "RUST_LOG";
250
251    // === constructors, etc ===
252
253    /// Returns a [builder] that can be used to configure a new [`EnvFilter`]
254    /// instance.
255    ///
256    /// The [`Builder`] type is used to set additional configurations, such as
257    /// [whether regular expressions are enabled](Builder::with_regex) or [the
258    /// default directive](Builder::with_default_directive) before parsing an
259    /// [`EnvFilter`] from a string or environment variable.
260    ///
261    /// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html
262    pub fn builder() -> Builder {
263        Builder::default()
264    }
265
266    /// Returns a new `EnvFilter` from the value of the `RUST_LOG` environment
267    /// variable, ignoring any invalid filter directives.
268    ///
269    /// If the environment variable is empty or not set, or if it contains only
270    /// invalid directives, a default directive enabling the [`ERROR`] level is
271    /// added.
272    ///
273    /// To set additional configuration options prior to parsing the filter, use
274    /// the [`Builder`] type instead.
275    ///
276    /// This function is equivalent to the following:
277    ///
278    /// ```rust
279    /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
280    ///
281    /// # fn docs() -> EnvFilter {
282    /// EnvFilter::builder()
283    ///     .with_default_directive(LevelFilter::ERROR.into())
284    ///     .from_env_lossy()
285    /// # }
286    /// ```
287    ///
288    /// [`ERROR`]: tracing::Level::ERROR
289    pub fn from_default_env() -> Self {
290        Self::builder()
291            .with_default_directive(LevelFilter::ERROR.into())
292            .from_env_lossy()
293    }
294
295    /// Returns a new `EnvFilter` from the value of the given environment
296    /// variable, ignoring any invalid filter directives.
297    ///
298    /// If the environment variable is empty or not set, or if it contains only
299    /// invalid directives, a default directive enabling the [`ERROR`] level is
300    /// added.
301    ///
302    /// To set additional configuration options prior to parsing the filter, use
303    /// the [`Builder`] type instead.
304    ///
305    /// This function is equivalent to the following:
306    ///
307    /// ```rust
308    /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
309    ///
310    /// # fn docs() -> EnvFilter {
311    /// # let env = "";
312    /// EnvFilter::builder()
313    ///     .with_default_directive(LevelFilter::ERROR.into())
314    ///     .with_env_var(env)
315    ///     .from_env_lossy()
316    /// # }
317    /// ```
318    ///
319    /// [`ERROR`]: tracing::Level::ERROR
320    pub fn from_env<A: AsRef<str>>(env: A) -> Self {
321        Self::builder()
322            .with_default_directive(LevelFilter::ERROR.into())
323            .with_env_var(env.as_ref())
324            .from_env_lossy()
325    }
326
327    /// Returns a new `EnvFilter` from the directives in the given string,
328    /// ignoring any that are invalid.
329    ///
330    /// If the string is empty or contains only invalid directives, a default
331    /// directive enabling the [`ERROR`] level is added.
332    ///
333    /// To set additional configuration options prior to parsing the filter, use
334    /// the [`Builder`] type instead.
335    ///
336    /// This function is equivalent to the following:
337    ///
338    /// ```rust
339    /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
340    ///
341    /// # fn docs() -> EnvFilter {
342    /// # let directives = "";
343    /// EnvFilter::builder()
344    ///     .with_default_directive(LevelFilter::ERROR.into())
345    ///     .parse_lossy(directives)
346    /// # }
347    /// ```
348    ///
349    /// [`ERROR`]: tracing::Level::ERROR
350    pub fn new<S: AsRef<str>>(directives: S) -> Self {
351        Self::builder()
352            .with_default_directive(LevelFilter::ERROR.into())
353            .parse_lossy(directives)
354    }
355
356    /// Returns a new `EnvFilter` from the directives in the given string,
357    /// or an error if any are invalid.
358    ///
359    /// If the string is empty, a default directive enabling the [`ERROR`] level
360    /// is added.
361    ///
362    /// To set additional configuration options prior to parsing the filter, use
363    /// the [`Builder`] type instead.
364    ///
365    /// This function is equivalent to the following:
366    ///
367    /// ```rust
368    /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
369    ///
370    /// # fn docs() -> Result<EnvFilter, tracing_subscriber::filter::ParseError> {
371    /// # let directives = "";
372    /// EnvFilter::builder()
373    ///     .with_default_directive(LevelFilter::ERROR.into())
374    ///     .parse(directives)
375    /// # }
376    /// ```
377    ///
378    /// [`ERROR`]: tracing::Level::ERROR
379    pub fn try_new<S: AsRef<str>>(dirs: S) -> Result<Self, directive::ParseError> {
380        Self::builder().parse(dirs)
381    }
382
383    /// Returns a new `EnvFilter` from the value of the `RUST_LOG` 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    /// EnvFilter::builder().try_from_env()
397    /// # }
398    /// ```
399    pub fn try_from_default_env() -> Result<Self, FromEnvError> {
400        Self::builder().try_from_env()
401    }
402
403    /// Returns a new `EnvFilter` from the value of the given environment
404    /// variable, or an error if the environment variable is unset or contains
405    /// any invalid filter directives.
406    ///
407    /// To set additional configuration options prior to parsing the filter, use
408    /// the [`Builder`] type instead.
409    ///
410    /// This function is equivalent to the following:
411    ///
412    /// ```rust
413    /// use tracing_subscriber::EnvFilter;
414    ///
415    /// # fn docs() -> Result<EnvFilter, tracing_subscriber::filter::FromEnvError> {
416    /// # let env = "";
417    /// EnvFilter::builder().with_env_var(env).try_from_env()
418    /// # }
419    /// ```
420    pub fn try_from_env<A: AsRef<str>>(env: A) -> Result<Self, FromEnvError> {
421        Self::builder().with_env_var(env.as_ref()).try_from_env()
422    }
423
424    /// Add a filtering directive to this `EnvFilter`.
425    ///
426    /// The added directive will be used in addition to any previously set
427    /// directives, either added using this method or provided when the filter
428    /// is constructed.
429    ///
430    /// Filters may be created from [`LevelFilter`] or [`Level`], which will
431    /// enable all traces at or below a certain verbosity level, or
432    /// parsed from a string specifying a directive.
433    ///
434    /// If a filter directive is inserted that matches exactly the same spans
435    /// and events as a previous filter, but sets a different level for those
436    /// spans and events, the previous directive is overwritten.
437    ///
438    /// [`LevelFilter`]: super::LevelFilter
439    /// [`Level`]: tracing_core::Level
440    ///
441    /// # Examples
442    ///
443    /// From [`LevelFilter`]:
444    ///
445    /// ```rust
446    /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
447    /// let mut filter = EnvFilter::from_default_env()
448    ///     .add_directive(LevelFilter::INFO.into());
449    /// ```
450    ///
451    /// Or from [`Level`]:
452    ///
453    /// ```rust
454    /// # use tracing_subscriber::filter::{EnvFilter, LevelFilter};
455    /// # use tracing::Level;
456    /// let mut filter = EnvFilter::from_default_env()
457    ///     .add_directive(Level::INFO.into());
458    /// ```
459    ///
460    /// Parsed from a string:
461    ///
462    /// ```rust