tracing_core/
dispatcher.rs

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
102//!
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!");
107//!
108//! // `my_subscriber` is now the default
109//! ```
110//!
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>
118//!
119//! ## Accessing the Default Subscriber
120//!
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.
125//!
126use core::ptr::addr_of;
127
128use crate::{
129    callsite, span,
130    subscriber::{self, NoSubscriber, Subscriber},
131    Event, LevelFilter, Metadata,
132};
133
134use crate::stdlib::{
135    any::Any,
136    fmt,
137    sync::{
138        atomic::{AtomicBool, AtomicUsize, Ordering},
139        Arc, Weak,
140    },
141};
142
143#[cfg(feature = "std")]
144use crate::stdlib::{
145    cell::{Cell, Ref, RefCell},
146    error,
147};
148
149/// `Dispatch` trace data to a [`Subscriber`].
150#[derive(Clone)]
151pub struct Dispatch {
152    subscriber: Kind<Arc<dyn Subscriber + Send + Sync>>,
153}
154
155/// `WeakDispatch` is a version of [`Dispatch`] that holds a non-owning reference
156/// to a [`Subscriber`].
157///
158/// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
159/// which returns an `Option<Dispatch>`. If all [`Dispatch`] clones that point
160/// at the `Subscriber` have been dropped, [`WeakDispatch::upgrade`] will return
161/// `None`. Otherwise, it will return `Some(Dispatch)`.
162///
163/// A `WeakDispatch` may be created from a [`Dispatch`] by calling the
164/// [`Dispatch::downgrade`] method. The primary use for creating a
165/// [`WeakDispatch`] is to allow a Subscriber` to hold a cyclical reference to
166/// itself without creating a memory leak. See [here] for details.
167///
168/// This type is analogous to the [`std::sync::Weak`] type, but for a
169/// [`Dispatch`] rather than an [`Arc`].
170///
171/// [`Arc`]: std::sync::Arc
172/// [here]: Subscriber#avoiding-memory-leaks
173#[derive(Clone)]
174pub struct WeakDispatch {
175    subscriber: Kind<Weak<dyn Subscriber + Send + Sync>>,
176}
177
178#[derive(Clone)]
179enum Kind<T> {
180    Global(&'static (dyn Subscriber + Send + Sync)),
181    Scoped(T),
182}
183
184#[cfg(feature = "std")]
185thread_local! {
186    static CURRENT_STATE: State = const {
187        State {
188            default: RefCell::new(None),
189            can_enter: Cell::new(true),
190        }
191    };
192}
193
194static EXISTS: AtomicBool = AtomicBool::new(false);
195static GLOBAL_INIT: AtomicUsize = AtomicUsize::new(UNINITIALIZED);
196
197#[cfg(feature = "std")]
198static SCOPED_COUNT: AtomicUsize = AtomicUsize::new(0);
199
200const UNINITIALIZED: usize = 0;
201const INITIALIZING: usize = 1;
202const INITIALIZED: usize = 2;
203
204static mut GLOBAL_DISPATCH: Dispatch = Dispatch {
205    subscriber: Kind::Global(&NO_SUBSCRIBER),
206};
207static NONE: Dispatch = Dispatch {
208    subscriber: Kind::Global(&NO_SUBSCRIBER),
209};
210static NO_SUBSCRIBER: NoSubscriber = NoSubscriber::new();
211
212/// The dispatch state of a thread.
213#[cfg(feature = "std")]
214struct State {
215    /// This thread's current default dispatcher.
216    default: RefCell<Option<Dispatch>>,
217    /// Whether or not we can currently begin dispatching a trace event.
218    ///
219    /// This is set to `false` when functions such as `enter`, `exit`, `event`,
220    /// and `new_span` are called on this thread's default dispatcher, to
221    /// prevent further trace events triggered inside those functions from
222    /// creating an infinite recursion. When we finish handling a dispatch, this
223    /// is set back to `true`.
224    can_enter: Cell<bool>,
225}
226
227/// While this guard is active, additional calls to subscriber functions on
228/// the default dispatcher will not be able to access the dispatch context.
229/// Dropping the guard will allow the dispatch context to be re-entered.
230#[cfg(feature = "std")]
231struct Entered<'a>(&'a State);
232
233/// A guard that resets the current default dispatcher to the prior
234/// default dispatcher when dropped.
235#[cfg(feature = "std")]
236#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
237#[derive(Debug)]
238pub struct DefaultGuard(Option<Dispatch>);
239
240/// Sets this dispatch as the default for the duration of a closure.
241///
242/// The default dispatcher is used when creating a new [span] or
243/// [`Event`].
244///
245/// <pre class="ignore" style="white-space:normal;font:inherit;">
246///     <strong>Note</strong>: This function required the Rust standard library.
247///     <code>no_std</code> users should use <a href="../fn.set_global_default.html">
248///     <code>set_global_default</code></a> instead.
249/// </pre>
250///
251/// [span]: super::span
252/// [`Subscriber`]: super::subscriber::Subscriber
253/// [`Event`]: super::event::Event
254/// [`set_global_default`]: super::set_global_default
255#[cfg(feature = "std")]
256#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
257pub fn with_default<T>(dispatcher: &Dispatch, f: impl FnOnce() -> T) -> T {
258    // When this guard is dropped, the default dispatcher will be reset to the
259    // prior default. Using this (rather than simply resetting after calling
260    // `f`) ensures that we always reset to the prior dispatcher even if `f`
261    // panics.
262    let _guard = set_default(dispatcher);
263    f()
264}
265
266/// Sets the dispatch as the default dispatch for the duration of the lifetime
267/// of the returned DefaultGuard
268///
269/// <pre class="ignore" style="white-space:normal;font:inherit;">
270///     <strong>Note</strong>: This function required the Rust standard library.
271///     <code>no_std</code> users should use <a href="../fn.set_global_default.html">
272///     <code>set_global_default</code></a> instead.
273/// </pre>
274///
275/// [`set_global_default`]: super::set_global_default
276#[cfg(feature = "std")]
277#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
278#[must_use = "Dropping the guard unregisters the dispatcher."]
279pub fn set_default(dispatcher: &Dispatch) -> DefaultGuard {
280    // When this guard is dropped, the default dispatcher will be reset to the
281    // prior default. Using this ensures that we always reset to the prior
282    // dispatcher even if the thread calling this function panics.
283    State::set_default(dispatcher.clone())
284}
285
286/// Sets this dispatch as the global default for the duration of the entire program.
287/// Will be used as a fallback if no thread-local dispatch has been set in a thread
288/// (using `with_default`.)
289///
290/// Can only be set once; subsequent attempts to set the global default will fail.
291/// Returns `Err` if the global default has already been set.
292///
293/// <div class="example-wrap" style="display:inline-block"><pre class="compile_fail" style="white-space:normal;font:inherit;">
294///     <strong>Warning</strong>: In general, libraries should <em>not</em> call
295///     <code>set_global_default()</code>! Doing so will cause conflicts when
296///     executables that depend on the library try to set the default later.
297/// </pre></div>
298///
299/// [span]: super::span
300/// [`Subscriber`]: super::subscriber::Subscriber
301/// [`Event`]: super::event::Event
302pub fn set_global_default(dispatcher: Dispatch) -> Result<(), SetGlobalDefaultError> {
303    // if `compare_exchange` returns Result::Ok(_), then `new` has been set and
304    // `current`—now the prior value—has been returned in the `Ok()` branch.
305    if GLOBAL_INIT
306        .compare_exchange(
307            UNINITIALIZED,
308            INITIALIZING,
309            Ordering::SeqCst,
310            Ordering::SeqCst,
311        )
312        .is_ok()
313    {
314        let subscriber = {
315            let subscriber = match dispatcher.subscriber {
316                Kind::Global(s) => s,
317                Kind::Scoped(s) => unsafe {
318                    // safety: this leaks the subscriber onto the heap. the
319                    // reference count will always be at least 1, because the
320                    // global default will never be dropped.
321                    &*Arc::into_raw(s)
322                },
323            };
324            Kind::Global(subscriber)
325        };
326        unsafe {
327            GLOBAL_DISPATCH = Dispatch { subscriber };
328        }
329        GLOBAL_INIT.store(INITIALIZED, Ordering::SeqCst);
330        EXISTS.store(true, Ordering::Release);
331        Ok(())
332    } else {
333        Err(SetGlobalDefaultError { _no_construct: () })
334    }
335}
336
337/// Returns true if a `tracing` dispatcher has ever been set.
338///
339/// This may be used to completely elide trace points if tracing is not in use
340/// at all or has yet to be initialized.
341#[doc(hidden)]
342#[inline(always)]
343pub fn has_been_set() -> bool {
344    EXISTS.load(Ordering::Relaxed)
345}
346
347/// Returned if setting the global dispatcher fails.
348pub struct SetGlobalDefaultError {
349    _no_construct: (),
350}
351
352impl fmt::Debug for SetGlobalDefaultError {
353    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
354        f.debug_tuple("SetGlobalDefaultError")
355            .field(&Self::MESSAGE)
356            .finish()
357    }
358}
359
360impl fmt::Display for SetGlobalDefaultError {
361    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
362        f.pad(Self::MESSAGE)
363    }
364}
365
366#[cfg(feature = "std")]
367#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
368impl error::Error for SetGlobalDefaultError {}
369
370impl SetGlobalDefaultError {
371    const MESSAGE: &'static str = "a global default trace dispatcher has already been set";
372}
373
374/// Executes a closure with a reference to this thread's current [dispatcher].
375///
376/// Note that calls to `get_default` should not be nested; if this function is
377/// called while inside of another `get_default`, that closure will be provided
378/// with `Dispatch::none` rather than the previously set dispatcher.
379///
380/// [dispatcher]: super::dispatcher::Dispatch
381#[cfg(feature = "std")]
382pub fn get_default<T, F>(mut f: F) -> T
383where
384    F: FnMut(&Dispatch) -> T,
385{
386    if SCOPED_COUNT.load(Ordering::Acquire) == 0 {
387        // fast path if no scoped dispatcher has been set; just use the global
388        // default.
389        return f(get_global());
390    }
391
392    CURRENT_STATE
393        .try_with(|state| {
394            if let Some(entered) = state.enter() {
395                return f(&entered.current());
396            }
397
398            f(&NONE)
399        })
400        .unwrap_or_else(|_| f(&NONE))
401}
402
403/// Executes a closure with a reference to this thread's current [dispatcher].
404///
405/// Note that calls to `get_default` should not be nested; if this function is
406/// called while inside of another `get_default`, that closure will be provided
407/// with `Dispatch::none` rather than the previously set dispatcher.
408///
409/// [dispatcher]: super::dispatcher::Dispatch
410#[cfg(feature = "std")]
411#[doc(hidden)]
412#[inline(never)]
413pub fn get_current<T>(f: impl FnOnce(&Dispatch) -> T) -> Option<T> {
414    if SCOPED_COUNT.load(Ordering::Acquire) == 0 {
415        // fast path if no scoped dispatcher has been set; just use the global
416        // default.
417        return Some(f(get_global()));
418    }
419
420    CURRENT_STATE
421        .try_with(|state| {
422            let entered = state.enter()?;
423            Some(f(&entered.current()))
424        })
425        .ok()?
426}
427
428/// Executes a closure with a reference to the current [dispatcher].
429///
430/// [dispatcher]: super::dispatcher::Dispatch
431#[cfg(not(feature = "std"))]
432#[doc(hidden)]
433pub fn get_current<T>(f: impl FnOnce(&Dispatch) -> T) -> Option<T> {
434    Some(f(get_global()))
435}
436
437/// Executes a closure with a reference to the current [dispatcher].
438///
439/// [dispatcher]: super::dispatcher::Dispatch
440#[cfg(not(feature = "std"))]
441pub fn get_default<T, F>(mut f: F) -> T
442where
443    F: FnMut(&Dispatch) -> T,
444{
445    f(&get_global())
446}
447
448#[inline]
449fn get_global() -> &'static Dispatch {
450    if GLOBAL_INIT.load(Ordering::SeqCst) != INITIALIZED {
451        return &NONE;
452    }
453    unsafe {
454        // This is safe given the invariant that setting the global dispatcher
455        // also sets `GLOBAL_INIT` to `INITIALIZED`.
456        &*addr_of!(GLOBAL_DISPATCH)
457    }
458}
459
460#[cfg(feature = "std")]
461pub(crate) struct Registrar(Kind<Weak<dyn Subscriber + Send + Sync>>);
462
463impl Dispatch {
464    /// Returns a new `Dispatch` that discards events and spans.
465    #[inline]
466    pub fn none() -> Self {
467        Dispatch {
468            subscriber: Kind::Global(&NO_SUBSCRIBER),
469        }
470    }
471
472    /// Returns a `Dispatch` that forwards to the given [`Subscriber`].
473    ///
474    /// [`Subscriber`]: super::subscriber::Subscriber
475    pub fn new<S>(subscriber: S) -> Self
476    where
477        S: Subscriber + Send + Sync + 'static,
478    {
479        let me = Dispatch {
480            subscriber: Kind::Scoped(Arc::new(subscriber)),
481        };
482        callsite::register_dispatch(&me);
483        me
484    }
485
486    #[cfg(feature = "std")]
487    pub(crate) fn registrar(&self) -> Registrar {
488        Registrar(self.subscriber.downgrade())
489    }
490
491    /// Creates a [`WeakDispatch`] from this `Dispatch`.
492    ///
493    /// A [`WeakDispatch`] is similar to a [`Dispatch`], but it does not prevent
494    /// the underlying [`Subscriber`] from being dropped. Instead, it only permits
495    /// access while other references to the `Subscriber` exist. This is equivalent
496    /// to the standard library's [`Arc::downgrade`] method, but for `Dispatch`
497    /// rather than `Arc`.
498    ///
499    /// The primary use for creating a [`WeakDispatch`] is to allow a `Subscriber`
500    /// to hold a cyclical reference to itself without creating a memory leak.
501    /// See [here] for details.
502    ///
503    /// [`Arc::downgrade`]: std::sync::Arc::downgrade
504    /// [here]: Subscriber#avoiding-memory-leaks
505    pub fn downgrade(&self) -> WeakDispatch {
506        WeakDispatch {
507            subscriber: self.subscriber.downgrade(),
508        }
509    }
510
511    #[inline(always)]
512    pub(crate) fn subscriber(&self) -> &(dyn Subscriber + Send + Sync) {
513        match self.subscriber {
514            Kind::Global(s) => s,
515            Kind::Scoped(ref s) => s.as_ref(),
516        }
517    }
518
519    /// Registers a new callsite with this subscriber, returning whether or not
520    /// the subscriber is interested in being notified about the callsite.
521    ///
522    /// This calls the [`register_callsite`] function on the [`Subscriber`]
523    /// that this `Dispatch` forwards to.
524    ///
525    /// [`Subscriber`]: super::subscriber::Subscriber
526    /// [`register_callsite`]: super::subscriber::Subscriber::register_callsite
527    #[inline]
528    pub fn register_callsite(&self, metadata: &'static Metadata<'static>) -> subscriber::Interest {
529        self.subscriber().register_callsite(metadata)
530    }
531
532    /// Returns the highest [verbosity level][level] that this [`Subscriber`] will
533    /// enable, or `None`, if the subscriber does not implement level-based
534    /// filtering or chooses not to implement this method.
535    ///
536    /// This calls the [`max_level_hint`] function on the [`Subscriber`]
537    /// that this `Dispatch` forwards to.
538    ///
539    /// [level]: super::Level
540    /// [`Subscriber`]: super::subscriber::Subscriber
541    /// [`register_callsite`]: super::subscriber::Subscriber::max_level_hint
542    // TODO(eliza): consider making this a public API?
543    #[inline]
544    pub(crate) fn max_level_hint(&self) -> Option<LevelFilter> {
545        self.subscriber().max_level_hint()
546    }
547
548    /// Record the construction of a new span, returning a new [ID] for the
549    /// span being constructed.
550    ///
551    /// This calls the [`new_span`] function on the [`Subscriber`] that this
552    /// `Dispatch` forwards to.
553    ///
554    /// [ID]: super::span::Id
555    /// [`Subscriber`]: super::subscriber::Subscriber
556    /// [`new_span`]: super::subscriber::Subscriber::new_span
557    #[inline]
558    pub fn new_span(&self, span: &span::Attributes<'_>) -> span::Id {
559        self.subscriber().new_span(span)
560    }
561
562    /// Record a set of values on a span.
563    ///
564    /// This calls the [`record`] function on the [`Subscriber`] that this
565    /// `Dispatch` forwards to.
566    ///
567    /// [`Subscriber`]: super::subscriber::Subscriber
568    /// [`record`]: super::subscriber::Subscriber::record
569    #[inline]
570    pub fn record(&self, span: &span::Id, values: &span::Record<'_>) {
571        self.subscriber().record(span, values)
572    }
573
574    /// Adds an indication that `span` follows from the span with the id
575    /// `follows`.
576    ///
577    /// This calls the [`record_follows_from`] function on the [`Subscriber`]
578    /// that this `Dispatch` forwards to.
579    ///
580    /// [`Subscriber`]: super::subscriber::Subscriber
581    /// [`record_follows_from`]: super::subscriber::Subscriber::record_follows_from
582    #[inline]
583    pub fn record_follows_from(&self, span: &span::Id, follows: &span::Id) {
584        self.subscriber().record_follows_from(span, follows)
585    }
586
587    /// Returns true if a span with the specified [metadata] would be
588    /// recorded.
589    ///
590    /// This calls the [`enabled`] function on the [`Subscriber`] that this
591    /// `Dispatch` forwards to.
592    ///
593    /// [metadata]: super::metadata::Metadata
594    /// [`Subscriber`]: super::subscriber::Subscriber
595    /// [`enabled`]: super::subscriber::Subscriber::enabled
596    #[inline]
597    pub fn enabled(&self, metadata: &Metadata<'_>) -> bool {
598        self.subscriber().enabled(metadata)
599    }
600
601    /// Records that an [`Event`] has occurred.
602    ///
603    /// This calls the [`event`] function on the [`Subscriber`] that this
604    /// `Dispatch` forwards to.
605    ///
606    /// [`Event`]: super::event::Event
607    /// [`Subscriber`]: super::subscriber::Subscriber
608    /// [`event`]: super::subscriber::Subscriber::event
609    #[inline]
610    pub fn event(&self, event: &Event<'_>) {
611        let subscriber = self.subscriber();
612        if subscriber.event_enabled(event) {
613            subscriber.event(event);
614        }
615    }
616
617    /// Records that a span has been can_enter.
618    ///
619    /// This calls the [`enter`] function on the [`Subscriber`] that this
620    /// `Dispatch` forwards to.
621    ///
622    /// [`Subscriber`]: super::subscriber::Subscriber
623    /// [`enter`]: super::subscriber::Subscriber::enter
624    pub fn enter(&self, span: &span::Id) {
625        self.subscriber().enter(span);
626    }
627
628    /// Records that a span has been exited.
629    ///
630    /// This calls the [`exit`] function on the [`Subscriber`] that this
631    /// `Dispatch` forwards to.
632    ///
633    /// [`Subscriber`]: super::subscriber::Subscriber
634    /// [`exit`]: super::subscriber::Subscriber::exit
635    pub fn exit(&self, span: &span::Id) {
636        self.subscriber().exit(span);
637    }
638
639    /// Notifies the subscriber that a [span ID] has been cloned.
640    ///
641    /// This function must only be called with span IDs that were returned by
642    /// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
643    /// this guarantee and any other libraries implementing instrumentation APIs
644    /// must as well.
645    ///
646    /// This calls the [`clone_span`] function on the `Subscriber` that this
647    /// `Dispatch` forwards to.
648    ///
649    /// [span ID]: super::span::Id
650    /// [`Subscriber`]: super::subscriber::Subscriber
651    /// [`clone_span`]: super::subscriber::Subscriber::clone_span
652    /// [`new_span`]: super::subscriber::Subscriber::new_span
653    #[inline]
654    pub fn clone_span(&self, id: &span::Id) -> span::Id {
655        self.subscriber().clone_span(id)
656    }
657
658    /// Notifies the subscriber that a [span ID] has been dropped.
659    ///
660    /// This function must only be called with span IDs that were returned by
661    /// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
662    /// this guarantee and any other libraries implementing instrumentation APIs
663    /// must as well.
664    ///
665    /// This calls the [`drop_span`] function on the [`Subscriber`] that this
666    /// `Dispatch` forwards to.
667    ///
668    /// <pre class="compile_fail" style="white-space:normal;font:inherit;">
669    ///     <strong>Deprecated</strong>: The <a href="#method.try_close"><code>
670    ///     try_close</code></a> method is functionally identical, but returns
671    ///     <code>true</code> if the span is now closed. It should be used
672    ///     instead of this method.
673    /// </pre>
674    ///
675    /// [span ID]: super::span::Id
676    /// [`Subscriber`]: super::subscriber::Subscriber
677    /// [`drop_span`]: super::subscriber::Subscriber::drop_span
678    /// [`new_span`]: super::subscriber::Subscriber::new_span
679    /// [`try_close`]: Entered::try_close()
680    #[inline]
681    #[deprecated(since = "0.1.2", note = "use `Dispatch::try_close` instead")]
682    pub fn drop_span(&self, id: span::Id) {
683        #[allow(deprecated)]
684        self.subscriber().drop_span(id);
685    }
686
687    /// Notifies the subscriber that a [span ID] has been dropped, and returns
688    /// `true` if there are now 0 IDs referring to that span.
689    ///
690    /// This function must only be called with span IDs that were returned by
691    /// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
692    /// this guarantee and any other libraries implementing instrumentation APIs
693    /// must as well.
694    ///
695    /// This calls the [`try_close`] function on the [`Subscriber`] that this
696    ///  `Dispatch` forwards to.
697    ///
698    /// [span ID]: super::span::Id
699    /// [`Subscriber`]: super::subscriber::Subscriber
700    /// [`try_close`]: super::subscriber::Subscriber::try_close
701    /// [`new_span`]: super::subscriber::Subscriber::new_span
702    pub fn try_close(&self, id: span::Id) -> bool {
703        self.subscriber().try_close(id)
704    }
705
706    /// Returns a type representing this subscriber's view of the current span.
707    ///
708    /// This calls the [`current`] function on the `Subscriber` that this
709    /// `Dispatch` forwards to.
710    ///
711    /// [`current`]: super::subscriber::Subscriber::current_span
712    #[inline]
713    pub fn current_span(&self) -> span::Current {
714        self.subscriber().current_span()
715    }
716
717    /// Returns `true` if this `Dispatch` forwards to a `Subscriber` of type
718    /// `T`.
719    #[inline]
720    pub fn is<T: Any>(&self) -> bool {
721        <dyn Subscriber>::is::<T>(self.subscriber())
722    }
723
724    /// Returns some reference to the `Subscriber` this `Dispatch` forwards to
725    /// if it is of type `T`, or `None` if it isn't.
726    #[inline]
727    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
728        <dyn Subscriber>::downcast_ref(self.subscriber())
729    }
730}
731
732impl Default for Dispatch {
733    /// Returns the current default dispatcher
734    fn default() -> Self {
735        get_default(|default| default.clone())
736    }
737}
738
739impl fmt::Debug for Dispatch {
740    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
741        match self.subscriber {
742            Kind::Scoped(ref s) => f
743                .debug_tuple("Dispatch::Scoped")
744                .field(&format_args!("{:p}", s))
745                .finish(),
746            Kind::Global(s) => f
747                .debug_tuple("Dispatch::Global")
748                .field(&format_args!("{:p}", s))
749                .finish(),
750        }
751    }
752}
753
754impl<S> From<S> for Dispatch
755where
756    S: Subscriber + Send + Sync + 'static,
757{
758    #[inline]
759    fn from(subscriber: S) -> Self {
760        Dispatch::new(subscriber)
761    }
762}
763
764// === impl WeakDispatch ===
765
766impl WeakDispatch {
767    /// Attempts to upgrade this `WeakDispatch` to a [`Dispatch`].
768    ///
769    /// Returns `None` if the referenced `Dispatch` has already been dropped.
770    ///
771    /// ## Examples
772    ///
773    /// ```
774    /// # use tracing_core::subscriber::NoSubscriber;
775    /// # use tracing_core::dispatcher::Dispatch;
776    /// let strong = Dispatch::new(NoSubscriber::default());
777    /// let weak = strong.downgrade();
778    ///
779    /// // The strong here keeps it alive, so we can still access the object.
780    /// assert!(weak.upgrade().is_some());
781    ///
782    /// drop(strong); // But not any more.
783    /// assert!(weak.upgrade().is_none());
784    /// ```
785    pub fn upgrade(&self) -> Option<Dispatch> {
786        self.subscriber
787            .upgrade()
788            .map(|subscriber| Dispatch { subscriber })
789    }
790}
791
792impl fmt::Debug for WeakDispatch {
793    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
794        match self.subscriber {
795            Kind::Scoped(ref s) => f
796                .debug_tuple("WeakDispatch::Scoped")
797                .field(&format_args!("{:p}", s))
798                .finish(),
799            Kind::Global(s) => f
800                .debug_tuple("WeakDispatch::Global")
801                .field(&format_args!("{:p}", s))
802                .finish(),
803        }
804    }
805}
806
807#[cfg(feature = "std")]
808impl Registrar {
809    pub(crate) fn upgrade(&self) -> Option<Dispatch> {
810        self.0.upgrade().map(|subscriber| Dispatch { subscriber })
811    }
812}
813
814// ===== impl State =====
815
816impl Kind<Arc<dyn Subscriber + Send + Sync>> {
817    fn downgrade(&self) -> Kind<Weak<dyn Subscriber + Send + Sync>> {
818        match self {
819            Kind::Global(s) => Kind::Global(*s),
820            Kind::Scoped(ref s) => Kind::Scoped(Arc::downgrade(s)),
821        }
822    }
823}
824
825impl Kind<Weak<dyn Subscriber + Send + Sync>> {
826    fn upgrade(&self) -> Option<Kind<Arc<dyn Subscriber + Send + Sync>>> {
827        match self {
828            Kind::Global(s) => Some(Kind::Global(*s)),
829            Kind::Scoped(ref s) => Some(Kind::Scoped(s.upgrade()?)),
830        }
831    }
832}
833
834// ===== impl State =====
835
836#[cfg(feature = "std")]
837impl State {
838    /// Replaces the current default dispatcher on this thread with the provided
839    /// dispatcher.Any
840    ///
841    /// Dropping the returned `ResetGuard` will reset the default dispatcher to
842    /// the previous value.
843    #[inline]
844    fn set_default(new_dispatch: Dispatch) -> DefaultGuard {
845        let prior = CURRENT_STATE
846            .try_with(|state| {
847                state.can_enter.set(true);
848                state.default.replace(Some(new_dispatch))
849            })
850            .ok()
851            .flatten();
852        EXISTS.store(true, Ordering::Release);
853        SCOPED_COUNT.fetch_add(1, Ordering::Release);
854        DefaultGuard(prior)
855    }
856
857    #[inline]
858    fn enter(&self) -> Option<Entered<'_>> {
859        if self.can_enter.replace(false) {
860            Some(Entered(self))
861        } else {
862            None
863        }
864    }
865}
866
867// ===== impl Entered =====
868
869#[cfg(feature = "std")]
870impl<'a> Entered<'a> {
871    #[inline]
872    fn current(&self) -> Ref<'a, Dispatch> {
873        let default = self.0.default.borrow();
874        Ref::map(default, |default| match default {
875            Some(default) => default,
876            None => get_global(),
877        })
878    }
879}
880
881#[cfg(feature = "std")]
882impl<'a> Drop for Entered<'a> {
883    #[inline]
884    fn drop(&mut self) {
885        self.0.can_enter.set(true);
886    }
887}
888
889// ===== impl DefaultGuard =====
890
891#[cfg(feature = "std")]
892impl Drop for DefaultGuard {
893    #[inline]
894    fn drop(&mut self) {
895        // Replace the dispatcher and then drop the old one outside
896        // of the thread-local context. Dropping the dispatch may
897        // lead to the drop of a subscriber which, in the process,
898        // could then also attempt to access the same thread local
899        // state -- causing a clash.
900        let prev = CURRENT_STATE.try_with(|state| state.default.replace(self.0.take()));
901        SCOPED_COUNT.fetch_sub(1, Ordering::Release);
902        drop(prev)
903    }
904}
905
906#[cfg(test)]
907mod test {
908    use super::*;
909    #[cfg(feature = "std")]
910    use crate::stdlib::sync::atomic::{AtomicUsize, Ordering};
911    use crate::{
912        callsite::Callsite,
913        metadata::{Kind, Level, Metadata},
914        subscriber::Interest,
915    };
916
917    #[test]
918    fn dispatch_is() {
919        let dispatcher = Dispatch::new(NoSubscriber::default());
920        assert!(dispatcher.is::<NoSubscriber>());
921    }
922
923    #[test]
924    fn dispatch_downcasts() {
925        let dispatcher = Dispatch::new(NoSubscriber::default());
926        assert!(dispatcher.downcast_ref::<NoSubscriber>().is_some());
927    }
928
929    struct TestCallsite;
930    static TEST_CALLSITE: TestCallsite = TestCallsite;
931    static TEST_META: Metadata<'static> = metadata! {
932        name: "test",
933        target: module_path!(),
934        level: Level::DEBUG,
935        fields: &[],
936        callsite: &TEST_CALLSITE,
937        kind: Kind::EVENT
938    };
939
940    impl Callsite for TestCallsite {
941        fn set_interest(&self, _: Interest) {}
942        fn metadata(&self) -> &Metadata<'_> {
943            &TEST_META
944        }
945    }
946
947    #[test]
948    #[cfg(feature = "std")]
949    fn events_dont_infinite_loop() {
950        // This test ensures that an event triggered within a subscriber
951        // won't cause an infinite loop of events.
952        struct TestSubscriber;
953        impl Subscriber for TestSubscriber {
954            fn enabled(&self, _: &Metadata<'_>) -> bool {
955                true
956            }
957
958            fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
959                span::Id::from_u64(0xAAAA)
960            }
961
962            fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
963
964            fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
965
966            fn event(&self, _: &Event<'_>) {
967                static EVENTS: AtomicUsize = AtomicUsize::new(0);
968                assert_eq!(
969                    EVENTS.fetch_add(1, Ordering::Relaxed),
970                    0,
971                    "event method called twice!"
972                );
973                Event::dispatch(&TEST_META, &TEST_META.fields().value_set(&[]))
974            }
975
976            fn enter(&self, _: &span::Id) {}
977
978            fn exit(&self, _: &span::Id) {}
979        }
980
981        with_default(&Dispatch::new(TestSubscriber), || {
982            Event::dispatch(&TEST_META, &TEST_META.fields().value_set(&[]))
983        })
984    }
985
986    #[test]
987    #[cfg(feature = "std")]
988    fn spans_dont_infinite_loop() {
989        // This test ensures that a span created within a subscriber
990        // won't cause an infinite loop of new spans.
991
992        fn mk_span() {
993            get_default(|current| {
994                current.new_span(&span::Attributes::new(
995                    &TEST_META,
996                    &TEST_META.fields().value_set(&[]),
997                ))
998            });
999        }
1000
1001        struct TestSubscriber;
1002        impl Subscriber for TestSubscriber {
1003            fn enabled(&self, _: &Metadata<'_>) -> bool {
1004                true
1005            }
1006
1007            fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
1008                static NEW_SPANS: AtomicUsize = AtomicUsize::new(0);
1009                assert_eq!(
1010                    NEW_SPANS.fetch_add(1, Ordering::Relaxed),
1011                    0,
1012                    "new_span method called twice!"
1013                );
1014                mk_span();
1015                span::Id::from_u64(0xAAAA)
1016            }
1017
1018            fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
1019
1020            fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
1021
1022            fn event(&self, _: &Event<'_>) {}
1023
1024            fn enter(&self, _: &span::Id) {}
1025
1026            fn exit(&self, _: &span::Id) {}
1027        }
1028
1029        with_default(&Dispatch::new(TestSubscriber), mk_span)
1030    }
1031
1032    #[test]
1033    fn default_no_subscriber() {
1034        let default_dispatcher = Dispatch::default();
1035        assert!(default_dispatcher.is::<NoSubscriber>());
1036    }
1037
1038    #[cfg(feature = "std")]
1039    #[test]
1040    fn default_dispatch() {
1041        struct TestSubscriber;
1042        impl Subscriber for TestSubscriber {
1043            fn enabled(&self, _: &Metadata<'_>) -> bool {
1044                true
1045            }
1046
1047            fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
1048                span::Id::from_u64(0xAAAA)
1049            }
1050
1051            fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
1052
1053            fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
1054
1055            fn event(&self, _: &Event<'_>) {}
1056
1057            fn enter(&self, _: &span::Id) {}
1058
1059            fn exit(&self, _: &span::Id) {}
1060        }
1061        let guard = set_default(&Dispatch::new(TestSubscriber));
1062        let default_dispatcher = Dispatch::default();
1063        assert!(default_dispatcher.is::<TestSubscriber>());
1064
1065        drop(guard);
1066        let default_dispatcher = Dispatch::default();
1067        assert!(default_dispatcher.is::<NoSubscriber>());
1068    }
1069}