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