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