tracing_subscriber/subscribe/mod.rs
1//! The [`Subscribe`] trait, a composable abstraction for building [collector]s.
2//!
3//! The [`Collect`] trait in `tracing-core` represents the _complete_ set of
4//! functionality required to consume `tracing` instrumentation. This means that
5//! a single `Collect` instance is a self-contained implementation of a
6//! complete strategy for collecting traces; but it _also_ means that the
7//! `Collect` trait cannot easily be composed with other collectors.
8//!
9//! In particular, [collector]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 collector 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 [`Collect`] 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 [`Subscribe`] trait represents this composable subset of the
19//! [`Collect`] behavior; it can _observe_ events and spans, but does not
20//! assign IDs.
21//!
22//! # Composing Subscribers
23//!
24//! Since a [subscriber] does not implement a complete strategy for collecting
25//! traces, it must be composed with a [collector] in order to be used. The
26//! [`Subscribe`] trait is generic over a type parameter (called `C` in the trait
27//! definition), representing the types of `Collect` they can be composed
28//! with. Thus, a subscriber may be implemented that will only compose with a
29//! particular `Collect` implementation, or additional trait bounds may be
30//! added to constrain what types implementing `Collect` a subscriber can wrap.
31//!
32//! Subscribers may be added to a collector by using the [`CollectExt::with`]
33//! method, which is provided by `tracing-subscriber`'s [prelude]. This method
34//! returns a [`Layered`] struct that implements [`Collect`] by composing the
35//! `Subscribe` with the collector.
36//!
37//! For example:
38//! ```rust
39//! use tracing_subscriber::Subscribe;
40//! use tracing_subscriber::prelude::*;
41//! use tracing::Collect;
42//!
43//! pub struct MySubscriber {
44//! // ...
45//! }
46//!
47//! impl<C: Collect> Subscribe<C> for MySubscriber {
48//! // ...
49//! }
50//!
51//! pub struct MyCollector {
52//! // ...
53//! }
54//!
55//! # use tracing_core::{span::{Id, Attributes, Record}, Metadata, Event};
56//! impl Collect for MyCollector {
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//! # fn current_span(&self) -> tracing_core::span::Current { tracing_core::span::Current::none() }
66//! }
67//! # impl MySubscriber {
68//! # fn new() -> Self { Self {} }
69//! # }
70//! # impl MyCollector {
71//! # fn new() -> Self { Self { }}
72//! # }
73//!
74//! let collector = MyCollector::new()
75//! .with(MySubscriber::new());
76//!
77//! tracing::collect::set_global_default(collector);
78//! ```
79//!
80//! Multiple subscriber may be composed in the same manner:
81//! ```rust
82//! # use tracing_subscriber::{Subscribe, subscribe::CollectExt};
83//! # use tracing::Collect;
84//! pub struct MyOtherSubscriber {
85//! // ...
86//! }
87//!
88//! impl<C: Collect> Subscribe<C> for MyOtherSubscriber {
89//! // ...
90//! }
91//!
92//! pub struct MyThirdSubscriber {
93//! // ...
94//! }
95//!
96//! impl<C: Collect> Subscribe<C> for MyThirdSubscriber {
97//! // ...
98//! }
99//! # pub struct MySubscriber {}
100//! # impl<C: Collect> Subscribe<C> for MySubscriber {}
101//! # pub struct MyCollector { }
102//! # use tracing_core::{span::{Id, Attributes, Record}, Metadata, Event};
103//! # impl Collect for MyCollector {
104//! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(1) }
105//! # fn record(&self, _: &Id, _: &Record) {}
106//! # fn event(&self, _: &Event) {}
107//! # fn record_follows_from(&self, _: &Id, _: &Id) {}
108//! # fn enabled(&self, _: &Metadata) -> bool { false }
109//! # fn current_span(&self) -> tracing_core::span::Current { tracing_core::span::Current::none() }
110//! # fn enter(&self, _: &Id) {}
111//! # fn exit(&self, _: &Id) {}
112//! }
113//! # impl MySubscriber {
114//! # fn new() -> Self { Self {} }
115//! # }
116//! # impl MyOtherSubscriber {
117//! # fn new() -> Self { Self {} }
118//! # }
119//! # impl MyThirdSubscriber {
120//! # fn new() -> Self { Self {} }
121//! # }
122//! # impl MyCollector {
123//! # fn new() -> Self { Self { }}
124//! # }
125//!
126//! let collect = MyCollector::new()
127//! .with(MySubscriber::new())
128//! .with(MyOtherSubscriber::new())
129//! .with(MyThirdSubscriber::new());
130//!
131//! tracing::collect::set_global_default(collect);
132//! ```
133//!
134//! The [`Subscribe::with_collector`] constructs the [`Layered`] type from a
135//! [`Subscribe`] and [`Collect`], and is called by [`CollectExt::with`]. In
136//! general, it is more idiomatic to use [`CollectExt::with`], and treat
137//! [`Subscribe::with_collector`] as an implementation detail, as `with_collector`
138//! calls must be nested, leading to less clear code for the reader.
139//!
140//! ## Runtime Configuration With Subscribers
141//!
142//! In some cases, a particular [subscriber] may be enabled or disabled based on
143//! runtime configuration. This can introduce challenges, because the type of a
144//! layered [collector] depends on which subscribers are added to it: if an `if`
145//! or `match` expression adds some [`Subscribe`] implementation in one branch,
146//! and other subscribers in another, the [collector] values returned by those
147//! branches will have different types. For example, the following _will not_
148//! work:
149//!
150//! ```compile_fail
151//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> {
152//! # struct Config {
153//! # is_prod: bool,
154//! # path: &'static str,
155//! # }
156//! # let cfg = Config { is_prod: false, path: "debug.log" };
157//! use std::fs::File;
158//! use tracing_subscriber::{Registry, prelude::*};
159//!
160//! let stdout_log = tracing_subscriber::fmt::subscriber().pretty();
161//! let collector = Registry::default().with(stdout_log);
162//!
163//! // The compile error will occur here because the if and else
164//! // branches have different (and therefore incompatible) types.
165//! let collector = if cfg.is_prod {
166//! let file = File::create(cfg.path)?;
167//! let collector = tracing_subscriber::fmt::subscriber()
168//! .json()
169//! .with_writer(Arc::new(file));
170//! collector.with(subscriber)
171//! } else {
172//! collector
173//! };
174//!
175//! tracing::collect::set_global_default(collector)
176//! .expect("Unable to set global collector");
177//! # Ok(()) }
178//! ```
179//!
180//! However, a [`Subscribe`] wrapped in an [`Option`] [also implements the `Subscribe`
181//! trait][option-impl]. This allows individual layers to be enabled or disabled at
182//! runtime while always producing a [`Collect`] of the same type. For
183//! example:
184//!
185//! ```
186//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> {
187//! # struct Config {
188//! # is_prod: bool,
189//! # path: &'static str,
190//! # }
191//! # let cfg = Config { is_prod: false, path: "debug.log" };
192//! use std::fs::File;
193//! use tracing_subscriber::{Registry, prelude::*};
194//!
195//! let stdout_log = tracing_subscriber::fmt::subscriber().pretty();
196//! let collector = Registry::default().with(stdout_log);
197//!
198//! // if `cfg.is_prod` is true, also log JSON-formatted logs to a file.
199//! let json_log = if cfg.is_prod {
200//! let file = File::create(cfg.path)?;
201//! let json_log = tracing_subscriber::fmt::subscriber()
202//! .json()
203//! .with_writer(file);
204//! Some(json_log)
205//! } else {
206//! None
207//! };
208//!
209//! // If `cfg.is_prod` is false, then `json` will be `None`, and this subscriber
210//! // will do nothing. However, the collector will still have the same type
211//! // regardless of whether the `Option`'s value is `None` or `Some`.
212//! let collector = collector.with(json_log);
213//!
214//! tracing::collect::set_global_default(collector)
215//! .expect("Unable to set global collector");
216//! # Ok(()) }
217//! ```
218//!
219//! If a subscriber may be one of several different types, note that [`Box<dyn
220//! Subscribe<C> + Send + Sync + 'static>` implements `Subscribe`][box-impl].
221//! This may be used to erase the type of a subscriber.
222//!
223//! For example, a function that configures a subscriber to log to one of
224//! several outputs might return a `Box<dyn Subscribe<C> + Send + Sync + 'static>`:
225//! ```
226//! use tracing_subscriber::{
227//! Subscribe,
228//! registry::LookupSpan,
229//! prelude::*,
230//! };
231//! use std::{path::PathBuf, fs::File, io};
232//!
233//! /// Configures whether logs are emitted to a file, to stdout, or to stderr.
234//! pub enum LogConfig {
235//! File(PathBuf),
236//! Stdout,
237//! Stderr,
238//! }
239//!
240//! impl LogConfig {
241//! pub fn subscriber<C>(self) -> Box<dyn Subscribe<C> + Send + Sync + 'static>
242//! where
243//! C: tracing_core::Collect,
244//! for<'a> C: LookupSpan<'a>,
245//! {
246//! // Shared configuration regardless of where logs are output to.
247//! let fmt = tracing_subscriber::fmt::subscriber()
248//! .with_target(true)
249//! .with_thread_names(true);
250//!
251//! // Configure the writer based on the desired log target:
252//! match self {
253//! LogConfig::File(path) => {
254//! let file = File::create(path).expect("failed to create log file");
255//! Box::new(fmt.with_writer(file))
256//! },
257//! LogConfig::Stdout => Box::new(fmt.with_writer(io::stdout)),
258//! LogConfig::Stderr => Box::new(fmt.with_writer(io::stderr)),
259//! }
260//! }
261//! }
262//!
263//! let config = LogConfig::Stdout;
264//! tracing_subscriber::registry()
265//! .with(config.subscriber())
266//! .init();
267//! ```
268//!
269//! The [`Subscribe::boxed`] method is provided to make boxing a subscriber
270//! more convenient, but [`Box::new`] may be used as well.
271//!
272//! When the number of subscribers varies at runtime, note that a
273//! [`Vec<S> where S: Subscribe` also implements `Subscribe`][vec-impl]. This
274//! can be used to add a variable number of subscribers to a collector:
275//!
276//! ```
277//! use tracing_subscriber::{Subscribe, prelude::*};
278//! struct MySubscriber {
279//! // ...
280//! }
281//! # impl MySubscriber { fn new() -> Self { Self {} }}
282//!
283//! impl<C: tracing_core::Collect> Subscribe<C> for MySubscriber {
284//! // ...
285//! }
286//!
287//! /// Returns how many subscribers we need
288//! fn how_many_subscribers() -> usize {
289//! // ...
290//! # 3
291//! }
292//!
293//! // Create a variable-length `Vec` of subscribers
294//! let mut subscribers = Vec::new();
295//! for _ in 0..how_many_subscribers() {
296//! subscribers.push(MySubscriber::new());
297//! }
298//!
299//! tracing_subscriber::registry()
300//! .with(subscribers)
301//! .init();
302//! ```
303//!
304//! If a variable number of subscribers is needed and those subscribers have
305//! different types, a `Vec` of [boxed subscriber trait objects][box-impl] may
306//! be used. For example:
307//!
308//! ```
309//! use tracing_subscriber::{filter::LevelFilter, Subscribe, prelude::*};
310//! use std::fs::File;
311//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
312//! struct Config {
313//! enable_log_file: bool,
314//! enable_stdout: bool,
315//! enable_stderr: bool,
316//! // ...
317//! }
318//! # impl Config {
319//! # fn from_config_file()-> Result<Self, Box<dyn std::error::Error>> {
320//! # // don't enable the log file so that the example doesn't actually create it
321//! # Ok(Self { enable_log_file: false, enable_stdout: true, enable_stderr: true })
322//! # }
323//! # }
324//!
325//! let cfg = Config::from_config_file()?;
326//!
327//! // Based on our dynamically loaded config file, create any number of subscribers:
328//! let mut subscribers = Vec::new();
329//!
330//! if cfg.enable_log_file {
331//! let file = File::create("myapp.log")?;
332//! let subscriber = tracing_subscriber::fmt::subscriber()
333//! .with_thread_names(true)
334//! .with_target(true)
335//! .json()
336//! .with_writer(file)
337//! // Box the subscriber as a type-erased trait object, so that it can
338//! // be pushed to the `Vec`.
339//! .boxed();
340//! subscribers.push(subscriber);
341//! }
342//!
343//! if cfg.enable_stdout {
344//! let subscriber = tracing_subscriber::fmt::subscriber()
345//! .pretty()
346//! .with_filter(LevelFilter::INFO)
347//! // Box the subscriber as a type-erased trait object, so that it can
348//! // be pushed to the `Vec`.
349//! .boxed();
350//! subscribers.push(subscriber);
351//! }
352//!
353//! if cfg.enable_stdout {
354//! let subscriber = tracing_subscriber::fmt::subscriber()
355//! .with_target(false)
356//! .with_filter(LevelFilter::WARN)
357//! // Box the subscriber as a type-erased trait object, so that it can
358//! // be pushed to the `Vec`.
359//! .boxed();
360//! subscribers.push(subscriber);
361//! }
362//!
363//! tracing_subscriber::registry()
364//! .with(subscribers)
365//! .init();
366//!# Ok(()) }
367//! ```
368//!
369//! Finally, if the number of subscribers _changes_ at runtime, a `Vec` of
370//! subscribers can be used alongside the [`reload`](crate::reload) module to
371//! add or remove subscribers dynamically at runtime.
372//!
373//! [prelude]: crate::prelude
374//! [option-impl]: crate::subscribe::Subscribe#impl-Subscribe<C>-for-Option<S>
375//! [box-impl]: Subscribe#impl-Subscribe%3CC%3E-for-Box%3Cdyn%20Subscribe%3CC%3E%20+%20Send%20+%20Sync%20+%20%27static%3E
376//! [vec-impl]: Subscribe#impl-Subscribe<C>-for-Vec<S>
377//!
378//! # Recording Traces
379//!
380//! The [`Subscribe`] trait defines a set of methods for consuming notifications from
381//! tracing instrumentation, which are generally equivalent to the similarly
382//! named methods on [`Collect`]. Unlike [`Collect`], the methods on
383//! `Subscribe` are additionally passed a [`Context`] type, which exposes additional
384//! information provided by the wrapped subscriber (such as [the current span])
385//! to the subscriber.
386//!
387//! # Filtering with `Subscriber`s
388//!
389//! As well as strategies for handling trace events, the `Subscribe` trait may also
390//! be used to represent composable _filters_. This allows the determination of
391//! what spans and events should be recorded to be decoupled from _how_ they are
392//! recorded: a filtering subscriber can be applied to other subscribers or
393//! subscribers. `Subscribe`s can be used to implement _global filtering_, where a
394//! `Subscribe` provides a filtering strategy for the entire subscriber.
395//! Additionally, individual recording `Subscribe`s or sets of `Subscribe`s may be
396//! combined with _per-subscriber filters_ that control what spans and events are
397//! recorded by those subscribers.
398//!
399//! ## Global Filtering
400//!
401//! A `Subscribe` that implements a filtering strategy should override the
402//! [`register_callsite`] and/or [`enabled`] methods. It may also choose to implement
403//! methods such as [`on_enter`], if it wishes to filter trace events based on
404//! the current span context.
405//!
406//! Note that the [`Subscribe::register_callsite`] and [`Subscribe::enabled`] methods
407//! determine whether a span or event is enabled *globally*. Thus, they should
408//! **not** be used to indicate whether an individual subscriber wishes to record a
409//! particular span or event. Instead, if a subscriber is only interested in a subset
410//! of trace data, but does *not* wish to disable other spans and events for the
411//! rest of the subscriber stack should ignore those spans and events in its
412//! notification methods.
413//!
414//! The filtering methods on a stack of `Subscribe`s are evaluated in a top-down
415//! order, starting with the outermost `Subscribe` and ending with the wrapped
416//! [`Collect`]. If any subscriber returns `false` from its [`enabled`] method, or
417//! [`Interest::never()`] from its [`register_callsite`] method, filter
418//! evaluation will short-circuit and the span or event will be disabled.
419//!
420//! ### Enabling Interest
421//!
422//! Whenever an tracing event (or span) is emitted, it goes through a number of
423//! steps to determine how and how much it should be processed. The earlier an
424//! event is disabled, the less work has to be done to process the event, so
425//! subscribers that implement filtering should attempt to disable unwanted
426//! events as early as possible. In order, each event checks:
427//!
428//! - [`register_callsite`], once per callsite (roughly: once per time that
429//! `event!` or `span!` is written in the source code; this is cached at the
430//! callsite). See [`Collect::register_callsite`] and
431//! [`tracing_core::callsite`] for a summary of how this behaves.
432//! - [`enabled`], once per emitted event (roughly: once per time that `event!`
433//! or `span!` is *executed*), and only if `register_callsite` registers an
434//! [`Interest::sometimes`]. This is the main customization point to globally
435//! filter events based on their [`Metadata`]. If an event can be disabled
436//! based only on [`Metadata`], it should be, as this allows the construction
437//! of the actual `Event`/`Span` to be skipped.
438//! - For events only (and not spans), [`event_enabled`] is called just before
439//! processing the event. This gives subscribers one last chance to say that
440//! an event should be filtered out, now that the event's fields are known.
441//!
442//! ## Per-Subscriber Filtering
443//!
444//! **Note**: per-subscriber filtering APIs currently require the [`"registry"` crate
445//! feature flag][feat] to be enabled.
446//!
447//! Sometimes, it may be desirable for one `Subscribe` to record a particular subset
448//! of spans and events, while a different subset of spans and events are
449//! recorded by other `Subscribe`s. For example:
450//!
451//! - A subscriber that records metrics may wish to observe only events including
452//! particular tracked values, while a logging subscriber ignores those events.
453//! - If recording a distributed trace is expensive, it might be desirable to
454//! only send spans with `INFO` and lower verbosity to the distributed tracing
455//! system, while logging more verbose spans to a file.
456//! - Spans and events with a particular target might be recorded differently
457//! from others, such as by generating an HTTP access log from a span that
458//! tracks the lifetime of an HTTP request.
459//!
460//! The [`Filter`] trait is used to control what spans and events are
461//! observed by an individual `Subscribe`, while still allowing other `Subscribe`s to
462//! potentially record them. The [`Subscribe::with_filter`] method combines a
463//! `Subscribe` with a [`Filter`], returning a [`Filtered`] subscriber.
464//!
465//! This crate's [`filter`] module provides a number of types which implement
466//! the [`Filter`] trait, such as [`LevelFilter`], [`Targets`], and
467//! [`FilterFn`]. These [`Filter`]s provide ready-made implementations of common
468//! forms of filtering. For custom filtering policies, the [`FilterFn`] and
469//! [`DynFilterFn`] types allow implementing a [`Filter`] with a closure or
470//! function pointer. In addition, when more control is required, the [`Filter`]
471//! trait may also be implemented for user-defined types.
472//!
473//! [`Option<Filter>`] also implements [`Filter`], which allows for an optional
474//! filter. [`None`](Option::None) filters out _nothing_ (that is, allows
475//! everything through). For example:
476//!
477//! ```rust
478//! # use tracing_subscriber::{filter::filter_fn, Subscribe};
479//! # use tracing_core::{Metadata, collect::Collect};
480//! # struct MySubscriber<C>(std::marker::PhantomData<C>);
481//! # impl<C> MySubscriber<C> { fn new() -> Self { Self(std::marker::PhantomData)} }
482//! # impl<C: Collect> Subscribe<C> for MySubscriber<C> {}
483//! # fn my_filter(_: &str) -> impl Fn(&Metadata) -> bool { |_| true }
484//! fn setup_tracing<C: Collect>(filter_config: Option<&str>) {
485//! let layer = MySubscriber::<C>::new()
486//! .with_filter(filter_config.map(|config| filter_fn(my_filter(config))));
487//! //...
488//! }
489//! ```
490//!
491//! <div class="example-wrap" style="display:inline-block">
492//! <pre class="compile_fail" style="white-space:normal;font:inherit;">
493//! <strong>Warning</strong>: Currently, the <a href="../struct.Registry.html">
494//! <code>Registry</code></a> type defined in this crate is the only root
495//! <code>Collect</code> capable of supporting subscriberss with
496//! per-subscriber filters. In the future, new APIs will be added to allow other
497//! root <code>Collect</code>s to support per-subscriber filters.
498//! </pre></div>
499//!
500//! For example, to generate an HTTP access log based on spans with
501//! the `http_access` target, while logging other spans and events to
502//! standard out, a [`Filter`] can be added to the access log subscriber:
503//!
504//! ```
505//! use tracing_subscriber::{filter, prelude::*};
506//!
507//! // Generates an HTTP access log.
508//! let access_log = // ...
509//! # filter::LevelFilter::INFO;
510//!
511//! // Add a filter to the access log subscriber so that it only observes
512//! // spans and events with the `http_access` target.
513//! let access_log = access_log.with_filter(filter::filter_fn(|metadata| {
514//! // Returns `true` if and only if the span or event's target is
515//! // "http_access".
516//! metadata.target() == "http_access"
517//! }));
518//!
519//! // A general-purpose logging subscriber.
520//! let fmt_subscriber = tracing_subscriber::fmt::subscriber();
521//!
522//! // Build a subscriber that combines the access log and stdout log
523//! // subscribers.
524//! tracing_subscriber::registry()
525//! .with(fmt_subscriber)
526//! .with(access_log)
527//! .init();
528//! ```
529//!
530//! Multiple subscribers can have their own, separate per-subscriber filters. A span or
531//! event will be recorded if it is enabled by _any_ per-subscriber filter, but it
532//! will be skipped by the subscribers whose filters did not enable it. Building on
533//! the previous example:
534//!
535//! ```
536//! use tracing_subscriber::{filter::{filter_fn, LevelFilter}, prelude::*};
537//!
538//! let access_log = // ...
539//! # LevelFilter::INFO;
540//! let fmt_subscriber = tracing_subscriber::fmt::subscriber();
541//!
542//! tracing_subscriber::registry()
543//! // Add the filter for the "http_access" target to the access
544//! // log subscriber, like before.
545//! .with(access_log.with_filter(filter_fn(|metadata| {
546//! metadata.target() == "http_access"
547//! })))
548//! // Add a filter for spans and events with the INFO level
549//! // and below to the logging subscriber.
550//! .with(fmt_subscriber.with_filter(LevelFilter::INFO))
551//! .init();
552//!
553//! // Neither subscriber will observe this event
554//! tracing::debug!(does_anyone_care = false, "a tree fell in the forest");
555//!
556//! // This event will be observed by the logging subscriber, but not
557//! // by the access log subscriber.
558//! tracing::warn!(dose_roentgen = %3.8, "not great, but not terrible");
559//!
560//! // This event will be observed only by the access log subscriber.
561//! tracing::trace!(target: "http_access", "HTTP request started");
562//!
563//! // Both subscribers will observe this event.
564//! tracing::error!(target: "http_access", "HTTP request failed with a very bad error!");
565//! ```
566//!
567//! A per-subscriber filter can be applied to multiple [`Subscribe`]s at a time, by
568//! combining them into a [`Layered`] subscriber using [`Subscribe::and_then`], and then
569//! calling [`Subscribe::with_filter`] on the resulting [`Layered`] subscriber.
570//!
571//! Consider the following:
572//! - `subscriber_a` and `subscriber_b`, which should only receive spans and events at
573//! the [`INFO`] [level] and above.
574//! - A third subscriber, `subscriber_c`, which should receive spans and events at
575//! the [`DEBUG`] [level] as well.
576//!
577//! The subscribers and filters would be composed thusly:
578//!
579//! ```
580//! use tracing_subscriber::{filter::LevelFilter, prelude::*};
581//!
582//! let subscriber_a = // ...
583//! # LevelFilter::INFO;
584//! let subscriber_b = // ...
585//! # LevelFilter::INFO;
586//! let subscriber_c = // ...
587//! # LevelFilter::INFO;
588//!
589//! let info_subscribers = subscriber_a
590//! // Combine `subscriber_a` and `subscriber_b` into a `Layered` subscriber:
591//! .and_then(subscriber_b)
592//! // ...and then add an `INFO` `LevelFilter` to that subscriber:
593//! .with_filter(LevelFilter::INFO);
594//!
595//! tracing_subscriber::registry()
596//! // Add `subscriber_c` with a `DEBUG` filter.
597//! .with(subscriber_c.with_filter(LevelFilter::DEBUG))
598//! .with(info_subscribers)
599//! .init();
600//!```
601//!
602//! If a [`Filtered`] [`Subscribe`] is combined with another [`Subscribe`]
603//! [`Subscribe::and_then`], and a filter is added to the [`Layered`] subscriber, that
604//! subscriber will be filtered by *both* the inner filter and the outer filter.
605//! Only spans and events that are enabled by *both* filters will be
606//! observed by that subscriber. This can be used to implement complex filtering
607//! trees.
608//!
609//! As an example, consider the following constraints:
610//! - Suppose that a particular [target] is used to indicate events that
611//! should be counted as part of a metrics system, which should be only
612//! observed by a subscriber that collects metrics.
613//! - A log of high-priority events ([`INFO`] and above) should be logged
614//! to stdout, while more verbose events should be logged to a debugging log file.
615//! - Metrics-focused events should *not* be included in either log output.
616//!
617//! In that case, it is possible to apply a filter to both logging subscribers to
618//! exclude the metrics events, while additionally adding a [`LevelFilter`]
619//! to the stdout log:
620//!
621//! ```
622//! # // wrap this in a function so we don't actually create `debug.log` when
623//! # // running the doctests..
624//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> {
625//! use tracing_subscriber::{filter, prelude::*};
626//! use std::{fs::File, sync::Arc};
627//!
628//! // A subscriber that logs events to stdout using the human-readable "pretty"
629//! // format.
630//! let stdout_log = tracing_subscriber::fmt::subscriber()
631//! .pretty();
632//!
633//! // A subscriber that logs events to a file.
634//! let file = File::create("debug.log")?;
635//! let debug_log = tracing_subscriber::fmt::subscriber()
636//! .with_writer(file);
637//!
638//! // A subscriber that collects metrics using specific events.
639//! let metrics_subscriber = /* ... */ filter::LevelFilter::INFO;
640//!
641//! tracing_subscriber::registry()
642//! .with(
643//! stdout_log
644//! // Add an `INFO` filter to the stdout logging subscriber
645//! .with_filter(filter::LevelFilter::INFO)
646//! // Combine the filtered `stdout_log` subscriber with the
647//! // `debug_log` subscriber, producing a new `Layered` subscriber.
648//! .and_then(debug_log)
649//! // Add a filter to *both* subscribers that rejects spans and
650//! // events whose targets start with `metrics`.
651//! .with_filter(filter::filter_fn(|metadata| {
652//! !metadata.target().starts_with("metrics")
653//! }))
654//! )
655//! .with(
656//! // Add a filter to the metrics label that *only* enables
657//! // events whose targets start with `metrics`.
658//! metrics_subscriber.with_filter(filter::filter_fn(|metadata| {
659//! metadata.target().starts_with("metrics")
660//! }))
661//! )
662//! .init();
663//!
664//! // This event will *only* be recorded by the metrics subscriber.
665//! tracing::info!(target: "metrics::cool_stuff_count", value = 42);
666//!
667//! // This event will only be seen by the debug log file subscriber:
668//! tracing::debug!("this is a message, and part of a system of messages");
669//!
670//! // This event will be seen by both the stdout log subscriber *and*
671//! // the debug log file subscriber, but not by the metrics subscriber.
672//! tracing::warn!("the message is a warning about danger!");
673//! # Ok(()) }
674//! ```
675//!
676//! [subscriber]: Subscribe
677//! [`Collect`]:tracing_core::Collect
678//! [collector]: tracing_core::Collect
679//! [span IDs]: https://docs.rs/tracing-core/latest/tracing_core/span/struct.Id.html
680//! [the current span]: Context::current_span
681//! [`register_callsite`]: Subscribe::register_callsite
682//! [`enabled`]: Subscribe::enabled
683//! [`event_enabled`]: Subscribe::event_enabled
684//! [`on_enter`]: Subscribe::on_enter
685//! [`Subscribe::register_callsite`]: Subscribe::register_callsite
686//! [`Subscribe::enabled`]: Subscribe::enabled
687//! [`Interest::never()`]: tracing_core::collect::Interest::never
688//! [`Filtered`]: crate::filter::Filtered
689//! [`filter`]: crate::filter
690//! [`Targets`]: crate::filter::Targets
691//! [`FilterFn`]: crate::filter::FilterFn
692//! [`DynFilterFn`]: crate::filter::DynFilterFn
693//! [level]: tracing_core::Level
694//! [`INFO`]: tracing_core::Level::INFO
695//! [`DEBUG`]: tracing_core::Level::DEBUG
696//! [target]: tracing_core::Metadata::target
697//! [`LevelFilter`]: crate::filter::LevelFilter
698//! [feat]: crate#feature-flags
699use crate::filter;
700
701use tracing_core::{
702 collect::{Collect, Interest},
703 metadata::Metadata,
704 span, Dispatch, Event, LevelFilter,
705};
706
707use core::{any::TypeId, ptr::NonNull};
708
709feature! {
710 #![feature = "alloc"]
711 use alloc::boxed::Box;
712 use core::ops::{Deref, DerefMut};
713}
714
715mod context;
716mod layered;
717pub use self::{context::*, layered::*};
718
719// The `tests` module is `pub(crate)` because it contains test utilities used by
720// other modules.
721#[cfg(test)]
722pub(crate) mod tests;
723
724/// A composable handler for `tracing` events.
725///
726/// A type that implements `Subscribe` &mdash a "subscriber" — provides a
727/// particular behavior for recording or collecting traces that can
728/// be composed together with other subscribers to build a [collector]. See the
729/// [module-level documentation](crate::subscribe) for details.
730///
731/// [collector]: tracing_core::Collect
732#[cfg_attr(docsrs, doc(notable_trait))]
733pub trait Subscribe<C>
734where
735 C: Collect,
736 Self: 'static,
737{
738 /// Performs late initialization when installing this subscriber as a
739 /// [collector].
740 ///
741 /// ## Avoiding Memory Leaks
742 ///
743 /// Subscribers should not store the [`Dispatch`] pointing to the collector
744 /// that they are a part of. Because the `Dispatch` owns the collector,
745 /// storing the `Dispatch` within the collector will create a reference
746 /// count cycle, preventing the `Dispatch` from ever being dropped.
747 ///
748 /// Instead, when it is necessary to store a cyclical reference to the
749 /// `Dispatch` within a subscriber, use [`Dispatch::downgrade`] to convert a
750 /// `Dispatch` into a [`WeakDispatch`]. This type is analogous to
751 /// [`std::sync::Weak`], and does not create a reference count cycle. A
752 /// [`WeakDispatch`] can be stored within a subscriber without causing a
753 /// memory leak, and can be [upgraded] into a `Dispatch` temporarily when
754 /// the `Dispatch` must be accessed by the subscriber.
755 ///
756 /// [`WeakDispatch`]: tracing_core::dispatch::WeakDispatch
757 /// [upgraded]: tracing_core::dispatch::WeakDispatch::upgrade
758 /// [collector]: tracing_core::Collect
759 fn on_register_dispatch(&self, collector: &Dispatch) {
760 let _ = collector;
761 }
762
763 /// Performs late initialization when attaching a subscriber to a
764 /// [collector].
765 ///
766 /// This is a callback that is called when the `Subscribe` is added to a
767 /// [`Collect`] (e.g. in [`Subscribe::with_collector`] and
768 /// [`CollectExt::with`]). Since this can only occur before the
769 /// [`Collect`] has been set as the default, both the subscriber and
770 /// [`Collect`] are passed to this method _mutably_. This gives the
771 /// subscribe the opportunity to set any of its own fields with values
772 /// received by method calls on the [`Collect`].
773 ///
774 /// For example, [`Filtered`] subscribers implement `on_subscribe` to call the
775 /// [`Collect`]'s [`register_filter`] method, and store the returned
776 /// [`FilterId`] as a field.
777 ///
778 /// **Note** In most cases, subscriber implementations will not need to
779 /// implement this method. However, in cases where a type implementing
780 /// subscriber wraps one or more other types that implement `Subscribe`, like the
781 /// [`Layered`] and [`Filtered`] types in this crate, that type MUST ensure
782 /// that the inner `Subscribe` instance's' `on_subscribe` methods are
783 /// called. Otherwise, unctionality that relies on `on_subscribe`, such as
784 /// [per-subscriber filtering], may not work correctly.
785 ///
786 /// [`Filtered`]: crate::filter::Filtered
787 /// [`register_filter`]: crate::registry::LookupSpan::register_filter
788 /// [per-subscribe filtering]: #per-subscriber-filtering
789 /// [`FilterId`]: crate::filter::FilterId
790 /// [collector]: tracing_core::Collect
791 fn on_subscribe(&mut self, collector: &mut C) {
792 let _ = collector;
793 }
794
795 /// Registers a new callsite with this subscriber, returning whether or not
796 /// the subscriber is interested in being notified about the callsite, similarly
797 /// to [`Collect::register_callsite`].
798 ///
799 /// By default, this returns [`Interest::always()`] if [`self.enabled`] returns
800 /// true, or [`Interest::never()`] if it returns false.
801 ///
802 /// <div class="example-wrap" style="display:inline-block">
803 /// <pre class="ignore" style="white-space:normal;font:inherit;">
804 ///
805 /// **Note**: This method (and [`Subscribe::enabled`]) determine whether a span or event is
806 /// globally enabled, *not* whether the individual subscriber will be notified about that
807 /// span or event. This is intended to be used by subscribers that implement filtering for
808 /// the entire stack. Subscribers which do not wish to be notified about certain spans or
809 /// events but do not wish to globally disable them should ignore those spans or events in
810 /// their [on_event][Self::on_event], [on_enter][Self::on_enter], [on_exit][Self::on_exit],
811 /// and other notification methods.
812 ///
813 /// </pre></div>
814 ///
815 /// See [the trait-level documentation] for more information on filtering
816 /// with subscribers.
817 ///
818 /// Subscribers may also implement this method to perform any behaviour that
819 /// should be run once per callsite. If the subscriber wishes to use
820 /// `register_callsite` for per-callsite behaviour, but does not want to
821 /// globally enable or disable those callsites, it should always return
822 /// [`Interest::always()`].
823 ///
824 /// [`Interest`]: tracing_core::collect::Interest
825 /// [`Collect::register_callsite`]: tracing_core::Collect::register_callsite()
826 /// [`self.enabled`]: Subscribe::enabled()
827 /// [the trait-level documentation]: #filtering-with-subscribers
828 fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
829 if self.enabled(metadata, Context::none()) {
830 Interest::always()
831 } else {
832 Interest::never()
833 }
834 }
835
836 /// Returns `true` if this subscriber is interested in a span or event with the
837 /// given `metadata` in the current [`Context`], similarly to
838 /// [`Collect::enabled`].
839 ///
840 /// By default, this always returns `true`, allowing the wrapped collector
841 /// to choose to disable the span.
842 ///
843 /// <div class="example-wrap" style="display:inline-block">
844 /// <pre class="ignore" style="white-space:normal;font:inherit;">
845 ///
846 /// **Note**: This method (and [`register_callsite`][Self::register_callsite])
847 /// determine whether a span or event is
848 /// globally enabled, *not* whether the individual subscriber will be
849 /// notified about that span or event. This is intended to be used
850 /// by subscribers that implement filtering for the entire stack. Layers which do
851 /// not wish to be notified about certain spans or events but do not wish to
852 /// globally disable them should ignore those spans or events in their
853 /// [on_event][Self::on_event], [on_enter][Self::on_enter], [on_exit][Self::on_exit],
854 /// and other notification methods.
855 ///
856 /// </pre></div>
857 ///
858 ///
859 /// See [the trait-level documentation] for more information on filtering
860 /// with subscribers.
861 ///
862 /// [`Interest`]: tracing_core::Interest
863 /// [the trait-level documentation]: #filtering-with-subscribers
864 fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, C>) -> bool {
865 let _ = (metadata, ctx);
866 true
867 }
868
869 /// Notifies this subscriber that a new span was constructed with the given
870 /// `Attributes` and `Id`.
871 fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, C>) {
872 let _ = (attrs, id, ctx);
873 }
874
875 // TODO(eliza): do we want this to be a public API? If we end up moving
876 // filtering subscribers to a separate trait, we may no longer want subscribers to
877 // be able to participate in max level hinting...
878 #[doc(hidden)]
879 fn max_level_hint(&self) -> Option<LevelFilter> {
880 None
881 }
882
883 /// Notifies this subscriber that a span with the given `Id` recorded the given
884 /// `values`.
885 // Note: it's unclear to me why we'd need the current span in `record` (the
886 // only thing the `Context` type currently provides), but passing it in anyway
887 // seems like a good future-proofing measure as it may grow other methods later...
888 fn on_record(&self, _span: &span::Id, _values: &span::Record<'_>, _ctx: Context<'_, C>) {}
889
890 /// Notifies this subscriber that a span with the ID `span` recorded that it
891 /// follows from the span with the ID `follows`.
892 // Note: it's unclear to me why we'd need the current span in `record` (the
893 // only thing the `Context` type currently provides), but passing it in anyway
894 // seems like a good future-proofing measure as it may grow other methods later...
895 fn on_follows_from(&self, _span: &span::Id, _follows: &span::Id, _ctx: Context<'_, C>) {}
896
897 /// Called before [`on_event`], to determine if `on_event` should be called.
898 ///
899 /// <div class="example-wrap" style="display:inline-block">
900 /// <pre class="ignore" style="white-space:normal;font:inherit;">
901 ///
902 /// **Note**: This method determines whether an event is globally enabled,
903 /// *not* whether the individual subscriber will be notified about the
904 /// event. This is intended to be used by subscribers that implement
905 /// filtering for the entire stack. Subscribers which do not wish to be
906 /// notified about certain events but do not wish to globally disable them
907 /// should ignore those events in their [on_event][Self::on_event].
908 ///
909 /// </pre></div>
910 ///
911 /// See [the trait-level documentation] for more information on filtering
912 /// with `Subscriber`s.
913 ///
914 /// [`on_event`]: Self::on_event
915 /// [`Interest`]: tracing_core::Interest
916 /// [the trait-level documentation]: #filtering-with-subscribers
917 #[inline] // collapse this to a constant please mrs optimizer
918 fn event_enabled(&self, _event: &Event<'_>, _ctx: Context<'_, C>) -> bool {
919 true
920 }
921
922 /// Notifies this subscriber that an event has occurred.
923 fn on_event(&self, _event: &Event<'_>, _ctx: Context<'_, C>) {}
924
925 /// Notifies this subscriber that a span with the given ID was entered.
926 fn on_enter(&self, _id: &span::Id, _ctx: Context<'_, C>) {}
927
928 /// Notifies this subscriber that the span with the given ID was exited.
929 fn on_exit(&self, _id: &span::Id, _ctx: Context<'_, C>) {}
930
931 /// Notifies this subscriber that the span with the given ID has been closed.
932 fn on_close(&self, _id: span::Id, _ctx: Context<'_, C>) {}
933
934 /// Notifies this subscriber that a span ID has been cloned, and that the
935 /// subscriber returned a different ID.
936 fn on_id_change(&self, _old: &span::Id, _new: &span::Id, _ctx: Context<'_, C>) {}
937
938 /// Composes this subscriber around the given collector, returning a `Layered`
939 /// struct implementing `Subscribe`.
940 ///
941 /// The returned subscriber will call the methods on this subscriber and then
942 /// those of the new subscriber, before calling the methods on the collector
943 /// it wraps. For example:
944 ///
945 /// ```rust
946 /// # use tracing_subscriber::subscribe::Subscribe;
947 /// # use tracing_core::Collect;
948 /// # use tracing_core::span::Current;
949 /// pub struct FooSubscriber {
950 /// // ...
951 /// }
952 ///
953 /// pub struct BarSubscriber {
954 /// // ...
955 /// }
956 ///
957 /// pub struct MyCollector {
958 /// // ...
959 /// }
960 ///
961 /// impl<C: Collect> Subscribe<C> for FooSubscriber {
962 /// // ...
963 /// }
964 ///
965 /// impl<C: Collect> Subscribe<C> for BarSubscriber {
966 /// // ...
967 /// }
968 ///
969 /// # impl FooSubscriber {
970 /// # fn new() -> Self { Self {} }
971 /// # }
972 /// # impl BarSubscriber {
973 /// # fn new() -> Self { Self { }}
974 /// # }
975 /// # impl MyCollector {
976 /// # fn new() -> Self { Self { }}
977 /// # }
978 /// # use tracing_core::{span::{Id, Attributes, Record}, Metadata, Event};
979 /// # impl tracing_core::Collect for MyCollector {
980 /// # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(1) }
981 /// # fn record(&self, _: &Id, _: &Record) {}
982 /// # fn event(&self, _: &Event) {}
983 /// # fn record_follows_from(&self, _: &Id, _: &Id) {}
984 /// # fn enabled(&self, _: &Metadata) -> bool { false }
985 /// # fn enter(&self, _: &Id) {}
986 /// # fn exit(&self, _: &Id) {}
987 /// # fn current_span(&self) -> Current { Current::unknown() }
988 /// # }
989 /// let collector = FooSubscriber::new()
990 /// .and_then(BarSubscriber::new())
991 /// .with_collector(MyCollector::new());
992 /// ```
993 ///
994 /// Multiple subscribers may be composed in this manner:
995 ///
996 /// ```rust
997 /// # use tracing_subscriber::subscribe::Subscribe;
998 /// # use tracing_core::{Collect, span::Current};
999 /// # pub struct FooSubscriber {}
1000 /// # pub struct BarSubscriber {}
1001 /// # pub struct MyCollector {}
1002 /// # impl<C: Collect> Subscribe<C> for FooSubscriber {}
1003 /// # impl<C: Collect> Subscribe<C> for BarSubscriber {}
1004 /// # impl FooSubscriber {
1005 /// # fn new() -> Self { Self {} }
1006 /// # }
1007 /// # impl BarSubscriber {
1008 /// # fn new() -> Self { Self { }}
1009 /// # }
1010 /// # impl MyCollector {
1011 /// # fn new() -> Self { Self { }}
1012 /// # }
1013 /// # use tracing_core::{span::{Id, Attributes, Record}, Metadata, Event};
1014 /// # impl tracing_core::Collect for MyCollector {
1015 /// # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(1) }
1016 /// # fn record(&self, _: &Id, _: &Record) {}
1017 /// # fn event(&self, _: &Event) {}
1018 /// # fn record_follows_from(&self, _: &Id, _: &Id) {}
1019 /// # fn enabled(&self, _: &Metadata) -> bool { false }
1020 /// # fn enter(&self, _: &Id) {}
1021 /// # fn exit(&self, _: &Id) {}
1022 /// # fn current_span(&self) -> Current { Current::unknown() }
1023 /// # }
1024 /// pub struct BazSubscriber {
1025 /// // ...
1026 /// }
1027 ///
1028 /// impl<C: Collect> Subscribe<C> for BazSubscriber {
1029 /// // ...
1030 /// }
1031 /// # impl BazSubscriber { fn new() -> Self { BazSubscriber {} } }
1032 ///
1033 /// let collector = FooSubscriber::new()
1034 /// .and_then(BarSubscriber::new())
1035 /// .and_then(BazSubscriber::new())
1036 /// .with_collector(MyCollector::new());
1037 /// ```
1038 fn and_then<S>(self, subscriber: S) -> Layered<S, Self, C>
1039 where
1040 S: Subscribe<C>,
1041 Self: Sized,
1042 {
1043 let inner_has_subscriber_filter = filter::subscriber_has_psf(&self);
1044 Layered::new(subscriber, self, inner_has_subscriber_filter)
1045 }
1046
1047 /// Composes this subscriber with the given collector, returning a
1048 /// `Layered` struct that implements [`Collect`].
1049 ///
1050 /// The returned `Layered` subscriber will call the methods on this subscriber
1051 /// and then those of the wrapped collector.
1052 ///
1053 /// For example:
1054 /// ```rust
1055 /// # use tracing_subscriber::subscribe::Subscribe;
1056 /// # use tracing_core::Collect;
1057 /// # use tracing_core::span::Current;
1058 /// pub struct FooSubscriber {
1059 /// // ...
1060 /// }
1061 ///
1062 /// pub struct MyCollector {
1063 /// // ...
1064 /// }
1065 ///
1066 /// impl<C: Collect> Subscribe<C> for FooSubscriber {
1067 /// // ...
1068 /// }
1069 ///
1070 /// # impl FooSubscriber {
1071 /// # fn new() -> Self { Self {} }
1072 /// # }
1073 /// # impl MyCollector {
1074 /// # fn new() -> Self { Self { }}
1075 /// # }
1076 /// # use tracing_core::{span::{Id, Attributes, Record}, Metadata};
1077 /// # impl tracing_core::Collect for MyCollector {
1078 /// # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
1079 /// # fn record(&self, _: &Id, _: &Record) {}
1080 /// # fn event(&self, _: &tracing_core::Event) {}
1081 /// # fn record_follows_from(&self, _: &Id, _: &Id) {}
1082 /// # fn enabled(&self, _: &Metadata) -> bool { false }
1083 /// # fn enter(&self, _: &Id) {}
1084 /// # fn exit(&self, _: &Id) {}
1085 /// # fn current_span(&self) -> Current { Current::unknown() }
1086 /// # }
1087 /// let collector = FooSubscriber::new()
1088 /// .with_collector(MyCollector::new());
1089 ///```
1090 ///
1091 /// [`Collect`]: tracing_core::Collect
1092 fn with_collector(mut self, mut inner: C) -> Layered<Self, C>
1093 where
1094 Self: Sized,
1095 {
1096 let inner_has_subscriber_filter = filter::collector_has_psf(&inner);
1097 self.on_subscribe(&mut inner);
1098 Layered::new(self, inner, inner_has_subscriber_filter)
1099 }
1100
1101 /// Combines `self` with a [`Filter`], returning a [`Filtered`] subscriber.
1102 ///
1103 /// The [`Filter`] will control which spans and events are enabled for
1104 /// this subscriber. See [the trait-level documentation][psf] for details on
1105 /// per-subscriber filtering.
1106 ///
1107 /// [`Filtered`]: crate::filter::Filtered
1108 /// [psf]: #per-subscriber-filtering
1109 #[cfg(all(feature = "registry", feature = "std"))]
1110 #[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))]
1111 fn with_filter<F>(self, filter: F) -> filter::Filtered<Self, F, C>
1112 where
1113 Self: Sized,
1114 F: Filter<C>,
1115 {
1116 filter::Filtered::new(self, filter)
1117 }
1118
1119 /// Erases the type of this subscriber, returning a [`Box`]ed `dyn
1120 /// Subscribe` trait object.
1121 ///
1122 /// This can be used when a function returns a subscriber which may be of
1123 /// one of several types, or when a composed subscriber has a very long type
1124 /// signature.
1125 ///
1126 /// # Examples
1127 ///
1128 /// The following example will *not* compile, because the value assigned to
1129 /// `log_subscriber` may have one of several different types:
1130 ///
1131 /// ```compile_fail
1132 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
1133 /// use tracing_subscriber::{Subscribe, filter::LevelFilter, prelude::*};
1134 /// use std::{path::PathBuf, fs::File, io};
1135 ///
1136 /// /// Configures whether logs are emitted to a file, to stdout, or to stderr.
1137 /// pub enum LogConfig {
1138 /// File(PathBuf),
1139 /// Stdout,
1140 /// Stderr,
1141 /// }
1142 ///
1143 /// let config = // ...
1144 /// # LogConfig::Stdout;
1145 ///
1146 /// // Depending on the config, construct a subscriber of one of several types.
1147 /// let log_subscriber = match config {
1148 /// // If logging to a file, use a maximally-verbose configuration.
1149 /// LogConfig::File(path) => {
1150 /// let file = File::create(path)?;
1151 /// tracing_subscriber::fmt::subscriber()
1152 /// .with_thread_ids(true)
1153 /// .with_thread_names(true)
1154 /// // Selecting the JSON logging format changes the subscriber's
1155 /// // type.
1156 /// .json()
1157 /// .with_span_list(true)
1158 /// // Setting the writer to use our log file changes the
1159 /// // subscriber's type again.
1160 /// .with_writer(file)
1161 /// },
1162 ///
1163 /// // If logging to stdout, use a pretty, human-readable configuration.
1164 /// LogConfig::Stdout => tracing_subscriber::fmt::subscriber()
1165 /// // Selecting the "pretty" logging format changes the
1166 /// // subscriber's type!
1167 /// .pretty()
1168 /// .with_writer(io::stdout)
1169 /// // Add a filter based on the RUST_LOG environment variable;
1170 /// // this changes the type too!
1171 /// .and_then(tracing_subscriber::EnvFilter::from_default_env()),
1172 ///
1173 /// // If logging to stdout, only log errors and warnings.
1174 /// LogConfig::Stderr => tracing_subscriber::fmt::subscriber()
1175 /// // Changing the writer changes the subscriber's type
1176 /// .with_writer(io::stderr)
1177 /// // Only log the `WARN` and `ERROR` levels. Adding a filter
1178 /// // changes the subscriber's type to `Filtered<LevelFilter, ...>`.
1179 /// .with_filter(LevelFilter::WARN),
1180 /// };
1181 ///
1182 /// tracing_subscriber::registry()
1183 /// .with(log_subscriber)
1184 /// .init();
1185 /// # Ok(()) }
1186 /// ```
1187 ///
1188 /// However, adding a call to `.boxed()` after each match arm erases the
1189 /// subscriber's type, so this code *does* compile:
1190 ///
1191 /// ```
1192 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
1193 /// # use tracing_subscriber::{Subscribe, filter::LevelFilter, prelude::*};
1194 /// # use std::{path::PathBuf, fs::File, io};
1195 /// # pub enum LogConfig {
1196 /// # File(PathBuf),
1197 /// # Stdout,
1198 /// # Stderr,
1199 /// # }
1200 /// # let config = LogConfig::Stdout;
1201 /// let log_subscriber = match config {
1202 /// LogConfig::File(path) => {
1203 /// let file = File::create(path)?;
1204 /// tracing_subscriber::fmt::subscriber()
1205 /// .with_thread_ids(true)
1206 /// .with_thread_names(true)
1207 /// .json()
1208 /// .with_span_list(true)
1209 /// .with_writer(file)
1210 /// // Erase the type by boxing the subscriber
1211 /// .boxed()
1212 /// },
1213 ///
1214 /// LogConfig::Stdout => tracing_subscriber::fmt::subscriber()
1215 /// .pretty()
1216 /// .with_writer(io::stdout)
1217 /// .and_then(tracing_subscriber::EnvFilter::from_default_env())
1218 /// // Erase the type by boxing the subscriber
1219 /// .boxed(),
1220 ///
1221 /// LogConfig::Stderr => tracing_subscriber::fmt::subscriber()
1222 /// .with_writer(io::stderr)
1223 /// .with_filter(LevelFilter::WARN)
1224 /// // Erase the type by boxing the subscriber
1225 /// .boxed(),
1226 /// };
1227 ///
1228 /// tracing_subscriber::registry()
1229 /// .with(log_subscriber)
1230 /// .init();
1231 /// # Ok(()) }
1232 /// ```
1233 #[cfg(any(feature = "alloc", feature = "std"))]
1234 #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
1235 fn boxed(self) -> Box<dyn Subscribe<C> + Send + Sync + 'static>
1236 where
1237 Self: Sized,
1238 Self: Subscribe<C> + Send + Sync + 'static,
1239 C: Collect,
1240 {
1241 Box::new(self)
1242 }
1243
1244 #[doc(hidden)]
1245 unsafe fn downcast_raw(&self, id: TypeId) -> Option<NonNull<()>> {
1246 if id == TypeId::of::<Self>() {
1247 Some(NonNull::from(self).cast())
1248 } else {
1249 None
1250 }
1251 }
1252}
1253
1254/// A per-[`Subscribe`] filter that determines whether a span or event is enabled
1255/// for an individual subscriber.
1256#[cfg(all(feature = "registry", feature = "std"))]
1257#[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))]
1258#[cfg_attr(docsrs, doc(notable_trait))]
1259pub trait Filter<S> {
1260 /// Returns `true` if this subscriber is interested in a span or event with the
1261 /// given [`Metadata`] in the current [`Context`], similarly to
1262 /// [`Collect::enabled`].
1263 ///
1264 /// If this returns `false`, the span or event will be disabled _for the
1265 /// wrapped [`Subscribe`]_. Unlike [`Subscribe::enabled`], the span or event will
1266 /// still be recorded if any _other_ subscribers choose to enable it. However,
1267 /// the subscriber [filtered] by this filter will skip recording that span or
1268 /// event.
1269 ///
1270 /// If all subscribers indicate that they do not wish to see this span or event,
1271 /// it will be disabled.
1272 ///
1273 /// [`metadata`]: tracing_core::Metadata
1274 /// [`Collect::enabled`]: tracing_core::Collect::enabled
1275 /// [filtered]: crate::filter::Filtered
1276 fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool;
1277
1278 /// Returns an [`Interest`] indicating whether this subscriber will [always],
1279 /// [sometimes], or [never] be interested in the given [`Metadata`].
1280 ///
1281 /// When a given callsite will [always] or [never] be enabled, the results
1282 /// of evaluating the filter may be cached for improved performance.
1283 /// Therefore, if a filter is capable of determining that it will always or
1284 /// never enable a particular callsite, providing an implementation of this
1285 /// function is recommended.
1286 ///
1287 /// <div class="example-wrap" style="display:inline-block">
1288 /// <pre class="ignore" style="white-space:normal;font:inherit;">
1289 /// <strong>Note</strong>: If a <code>Filter</code> will perform
1290 /// <em>dynamic filtering</em> that depends on the current context in which
1291 /// a span or event was observed (e.g. only enabling an event when it
1292 /// occurs within a particular span), it <strong>must</strong> return
1293 /// <code>Interest::sometimes()</code> from this method. If it returns
1294 /// <code>Interest::always()</code> or <code>Interest::never()</code>, the
1295 /// <code>enabled</code> method may not be called when a particular instance
1296 /// of that span or event is recorded.
1297 /// </pre>
1298 /// </div>
1299 ///
1300 /// This method is broadly similar to [`Collect::register_callsite`];
1301 /// however, since the returned value represents only the interest of
1302 /// *this* subscriber, the resulting behavior is somewhat different.
1303 ///
1304 /// If a [`Collect`] returns [`Interest::always()`][always] or
1305 /// [`Interest::never()`][never] for a given [`Metadata`], its [`enabled`]
1306 /// method is then *guaranteed* to never be called for that callsite. On the
1307 /// other hand, when a `Filter` returns [`Interest::always()`][always] or
1308 /// [`Interest::never()`][never] for a callsite, _other_ [`Subscribe`]s may have
1309 /// differing interests in that callsite. If this is the case, the callsite
1310 /// will receive [`Interest::sometimes()`][sometimes], and the [`enabled`]
1311 /// method will still be called for that callsite when it records a span or
1312 /// event.
1313 ///
1314 /// Returning [`Interest::always()`][always] or [`Interest::never()`][never] from
1315 /// `Filter::callsite_enabled` will permanently enable or disable a
1316 /// callsite (without requiring subsequent calls to [`enabled`]) if and only
1317 /// if the following is true:
1318 ///
1319 /// - all [`Subscribe`]s that comprise the subscriber include `Filter`s
1320 /// (this includes a tree of [`Layered`] subscribers that share the same
1321 /// `Filter`)
1322 /// - all those `Filter`s return the same [`Interest`].
1323 ///
1324 /// For example, if a [`Collect`] consists of two [`Filtered`] subscribers,
1325 /// and both of those subscribers return [`Interest::never()`][never], that
1326 /// callsite *will* never be enabled, and the [`enabled`] methods of those
1327 /// [`Filter`]s will not be called.
1328 ///
1329 /// ## Default Implementation
1330 ///
1331 /// The default implementation of this method assumes that the
1332 /// `Filter`'s [`enabled`] method _may_ perform dynamic filtering, and
1333 /// returns [`Interest::sometimes()`][sometimes], to ensure that [`enabled`]
1334 /// is called to determine whether a particular _instance_ of the callsite
1335 /// is enabled in the current context. If this is *not* the case, and the
1336 /// `Filter`'s [`enabled`] method will always return the same result
1337 /// for a particular [`Metadata`], this method can be overridden as
1338 /// follows:
1339 ///
1340 /// ```
1341 /// use tracing_subscriber::subscribe;
1342 /// use tracing_core::{Metadata, collect::Interest};
1343 ///
1344 /// struct MyFilter {
1345 /// // ...
1346 /// }
1347 ///
1348 /// impl MyFilter {
1349 /// // The actual logic for determining whether a `Metadata` is enabled
1350 /// // must be factored out from the `enabled` method, so that it can be
1351 /// // called without a `Context` (which is not provided to the
1352 /// // `callsite_enabled` method).
1353 /// fn is_enabled(&self, metadata: &Metadata<'_>) -> bool {
1354 /// // ...
1355 /// # drop(metadata); true
1356 /// }
1357 /// }
1358 ///
1359 /// impl<C> subscribe::Filter<C> for MyFilter {
1360 /// fn enabled(&self, metadata: &Metadata<'_>, _: &subscribe::Context<'_, C>) -> bool {
1361 /// // Even though we are implementing `callsite_enabled`, we must still provide a
1362 /// // working implementation of `enabled`, as returning `Interest::always()` or
1363 /// // `Interest::never()` will *allow* caching, but will not *guarantee* it.
1364 /// // Other filters may still return `Interest::sometimes()`, so we may be
1365 /// // asked again in `enabled`.
1366 /// self.is_enabled(metadata)
1367 /// }
1368 ///
1369 /// fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest {
1370 /// // The result of `self.enabled(metadata, ...)` will always be
1371 /// // the same for any given `Metadata`, so we can convert it into
1372 /// // an `Interest`:
1373 /// if self.is_enabled(metadata) {
1374 /// Interest::always()
1375 /// } else {
1376 /// Interest::never()
1377 /// }
1378 /// }
1379 /// }
1380 /// ```
1381 ///
1382 /// [`Metadata`]: tracing_core::Metadata
1383 /// [`Interest`]: tracing_core::Interest
1384 /// [always]: tracing_core::Interest::always
1385 /// [sometimes]: tracing_core::Interest::sometimes
1386 /// [never]: tracing_core::Interest::never
1387 /// [`Collect::register_callsite`]: tracing_core::Collect::register_callsite
1388 /// [`Collect`]: tracing_core::Collect
1389 /// [`enabled`]: Filter::enabled
1390 /// [`Filtered`]: crate::filter::Filtered
1391 fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest {
1392 let _ = meta;
1393 Interest::sometimes()
1394 }
1395
1396 /// Returns an optional hint of the highest [verbosity level][level] that
1397 /// this `Filter` will enable.
1398 ///
1399 /// If this method returns a [`LevelFilter`], it will be used as a hint to
1400 /// determine the most verbose level that will be enabled. This will allow
1401 /// spans and events which are more verbose than that level to be skipped
1402 /// more efficiently. An implementation of this method is optional, but
1403 /// strongly encouraged.
1404 ///
1405 /// If the maximum level the `Filter` will enable can change over the
1406 /// course of its lifetime, it is free to return a different value from
1407 /// multiple invocations of this method. However, note that changes in the
1408 /// maximum level will **only** be reflected after the callsite [`Interest`]
1409 /// cache is rebuilt, by calling the
1410 /// [`tracing_core::callsite::rebuild_interest_cache`] function.
1411 /// Therefore, if the `Filter will change the value returned by this
1412 /// method, it is responsible for ensuring that [`rebuild_interest_cache`]
1413 /// is called after the value of the max level changes.
1414 ///
1415 /// ## Default Implementation
1416 ///
1417 /// By default, this method returns `None`, indicating that the maximum
1418 /// level is unknown.
1419 ///
1420 /// [level]: tracing_core::metadata::Level
1421 /// [`LevelFilter`]: crate::filter::LevelFilter
1422 /// [`Interest`]: tracing_core::collect::Interest
1423 /// [`rebuild_interest_cache`]: tracing_core::callsite::rebuild_interest_cache
1424 fn max_level_hint(&self) -> Option<LevelFilter> {
1425 None
1426 }
1427
1428 /// Called before the filtered subscribers' [`on_event`], to determine if
1429 /// `on_event` should be called.
1430 ///
1431 /// This gives a chance to filter events based on their fields. Note,
1432 /// however, that this *does not* override [`enabled`], and is not even
1433 /// called if [`enabled`] returns `false`.
1434 ///
1435 /// ## Default Implementation
1436 ///
1437 /// By default, this method returns `true`, indicating that no events are
1438 /// filtered out based on their fields.
1439 ///
1440 /// [`enabled`]: crate::subscribe::Filter::enabled
1441 /// [`on_event`]: crate::subscribe::Subscribe::on_event
1442 #[inline] // collapse this to a constant please mrs optimizer
1443 fn event_enabled(&self, event: &Event<'_>, cx: &Context<'_, S>) -> bool {
1444 let _ = (event, cx);
1445 true
1446 }
1447
1448 /// Notifies this filter that a new span was constructed with the given
1449 /// `Attributes` and `Id`.
1450 ///
1451 /// By default, this method does nothing. `Filter` implementations that
1452 /// need to be notified when new spans are created can override this
1453 /// method.
1454 fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) {
1455 let _ = (attrs, id, ctx);
1456 }
1457
1458 /// Notifies this filter that a span with the given `Id` recorded the given
1459 /// `values`.
1460 ///
1461 /// By default, this method does nothing. `Filter` implementations that
1462 /// need to be notified when new spans are created can override this
1463 /// method.
1464 fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) {
1465 let _ = (id, values, ctx);
1466 }
1467
1468 /// Notifies this filter that a span with the given ID was entered.
1469 ///
1470 /// By default, this method does nothing. `Filter` implementations that
1471 /// need to be notified when a span is entered can override this method.
1472 fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
1473 let _ = (id, ctx);
1474 }
1475
1476 /// Notifies this filter that a span with the given ID was exited.
1477 ///
1478 /// By default, this method does nothing. `Filter` implementations that
1479 /// need to be notified when a span is exited can override this method.
1480 fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
1481 let _ = (id, ctx);
1482 }
1483
1484 /// Notifies this filter that a span with the given ID has been closed.
1485 ///
1486 /// By default, this method does nothing. `Filter` implementations that
1487 /// need to be notified when a span is closed can override this method.
1488 fn on_close(&self, id: span::Id, ctx: Context<'_, S>) {
1489 let _ = (id, ctx);
1490 }
1491}
1492
1493/// Extension trait adding a `with(Subscribe)` combinator to types implementing
1494/// [`Collect`].
1495pub trait CollectExt: Collect + crate::sealed::Sealed {
1496 /// Wraps `self` with the provided `subscriber`.
1497 fn with<S>(self, subscriber: S) -> Layered<S, Self>
1498 where
1499 S: Subscribe<Self>,
1500 Self: Sized,
1501 {
1502 subscriber.with_collector(self)
1503 }
1504}
1505/// A subscriber that does nothing.
1506#[derive(Clone, Debug, Default)]
1507pub struct Identity {
1508 _p: (),
1509}
1510
1511// === impl Subscribe ===
1512
1513#[derive(Clone, Copy)]
1514pub(crate) struct NoneLayerMarker(());
1515static NONE_LAYER_MARKER: NoneLayerMarker = NoneLayerMarker(());
1516
1517/// Is a type implementing `Subscriber` `Option::<_>::None`?
1518pub(crate) fn subscriber_is_none<S, C>(subscriber: &S) -> bool
1519where
1520 S: Subscribe<C>,
1521 C: Collect,
1522{
1523 unsafe {
1524 // Safety: we're not actually *doing* anything with this pointer ---
1525 // this only care about the `Option`, which is essentially being used
1526 // as a bool. We can rely on the pointer being valid, because it is
1527 // a crate-private type, and is only returned by the `Subscribe` impl
1528 // for `Option`s. However, even if the subscriber *does* decide to be
1529 // evil and give us an invalid pointer here, that's fine, because we'll
1530 // never actually dereference it.
1531 subscriber.downcast_raw(TypeId::of::<NoneLayerMarker>())
1532 }
1533 .is_some()
1534}
1535
1536/// Is a type implementing `Collect` `Option::<_>::None`?
1537pub(crate) fn collector_is_none<C>(collector: &C) -> bool
1538where
1539 C: Collect,
1540{
1541 unsafe {
1542 // Safety: we're not actually *doing* anything with this pointer ---
1543 // this only care about the `Option`, which is essentially being used
1544 // as a bool. We can rely on the pointer being valid, because it is
1545 // a crate-private type, and is only returned by the `Subscribe` impl
1546 // for `Option`s. However, even if the subscriber *does* decide to be
1547 // evil and give us an invalid pointer here, that's fine, because we'll
1548 // never actually dereference it.
1549 collector.downcast_raw(TypeId::of::<NoneLayerMarker>())
1550 }
1551 .is_some()
1552}
1553
1554impl<S, C> Subscribe<C> for Option<S>
1555where
1556 S: Subscribe<C>,
1557 C: Collect,
1558{
1559 fn on_register_dispatch(&self, collector: &Dispatch) {
1560 if let Some(ref subscriber) = self {
1561 subscriber.on_register_dispatch(collector)
1562 }
1563 }
1564
1565 fn on_subscribe(&mut self, collector: &mut C) {
1566 if let Some(ref mut subscriber) = self {
1567 subscriber.on_subscribe(collector)
1568 }
1569 }
1570
1571 #[inline]
1572 fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, C>) {
1573 if let Some(ref inner) = self {
1574 inner.on_new_span(attrs, id, ctx)
1575 }
1576 }
1577
1578 #[inline]
1579 fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
1580 match self {
1581 Some(ref inner) => inner.register_callsite(metadata),
1582 None => Interest::always(),
1583 }
1584 }
1585
1586 #[inline]
1587 fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, C>) -> bool {
1588 match self {
1589 Some(ref inner) => inner.enabled(metadata, ctx),
1590 None => true,
1591 }
1592 }
1593
1594 #[inline]
1595 fn max_level_hint(&self) -> Option<LevelFilter> {
1596 match self {
1597 Some(ref inner) => inner.max_level_hint(),
1598 None => {
1599 // There is no inner subscriber, so this subscriber will
1600 // never enable anything.
1601 Some(LevelFilter::OFF)
1602 }
1603 }
1604 }
1605
1606 #[inline]
1607 fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: Context<'_, C>) {
1608 if let Some(ref inner) = self {
1609 inner.on_record(span, values, ctx);
1610 }
1611 }
1612
1613 #[inline]
1614 fn on_follows_from(&self, span: &span::Id, follows: &span::Id, ctx: Context<'_, C>) {
1615 if let Some(ref inner) = self {
1616 inner.on_follows_from(span, follows, ctx);
1617 }
1618 }
1619
1620 #[inline]
1621 fn event_enabled(&self, event: &Event<'_>, ctx: Context<'_, C>) -> bool {
1622 match self {
1623 Some(ref inner) => inner.event_enabled(event, ctx),
1624 None => true,
1625 }
1626 }
1627
1628 #[inline]
1629 fn on_event(&self, event: &Event<'_>, ctx: Context<'_, C>) {
1630 if let Some(ref inner) = self {
1631 inner.on_event(event, ctx);
1632 }
1633 }
1634
1635 #[inline]
1636 fn on_enter(&self, id: &span::Id, ctx: Context<'_, C>) {
1637 if let Some(ref inner) = self {
1638 inner.on_enter(id, ctx);
1639 }
1640 }
1641
1642 #[inline]
1643 fn on_exit(&self, id: &span::Id, ctx: Context<'_, C>) {
1644 if let Some(ref inner) = self {
1645 inner.on_exit(id, ctx);
1646 }
1647 }
1648
1649 #[inline]
1650 fn on_close(&self, id: span::Id, ctx: Context<'_, C>) {
1651 if let Some(ref inner) = self {
1652 inner.on_close(id, ctx);
1653 }
1654 }
1655
1656 #[inline]
1657 fn on_id_change(&self, old: &span::Id, new: &span::Id, ctx: Context<'_, C>) {
1658 if let Some(ref inner) = self {
1659 inner.on_id_change(old, new, ctx)
1660 }
1661 }
1662
1663 #[doc(hidden)]
1664 #[inline]
1665 unsafe fn downcast_raw(&self, id: TypeId) -> Option<NonNull<()>> {
1666 if id == TypeId::of::<Self>() {
1667 Some(NonNull::from(self).cast())
1668 } else if id == TypeId::of::<NoneLayerMarker>() && self.is_none() {
1669 Some(NonNull::from(&NONE_LAYER_MARKER).cast())
1670 } else {
1671 self.as_ref().and_then(|inner| inner.downcast_raw(id))
1672 }
1673 }
1674}
1675
1676#[cfg(any(feature = "std", feature = "alloc"))]
1677macro_rules! subscriber_impl_body {
1678 () => {
1679 fn on_register_dispatch(&self, collector: &Dispatch) {
1680 self.deref().on_register_dispatch(collector);
1681 }
1682
1683 #[inline]
1684 fn on_subscribe(&mut self, collect: &mut C) {
1685 self.deref_mut().on_subscribe(collect);
1686 }
1687
1688 #[inline]
1689 fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
1690 self.deref().register_callsite(metadata)
1691 }
1692
1693 #[inline]
1694 fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, C>) {
1695 self.deref().on_new_span(attrs, id, ctx)
1696 }
1697
1698 #[inline]
1699 fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, C>) -> bool {
1700 self.deref().enabled(metadata, ctx)
1701 }
1702
1703 #[inline]
1704 fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: Context<'_, C>) {
1705 self.deref().on_record(span, values, ctx)
1706 }
1707
1708 #[inline]
1709 fn on_follows_from(&self, span: &span::Id, follows: &span::Id, ctx: Context<'_, C>) {
1710 self.deref().on_follows_from(span, follows, ctx)
1711 }
1712
1713 #[inline]
1714 fn event_enabled(&self, event: &Event<'_>, ctx: Context<'_, C>) -> bool {
1715 self.deref().event_enabled(event, ctx)
1716 }
1717
1718 #[inline]
1719 fn on_event(&self, event: &Event<'_>, ctx: Context<'_, C>) {
1720 self.deref().on_event(event, ctx)
1721 }
1722
1723 #[inline]
1724 fn on_enter(&self, id: &span::Id, ctx: Context<'_, C>) {
1725 self.deref().on_enter(id, ctx)
1726 }
1727
1728 #[inline]
1729 fn on_exit(&self, id: &span::Id, ctx: Context<'_, C>) {
1730 self.deref().on_exit(id, ctx)
1731 }
1732
1733 #[inline]
1734 fn on_close(&self, id: span::Id, ctx: Context<'_, C>) {
1735 self.deref().on_close(id, ctx)
1736 }
1737
1738 #[inline]
1739 fn on_id_change(&self, old: &span::Id, new: &span::Id, ctx: Context<'_, C>) {
1740 self.deref().on_id_change(old, new, ctx)
1741 }
1742
1743 #[inline]
1744 fn max_level_hint(&self) -> Option<LevelFilter> {
1745 self.deref().max_level_hint()
1746 }
1747
1748 #[doc(hidden)]
1749 #[inline]
1750 unsafe fn downcast_raw(&self, id: TypeId) -> ::core::option::Option<NonNull<()>> {
1751 self.deref().downcast_raw(id)
1752 }
1753 };
1754}
1755
1756feature! {
1757 #![any(feature = "std", feature = "alloc")]
1758
1759 impl<S, C> Subscribe<C> for Box<S>
1760 where
1761 S: Subscribe<C>,
1762 C: Collect,
1763 {
1764 subscriber_impl_body! {}
1765 }
1766
1767 impl<C> Subscribe<C> for Box<dyn Subscribe<C> + Send + Sync + 'static>
1768 where
1769 C: Collect,
1770 {
1771 subscriber_impl_body! {}
1772 }
1773
1774
1775 impl<C, S> Subscribe<C> for alloc::vec::Vec<S>
1776 where
1777 S: Subscribe<C>,
1778 C: Collect,
1779 {
1780 fn on_register_dispatch(&self, collector: &Dispatch) {
1781 for s in self {
1782 s.on_register_dispatch(collector);
1783 }
1784 }
1785
1786 fn on_subscribe(&mut self, collector: &mut C) {
1787 for s in self {
1788 s.on_subscribe(collector);
1789 }
1790 }
1791
1792 fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
1793 // Return highest level of interest.
1794 let mut interest = Interest::never();
1795 for s in self {
1796 let new_interest = s.register_callsite(metadata);
1797 if (interest.is_sometimes() && new_interest.is_always())
1798 || (interest.is_never() && !new_interest.is_never())
1799 {
1800 interest = new_interest;
1801 }
1802 }
1803
1804 interest
1805 }
1806
1807 fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, C>) -> bool {
1808 self.iter().all(|s| s.enabled(metadata, ctx.clone()))
1809 }
1810
1811 fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, C>) {
1812 for s in self {
1813 s.on_new_span(attrs, id, ctx.clone());
1814 }
1815 }
1816
1817 fn max_level_hint(&self) -> Option<LevelFilter> {
1818 // Default to `OFF` if there are no underlying subscribers
1819 let mut max_level = LevelFilter::OFF;
1820 for s in self {
1821 // NOTE(eliza): this is slightly subtle: if *any* subscriber
1822 // returns `None`, we have to return `None`, assuming there is
1823 // no max level hint, since that particular subscriber cannot
1824 // provide a hint.
1825 let hint = s.max_level_hint()?;
1826 max_level = core::cmp::max(hint, max_level);
1827 }
1828 Some(max_level)
1829 }
1830
1831 fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: Context<'_, C>) {
1832 for s in self {
1833 s.on_record(span, values, ctx.clone())
1834 }
1835 }
1836
1837 fn on_follows_from(&self, span: &span::Id, follows: &span::Id, ctx: Context<'_, C>) {
1838 for s in self {
1839 s.on_follows_from(span, follows, ctx.clone());
1840 }
1841 }
1842
1843 fn on_event(&self, event: &Event<'_>, ctx: Context<'_, C>) {
1844 for s in self {
1845 s.on_event(event, ctx.clone());
1846 }
1847 }
1848
1849 fn on_enter(&self, id: &span::Id, ctx: Context<'_, C>) {
1850 for s in self {
1851 s.on_enter(id, ctx.clone());
1852 }
1853 }
1854
1855 fn on_exit(&self, id: &span::Id, ctx: Context<'_, C>) {
1856 for s in self {
1857 s.on_exit(id, ctx.clone());
1858 }
1859 }
1860
1861 fn on_close(&self, id: span::Id, ctx: Context<'_, C>) {
1862 for s in self {
1863 s.on_close(id.clone(), ctx.clone());
1864 }
1865 }
1866
1867 #[doc(hidden)]
1868 unsafe fn downcast_raw(&self, id: TypeId) -> Option<NonNull<()>> {
1869 // If downcasting to `Self`, return a pointer to `self`.
1870 if id == TypeId::of::<Self>() {
1871 return Some(NonNull::from(self).cast());
1872 }
1873
1874 // Someone is looking for per-subscriber filters. But, this `Vec`
1875 // might contain subscribers with per-subscriber filters *and*
1876 // subscribers without filters. It should only be treated as a
1877 // per-subscriber-filtered subscriber if *all* its subscribers have
1878 // per-subscriber filters.
1879 // XXX(eliza): it's a bummer we have to do this linear search every
1880 // time. It would be nice if this could be cached, but that would
1881 // require replacing the `Vec` impl with an impl for a newtype...
1882 if filter::is_psf_downcast_marker(id) && self.iter().any(|s| s.downcast_raw(id).is_none()) {
1883 return None;
1884 }
1885
1886 // Otherwise, return the first child of `self` that downcaaasts to
1887 // the selected type, if any.
1888 // XXX(eliza): hope this is reasonable lol
1889 self.iter().find_map(|s| s.downcast_raw(id))
1890 }
1891 }
1892}
1893
1894// === impl CollectExt ===
1895
1896impl<C: Collect> crate::sealed::Sealed for C {}
1897impl<C: Collect> CollectExt for C {}
1898
1899// === impl Identity ===
1900
1901impl<C: Collect> Subscribe<C> for Identity {}
1902
1903impl Identity {
1904 /// Returns a new `Identity` subscriber.
1905 pub fn new() -> Self {
1906 Self { _p: () }
1907 }
1908}