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