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