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