Bug 1885602 - Part 2: Add a MozillaAccountMenuButton composable for the menu redesign...
[gecko.git] / third_party / rust / tracing-core / src / dispatcher.rs
blob36b3cfd85f7561569f80aa742c969bedeecaa354
1 //! Dispatches trace events to [`Subscriber`]s.
2 //!
3 //! The _dispatcher_ is the component of the tracing system which is responsible
4 //! for forwarding trace data from the instrumentation points that generate it
5 //! to the subscriber that collects it.
6 //!
7 //! # Using the Trace Dispatcher
8 //!
9 //! Every thread in a program using `tracing` has a _default subscriber_. When
10 //! events occur, or spans are created, they are dispatched to the thread's
11 //! current subscriber.
12 //!
13 //! ## Setting the Default Subscriber
14 //!
15 //! By default, the current subscriber is an empty implementation that does
16 //! nothing. To use a subscriber implementation, it must be set as the default.
17 //! There are two methods for doing so: [`with_default`] and
18 //! [`set_global_default`]. `with_default` sets the default subscriber for the
19 //! duration of a scope, while `set_global_default` sets a default subscriber
20 //! for the entire process.
21 //!
22 //! To use either of these functions, we must first wrap our subscriber in a
23 //! [`Dispatch`], a cloneable, type-erased reference to a subscriber. For
24 //! example:
25 //! ```rust
26 //! # pub struct FooSubscriber;
27 //! # use tracing_core::{
28 //! #   dispatcher, Event, Metadata,
29 //! #   span::{Attributes, Id, Record}
30 //! # };
31 //! # impl tracing_core::Subscriber for FooSubscriber {
32 //! #   fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
33 //! #   fn record(&self, _: &Id, _: &Record) {}
34 //! #   fn event(&self, _: &Event) {}
35 //! #   fn record_follows_from(&self, _: &Id, _: &Id) {}
36 //! #   fn enabled(&self, _: &Metadata) -> bool { false }
37 //! #   fn enter(&self, _: &Id) {}
38 //! #   fn exit(&self, _: &Id) {}
39 //! # }
40 //! # impl FooSubscriber { fn new() -> Self { FooSubscriber } }
41 //! use dispatcher::Dispatch;
42 //!
43 //! let my_subscriber = FooSubscriber::new();
44 //! let my_dispatch = Dispatch::new(my_subscriber);
45 //! ```
46 //! Then, we can use [`with_default`] to set our `Dispatch` as the default for
47 //! the duration of a block:
48 //! ```rust
49 //! # pub struct FooSubscriber;
50 //! # use tracing_core::{
51 //! #   dispatcher, Event, Metadata,
52 //! #   span::{Attributes, Id, Record}
53 //! # };
54 //! # impl tracing_core::Subscriber for FooSubscriber {
55 //! #   fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
56 //! #   fn record(&self, _: &Id, _: &Record) {}
57 //! #   fn event(&self, _: &Event) {}
58 //! #   fn record_follows_from(&self, _: &Id, _: &Id) {}
59 //! #   fn enabled(&self, _: &Metadata) -> bool { false }
60 //! #   fn enter(&self, _: &Id) {}
61 //! #   fn exit(&self, _: &Id) {}
62 //! # }
63 //! # impl FooSubscriber { fn new() -> Self { FooSubscriber } }
64 //! # let my_subscriber = FooSubscriber::new();
65 //! # let my_dispatch = dispatcher::Dispatch::new(my_subscriber);
66 //! // no default subscriber
67 //!
68 //! # #[cfg(feature = "std")]
69 //! dispatcher::with_default(&my_dispatch, || {
70 //!     // my_subscriber is the default
71 //! });
72 //!
73 //! // no default subscriber again
74 //! ```
75 //! It's important to note that `with_default` will not propagate the current
76 //! thread's default subscriber to any threads spawned within the `with_default`
77 //! block. To propagate the default subscriber to new threads, either use
78 //! `with_default` from the new thread, or use `set_global_default`.
79 //!
80 //! As an alternative to `with_default`, we can use [`set_global_default`] to
81 //! set a `Dispatch` as the default for all threads, for the lifetime of the
82 //! program. For example:
83 //! ```rust
84 //! # pub struct FooSubscriber;
85 //! # use tracing_core::{
86 //! #   dispatcher, Event, Metadata,
87 //! #   span::{Attributes, Id, Record}
88 //! # };
89 //! # impl tracing_core::Subscriber for FooSubscriber {
90 //! #   fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
91 //! #   fn record(&self, _: &Id, _: &Record) {}
92 //! #   fn event(&self, _: &Event) {}
93 //! #   fn record_follows_from(&self, _: &Id, _: &Id) {}
94 //! #   fn enabled(&self, _: &Metadata) -> bool { false }
95 //! #   fn enter(&self, _: &Id) {}
96 //! #   fn exit(&self, _: &Id) {}
97 //! # }
98 //! # impl FooSubscriber { fn new() -> Self { FooSubscriber } }
99 //! # let my_subscriber = FooSubscriber::new();
100 //! # let my_dispatch = dispatcher::Dispatch::new(my_subscriber);
101 //! // no default subscriber
103 //! dispatcher::set_global_default(my_dispatch)
104 //!     // `set_global_default` will return an error if the global default
105 //!     // subscriber has already been set.
106 //!     .expect("global default was already set!");
108 //! // `my_subscriber` is now the default
109 //! ```
111 //! <pre class="ignore" style="white-space:normal;font:inherit;">
112 //!     <strong>Note</strong>:the thread-local scoped dispatcher
113 //!     (<a href="#fn.with_default"><code>with_default</code></a>) requires the
114 //!     Rust standard library. <code>no_std</code> users should use
115 //!     <a href="#fn.set_global_default"><code>set_global_default</code></a>
116 //!     instead.
117 //! </pre>
119 //! ## Accessing the Default Subscriber
121 //! A thread's current default subscriber can be accessed using the
122 //! [`get_default`] function, which executes a closure with a reference to the
123 //! currently default `Dispatch`. This is used primarily by `tracing`
124 //! instrumentation.
126 use crate::{
127     callsite, span,
128     subscriber::{self, NoSubscriber, Subscriber},
129     Event, LevelFilter, Metadata,
132 use crate::stdlib::{
133     any::Any,
134     fmt,
135     sync::{
136         atomic::{AtomicBool, AtomicUsize, Ordering},
137         Arc, Weak,
138     },
141 #[cfg(feature = "std")]
142 use crate::stdlib::{
143     cell::{Cell, RefCell, RefMut},
144     error,
147 #[cfg(feature = "alloc")]
148 use alloc::sync::{Arc, Weak};
150 #[cfg(feature = "alloc")]
151 use core::ops::Deref;
153 /// `Dispatch` trace data to a [`Subscriber`].
154 #[derive(Clone)]
155 pub struct Dispatch {
156     subscriber: Arc<dyn Subscriber + Send + Sync>,
159 /// `WeakDispatch` is a version of [`Dispatch`] that holds a non-owning reference
160 /// to a [`Subscriber`].
162 /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
163 /// which returns an `Option<Dispatch>`. If all [`Dispatch`] clones that point
164 /// at the `Subscriber` have been dropped, [`WeakDispatch::upgrade`] will return
165 /// `None`. Otherwise, it will return `Some(Dispatch)`.
167 /// A `WeakDispatch` may be created from a [`Dispatch`] by calling the
168 /// [`Dispatch::downgrade`] method. The primary use for creating a
169 /// [`WeakDispatch`] is to allow a Subscriber` to hold a cyclical reference to
170 /// itself without creating a memory leak. See [here] for details.
172 /// This type is analogous to the [`std::sync::Weak`] type, but for a
173 /// [`Dispatch`] rather than an [`Arc`].
175 /// [`Arc`]: std::sync::Arc
176 /// [here]: Subscriber#avoiding-memory-leaks
177 #[derive(Clone)]
178 pub struct WeakDispatch {
179     subscriber: Weak<dyn Subscriber + Send + Sync>,
182 #[cfg(feature = "alloc")]
183 #[derive(Clone)]
184 enum Kind<T> {
185     Global(&'static (dyn Collect + Send + Sync)),
186     Scoped(T),
189 #[cfg(feature = "std")]
190 thread_local! {
191     static CURRENT_STATE: State = State {
192         default: RefCell::new(None),
193         can_enter: Cell::new(true),
194     };
197 static EXISTS: AtomicBool = AtomicBool::new(false);
198 static GLOBAL_INIT: AtomicUsize = AtomicUsize::new(UNINITIALIZED);
200 const UNINITIALIZED: usize = 0;
201 const INITIALIZING: usize = 1;
202 const INITIALIZED: usize = 2;
204 static mut GLOBAL_DISPATCH: Option<Dispatch> = None;
206 /// The dispatch state of a thread.
207 #[cfg(feature = "std")]
208 struct State {
209     /// This thread's current default dispatcher.
210     default: RefCell<Option<Dispatch>>,
211     /// Whether or not we can currently begin dispatching a trace event.
212     ///
213     /// This is set to `false` when functions such as `enter`, `exit`, `event`,
214     /// and `new_span` are called on this thread's default dispatcher, to
215     /// prevent further trace events triggered inside those functions from
216     /// creating an infinite recursion. When we finish handling a dispatch, this
217     /// is set back to `true`.
218     can_enter: Cell<bool>,
221 /// While this guard is active, additional calls to subscriber functions on
222 /// the default dispatcher will not be able to access the dispatch context.
223 /// Dropping the guard will allow the dispatch context to be re-entered.
224 #[cfg(feature = "std")]
225 struct Entered<'a>(&'a State);
227 /// A guard that resets the current default dispatcher to the prior
228 /// default dispatcher when dropped.
229 #[cfg(feature = "std")]
230 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
231 #[derive(Debug)]
232 pub struct DefaultGuard(Option<Dispatch>);
234 /// Sets this dispatch as the default for the duration of a closure.
236 /// The default dispatcher is used when creating a new [span] or
237 /// [`Event`].
239 /// <pre class="ignore" style="white-space:normal;font:inherit;">
240 ///     <strong>Note</strong>: This function required the Rust standard library.
241 ///     <code>no_std</code> users should use <a href="../fn.set_global_default.html">
242 ///     <code>set_global_default</code></a> instead.
243 /// </pre>
245 /// [span]: super::span
246 /// [`Subscriber`]: super::subscriber::Subscriber
247 /// [`Event`]: super::event::Event
248 /// [`set_global_default`]: super::set_global_default
249 #[cfg(feature = "std")]
250 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
251 pub fn with_default<T>(dispatcher: &Dispatch, f: impl FnOnce() -> T) -> T {
252     // When this guard is dropped, the default dispatcher will be reset to the
253     // prior default. Using this (rather than simply resetting after calling
254     // `f`) ensures that we always reset to the prior dispatcher even if `f`
255     // panics.
256     let _guard = set_default(dispatcher);
257     f()
260 /// Sets the dispatch as the default dispatch for the duration of the lifetime
261 /// of the returned DefaultGuard
263 /// <pre class="ignore" style="white-space:normal;font:inherit;">
264 ///     <strong>Note</strong>: This function required the Rust standard library.
265 ///     <code>no_std</code> users should use <a href="../fn.set_global_default.html">
266 ///     <code>set_global_default</code></a> instead.
267 /// </pre>
269 /// [`set_global_default`]: super::set_global_default
270 #[cfg(feature = "std")]
271 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
272 #[must_use = "Dropping the guard unregisters the dispatcher."]
273 pub fn set_default(dispatcher: &Dispatch) -> DefaultGuard {
274     // When this guard is dropped, the default dispatcher will be reset to the
275     // prior default. Using this ensures that we always reset to the prior
276     // dispatcher even if the thread calling this function panics.
277     State::set_default(dispatcher.clone())
280 /// Sets this dispatch as the global default for the duration of the entire program.
281 /// Will be used as a fallback if no thread-local dispatch has been set in a thread
282 /// (using `with_default`.)
284 /// Can only be set once; subsequent attempts to set the global default will fail.
285 /// Returns `Err` if the global default has already been set.
287 /// <div class="example-wrap" style="display:inline-block"><pre class="compile_fail" style="white-space:normal;font:inherit;">
288 ///     <strong>Warning</strong>: In general, libraries should <em>not</em> call
289 ///     <code>set_global_default()</code>! Doing so will cause conflicts when
290 ///     executables that depend on the library try to set the default later.
291 /// </pre></div>
293 /// [span]: super::span
294 /// [`Subscriber`]: super::subscriber::Subscriber
295 /// [`Event`]: super::event::Event
296 pub fn set_global_default(dispatcher: Dispatch) -> Result<(), SetGlobalDefaultError> {
297     // if `compare_exchange` returns Result::Ok(_), then `new` has been set and
298     // `current`—now the prior value—has been returned in the `Ok()` branch.
299     if GLOBAL_INIT
300         .compare_exchange(
301             UNINITIALIZED,
302             INITIALIZING,
303             Ordering::SeqCst,
304             Ordering::SeqCst,
305         )
306         .is_ok()
307     {
308         unsafe {
309             GLOBAL_DISPATCH = Some(dispatcher);
310         }
311         GLOBAL_INIT.store(INITIALIZED, Ordering::SeqCst);
312         EXISTS.store(true, Ordering::Release);
313         Ok(())
314     } else {
315         Err(SetGlobalDefaultError { _no_construct: () })
316     }
319 /// Returns true if a `tracing` dispatcher has ever been set.
321 /// This may be used to completely elide trace points if tracing is not in use
322 /// at all or has yet to be initialized.
323 #[doc(hidden)]
324 #[inline(always)]
325 pub fn has_been_set() -> bool {
326     EXISTS.load(Ordering::Relaxed)
329 /// Returned if setting the global dispatcher fails.
330 pub struct SetGlobalDefaultError {
331     _no_construct: (),
334 impl fmt::Debug for SetGlobalDefaultError {
335     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
336         f.debug_tuple("SetGlobalDefaultError")
337             .field(&Self::MESSAGE)
338             .finish()
339     }
342 impl fmt::Display for SetGlobalDefaultError {
343     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
344         f.pad(Self::MESSAGE)
345     }
348 #[cfg(feature = "std")]
349 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
350 impl error::Error for SetGlobalDefaultError {}
352 impl SetGlobalDefaultError {
353     const MESSAGE: &'static str = "a global default trace dispatcher has already been set";
356 /// Executes a closure with a reference to this thread's current [dispatcher].
358 /// Note that calls to `get_default` should not be nested; if this function is
359 /// called while inside of another `get_default`, that closure will be provided
360 /// with `Dispatch::none` rather than the previously set dispatcher.
362 /// [dispatcher]: super::dispatcher::Dispatch
363 #[cfg(feature = "std")]
364 pub fn get_default<T, F>(mut f: F) -> T
365 where
366     F: FnMut(&Dispatch) -> T,
368     CURRENT_STATE
369         .try_with(|state| {
370             if let Some(entered) = state.enter() {
371                 return f(&*entered.current());
372             }
374             f(&Dispatch::none())
375         })
376         .unwrap_or_else(|_| f(&Dispatch::none()))
379 /// Executes a closure with a reference to this thread's current [dispatcher].
381 /// Note that calls to `get_default` should not be nested; if this function is
382 /// called while inside of another `get_default`, that closure will be provided
383 /// with `Dispatch::none` rather than the previously set dispatcher.
385 /// [dispatcher]: super::dispatcher::Dispatch
386 #[cfg(feature = "std")]
387 #[doc(hidden)]
388 #[inline(never)]
389 pub fn get_current<T>(f: impl FnOnce(&Dispatch) -> T) -> Option<T> {
390     CURRENT_STATE
391         .try_with(|state| {
392             let entered = state.enter()?;
393             Some(f(&*entered.current()))
394         })
395         .ok()?
398 /// Executes a closure with a reference to the current [dispatcher].
400 /// [dispatcher]: super::dispatcher::Dispatch
401 #[cfg(not(feature = "std"))]
402 #[doc(hidden)]
403 pub fn get_current<T>(f: impl FnOnce(&Dispatch) -> T) -> Option<T> {
404     let dispatch = get_global()?;
405     Some(f(&dispatch))
408 /// Executes a closure with a reference to the current [dispatcher].
410 /// [dispatcher]: super::dispatcher::Dispatch
411 #[cfg(not(feature = "std"))]
412 pub fn get_default<T, F>(mut f: F) -> T
413 where
414     F: FnMut(&Dispatch) -> T,
416     if let Some(d) = get_global() {
417         f(d)
418     } else {
419         f(&Dispatch::none())
420     }
423 fn get_global() -> Option<&'static Dispatch> {
424     if GLOBAL_INIT.load(Ordering::SeqCst) != INITIALIZED {
425         return None;
426     }
427     unsafe {
428         // This is safe given the invariant that setting the global dispatcher
429         // also sets `GLOBAL_INIT` to `INITIALIZED`.
430         Some(GLOBAL_DISPATCH.as_ref().expect(
431             "invariant violated: GLOBAL_DISPATCH must be initialized before GLOBAL_INIT is set",
432         ))
433     }
436 #[cfg(feature = "std")]
437 pub(crate) struct Registrar(Weak<dyn Subscriber + Send + Sync>);
439 impl Dispatch {
440     /// Returns a new `Dispatch` that discards events and spans.
441     #[inline]
442     pub fn none() -> Self {
443         Dispatch {
444             subscriber: Arc::new(NoSubscriber::default()),
445         }
446     }
448     /// Returns a `Dispatch` that forwards to the given [`Subscriber`].
449     ///
450     /// [`Subscriber`]: super::subscriber::Subscriber
451     pub fn new<S>(subscriber: S) -> Self
452     where
453         S: Subscriber + Send + Sync + 'static,
454     {
455         let me = Dispatch {
456             subscriber: Arc::new(subscriber),
457         };
458         callsite::register_dispatch(&me);
459         me
460     }
462     #[cfg(feature = "std")]
463     pub(crate) fn registrar(&self) -> Registrar {
464         Registrar(Arc::downgrade(&self.subscriber))
465     }
467     /// Creates a [`WeakDispatch`] from this `Dispatch`.
468     ///
469     /// A [`WeakDispatch`] is similar to a [`Dispatch`], but it does not prevent
470     /// the underlying [`Subscriber`] from being dropped. Instead, it only permits
471     /// access while other references to the `Subscriber` exist. This is equivalent
472     /// to the standard library's [`Arc::downgrade`] method, but for `Dispatch`
473     /// rather than `Arc`.
474     ///
475     /// The primary use for creating a [`WeakDispatch`] is to allow a `Subscriber`
476     /// to hold a cyclical reference to itself without creating a memory leak.
477     /// See [here] for details.
478     ///
479     /// [`Arc::downgrade`]: std::sync::Arc::downgrade
480     /// [here]: Subscriber#avoiding-memory-leaks
481     pub fn downgrade(&self) -> WeakDispatch {
482         WeakDispatch {
483             subscriber: Arc::downgrade(&self.subscriber),
484         }
485     }
487     #[inline(always)]
488     #[cfg(not(feature = "alloc"))]
489     pub(crate) fn subscriber(&self) -> &(dyn Subscriber + Send + Sync) {
490         &self.subscriber
491     }
493     /// Registers a new callsite with this collector, returning whether or not
494     /// the collector is interested in being notified about the callsite.
495     ///
496     /// This calls the [`register_callsite`] function on the [`Subscriber`]
497     /// that this `Dispatch` forwards to.
498     ///
499     /// [`Subscriber`]: super::subscriber::Subscriber
500     /// [`register_callsite`]: super::subscriber::Subscriber::register_callsite
501     #[inline]
502     pub fn register_callsite(&self, metadata: &'static Metadata<'static>) -> subscriber::Interest {
503         self.subscriber.register_callsite(metadata)
504     }
506     /// Returns the highest [verbosity level][level] that this [`Subscriber`] will
507     /// enable, or `None`, if the subscriber does not implement level-based
508     /// filtering or chooses not to implement this method.
509     ///
510     /// This calls the [`max_level_hint`] function on the [`Subscriber`]
511     /// that this `Dispatch` forwards to.
512     ///
513     /// [level]: super::Level
514     /// [`Subscriber`]: super::subscriber::Subscriber
515     /// [`register_callsite`]: super::subscriber::Subscriber::max_level_hint
516     // TODO(eliza): consider making this a public API?
517     #[inline]
518     pub(crate) fn max_level_hint(&self) -> Option<LevelFilter> {
519         self.subscriber.max_level_hint()
520     }
522     /// Record the construction of a new span, returning a new [ID] for the
523     /// span being constructed.
524     ///
525     /// This calls the [`new_span`] function on the [`Subscriber`] that this
526     /// `Dispatch` forwards to.
527     ///
528     /// [ID]: super::span::Id
529     /// [`Subscriber`]: super::subscriber::Subscriber
530     /// [`new_span`]: super::subscriber::Subscriber::new_span
531     #[inline]
532     pub fn new_span(&self, span: &span::Attributes<'_>) -> span::Id {
533         self.subscriber.new_span(span)
534     }
536     /// Record a set of values on a span.
537     ///
538     /// This calls the [`record`] function on the [`Subscriber`] that this
539     /// `Dispatch` forwards to.
540     ///
541     /// [`Subscriber`]: super::subscriber::Subscriber
542     /// [`record`]: super::subscriber::Subscriber::record
543     #[inline]
544     pub fn record(&self, span: &span::Id, values: &span::Record<'_>) {
545         self.subscriber.record(span, values)
546     }
548     /// Adds an indication that `span` follows from the span with the id
549     /// `follows`.
550     ///
551     /// This calls the [`record_follows_from`] function on the [`Subscriber`]
552     /// that this `Dispatch` forwards to.
553     ///
554     /// [`Subscriber`]: super::subscriber::Subscriber
555     /// [`record_follows_from`]: super::subscriber::Subscriber::record_follows_from
556     #[inline]
557     pub fn record_follows_from(&self, span: &span::Id, follows: &span::Id) {
558         self.subscriber.record_follows_from(span, follows)
559     }
561     /// Returns true if a span with the specified [metadata] would be
562     /// recorded.
563     ///
564     /// This calls the [`enabled`] function on the [`Subscriber`] that this
565     /// `Dispatch` forwards to.
566     ///
567     /// [metadata]: super::metadata::Metadata
568     /// [`Subscriber`]: super::subscriber::Subscriber
569     /// [`enabled`]: super::subscriber::Subscriber::enabled
570     #[inline]
571     pub fn enabled(&self, metadata: &Metadata<'_>) -> bool {
572         self.subscriber.enabled(metadata)
573     }
575     /// Records that an [`Event`] has occurred.
576     ///
577     /// This calls the [`event`] function on the [`Subscriber`] that this
578     /// `Dispatch` forwards to.
579     ///
580     /// [`Event`]: super::event::Event
581     /// [`Subscriber`]: super::subscriber::Subscriber
582     /// [`event`]: super::subscriber::Subscriber::event
583     #[inline]
584     pub fn event(&self, event: &Event<'_>) {
585         if self.subscriber.event_enabled(event) {
586             self.subscriber.event(event);
587         }
588     }
590     /// Records that a span has been can_enter.
591     ///
592     /// This calls the [`enter`] function on the [`Subscriber`] that this
593     /// `Dispatch` forwards to.
594     ///
595     /// [`Subscriber`]: super::subscriber::Subscriber
596     /// [`enter`]: super::subscriber::Subscriber::enter
597     pub fn enter(&self, span: &span::Id) {
598         self.subscriber.enter(span);
599     }
601     /// Records that a span has been exited.
602     ///
603     /// This calls the [`exit`] function on the [`Subscriber`] that this
604     /// `Dispatch` forwards to.
605     ///
606     /// [`Subscriber`]: super::subscriber::Subscriber
607     /// [`exit`]: super::subscriber::Subscriber::exit
608     pub fn exit(&self, span: &span::Id) {
609         self.subscriber.exit(span);
610     }
612     /// Notifies the subscriber that a [span ID] has been cloned.
613     ///
614     /// This function must only be called with span IDs that were returned by
615     /// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
616     /// this guarantee and any other libraries implementing instrumentation APIs
617     /// must as well.
618     ///
619     /// This calls the [`clone_span`] function on the `Subscriber` that this
620     /// `Dispatch` forwards to.
621     ///
622     /// [span ID]: super::span::Id
623     /// [`Subscriber`]: super::subscriber::Subscriber
624     /// [`clone_span`]: super::subscriber::Subscriber::clone_span
625     /// [`new_span`]: super::subscriber::Subscriber::new_span
626     #[inline]
627     pub fn clone_span(&self, id: &span::Id) -> span::Id {
628         self.subscriber.clone_span(id)
629     }
631     /// Notifies the subscriber that a [span ID] has been dropped.
632     ///
633     /// This function must only be called with span IDs that were returned by
634     /// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
635     /// this guarantee and any other libraries implementing instrumentation APIs
636     /// must as well.
637     ///
638     /// This calls the [`drop_span`] function on the [`Subscriber`] that this
639     /// `Dispatch` forwards to.
640     ///
641     /// <pre class="compile_fail" style="white-space:normal;font:inherit;">
642     ///     <strong>Deprecated</strong>: The <a href="#method.try_close"><code>
643     ///     try_close</code></a> method is functionally identical, but returns
644     ///     <code>true</code> if the span is now closed. It should be used
645     ///     instead of this method.
646     /// </pre>
647     ///
648     /// [span ID]: super::span::Id
649     /// [`Subscriber`]: super::subscriber::Subscriber
650     /// [`drop_span`]: super::subscriber::Subscriber::drop_span
651     /// [`new_span`]: super::subscriber::Subscriber::new_span
652     /// [`try_close`]: Entered::try_close()
653     #[inline]
654     #[deprecated(since = "0.1.2", note = "use `Dispatch::try_close` instead")]
655     pub fn drop_span(&self, id: span::Id) {
656         #[allow(deprecated)]
657         self.subscriber.drop_span(id);
658     }
660     /// Notifies the subscriber that a [span ID] has been dropped, and returns
661     /// `true` if there are now 0 IDs referring to that span.
662     ///
663     /// This function must only be called with span IDs that were returned by
664     /// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
665     /// this guarantee and any other libraries implementing instrumentation APIs
666     /// must as well.
667     ///
668     /// This calls the [`try_close`] function on the [`Subscriber`] that this
669     ///  `Dispatch` forwards to.
670     ///
671     /// [span ID]: super::span::Id
672     /// [`Subscriber`]: super::subscriber::Subscriber
673     /// [`try_close`]: super::subscriber::Subscriber::try_close
674     /// [`new_span`]: super::subscriber::Subscriber::new_span
675     pub fn try_close(&self, id: span::Id) -> bool {
676         self.subscriber.try_close(id)
677     }
679     /// Returns a type representing this subscriber's view of the current span.
680     ///
681     /// This calls the [`current`] function on the `Subscriber` that this
682     /// `Dispatch` forwards to.
683     ///
684     /// [`current`]: super::subscriber::Subscriber::current_span
685     #[inline]
686     pub fn current_span(&self) -> span::Current {
687         self.subscriber.current_span()
688     }
690     /// Returns `true` if this `Dispatch` forwards to a `Subscriber` of type
691     /// `T`.
692     #[inline]
693     pub fn is<T: Any>(&self) -> bool {
694         <dyn Subscriber>::is::<T>(&self.subscriber)
695     }
697     /// Returns some reference to the `Subscriber` this `Dispatch` forwards to
698     /// if it is of type `T`, or `None` if it isn't.
699     #[inline]
700     pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
701         <dyn Subscriber>::downcast_ref(&self.subscriber)
702     }
705 impl Default for Dispatch {
706     /// Returns the current default dispatcher
707     fn default() -> Self {
708         get_default(|default| default.clone())
709     }
712 impl fmt::Debug for Dispatch {
713     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
714         f.debug_tuple("Dispatch")
715             .field(&format_args!("{:p}", self.subscriber))
716             .finish()
717     }
720 impl<S> From<S> for Dispatch
721 where
722     S: Subscriber + Send + Sync + 'static,
724     #[inline]
725     fn from(subscriber: S) -> Self {
726         Dispatch::new(subscriber)
727     }
730 // === impl WeakDispatch ===
732 impl WeakDispatch {
733     /// Attempts to upgrade this `WeakDispatch` to a [`Dispatch`].
734     ///
735     /// Returns `None` if the referenced `Dispatch` has already been dropped.
736     ///
737     /// ## Examples
738     ///
739     /// ```
740     /// # use tracing_core::subscriber::NoSubscriber;
741     /// # use tracing_core::dispatcher::Dispatch;
742     /// let strong = Dispatch::new(NoSubscriber::default());
743     /// let weak = strong.downgrade();
744     ///
745     /// // The strong here keeps it alive, so we can still access the object.
746     /// assert!(weak.upgrade().is_some());
747     ///
748     /// drop(strong); // But not any more.
749     /// assert!(weak.upgrade().is_none());
750     /// ```
751     pub fn upgrade(&self) -> Option<Dispatch> {
752         self.subscriber
753             .upgrade()
754             .map(|subscriber| Dispatch { subscriber })
755     }
758 impl fmt::Debug for WeakDispatch {
759     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
760         let mut tuple = f.debug_tuple("WeakDispatch");
761         match self.subscriber.upgrade() {
762             Some(subscriber) => tuple.field(&format_args!("Some({:p})", subscriber)),
763             None => tuple.field(&format_args!("None")),
764         };
765         tuple.finish()
766     }
769 #[cfg(feature = "std")]
770 impl Registrar {
771     pub(crate) fn upgrade(&self) -> Option<Dispatch> {
772         self.0.upgrade().map(|subscriber| Dispatch { subscriber })
773     }
776 // ===== impl State =====
778 #[cfg(feature = "std")]
779 impl State {
780     /// Replaces the current default dispatcher on this thread with the provided
781     /// dispatcher.Any
782     ///
783     /// Dropping the returned `ResetGuard` will reset the default dispatcher to
784     /// the previous value.
785     #[inline]
786     fn set_default(new_dispatch: Dispatch) -> DefaultGuard {
787         let prior = CURRENT_STATE
788             .try_with(|state| {
789                 state.can_enter.set(true);
790                 state.default.replace(Some(new_dispatch))
791             })
792             .ok()
793             .flatten();
794         EXISTS.store(true, Ordering::Release);
795         DefaultGuard(prior)
796     }
798     #[inline]
799     fn enter(&self) -> Option<Entered<'_>> {
800         if self.can_enter.replace(false) {
801             Some(Entered(self))
802         } else {
803             None
804         }
805     }
808 // ===== impl Entered =====
810 #[cfg(feature = "std")]
811 impl<'a> Entered<'a> {
812     #[inline]
813     fn current(&self) -> RefMut<'a, Dispatch> {
814         let default = self.0.default.borrow_mut();
815         RefMut::map(default, |default| {
816             default.get_or_insert_with(|| get_global().cloned().unwrap_or_else(Dispatch::none))
817         })
818     }
821 #[cfg(feature = "std")]
822 impl<'a> Drop for Entered<'a> {
823     #[inline]
824     fn drop(&mut self) {
825         self.0.can_enter.set(true);
826     }
829 // ===== impl DefaultGuard =====
831 #[cfg(feature = "std")]
832 impl Drop for DefaultGuard {
833     #[inline]
834     fn drop(&mut self) {
835         // Replace the dispatcher and then drop the old one outside
836         // of the thread-local context. Dropping the dispatch may
837         // lead to the drop of a subscriber which, in the process,
838         // could then also attempt to access the same thread local
839         // state -- causing a clash.
840         let prev = CURRENT_STATE.try_with(|state| state.default.replace(self.0.take()));
841         drop(prev)
842     }
845 #[cfg(test)]
846 mod test {
847     use super::*;
848     #[cfg(feature = "std")]
849     use crate::stdlib::sync::atomic::{AtomicUsize, Ordering};
850     use crate::{
851         callsite::Callsite,
852         metadata::{Kind, Level, Metadata},
853         subscriber::Interest,
854     };
856     #[test]
857     fn dispatch_is() {
858         let dispatcher = Dispatch::new(NoSubscriber::default());
859         assert!(dispatcher.is::<NoSubscriber>());
860     }
862     #[test]
863     fn dispatch_downcasts() {
864         let dispatcher = Dispatch::new(NoSubscriber::default());
865         assert!(dispatcher.downcast_ref::<NoSubscriber>().is_some());
866     }
868     struct TestCallsite;
869     static TEST_CALLSITE: TestCallsite = TestCallsite;
870     static TEST_META: Metadata<'static> = metadata! {
871         name: "test",
872         target: module_path!(),
873         level: Level::DEBUG,
874         fields: &[],
875         callsite: &TEST_CALLSITE,
876         kind: Kind::EVENT
877     };
879     impl Callsite for TestCallsite {
880         fn set_interest(&self, _: Interest) {}
881         fn metadata(&self) -> &Metadata<'_> {
882             &TEST_META
883         }
884     }
886     #[test]
887     #[cfg(feature = "std")]
888     fn events_dont_infinite_loop() {
889         // This test ensures that an event triggered within a subscriber
890         // won't cause an infinite loop of events.
891         struct TestSubscriber;
892         impl Subscriber for TestSubscriber {
893             fn enabled(&self, _: &Metadata<'_>) -> bool {
894                 true
895             }
897             fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
898                 span::Id::from_u64(0xAAAA)
899             }
901             fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
903             fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
905             fn event(&self, _: &Event<'_>) {
906                 static EVENTS: AtomicUsize = AtomicUsize::new(0);
907                 assert_eq!(
908                     EVENTS.fetch_add(1, Ordering::Relaxed),
909                     0,
910                     "event method called twice!"
911                 );
912                 Event::dispatch(&TEST_META, &TEST_META.fields().value_set(&[]))
913             }
915             fn enter(&self, _: &span::Id) {}
917             fn exit(&self, _: &span::Id) {}
918         }
920         with_default(&Dispatch::new(TestSubscriber), || {
921             Event::dispatch(&TEST_META, &TEST_META.fields().value_set(&[]))
922         })
923     }
925     #[test]
926     #[cfg(feature = "std")]
927     fn spans_dont_infinite_loop() {
928         // This test ensures that a span created within a subscriber
929         // won't cause an infinite loop of new spans.
931         fn mk_span() {
932             get_default(|current| {
933                 current.new_span(&span::Attributes::new(
934                     &TEST_META,
935                     &TEST_META.fields().value_set(&[]),
936                 ))
937             });
938         }
940         struct TestSubscriber;
941         impl Subscriber for TestSubscriber {
942             fn enabled(&self, _: &Metadata<'_>) -> bool {
943                 true
944             }
946             fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
947                 static NEW_SPANS: AtomicUsize = AtomicUsize::new(0);
948                 assert_eq!(
949                     NEW_SPANS.fetch_add(1, Ordering::Relaxed),
950                     0,
951                     "new_span method called twice!"
952                 );
953                 mk_span();
954                 span::Id::from_u64(0xAAAA)
955             }
957             fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
959             fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
961             fn event(&self, _: &Event<'_>) {}
963             fn enter(&self, _: &span::Id) {}
965             fn exit(&self, _: &span::Id) {}
966         }
968         with_default(&Dispatch::new(TestSubscriber), mk_span)
969     }
971     #[test]
972     fn default_no_subscriber() {
973         let default_dispatcher = Dispatch::default();
974         assert!(default_dispatcher.is::<NoSubscriber>());
975     }
977     #[cfg(feature = "std")]
978     #[test]
979     fn default_dispatch() {
980         struct TestSubscriber;
981         impl Subscriber for TestSubscriber {
982             fn enabled(&self, _: &Metadata<'_>) -> bool {
983                 true
984             }
986             fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
987                 span::Id::from_u64(0xAAAA)
988             }
990             fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
992             fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
994             fn event(&self, _: &Event<'_>) {}
996             fn enter(&self, _: &span::Id) {}
998             fn exit(&self, _: &span::Id) {}
999         }
1000         let guard = set_default(&Dispatch::new(TestSubscriber));
1001         let default_dispatcher = Dispatch::default();
1002         assert!(default_dispatcher.is::<TestSubscriber>());
1004         drop(guard);
1005         let default_dispatcher = Dispatch::default();
1006         assert!(default_dispatcher.is::<NoSubscriber>());
1007     }