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 //! # fn main() {
42 //! use dispatcher::Dispatch;
43 //!
44 //! let my_subscriber = FooSubscriber::new();
45 //! let my_dispatch = Dispatch::new(my_subscriber);
46 //! # }
47 //! ```
48 //! Then, we can use [`with_default`] to set our `Dispatch` as the default for
49 //! the duration of a block:
50 //! ```rust
51 //! # pub struct FooSubscriber;
52 //! # use tracing_core::{
53 //! #   dispatcher, Event, Metadata,
54 //! #   span::{Attributes, Id, Record}
55 //! # };
56 //! # impl tracing_core::Subscriber for FooSubscriber {
57 //! #   fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
58 //! #   fn record(&self, _: &Id, _: &Record) {}
59 //! #   fn event(&self, _: &Event) {}
60 //! #   fn record_follows_from(&self, _: &Id, _: &Id) {}
61 //! #   fn enabled(&self, _: &Metadata) -> bool { false }
62 //! #   fn enter(&self, _: &Id) {}
63 //! #   fn exit(&self, _: &Id) {}
64 //! # }
65 //! # impl FooSubscriber { fn new() -> Self { FooSubscriber } }
66 //! # fn main() {
67 //! # let my_subscriber = FooSubscriber::new();
68 //! # let my_dispatch = dispatcher::Dispatch::new(my_subscriber);
69 //! // no default subscriber
70 //!
71 //! # #[cfg(feature = "std")]
72 //! dispatcher::with_default(&my_dispatch, || {
73 //!     // my_subscriber is the default
74 //! });
75 //!
76 //! // no default subscriber again
77 //! # }
78 //! ```
79 //! It's important to note that `with_default` will not propagate the current
80 //! thread's default subscriber to any threads spawned within the `with_default`
81 //! block. To propagate the default subscriber to new threads, either use
82 //! `with_default` from the new thread, or use `set_global_default`.
83 //!
84 //! As an alternative to `with_default`, we can use [`set_global_default`] to
85 //! set a `Dispatch` as the default for all threads, for the lifetime of the
86 //! program. For example:
87 //! ```rust
88 //! # pub struct FooSubscriber;
89 //! # use tracing_core::{
90 //! #   dispatcher, Event, Metadata,
91 //! #   span::{Attributes, Id, Record}
92 //! # };
93 //! # impl tracing_core::Subscriber for FooSubscriber {
94 //! #   fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
95 //! #   fn record(&self, _: &Id, _: &Record) {}
96 //! #   fn event(&self, _: &Event) {}
97 //! #   fn record_follows_from(&self, _: &Id, _: &Id) {}
98 //! #   fn enabled(&self, _: &Metadata) -> bool { false }
99 //! #   fn enter(&self, _: &Id) {}
100 //! #   fn exit(&self, _: &Id) {}
101 //! # }
102 //! # impl FooSubscriber { fn new() -> Self { FooSubscriber } }
103 //! # fn main() {
104 //! # let my_subscriber = FooSubscriber::new();
105 //! # let my_dispatch = dispatcher::Dispatch::new(my_subscriber);
106 //! // no default subscriber
107 //!
108 //! dispatcher::set_global_default(my_dispatch)
109 //!     // `set_global_default` will return an error if the global default
110 //!     // subscriber has already been set.
111 //!     .expect("global default was already set!");
112 //!
113 //! // `my_subscriber` is now the default
114 //! # }
115 //! ```
116 //!
117 //! **Note**: the thread-local scoped dispatcher (`with_default`) requires the
118 //! Rust standard library. `no_std` users should use [`set_global_default`]
119 //! instead.
120 //!
121 //! Finally, `tokio` users should note that versions of `tokio` >= 0.1.22
122 //! support an `experimental-tracing` feature flag. When this flag is enabled,
123 //! the `tokio` runtime's thread pool will automatically propagate the default
124 //! subscriber. This means that if `tokio::runtime::Runtime::new()` or
125 //! `tokio::run()` are invoked when a default subscriber is set, it will also be
126 //! set by all worker threads created by that runtime.
127 //!
128 //! ## Accessing the Default Subscriber
129 //!
130 //! A thread's current default subscriber can be accessed using the
131 //! [`get_default`] function, which executes a closure with a reference to the
132 //! currently default `Dispatch`. This is used primarily by `tracing`
133 //! instrumentation.
134 //!
135 //! [`Subscriber`]: struct.Subscriber.html
136 //! [`with_default`]: fn.with_default.html
137 //! [`set_global_default`]: fn.set_global_default.html
138 //! [`get_default`]: fn.get_default.html
139 //! [`Dispatch`]: struct.Dispatch.html
140 use crate::{
141     callsite, span,
142     subscriber::{self, Subscriber},
143     Event, Metadata,
144 };
145 
146 use crate::stdlib::{
147     any::Any,
148     fmt,
149     sync::{
150         atomic::{AtomicBool, AtomicUsize, Ordering},
151         Arc, Weak,
152     },
153 };
154 
155 #[cfg(feature = "std")]
156 use crate::stdlib::{
157     cell::{Cell, RefCell},
158     error,
159 };
160 
161 /// `Dispatch` trace data to a [`Subscriber`].
162 ///
163 /// [`Subscriber`]: trait.Subscriber.html
164 #[derive(Clone)]
165 pub struct Dispatch {
166     subscriber: Arc<dyn Subscriber + Send + Sync>,
167 }
168 
169 #[cfg(feature = "std")]
170 thread_local! {
171     static CURRENT_STATE: State = State {
172         default: RefCell::new(Dispatch::none()),
173         can_enter: Cell::new(true),
174     };
175 }
176 
177 static EXISTS: AtomicBool = AtomicBool::new(false);
178 static GLOBAL_INIT: AtomicUsize = AtomicUsize::new(UNINITIALIZED);
179 
180 const UNINITIALIZED: usize = 0;
181 const INITIALIZING: usize = 1;
182 const INITIALIZED: usize = 2;
183 
184 static mut GLOBAL_DISPATCH: Option<Dispatch> = None;
185 
186 /// The dispatch state of a thread.
187 #[cfg(feature = "std")]
188 struct State {
189     /// This thread's current default dispatcher.
190     default: RefCell<Dispatch>,
191     /// Whether or not we can currently begin dispatching a trace event.
192     ///
193     /// This is set to `false` when functions such as `enter`, `exit`, `event`,
194     /// and `new_span` are called on this thread's default dispatcher, to
195     /// prevent further trace events triggered inside those functions from
196     /// creating an infinite recursion. When we finish handling a dispatch, this
197     /// is set back to `true`.
198     can_enter: Cell<bool>,
199 }
200 
201 /// A guard that resets the current default dispatcher to the prior
202 /// default dispatcher when dropped.
203 #[cfg(feature = "std")]
204 #[derive(Debug)]
205 pub struct DefaultGuard(Option<Dispatch>);
206 
207 /// Sets this dispatch as the default for the duration of a closure.
208 ///
209 /// The default dispatcher is used when creating a new [span] or
210 /// [`Event`].
211 ///
212 /// **Note**: This function requires the Rust standard library. `no_std` users
213 /// should use [`set_global_default`] instead.
214 ///
215 /// [span]: ../span/index.html
216 /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
217 /// [`Event`]: ../event/struct.Event.html
218 /// [`set_global_default`]: ../fn.set_global_default.html
219 #[cfg(feature = "std")]
with_default<T>(dispatcher: &Dispatch, f: impl FnOnce() -> T) -> T220 pub fn with_default<T>(dispatcher: &Dispatch, f: impl FnOnce() -> T) -> T {
221     // When this guard is dropped, the default dispatcher will be reset to the
222     // prior default. Using this (rather than simply resetting after calling
223     // `f`) ensures that we always reset to the prior dispatcher even if `f`
224     // panics.
225     let _guard = set_default(dispatcher);
226     f()
227 }
228 
229 /// Sets the dispatch as the default dispatch for the duration of the lifetime
230 /// of the returned DefaultGuard
231 ///
232 /// **Note**: This function required the Rust standard library. `no_std`  users
233 /// should use [`set_global_default`] instead.
234 ///
235 /// [`set_global_default`]: ../fn.set_global_default.html
236 #[cfg(feature = "std")]
set_default(dispatcher: &Dispatch) -> DefaultGuard237 pub fn set_default(dispatcher: &Dispatch) -> DefaultGuard {
238     // When this guard is dropped, the default dispatcher will be reset to the
239     // prior default. Using this ensures that we always reset to the prior
240     // dispatcher even if the thread calling this function panics.
241     State::set_default(dispatcher.clone())
242 }
243 
244 /// Sets this dispatch as the global default for the duration of the entire program.
245 /// Will be used as a fallback if no thread-local dispatch has been set in a thread
246 /// (using `with_default`.)
247 ///
248 /// Can only be set once; subsequent attempts to set the global default will fail.
249 /// Returns `Err` if the global default has already been set.
250 ///
251 /// Note: Libraries should *NOT* call `set_global_default()`! That will cause conflicts when
252 /// executables try to set them later.
253 ///
254 /// [span]: ../span/index.html
255 /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
256 /// [`Event`]: ../event/struct.Event.html
set_global_default(dispatcher: Dispatch) -> Result<(), SetGlobalDefaultError>257 pub fn set_global_default(dispatcher: Dispatch) -> Result<(), SetGlobalDefaultError> {
258     if GLOBAL_INIT.compare_and_swap(UNINITIALIZED, INITIALIZING, Ordering::SeqCst) == UNINITIALIZED
259     {
260         unsafe {
261             GLOBAL_DISPATCH = Some(dispatcher.clone());
262         }
263         GLOBAL_INIT.store(INITIALIZED, Ordering::SeqCst);
264         EXISTS.store(true, Ordering::Release);
265         Ok(())
266     } else {
267         Err(SetGlobalDefaultError { _no_construct: () })
268     }
269 }
270 
271 /// Returns true if a `tracing` dispatcher has ever been set.
272 ///
273 /// This may be used to completely elide trace points if tracing is not in use
274 /// at all or has yet to be initialized.
275 #[doc(hidden)]
276 #[inline(always)]
has_been_set() -> bool277 pub fn has_been_set() -> bool {
278     EXISTS.load(Ordering::Relaxed)
279 }
280 
281 /// Returned if setting the global dispatcher fails.
282 #[derive(Debug)]
283 pub struct SetGlobalDefaultError {
284     _no_construct: (),
285 }
286 
287 impl fmt::Display for SetGlobalDefaultError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result288     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
289         f.pad("a global default trace dispatcher has already been set")
290     }
291 }
292 
293 #[cfg(feature = "std")]
294 impl error::Error for SetGlobalDefaultError {}
295 
296 /// Executes a closure with a reference to this thread's current [dispatcher].
297 ///
298 /// Note that calls to `get_default` should not be nested; if this function is
299 /// called while inside of another `get_default`, that closure will be provided
300 /// with `Dispatch::none` rather than the previously set dispatcher.
301 ///
302 /// [dispatcher]: ../dispatcher/struct.Dispatch.html
303 #[cfg(feature = "std")]
get_default<T, F>(mut f: F) -> T where F: FnMut(&Dispatch) -> T,304 pub fn get_default<T, F>(mut f: F) -> T
305 where
306     F: FnMut(&Dispatch) -> T,
307 {
308     // While this guard is active, additional calls to subscriber functions on
309     // the default dispatcher will not be able to access the dispatch context.
310     // Dropping the guard will allow the dispatch context to be re-entered.
311     struct Entered<'a>(&'a Cell<bool>);
312     impl<'a> Drop for Entered<'a> {
313         #[inline]
314         fn drop(&mut self) {
315             self.0.set(true);
316         }
317     }
318 
319     CURRENT_STATE
320         .try_with(|state| {
321             if state.can_enter.replace(false) {
322                 let _guard = Entered(&state.can_enter);
323 
324                 let mut default = state.default.borrow_mut();
325 
326                 if default.is::<NoSubscriber>() {
327                     if let Some(global) = get_global() {
328                         // don't redo this call on the next check
329                         *default = global.clone();
330                     }
331                 }
332                 f(&*default)
333             } else {
334                 f(&Dispatch::none())
335             }
336         })
337         .unwrap_or_else(|_| f(&Dispatch::none()))
338 }
339 
340 /// Executes a closure with a reference to the current [dispatcher].
341 ///
342 /// [dispatcher]: ../dispatcher/struct.Dispatch.html
343 #[cfg(not(feature = "std"))]
get_default<T, F>(mut f: F) -> T where F: FnMut(&Dispatch) -> T,344 pub fn get_default<T, F>(mut f: F) -> T
345 where
346     F: FnMut(&Dispatch) -> T,
347 {
348     if let Some(d) = get_global() {
349         f(d)
350     } else {
351         f(&Dispatch::none())
352     }
353 }
354 
get_global() -> Option<&'static Dispatch>355 fn get_global() -> Option<&'static Dispatch> {
356     if GLOBAL_INIT.load(Ordering::SeqCst) != INITIALIZED {
357         return None;
358     }
359     unsafe {
360         // This is safe given the invariant that setting the global dispatcher
361         // also sets `GLOBAL_INIT` to `INITIALIZED`.
362         Some(GLOBAL_DISPATCH.as_ref().expect(
363             "invariant violated: GLOBAL_DISPATCH must be initialized before GLOBAL_INIT is set",
364         ))
365     }
366 }
367 
368 pub(crate) struct Registrar(Weak<dyn Subscriber + Send + Sync>);
369 
370 impl Dispatch {
371     /// Returns a new `Dispatch` that discards events and spans.
372     #[inline]
none() -> Self373     pub fn none() -> Self {
374         Dispatch {
375             subscriber: Arc::new(NoSubscriber),
376         }
377     }
378 
379     /// Returns a `Dispatch` that forwards to the given [`Subscriber`].
380     ///
381     /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
new<S>(subscriber: S) -> Self where S: Subscriber + Send + Sync + 'static,382     pub fn new<S>(subscriber: S) -> Self
383     where
384         S: Subscriber + Send + Sync + 'static,
385     {
386         let me = Dispatch {
387             subscriber: Arc::new(subscriber),
388         };
389         callsite::register_dispatch(&me);
390         me
391     }
392 
registrar(&self) -> Registrar393     pub(crate) fn registrar(&self) -> Registrar {
394         Registrar(Arc::downgrade(&self.subscriber))
395     }
396 
397     /// Registers a new callsite with this subscriber, returning whether or not
398     /// the subscriber is interested in being notified about the callsite.
399     ///
400     /// This calls the [`register_callsite`] function on the [`Subscriber`]
401     /// that this `Dispatch` forwards to.
402     ///
403     /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
404     /// [`register_callsite`]: ../subscriber/trait.Subscriber.html#method.register_callsite
405     #[inline]
register_callsite(&self, metadata: &'static Metadata<'static>) -> subscriber::Interest406     pub fn register_callsite(&self, metadata: &'static Metadata<'static>) -> subscriber::Interest {
407         self.subscriber.register_callsite(metadata)
408     }
409 
410     /// Record the construction of a new span, returning a new [ID] for the
411     /// span being constructed.
412     ///
413     /// This calls the [`new_span`] function on the [`Subscriber`] that this
414     /// `Dispatch` forwards to.
415     ///
416     /// [ID]: ../span/struct.Id.html
417     /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
418     /// [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span
419     #[inline]
new_span(&self, span: &span::Attributes<'_>) -> span::Id420     pub fn new_span(&self, span: &span::Attributes<'_>) -> span::Id {
421         self.subscriber.new_span(span)
422     }
423 
424     /// Record a set of values on a span.
425     ///
426     /// This calls the [`record`] function on the [`Subscriber`] that this
427     /// `Dispatch` forwards to.
428     ///
429     /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
430     /// [`record`]: ../subscriber/trait.Subscriber.html#method.record
431     #[inline]
record(&self, span: &span::Id, values: &span::Record<'_>)432     pub fn record(&self, span: &span::Id, values: &span::Record<'_>) {
433         self.subscriber.record(span, values)
434     }
435 
436     /// Adds an indication that `span` follows from the span with the id
437     /// `follows`.
438     ///
439     /// This calls the [`record_follows_from`] function on the [`Subscriber`]
440     /// that this `Dispatch` forwards to.
441     ///
442     /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
443     /// [`record_follows_from`]: ../subscriber/trait.Subscriber.html#method.record_follows_from
444     #[inline]
record_follows_from(&self, span: &span::Id, follows: &span::Id)445     pub fn record_follows_from(&self, span: &span::Id, follows: &span::Id) {
446         self.subscriber.record_follows_from(span, follows)
447     }
448 
449     /// Returns true if a span with the specified [metadata] would be
450     /// recorded.
451     ///
452     /// This calls the [`enabled`] function on the [`Subscriber`] that this
453     /// `Dispatch` forwards to.
454     ///
455     /// [metadata]: ../metadata/struct.Metadata.html
456     /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
457     /// [`enabled`]: ../subscriber/trait.Subscriber.html#method.enabled
458     #[inline]
enabled(&self, metadata: &Metadata<'_>) -> bool459     pub fn enabled(&self, metadata: &Metadata<'_>) -> bool {
460         self.subscriber.enabled(metadata)
461     }
462 
463     /// Records that an [`Event`] has occurred.
464     ///
465     /// This calls the [`event`] function on the [`Subscriber`] that this
466     /// `Dispatch` forwards to.
467     ///
468     /// [`Event`]: ../event/struct.Event.html
469     /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
470     /// [`event`]: ../subscriber/trait.Subscriber.html#method.event
471     #[inline]
event(&self, event: &Event<'_>)472     pub fn event(&self, event: &Event<'_>) {
473         self.subscriber.event(event)
474     }
475 
476     /// Records that a span has been can_enter.
477     ///
478     /// This calls the [`enter`] function on the [`Subscriber`] that this
479     /// `Dispatch` forwards to.
480     ///
481     /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
482     /// [`event`]: ../subscriber/trait.Subscriber.html#method.event
483     #[inline]
enter(&self, span: &span::Id)484     pub fn enter(&self, span: &span::Id) {
485         self.subscriber.enter(span);
486     }
487 
488     /// Records that a span has been exited.
489     ///
490     /// This calls the [`exit`](::Subscriber::exit) function on the `Subscriber`
491     /// that this `Dispatch` forwards to.
492     #[inline]
exit(&self, span: &span::Id)493     pub fn exit(&self, span: &span::Id) {
494         self.subscriber.exit(span);
495     }
496 
497     /// Notifies the subscriber that a [span ID] has been cloned.
498     ///
499     /// This function must only be called with span IDs that were returned by
500     /// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
501     /// this guarantee and any other libraries implementing instrumentation APIs
502     /// must as well.
503     ///
504     /// This calls the [`clone_span`] function on the `Subscriber` that this
505     /// `Dispatch` forwards to.
506     ///
507     /// [span ID]: ../span/struct.Id.html
508     /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
509     /// [`clone_span`]: ../subscriber/trait.Subscriber.html#method.clone_span
510     /// [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span
511     #[inline]
clone_span(&self, id: &span::Id) -> span::Id512     pub fn clone_span(&self, id: &span::Id) -> span::Id {
513         self.subscriber.clone_span(&id)
514     }
515 
516     /// Notifies the subscriber that a [span ID] has been dropped.
517     ///
518     /// This function must only be called with span IDs that were returned by
519     /// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
520     /// this guarantee and any other libraries implementing instrumentation APIs
521     /// must as well.
522     ///
523     /// This calls the [`drop_span`]  function on the [`Subscriber`] that this
524     ///  `Dispatch` forwards to.
525     ///
526     /// **Note:** the [`try_close`] function is functionally identical, but
527     /// returns `true` if the span is now closed.
528     ///
529     /// [span ID]: ../span/struct.Id.html
530     /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
531     /// [`clone_span`]: ../subscriber/trait.Subscriber.html#method.clone_span
532     /// [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span
533     /// [`try_close`]: #method.try_close
534     #[inline]
535     #[deprecated(since = "0.1.2", note = "use `Dispatch::try_close` instead")]
drop_span(&self, id: span::Id)536     pub fn drop_span(&self, id: span::Id) {
537         #[allow(deprecated)]
538         self.subscriber.drop_span(id);
539     }
540 
541     /// Notifies the subscriber that a [span ID] has been dropped, and returns
542     /// `true` if there are now 0 IDs referring to that span.
543     ///
544     /// This function must only be called with span IDs that were returned by
545     /// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
546     /// this guarantee and any other libraries implementing instrumentation APIs
547     /// must as well.
548     ///
549     /// This calls the [`try_close`]  function on the [`Subscriber`] that this
550     ///  `Dispatch` forwards to.
551     ///
552     /// [span ID]: ../span/struct.Id.html
553     /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
554     /// [`try_close`]: ../subscriber/trait.Subscriber.html#method.try_close
555     /// [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span
556     #[inline]
try_close(&self, id: span::Id) -> bool557     pub fn try_close(&self, id: span::Id) -> bool {
558         self.subscriber.try_close(id)
559     }
560 
561     /// Returns a type representing this subscriber's view of the current span.
562     ///
563     /// This calls the [`current`] function on the `Subscriber` that this
564     /// `Dispatch` forwards to.
565     ///
566     /// [`current`]: ../subscriber/trait.Subscriber.html#method.current
567     #[inline]
current_span(&self) -> span::Current568     pub fn current_span(&self) -> span::Current {
569         self.subscriber.current_span()
570     }
571 
572     /// Returns `true` if this `Dispatch` forwards to a `Subscriber` of type
573     /// `T`.
574     #[inline]
is<T: Any>(&self) -> bool575     pub fn is<T: Any>(&self) -> bool {
576         Subscriber::is::<T>(&*self.subscriber)
577     }
578 
579     /// Returns some reference to the `Subscriber` this `Dispatch` forwards to
580     /// if it is of type `T`, or `None` if it isn't.
581     #[inline]
downcast_ref<T: Any>(&self) -> Option<&T>582     pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
583         Subscriber::downcast_ref(&*self.subscriber)
584     }
585 }
586 
587 impl Default for Dispatch {
588     /// Returns the current default dispatcher
default() -> Self589     fn default() -> Self {
590         get_default(|default| default.clone())
591     }
592 }
593 
594 impl fmt::Debug for Dispatch {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result595     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
596         f.pad("Dispatch(...)")
597     }
598 }
599 
600 impl<S> From<S> for Dispatch
601 where
602     S: Subscriber + Send + Sync + 'static,
603 {
604     #[inline]
from(subscriber: S) -> Self605     fn from(subscriber: S) -> Self {
606         Dispatch::new(subscriber)
607     }
608 }
609 
610 struct NoSubscriber;
611 impl Subscriber for NoSubscriber {
612     #[inline]
register_callsite(&self, _: &'static Metadata<'static>) -> subscriber::Interest613     fn register_callsite(&self, _: &'static Metadata<'static>) -> subscriber::Interest {
614         subscriber::Interest::never()
615     }
616 
new_span(&self, _: &span::Attributes<'_>) -> span::Id617     fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
618         span::Id::from_u64(0xDEAD)
619     }
620 
event(&self, _event: &Event<'_>)621     fn event(&self, _event: &Event<'_>) {}
622 
record(&self, _span: &span::Id, _values: &span::Record<'_>)623     fn record(&self, _span: &span::Id, _values: &span::Record<'_>) {}
624 
record_follows_from(&self, _span: &span::Id, _follows: &span::Id)625     fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
626 
627     #[inline]
enabled(&self, _metadata: &Metadata<'_>) -> bool628     fn enabled(&self, _metadata: &Metadata<'_>) -> bool {
629         false
630     }
631 
enter(&self, _span: &span::Id)632     fn enter(&self, _span: &span::Id) {}
exit(&self, _span: &span::Id)633     fn exit(&self, _span: &span::Id) {}
634 }
635 
636 impl Registrar {
try_register( &self, metadata: &'static Metadata<'static>, ) -> Option<subscriber::Interest>637     pub(crate) fn try_register(
638         &self,
639         metadata: &'static Metadata<'static>,
640     ) -> Option<subscriber::Interest> {
641         self.0.upgrade().map(|s| s.register_callsite(metadata))
642     }
643 
is_alive(&self) -> bool644     pub(crate) fn is_alive(&self) -> bool {
645         self.0.upgrade().is_some()
646     }
647 }
648 
649 // ===== impl State =====
650 
651 #[cfg(feature = "std")]
652 impl State {
653     /// Replaces the current default dispatcher on this thread with the provided
654     /// dispatcher.Any
655     ///
656     /// Dropping the returned `ResetGuard` will reset the default dispatcher to
657     /// the previous value.
658     #[inline]
set_default(new_dispatch: Dispatch) -> DefaultGuard659     fn set_default(new_dispatch: Dispatch) -> DefaultGuard {
660         let prior = CURRENT_STATE
661             .try_with(|state| {
662                 state.can_enter.set(true);
663                 state.default.replace(new_dispatch)
664             })
665             .ok();
666         EXISTS.store(true, Ordering::Release);
667         DefaultGuard(prior)
668     }
669 }
670 
671 // ===== impl DefaultGuard =====
672 
673 #[cfg(feature = "std")]
674 impl Drop for DefaultGuard {
675     #[inline]
drop(&mut self)676     fn drop(&mut self) {
677         if let Some(dispatch) = self.0.take() {
678             let _ = CURRENT_STATE.try_with(|state| {
679                 *state.default.borrow_mut() = dispatch;
680             });
681         }
682     }
683 }
684 
685 #[cfg(test)]
686 mod test {
687     use super::*;
688     #[cfg(feature = "std")]
689     use crate::stdlib::sync::atomic::{AtomicUsize, Ordering};
690     use crate::{
691         callsite::Callsite,
692         metadata::{Kind, Level, Metadata},
693         subscriber::Interest,
694     };
695 
696     #[test]
dispatch_is()697     fn dispatch_is() {
698         let dispatcher = Dispatch::new(NoSubscriber);
699         assert!(dispatcher.is::<NoSubscriber>());
700     }
701 
702     #[test]
dispatch_downcasts()703     fn dispatch_downcasts() {
704         let dispatcher = Dispatch::new(NoSubscriber);
705         assert!(dispatcher.downcast_ref::<NoSubscriber>().is_some());
706     }
707 
708     struct TestCallsite;
709     static TEST_CALLSITE: TestCallsite = TestCallsite;
710     static TEST_META: Metadata<'static> = metadata! {
711         name: "test",
712         target: module_path!(),
713         level: Level::DEBUG,
714         fields: &[],
715         callsite: &TEST_CALLSITE,
716         kind: Kind::EVENT
717     };
718 
719     impl Callsite for TestCallsite {
set_interest(&self, _: Interest)720         fn set_interest(&self, _: Interest) {}
metadata(&self) -> &Metadata<'_>721         fn metadata(&self) -> &Metadata<'_> {
722             &TEST_META
723         }
724     }
725 
726     #[test]
727     #[cfg(feature = "std")]
events_dont_infinite_loop()728     fn events_dont_infinite_loop() {
729         // This test ensures that an event triggered within a subscriber
730         // won't cause an infinite loop of events.
731         struct TestSubscriber;
732         impl Subscriber for TestSubscriber {
733             fn enabled(&self, _: &Metadata<'_>) -> bool {
734                 true
735             }
736 
737             fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
738                 span::Id::from_u64(0xAAAA)
739             }
740 
741             fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
742 
743             fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
744 
745             fn event(&self, _: &Event<'_>) {
746                 static EVENTS: AtomicUsize = AtomicUsize::new(0);
747                 assert_eq!(
748                     EVENTS.fetch_add(1, Ordering::Relaxed),
749                     0,
750                     "event method called twice!"
751                 );
752                 Event::dispatch(&TEST_META, &TEST_META.fields().value_set(&[]))
753             }
754 
755             fn enter(&self, _: &span::Id) {}
756 
757             fn exit(&self, _: &span::Id) {}
758         }
759 
760         with_default(&Dispatch::new(TestSubscriber), || {
761             Event::dispatch(&TEST_META, &TEST_META.fields().value_set(&[]))
762         })
763     }
764 
765     #[test]
766     #[cfg(feature = "std")]
spans_dont_infinite_loop()767     fn spans_dont_infinite_loop() {
768         // This test ensures that a span created within a subscriber
769         // won't cause an infinite loop of new spans.
770 
771         fn mk_span() {
772             get_default(|current| {
773                 current.new_span(&span::Attributes::new(
774                     &TEST_META,
775                     &TEST_META.fields().value_set(&[]),
776                 ))
777             });
778         }
779 
780         struct TestSubscriber;
781         impl Subscriber for TestSubscriber {
782             fn enabled(&self, _: &Metadata<'_>) -> bool {
783                 true
784             }
785 
786             fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
787                 static NEW_SPANS: AtomicUsize = AtomicUsize::new(0);
788                 assert_eq!(
789                     NEW_SPANS.fetch_add(1, Ordering::Relaxed),
790                     0,
791                     "new_span method called twice!"
792                 );
793                 mk_span();
794                 span::Id::from_u64(0xAAAA)
795             }
796 
797             fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
798 
799             fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
800 
801             fn event(&self, _: &Event<'_>) {}
802 
803             fn enter(&self, _: &span::Id) {}
804 
805             fn exit(&self, _: &span::Id) {}
806         }
807 
808         with_default(&Dispatch::new(TestSubscriber), || mk_span())
809     }
810 
811     #[test]
default_no_subscriber()812     fn default_no_subscriber() {
813         let default_dispatcher = Dispatch::default();
814         assert!(default_dispatcher.is::<NoSubscriber>());
815     }
816 
817     #[cfg(feature = "std")]
818     #[test]
default_dispatch()819     fn default_dispatch() {
820         struct TestSubscriber;
821         impl Subscriber for TestSubscriber {
822             fn enabled(&self, _: &Metadata<'_>) -> bool {
823                 true
824             }
825 
826             fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
827                 span::Id::from_u64(0xAAAA)
828             }
829 
830             fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
831 
832             fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
833 
834             fn event(&self, _: &Event<'_>) {}
835 
836             fn enter(&self, _: &span::Id) {}
837 
838             fn exit(&self, _: &span::Id) {}
839         }
840         let guard = set_default(&Dispatch::new(TestSubscriber));
841         let default_dispatcher = Dispatch::default();
842         assert!(default_dispatcher.is::<TestSubscriber>());
843 
844         drop(guard);
845         let default_dispatcher = Dispatch::default();
846         assert!(default_dispatcher.is::<NoSubscriber>());
847     }
848 }
849