tracing_subscriber/layer/
mod.rs

1//! The [`Layer`] trait, a composable abstraction for building [`Subscriber`]s.
2//!
3//! The [`Subscriber`] trait in `tracing-core` represents the _complete_ set of
4//! functionality required to consume `tracing` instrumentation. This means that
5//! a single `Subscriber` instance is a self-contained implementation of a
6//! complete strategy for collecting traces; but it _also_ means that the
7//! `Subscriber` trait cannot easily be composed with other `Subscriber`s.
8//!
9//! In particular, [`Subscriber`]s are responsible for generating [span IDs] and
10//! assigning them to spans. Since these IDs must uniquely identify a span
11//! within the context of the current trace, this means that there may only be
12//! a single `Subscriber` for a given thread at any point in time —
13//! otherwise, there would be no authoritative source of span IDs.
14//!
15//! On the other hand, the majority of the [`Subscriber`] trait's functionality
16//! is composable: any number of subscribers may _observe_ events, span entry
17//! and exit, and so on, provided that there is a single authoritative source of
18//! span IDs. The [`Layer`] trait represents this composable subset of the
19//! [`Subscriber`] behavior; it can _observe_ events and spans, but does not
20//! assign IDs.
21//!
22//! # Composing Layers
23//!
24//! Since a [`Layer`] does not implement a complete strategy for collecting
25//! traces, it must be composed with a `Subscriber` in order to be used. The
26//! [`Layer`] trait is generic over a type parameter (called `S` in the trait
27//! definition), representing the types of `Subscriber` they can be composed
28//! with. Thus, a [`Layer`] may be implemented that will only compose with a
29//! particular `Subscriber` implementation, or additional trait bounds may be
30//! added to constrain what types implementing `Subscriber` a `Layer` can wrap.
31//!
32//! `Layer`s may be added to a `Subscriber` by using the [`SubscriberExt::with`]
33//! method, which is provided by `tracing-subscriber`'s [prelude]. This method
34//! returns a [`Layered`] struct that implements `Subscriber` by composing the
35//! `Layer` with the `Subscriber`.
36//!
37//! For example:
38//! ```rust
39//! use tracing_subscriber::Layer;
40//! use tracing_subscriber::prelude::*;
41//! use tracing::Subscriber;
42//!
43//! pub struct MyLayer {
44//!     // ...
45//! }
46//!
47//! impl<S: Subscriber> Layer<S> for MyLayer {
48//!     // ...
49//! }
50//!
51//! pub struct MySubscriber {
52//!     // ...
53//! }
54//!
55//! # use tracing_core::{span::{Id, Attributes, Record}, Metadata, Event};
56//! impl Subscriber for MySubscriber {
57//!     // ...
58//! #   fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(1) }
59//! #   fn record(&self, _: &Id, _: &Record) {}
60//! #   fn event(&self, _: &Event) {}
61//! #   fn record_follows_from(&self, _: &Id, _: &Id) {}
62//! #   fn enabled(&self, _: &Metadata) -> bool { false }
63//! #   fn enter(&self, _: &Id) {}
64//! #   fn exit(&self, _: &Id) {}
65//! }
66//! # impl MyLayer {
67//! # fn new() -> Self { Self {} }
68//! # }
69//! # impl MySubscriber {
70//! # fn new() -> Self { Self {} }
71//! # }
72//!
73//! let subscriber = MySubscriber::new()
74//!     .with(MyLayer::new());
75//!
76//! tracing::subscriber::set_global_default(subscriber);
77//! ```
78//!
79//! Multiple `Layer`s may be composed in the same manner:
80//! ```rust
81//! # use tracing_subscriber::{Layer, layer::SubscriberExt};
82//! # use tracing::Subscriber;
83//! pub struct MyOtherLayer {
84//!     // ...
85//! }
86//!
87//! impl<S: Subscriber> Layer<S> for MyOtherLayer {
88//!     // ...
89//! }
90//!
91//! pub struct MyThirdLayer {
92//!     // ...
93//! }
94//!
95//! impl<S: Subscriber> Layer<S> for MyThirdLayer {
96//!     // ...
97//! }
98//! # pub struct MyLayer {}
99//! # impl<S: Subscriber> Layer<S> for MyLayer {}
100//! # pub struct MySubscriber { }
101//! # use tracing_core::{span::{Id, Attributes, Record}, Metadata, Event};
102//! # impl Subscriber for MySubscriber {
103//! #   fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(1) }
104//! #   fn record(&self, _: &Id, _: &Record) {}
105//! #   fn event(&self, _: &Event) {}
106//! #   fn record_follows_from(&self, _: &Id, _: &Id) {}
107//! #   fn enabled(&self, _: &Metadata) -> bool { false }
108//! #   fn enter(&self, _: &Id) {}
109//! #   fn exit(&self, _: &Id) {}
110//! # }
111//! # impl MyLayer {
112//! # fn new() -> Self { Self {} }
113//! # }
114//! # impl MyOtherLayer {
115//! # fn new() -> Self { Self {} }
116//! # }
117//! # impl MyThirdLayer {
118//! # fn new() -> Self { Self {} }
119//! # }
120//! # impl MySubscriber {
121//! # fn new() -> Self { Self {} }
122//! # }
123//!
124//! let subscriber = MySubscriber::new()
125//!     .with(MyLayer::new())
126//!     .with(MyOtherLayer::new())
127//!     .with(MyThirdLayer::new());
128//!
129//! tracing::subscriber::set_global_default(subscriber);
130//! ```
131//!
132//! The [`Layer::with_subscriber`] constructs the [`Layered`] type from a
133//! [`Layer`] and [`Subscriber`], and is called by [`SubscriberExt::with`]. In
134//! general, it is more idiomatic to use [`SubscriberExt::with`], and treat
135//! [`Layer::with_subscriber`] as an implementation detail, as `with_subscriber`
136//! calls must be nested, leading to less clear code for the reader.
137//!
138//! ## Runtime Configuration With `Layer`s
139//!
140//! In some cases, a particular [`Layer`] may be enabled or disabled based on
141//! runtime configuration. This can introduce challenges, because the type of a
142//! layered [`Subscriber`] depends on which layers are added to it: if an `if`
143//! or `match` expression adds some [`Layer`] implementation in one branch,
144//! and other layers in another, the [`Subscriber`] values returned by those
145//! branches will have different types. For example, the following _will not_
146//! work:
147//!
148//! ```compile_fail
149//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> {
150//! # struct Config {
151//! #    is_prod: bool,
152//! #    path: &'static str,
153//! # }
154//! # let cfg = Config { is_prod: false, path: "debug.log" };
155//! use std::fs::File;
156//! use tracing_subscriber::{Registry, prelude::*};
157//!
158//! let stdout_log = tracing_subscriber::fmt::layer().pretty();
159//! let subscriber = Registry::default().with(stdout_log);
160//!
161//! // The compile error will occur here because the if and else
162//! // branches have different (and therefore incompatible) types.
163//! let subscriber = if cfg.is_prod {
164//!     let file = File::create(cfg.path)?;
165//!     let layer = tracing_subscriber::fmt::layer()
166//!         .json()
167//!         .with_writer(Arc::new(file));
168//!     layer.with(subscriber)
169//! } else {
170//!     layer
171//! };
172//!
173//! tracing::subscriber::set_global_default(subscriber)
174//!     .expect("Unable to set global subscriber");
175//! # Ok(()) }
176//! ```
177//!
178//! However, a [`Layer`] wrapped in an [`Option`] [also implements the `Layer`
179//! trait][option-impl]. This allows individual layers to be enabled or disabled at
180//! runtime while always producing a [`Subscriber`] of the same type. For
181//! example:
182//!
183//! ```
184//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> {
185//! # struct Config {
186//! #    is_prod: bool,
187//! #    path: &'static str,
188//! # }
189//! # let cfg = Config { is_prod: false, path: "debug.log" };
190//! use std::fs::File;
191//! use tracing_subscriber::{Registry, prelude::*};
192//!
193//! let stdout_log = tracing_subscriber::fmt::layer().pretty();
194//! let subscriber = Registry::default().with(stdout_log);
195//!
196//! // if `cfg.is_prod` is true, also log JSON-formatted logs to a file.
197//! let json_log = if cfg.is_prod {
198//!     let file = File::create(cfg.path)?;
199//!     let json_log = tracing_subscriber::fmt::layer()
200//!         .json()
201//!         .with_writer(file);
202//!     Some(json_log)
203//! } else {
204//!     None
205//! };
206//!
207//! // If `cfg.is_prod` is false, then `json` will be `None`, and this layer
208//! // will do nothing. However, the subscriber will still have the same type
209//! // regardless of whether the `Option`'s value is `None` or `Some`.
210//! let subscriber = subscriber.with(json_log);
211//!
212//! tracing::subscriber::set_global_default(subscriber)
213//!    .expect("Unable to set global subscriber");
214//! # Ok(()) }
215//! ```
216//!
217//! If a [`Layer`] may be one of several different types, note that [`Box<dyn
218//! Layer<S> + Send + Sync>` implements `Layer`][box-impl].
219//! This may be used to erase the type of a [`Layer`].
220//!
221//! For example, a function that configures a [`Layer`] to log to one of
222//! several outputs might return a `Box<dyn Layer<S> + Send + Sync + 'static>`:
223//! ```
224//! use tracing_subscriber::{
225//!     Layer,
226//!     registry::LookupSpan,
227//!     prelude::*,
228//! };
229//! use std::{path::PathBuf, fs::File, io};
230//!
231//! /// Configures whether logs are emitted to a file, to stdout, or to stderr.
232//! pub enum LogConfig {
233//!     File(PathBuf),
234//!     Stdout,
235//!     Stderr,
236//! }
237//!
238//! impl LogConfig {
239//!     pub fn layer<S>(self) -> Box<dyn Layer<S> + Send + Sync + 'static>
240//!     where
241//!         S: tracing_core::Subscriber,
242//!         for<'a> S: LookupSpan<'a>,
243//!     {
244//!         // Shared configuration regardless of where logs are output to.
245//!         let fmt = tracing_subscriber::fmt::layer()
246//!             .with_target(true)
247//!             .with_thread_names(true);
248//!
249//!         // Configure the writer based on the desired log target:
250//!         match self {
251//!             LogConfig::File(path) => {
252//!                 let file = File::create(path).expect("failed to create log file");
253//!                 Box::new(fmt.with_writer(file))
254//!             },
255//!             LogConfig::Stdout => Box::new(fmt.with_writer(io::stdout)),
256//!             LogConfig::Stderr => Box::new(fmt.with_writer(io::stderr)),
257//!         }
258//!     }
259//! }
260//!
261//! let config = LogConfig::Stdout;
262//! tracing_subscriber::registry()
263//!     .with(config.layer())
264//!     .init();
265//! ```
266//!
267//! The [`Layer::boxed`] method is provided to make boxing a `Layer`
268//! more convenient, but [`Box::new`] may be used as well.
269//!
270//! When the number of `Layer`s varies at runtime, note that a
271//! [`Vec<L> where L: Layer` also implements `Layer`][vec-impl]. This
272//! can be used to add a variable number of `Layer`s to a `Subscriber`:
273//!
274//! ```
275//! use tracing_subscriber::{Layer, prelude::*};
276//! struct MyLayer {
277//!     // ...
278//! }
279//! # impl MyLayer { fn new() -> Self { Self {} }}
280//!
281//! impl<S: tracing_core::Subscriber> Layer<S> for MyLayer {
282//!     // ...
283//! }
284//!
285//! /// Returns how many layers we need
286//! fn how_many_layers() -> usize {
287//!     // ...
288//!     # 3
289//! }
290//!
291//! // Create a variable-length `Vec` of layers
292//! let mut layers = Vec::new();
293//! for _ in 0..how_many_layers() {
294//!     layers.push(MyLayer::new());
295//! }
296//!
297//! tracing_subscriber::registry()
298//!     .with(layers)
299//!     .init();
300//! ```
301//!
302//! If a variable number of `Layer` is needed and those `Layer`s have
303//! different types, a `Vec` of [boxed `Layer` trait objects][box-impl] may
304//! be used. For example:
305//!
306//! ```
307//! use tracing_subscriber::{filter::LevelFilter, Layer, prelude::*};
308//! use std::fs::File;
309//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
310//! struct Config {
311//!     enable_log_file: bool,
312//!     enable_stdout: bool,
313//!     enable_stderr: bool,
314//!     // ...
315//! }
316//! # impl Config {
317//! #    fn from_config_file()-> Result<Self, Box<dyn std::error::Error>> {
318//! #         // don't enable the log file so that the example doesn't actually create it
319//! #         Ok(Self { enable_log_file: false, enable_stdout: true, enable_stderr: true })
320//! #    }
321//! # }
322//!
323//! let cfg = Config::from_config_file()?;
324//!
325//! // Based on our dynamically loaded config file, create any number of layers:
326//! let mut layers = Vec::new();
327//!
328//! if cfg.enable_log_file {
329//!     let file = File::create("myapp.log")?;
330//!     let layer = tracing_subscriber::fmt::layer()
331//!         .with_thread_names(true)
332//!         .with_target(true)
333//!         .json()
334//!         .with_writer(file)
335//!         // Box the layer as a type-erased trait object, so that it can
336//!         // be pushed to the `Vec`.
337//!         .boxed();
338//!     layers.push(layer);
339//! }
340//!
341//! if cfg.enable_stdout {
342//!     let layer = tracing_subscriber::fmt::layer()
343//!         .pretty()
344//!         .with_filter(LevelFilter::INFO)
345//!         // Box the layer as a type-erased trait object, so that it can
346//!         // be pushed to the `Vec`.
347//!         .boxed();
348//!     layers.push(layer);
349//! }
350//!
351//! if cfg.enable_stdout {
352//!     let layer = tracing_subscriber::fmt::layer()
353//!         .with_target(false)
354//!         .with_filter(LevelFilter::WARN)
355//!         // Box the layer as a type-erased trait object, so that it can
356//!         // be pushed to the `Vec`.
357//!         .boxed();
358//!     layers.push(layer);
359//! }
360//!
361//! tracing_subscriber::registry()
362//!     .with(layers)
363//!     .init();
364//!# Ok(()) }
365//! ```
366//!
367//! Finally, if the number of layers _changes_ at runtime, a `Vec` of
368//! subscribers can be used alongside the [`reload`](crate::reload) module to
369//! add or remove subscribers dynamically at runtime.
370//!
371//! [option-impl]: Layer#impl-Layer<S>-for-Option<L>
372//! [box-impl]: Layer#impl-Layer%3CS%3E-for-Box%3Cdyn%20Layer%3CS%3E%20+%20Send%20+%20Sync%3E
373//! [vec-impl]: Layer#impl-Layer<S>-for-Vec<L>
374//! [prelude]: crate::prelude
375//!
376//! # Recording Traces
377//!
378//! The [`Layer`] trait defines a set of methods for consuming notifications from
379//! tracing instrumentation, which are generally equivalent to the similarly
380//! named methods on [`Subscriber`]. Unlike [`Subscriber`], the methods on
381//! `Layer` are additionally passed a [`Context`] type, which exposes additional
382//! information provided by the wrapped subscriber (such as [the current span])
383//! to the layer.
384//!
385//! # Filtering with `Layer`s
386//!
387//! As well as strategies for handling trace events, the `Layer` trait may also
388//! be used to represent composable _filters_. This allows the determination of
389//! what spans and events should be recorded to be decoupled from _how_ they are
390//! recorded: a filtering layer can be applied to other layers or
391//! subscribers. `Layer`s can be used to implement _global filtering_, where a
392//! `Layer` provides a filtering strategy for the entire subscriber.
393//! Additionally, individual recording `Layer`s or sets of `Layer`s may be
394//! combined with _per-layer filters_ that control what spans and events are
395//! recorded by those layers.
396//!
397//! ## Global Filtering
398//!
399//! A `Layer` that implements a filtering strategy should override the
400//! [`register_callsite`] and/or [`enabled`] methods. It may also choose to implement
401//! methods such as [`on_enter`], if it wishes to filter trace events based on
402//! the current span context.
403//!
404//! Note that the [`Layer::register_callsite`] and [`Layer::enabled`] methods
405//! determine whether a span or event is enabled *globally*. Thus, they should
406//! **not** be used to indicate whether an individual layer wishes to record a
407//! particular span or event. Instead, if a layer is only interested in a subset
408//! of trace data, but does *not* wish to disable other spans and events for the
409//! rest of the layer stack should ignore those spans and events in its
410//! notification methods.
411//!
412//! The filtering methods on a stack of `Layer`s are evaluated in a top-down
413//! order, starting with the outermost `Layer` and ending with the wrapped
414//! [`Subscriber`]. If any layer returns `false` from its [`enabled`] method, or
415//! [`Interest::never()`] from its [`register_callsite`] method, filter
416//! evaluation will short-circuit and the span or event will be disabled.
417//!
418//! ### Enabling Interest
419//!
420//! Whenever an tracing event (or span) is emitted, it goes through a number of
421//! steps to determine how and how much it should be processed. The earlier an
422//! event is disabled, the less work has to be done to process the event, so
423//! `Layer`s that implement filtering should attempt to disable unwanted
424//! events as early as possible. In order, each event checks:
425//!
426//! - [`register_callsite`], once per callsite (roughly: once per time that
427//!   `event!` or `span!` is written in the source code; this is cached at the
428//!   callsite). See [`Subscriber::register_callsite`] and
429//!   [`tracing_core::callsite`] for a summary of how this behaves.
430//! - [`enabled`], once per emitted event (roughly: once per time that `event!`
431//!   or `span!` is *executed*), and only if `register_callsite` registers an
432//!   [`Interest::sometimes`]. This is the main customization point to globally
433//!   filter events based on their [`Metadata`]. If an event can be disabled
434//!   based only on [`Metadata`], it should be, as this allows the construction
435//!   of the actual `Event`/`Span` to be skipped.
436//! - For events only (and not spans), [`event_enabled`] is called just before
437//!   processing the event. This gives layers one last chance to say that
438//!   an event should be filtered out, now that the event's fields are known.
439//!
440//! ## Per-Layer Filtering
441//!
442//! **Note**: per-layer filtering APIs currently require the [`"registry"` crate
443//! feature flag][feat] to be enabled.
444//!
445//! Sometimes, it may be desirable for one `Layer` to record a particular subset
446//! of spans and events, while a different subset of spans and events are
447//! recorded by other `Layer`s. For example:
448//!
449//! - A layer that records metrics may wish to observe only events including
450//!   particular tracked values, while a logging layer ignores those events.
451//! - If recording a distributed trace is expensive, it might be desirable to
452//!   only send spans with `INFO` and lower verbosity to the distributed tracing
453//!   system, while logging more verbose spans to a file.
454//! - Spans and events with a particular target might be recorded differently
455//!   from others, such as by generating an HTTP access log from a span that
456//!   tracks the lifetime of an HTTP request.
457//!
458//! The [`Filter`] trait is used to control what spans and events are
459//! observed by an individual `Layer`, while still allowing other `Layer`s to
460//! potentially record them. The [`Layer::with_filter`] method combines a
461//! `Layer` with a [`Filter`], returning a [`Filtered`] layer.
462//!
463//! This crate's [`filter`] module provides a number of types which implement
464//! the [`Filter`] trait, such as [`LevelFilter`], [`Targets`], and
465//! [`FilterFn`]. These [`Filter`]s provide ready-made implementations of
466//! common forms of filtering. For custom filtering policies, the [`FilterFn`]
467//! and [`DynFilterFn`] types allow implementing a [`Filter`] with a closure or
468//! function pointer. In addition, when more control is required, the [`Filter`]
469//! trait may also be implemented for user-defined types.
470//!
471//! [`Option<Filter>`] also implements [`Filter`], which allows for an optional
472//! filter. [`None`] filters out _nothing_ (that is, allows everything through). For
473//! example:
474//!
475//! ```rust
476//! # use tracing_subscriber::{filter::filter_fn, Layer};
477//! # use tracing_core::{Metadata, subscriber::Subscriber};
478//! # struct MyLayer<S>(std::marker::PhantomData<S>);
479//! # impl<S> MyLayer<S> { fn new() -> Self { Self(std::marker::PhantomData)} }
480//! # impl<S: Subscriber> Layer<S> for MyLayer<S> {}
481//! # fn my_filter(_: &str) -> impl Fn(&Metadata) -> bool { |_| true  }
482//! fn setup_tracing<S: Subscriber>(filter_config: Option<&str>) {
483//!     let layer = MyLayer::<S>::new()
484//!         .with_filter(filter_config.map(|config| filter_fn(my_filter(config))));
485//! //...
486//! }
487//! ```
488//!
489//! <pre class="compile_fail" style="white-space:normal;font:inherit;">
490//!     <strong>Warning</strong>: Currently, the <a href="../struct.Registry.html">
491//!     <code>Registry</code></a> type defined in this crate is the only root
492//!     <code>Subscriber</code> capable of supporting <code>Layer</code>s with
493//!     per-layer filters. In the future, new APIs will be added to allow other
494//!     root <code>Subscriber</code>s to support per-layer filters.
495//! </pre>
496//!
497//! For example, to generate an HTTP access log based on spans with
498//! the `http_access` target, while logging other spans and events to
499//! standard out, a [`Filter`] can be added to the access log layer:
500//!
501//! ```
502//! use tracing_subscriber::{filter, prelude::*};
503//!
504//! // Generates an HTTP access log.
505//! let access_log = // ...
506//!     # filter::LevelFilter::INFO;
507//!
508//! // Add a filter to the access log layer so that it only observes
509//! // spans and events with the `http_access` target.
510//! let access_log = access_log.with_filter(filter::filter_fn(|metadata| {
511//!     // Returns `true` if and only if the span or event's target is
512//!     // "http_access".
513//!     metadata.target() == "http_access"
514//! }));
515//!
516//! // A general-purpose logging layer.
517//! let fmt_layer = tracing_subscriber::fmt::layer();
518//!
519//! // Build a subscriber that combines the access log and stdout log
520//! // layers.
521//! tracing_subscriber::registry()
522//!     .with(fmt_layer)
523//!     .with(access_log)
524//!     .init();
525//! ```
526//!
527//! Multiple layers can have their own, separate per-layer filters. A span or
528//! event will be recorded if it is enabled by _any_ per-layer filter, but it
529//! will be skipped by the layers whose filters did not enable it. Building on
530//! the previous example:
531//!
532//! ```
533//! use tracing_subscriber::{filter::{filter_fn, LevelFilter}, prelude::*};
534//!
535//! let access_log = // ...
536//!     # LevelFilter::INFO;
537//! let fmt_layer = tracing_subscriber::fmt::layer();
538//!
539//! tracing_subscriber::registry()
540//!     // Add the filter for the "http_access" target to the access
541//!     // log layer, like before.
542//!     .with(access_log.with_filter(filter_fn(|metadata| {
543//!         metadata.target() == "http_access"
544//!     })))
545//!     // Add a filter for spans and events with the INFO level
546//!     // and below to the logging layer.
547//!     .with(fmt_layer.with_filter(LevelFilter::INFO))
548//!     .init();
549//!
550//! // Neither layer will observe this event
551//! tracing::debug!(does_anyone_care = false, "a tree fell in the forest");
552//!
553//! // This event will be observed by the logging layer, but not
554//! // by the access log layer.
555//! tracing::warn!(dose_roentgen = %3.8, "not great, but not terrible");
556//!
557//! // This event will be observed only by the access log layer.
558//! tracing::trace!(target: "http_access", "HTTP request started");
559//!
560//! // Both layers will observe this event.
561//! tracing::error!(target: "http_access", "HTTP request failed with a very bad error!");
562//! ```
563//!
564//! A per-layer filter can be applied to multiple [`Layer`]s at a time, by
565//! combining them into a [`Layered`] layer using [`Layer::and_then`], and then
566//! calling [`Layer::with_filter`] on the resulting [`Layered`] layer.
567//!
568//! Consider the following:
569//! - `layer_a` and `layer_b`, which should only receive spans and events at
570//!   the [`INFO`] [level] and above.
571//! - A third layer, `layer_c`, which should receive spans and events at
572//!   the [`DEBUG`] [level] as well.
573//!
574//! The layers and filters would be composed thusly:
575//!
576//! ```
577//! use tracing_subscriber::{filter::LevelFilter, prelude::*};
578//!
579//! let layer_a = // ...
580//! # LevelFilter::INFO;
581//! let layer_b =  // ...
582//! # LevelFilter::INFO;
583//! let layer_c =  // ...
584//! # LevelFilter::INFO;
585//!
586//! let info_layers = layer_a
587//!     // Combine `layer_a` and `layer_b` into a `Layered` layer:
588//!     .and_then(layer_b)
589//!     // ...and then add an `INFO` `LevelFilter` to that layer:
590//!     .with_filter(LevelFilter::INFO);
591//!
592//! tracing_subscriber::registry()
593//!     // Add `layer_c` with a `DEBUG` filter.
594//!     .with(layer_c.with_filter(LevelFilter::DEBUG))
595//!     .with(info_layers)
596//!     .init();
597//!```
598//!
599//! If a [`Filtered`] [`Layer`] is combined with another [`Layer`]
600//! [`Layer::and_then`], and a filter is added to the [`Layered`] layer, that
601//! layer will be filtered by *both* the inner filter and the outer filter.
602//! Only spans and events that are enabled by *both* filters will be
603//! observed by that layer. This can be used to implement complex filtering
604//! trees.
605//!
606//! As an example, consider the following constraints:
607//! - Suppose that a particular [target] is used to indicate events that