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)]
7 pub use self::{builder::Builder, directive::Directive, field::BadName as BadFieldName};
8 mod builder;
9 mod directive;
10 mod field;
11 
12 use crate::{
13     filter::LevelFilter,
14     layer::{Context, Layer},
15     sync::RwLock,
16 };
17 use directive::ParseError;
18 use std::{cell::RefCell, collections::HashMap, env, error::Error, fmt, str::FromStr};
19 use thread_local::ThreadLocal;
20 use 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)]
197 pub 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 type 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)]
213 pub struct FromEnvError {
214     kind: ErrorKind,
215 }
216 
217 #[derive(Debug)]
218 enum ErrorKind {
219     Parse(ParseError),
220     Env(env::VarError),
221 }
222 
223 impl 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
builder() -> Builder242     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
from_default_env() -> Self269     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
from_env<A: AsRef<str>>(env: A) -> Self300     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
new<S: AsRef<str>>(directives: S) -> Self330     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
try_new<S: AsRef<str>>(dirs: S) -> Result<Self, directive::ParseError>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     /// ```
try_from_default_env() -> Result<Self, FromEnvError>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     /// ```
try_from_env<A: AsRef<str>>(env: A) -> Result<Self, FromEnvError>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`:
add_directive(mut self, mut directive: Directive) -> Self457     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.
enabled<S>(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool478     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 loca'l 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
max_level_hint(&self) -> Option<LevelFilter>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.
on_new_span<S>(&self, attrs: &span::Attributes<'_>, id: &span::Id, _: Context<'_, S>)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.
on_enter<S>(&self, id: &span::Id, _: Context<'_, S>)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.
on_exit<S>(&self, id: &span::Id, _: Context<'_, S>)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.
on_close<S>(&self, id: span::Id, _: Context<'_, S>)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
on_record<S>(&self, id: &span::Id, values: &span::Record<'_>, _: Context<'_, S>)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 
cares_about_span(&self, span: &span::Id) -> bool608     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 
base_interest(&self) -> Interest613     fn base_interest(&self) -> Interest {
614         if self.has_dynamics {
615             Interest::sometimes()
616         } else {
617             Interest::never()
618         }
619     }
620 
register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest621     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 
642 impl<S: Subscriber> Layer<S> for EnvFilter {
643     #[inline]
register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest644     fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
645         EnvFilter::register_callsite(self, metadata)
646     }
647 
648     #[inline]
max_level_hint(&self) -> Option<LevelFilter>649     fn max_level_hint(&self) -> Option<LevelFilter> {
650         EnvFilter::max_level_hint(self)
651     }
652 
653     #[inline]
enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool654     fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool {
655         self.enabled(metadata, ctx)
656     }
657 
658     #[inline]
on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>)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]
on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>)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]
on_enter(&self, id: &span::Id, ctx: Context<'_, S>)669     fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
670         self.on_enter(id, ctx);
671     }
672 
673     #[inline]
on_exit(&self, id: &span::Id, ctx: Context<'_, S>)674     fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
675         self.on_exit(id, ctx);
676     }
677 
678     #[inline]
on_close(&self, id: span::Id, ctx: Context<'_, S>)679     fn on_close(&self, id: span::Id, ctx: Context<'_, S>) {
680         self.on_close(id, ctx);
681     }
682 }
683 
684 feature! {
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 
731 impl FromStr for EnvFilter {
732     type Err = directive::ParseError;
733 
from_str(spec: &str) -> Result<Self, Self::Err>734     fn from_str(spec: &str) -> Result<Self, Self::Err> {
735         Self::try_new(spec)
736     }
737 }
738 
739 impl<S> From<S> for EnvFilter
740 where
741     S: AsRef<str>,
742 {
from(s: S) -> Self743     fn from(s: S) -> Self {
744         Self::new(s)
745     }
746 }
747 
748 impl Default for EnvFilter {
default() -> Self749     fn default() -> Self {
750         Builder::default().from_directives(std::iter::empty())
751     }
752 }
753 
754 impl fmt::Display for EnvFilter {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result755     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 
783 impl From<directive::ParseError> for FromEnvError {
from(p: directive::ParseError) -> Self784     fn from(p: directive::ParseError) -> Self {
785         Self {
786             kind: ErrorKind::Parse(p),
787         }
788     }
789 }
790 
791 impl From<env::VarError> for FromEnvError {
from(v: env::VarError) -> Self792     fn from(v: env::VarError) -> Self {
793         Self {
794             kind: ErrorKind::Env(v),
795         }
796     }
797 }
798 
799 impl fmt::Display for FromEnvError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result800     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 
808 impl Error for FromEnvError {
source(&self) -> Option<&(dyn Error + 'static)>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)]
818 mod 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]
register_callsite(&self, _: &'static Metadata<'static>) -> subscriber::Interest826         fn register_callsite(&self, _: &'static Metadata<'static>) -> subscriber::Interest {
827             subscriber::Interest::always()
828         }
new_span(&self, _: &span::Attributes<'_>) -> span::Id829         fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
830             span::Id::from_u64(0xDEAD)
831         }
event(&self, _event: &Event<'_>)832         fn event(&self, _event: &Event<'_>) {}
record(&self, _span: &span::Id, _values: &span::Record<'_>)833         fn record(&self, _span: &span::Id, _values: &span::Record<'_>) {}
record_follows_from(&self, _span: &span::Id, _follows: &span::Id)834         fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
835 
836         #[inline]
enabled(&self, _metadata: &Metadata<'_>) -> bool837         fn enabled(&self, _metadata: &Metadata<'_>) -> bool {
838             true
839         }
enter(&self, _span: &span::Id)840         fn enter(&self, _span: &span::Id) {}
exit(&self, _span: &span::Id)841         fn exit(&self, _span: &span::Id) {}
842     }
843 
844     struct Cs;
845     impl Callsite for Cs {
set_interest(&self, _interest: Interest)846         fn set_interest(&self, _interest: Interest) {}
metadata(&self) -> &Metadata<'_>847         fn metadata(&self) -> &Metadata<'_> {
848             unimplemented!()
849         }
850     }
851 
852     #[test]
callsite_enabled_no_span_directive()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]
callsite_off()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]
callsite_enabled_includes_span_directive()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]
callsite_enabled_includes_span_directive_field()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]
callsite_enabled_includes_span_directive_multiple_fields()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]
roundtrip()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]
size_of_filters()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]
parse_empty_string()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 }
992