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 ///