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