• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //!
126 use core::ptr::addr_of;
127 
128 use crate::{
129     callsite, span,
130     subscriber::{self, NoSubscriber, Subscriber},
131     Event, LevelFilter, Metadata,
132 };
133 
134 use crate::stdlib::{
135     any::Any,
136     fmt,
137     sync::{
138         atomic::{AtomicBool, AtomicUsize, Ordering},
139         Arc, Weak,
140     },
141 };
142 
143 #[cfg(feature = "std")]
144 use crate::stdlib::{
145     cell::{Cell, Ref, RefCell},
146     error,
147 };
148 
149 /// `Dispatch` trace data to a [`Subscriber`].
150 #[derive(Clone)]
151 pub 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)]
174 pub struct WeakDispatch {
175     subscriber: Kind<Weak<dyn Subscriber + Send + Sync>>,
176 }
177 
178 #[derive(Clone)]
179 enum Kind<T> {
180     Global(&'static (dyn Subscriber + Send + Sync)),
181     Scoped(T),
182 }
183 
184 #[cfg(feature = "std")]
185 thread_local! {
186     static CURRENT_STATE: State = const {
187         State {
188             default: RefCell::new(None),
189             can_enter: Cell::new(true),
190         }
191     };
192 }
193 
194 static EXISTS: AtomicBool = AtomicBool::new(false);
195 static GLOBAL_INIT: AtomicUsize = AtomicUsize::new(UNINITIALIZED);
196 
197 #[cfg(feature = "std")]
198 static SCOPED_COUNT: AtomicUsize = AtomicUsize::new(0);
199 
200 const UNINITIALIZED: usize = 0;
201 const INITIALIZING: usize = 1;
202 const INITIALIZED: usize = 2;
203 
204 static mut GLOBAL_DISPATCH: Dispatch = Dispatch {
205     subscriber: Kind::Global(&NO_SUBSCRIBER),
206 };
207 static NONE: Dispatch = Dispatch {
208     subscriber: Kind::Global(&NO_SUBSCRIBER),
209 };
210 static NO_SUBSCRIBER: NoSubscriber = NoSubscriber::new();
211 
212 /// The dispatch state of a thread.
213 #[cfg(feature = "std")]
214 struct 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")]
231 struct 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)]
238 pub 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")))]
with_default<T>(dispatcher: &Dispatch, f: impl FnOnce() -> T) -> T257 pub 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."]
set_default(dispatcher: &Dispatch) -> DefaultGuard279 pub 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
set_global_default(dispatcher: Dispatch) -> Result<(), SetGlobalDefaultError>302 pub 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)]
has_been_set() -> bool343 pub fn has_been_set() -> bool {
344     EXISTS.load(Ordering::Relaxed)
345 }
346 
347 /// Returned if setting the global dispatcher fails.
348 pub struct SetGlobalDefaultError {
349     _no_construct: (),
350 }
351 
352 impl fmt::Debug for SetGlobalDefaultError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result353     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
354         f.debug_tuple("SetGlobalDefaultError")
355             .field(&Self::MESSAGE)
356             .finish()
357     }
358 }
359 
360 impl fmt::Display for SetGlobalDefaultError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result361     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")))]
368 impl error::Error for SetGlobalDefaultError {}
369 
370 impl 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")]
get_default<T, F>(mut f: F) -> T where F: FnMut(&Dispatch) -> T,382 pub fn get_default<T, F>(mut f: F) -> T
383 where
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)]
get_current<T>(f: impl FnOnce(&Dispatch) -> T) -> Option<T>413 pub 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)]
get_current<T>(f: impl FnOnce(&Dispatch) -> T) -> Option<T>433 pub 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"))]
get_default<T, F>(mut f: F) -> T where F: FnMut(&Dispatch) -> T,441 pub fn get_default<T, F>(mut f: F) -> T
442 where
443     F: FnMut(&Dispatch) -> T,
444 {
445     f(&get_global())
446 }
447 
448 #[inline]
get_global() -> &'static Dispatch449 fn 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")]
461 pub(crate) struct Registrar(Kind<Weak<dyn Subscriber + Send + Sync>>);
462 
463 impl Dispatch {
464     /// Returns a new `Dispatch` that discards events and spans.
465     #[inline]
none() -> Self466     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
new<S>(subscriber: S) -> Self where S: Subscriber + Send + Sync + 'static,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")]
registrar(&self) -> Registrar487     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
downgrade(&self) -> WeakDispatch505     pub fn downgrade(&self) -> WeakDispatch {
506         WeakDispatch {
507             subscriber: self.subscriber.downgrade(),
508         }
509     }
510 
511     #[inline(always)]
subscriber(&self) -> &(dyn Subscriber + Send + Sync)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]
register_callsite(&self, metadata: &'static Metadata<'static>) -> subscriber::Interest528     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]
max_level_hint(&self) -> Option<LevelFilter>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]
new_span(&self, span: &span::Attributes<'_>) -> span::Id558     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]
record(&self, span: &span::Id, values: &span::Record<'_>)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]
record_follows_from(&self, span: &span::Id, follows: &span::Id)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]
enabled(&self, metadata: &Metadata<'_>) -> bool597     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]
event(&self, event: &Event<'_>)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
enter(&self, span: &span::Id)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
exit(&self, span: &span::Id)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]
clone_span(&self, id: &span::Id) -> span::Id654     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")]
drop_span(&self, id: span::Id)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
try_close(&self, id: span::Id) -> bool702     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]
current_span(&self) -> span::Current713     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]
is<T: Any>(&self) -> bool720     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]
downcast_ref<T: Any>(&self) -> Option<&T>727     pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
728         <dyn Subscriber>::downcast_ref(self.subscriber())
729     }
730 }
731 
732 impl Default for Dispatch {
733     /// Returns the current default dispatcher
default() -> Self734     fn default() -> Self {
735         get_default(|default| default.clone())
736     }
737 }
738 
739 impl fmt::Debug for Dispatch {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result740     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 
754 impl<S> From<S> for Dispatch
755 where
756     S: Subscriber + Send + Sync + 'static,
757 {
758     #[inline]
from(subscriber: S) -> Self759     fn from(subscriber: S) -> Self {
760         Dispatch::new(subscriber)
761     }
762 }
763 
764 // === impl WeakDispatch ===
765 
766 impl 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     /// ```
upgrade(&self) -> Option<Dispatch>785     pub fn upgrade(&self) -> Option<Dispatch> {
786         self.subscriber
787             .upgrade()
788             .map(|subscriber| Dispatch { subscriber })
789     }
790 }
791 
792 impl fmt::Debug for WeakDispatch {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result793     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")]
808 impl Registrar {
upgrade(&self) -> Option<Dispatch>809     pub(crate) fn upgrade(&self) -> Option<Dispatch> {
810         self.0.upgrade().map(|subscriber| Dispatch { subscriber })
811     }
812 }
813 
814 // ===== impl State =====
815 
816 impl Kind<Arc<dyn Subscriber + Send + Sync>> {
downgrade(&self) -> Kind<Weak<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 
825 impl Kind<Weak<dyn Subscriber + Send + Sync>> {
upgrade(&self) -> Option<Kind<Arc<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")]
837 impl 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]
set_default(new_dispatch: Dispatch) -> DefaultGuard844     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]
enter(&self) -> Option<Entered<'_>>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")]
870 impl<'a> Entered<'a> {
871     #[inline]
current(&self) -> Ref<'a, Dispatch>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")]
882 impl<'a> Drop for Entered<'a> {
883     #[inline]
drop(&mut self)884     fn drop(&mut self) {
885         self.0.can_enter.set(true);
886     }
887 }
888 
889 // ===== impl DefaultGuard =====
890 
891 #[cfg(feature = "std")]
892 impl Drop for DefaultGuard {
893     #[inline]
drop(&mut self)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)]
907 mod 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]
dispatch_is()918     fn dispatch_is() {
919         let dispatcher = Dispatch::new(NoSubscriber::default());
920         assert!(dispatcher.is::<NoSubscriber>());
921     }
922 
923     #[test]
dispatch_downcasts()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 {
set_interest(&self, _: Interest)941         fn set_interest(&self, _: Interest) {}
metadata(&self) -> &Metadata<'_>942         fn metadata(&self) -> &Metadata<'_> {
943             &TEST_META
944         }
945     }
946 
947     #[test]
948     #[cfg(feature = "std")]
events_dont_infinite_loop()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")]
spans_dont_infinite_loop()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]
default_no_subscriber()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]
default_dispatch()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 }
1070