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