1 //! Dispatches trace events to [`Subscriber`]s.
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.
7 //! # Using the Trace Dispatcher
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.
13 //! ## Setting the Default Subscriber
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.
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
26 //! # pub struct FooSubscriber;
27 //! # use tracing_core::{
28 //! # dispatcher, Event, Metadata,
29 //! # span::{Attributes, Id, Record}
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) {}
40 //! # impl FooSubscriber { fn new() -> Self { FooSubscriber } }
41 //! use dispatcher::Dispatch;
43 //! let my_subscriber = FooSubscriber::new();
44 //! let my_dispatch = Dispatch::new(my_subscriber);
46 //! Then, we can use [`with_default`] to set our `Dispatch` as the default for
47 //! the duration of a block:
49 //! # pub struct FooSubscriber;
50 //! # use tracing_core::{
51 //! # dispatcher, Event, Metadata,
52 //! # span::{Attributes, Id, Record}
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) {}
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
68 //! # #[cfg(feature = "std")]
69 //! dispatcher::with_default(&my_dispatch, || {
70 //! // my_subscriber is the default
73 //! // no default subscriber again
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`.
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:
84 //! # pub struct FooSubscriber;
85 //! # use tracing_core::{
86 //! # dispatcher, Event, Metadata,
87 //! # span::{Attributes, Id, Record}
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) {}
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
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!");
108 //! // `my_subscriber` is now the default
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>
119 //! ## Accessing the Default Subscriber
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`
128 subscriber
::{self, NoSubscriber, Subscriber}
,
129 Event
, LevelFilter
, Metadata
,
136 atomic
::{AtomicBool, AtomicUsize, Ordering}
,
141 #[cfg(feature = "std")]
143 cell
::{Cell, Ref, RefCell}
,
147 #[cfg(feature = "alloc")]
148 use alloc
::sync
::{Arc, Weak}
;
150 #[cfg(feature = "alloc")]
151 use core
::ops
::Deref
;
153 /// `Dispatch` trace data to a [`Subscriber`].
155 pub struct Dispatch
{
156 subscriber
: Kind
<Arc
<dyn Subscriber
+ Send
+ Sync
>>,
159 /// `WeakDispatch` is a version of [`Dispatch`] that holds a non-owning reference
160 /// to a [`Subscriber`].
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)`.
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.
172 /// This type is analogous to the [`std::sync::Weak`] type, but for a
173 /// [`Dispatch`] rather than an [`Arc`].
175 /// [`Arc`]: std::sync::Arc
176 /// [here]: Subscriber#avoiding-memory-leaks
178 pub struct WeakDispatch
{
179 subscriber
: Kind
<Weak
<dyn Subscriber
+ Send
+ Sync
>>,
184 Global(&'
static (dyn Subscriber
+ Send
+ Sync
)),
188 #[cfg(feature = "std")]
190 static CURRENT_STATE
: State
= State
{
191 default: RefCell
::new(None
),
192 can_enter
: Cell
::new(true),
196 static EXISTS
: AtomicBool
= AtomicBool
::new(false);
197 static GLOBAL_INIT
: AtomicUsize
= AtomicUsize
::new(UNINITIALIZED
);
199 #[cfg(feature = "std")]
200 static SCOPED_COUNT
: AtomicUsize
= AtomicUsize
::new(0);
202 const UNINITIALIZED
: usize = 0;
203 const INITIALIZING
: usize = 1;
204 const INITIALIZED
: usize = 2;
206 static mut GLOBAL_DISPATCH
: Dispatch
= Dispatch
{
207 subscriber
: Kind
::Global(&NO_SUBSCRIBER
),
209 static NONE
: Dispatch
= Dispatch
{
210 subscriber
: Kind
::Global(&NO_SUBSCRIBER
),
212 static NO_SUBSCRIBER
: NoSubscriber
= NoSubscriber
::new();
214 /// The dispatch state of a thread.
215 #[cfg(feature = "std")]
217 /// This thread's current default dispatcher.
218 default: RefCell
<Option
<Dispatch
>>,
219 /// Whether or not we can currently begin dispatching a trace event.
221 /// This is set to `false` when functions such as `enter`, `exit`, `event`,
222 /// and `new_span` are called on this thread's default dispatcher, to
223 /// prevent further trace events triggered inside those functions from
224 /// creating an infinite recursion. When we finish handling a dispatch, this
225 /// is set back to `true`.
226 can_enter
: Cell
<bool
>,
229 /// While this guard is active, additional calls to subscriber functions on
230 /// the default dispatcher will not be able to access the dispatch context.
231 /// Dropping the guard will allow the dispatch context to be re-entered.
232 #[cfg(feature = "std")]
233 struct Entered
<'a
>(&'a State
);
235 /// A guard that resets the current default dispatcher to the prior
236 /// default dispatcher when dropped.
237 #[cfg(feature = "std")]
238 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
240 pub struct DefaultGuard(Option
<Dispatch
>);
242 /// Sets this dispatch as the default for the duration of a closure.
244 /// The default dispatcher is used when creating a new [span] or
247 /// <pre class="ignore" style="white-space:normal;font:inherit;">
248 /// <strong>Note</strong>: This function required the Rust standard library.
249 /// <code>no_std</code> users should use <a href="../fn.set_global_default.html">
250 /// <code>set_global_default</code></a> instead.
253 /// [span]: super::span
254 /// [`Subscriber`]: super::subscriber::Subscriber
255 /// [`Event`]: super::event::Event
256 /// [`set_global_default`]: super::set_global_default
257 #[cfg(feature = "std")]
258 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
259 pub fn with_default
<T
>(dispatcher
: &Dispatch
, f
: impl FnOnce() -> T
) -> T
{
260 // When this guard is dropped, the default dispatcher will be reset to the
261 // prior default. Using this (rather than simply resetting after calling
262 // `f`) ensures that we always reset to the prior dispatcher even if `f`
264 let _guard
= set_default(dispatcher
);
268 /// Sets the dispatch as the default dispatch for the duration of the lifetime
269 /// of the returned DefaultGuard
271 /// <pre class="ignore" style="white-space:normal;font:inherit;">
272 /// <strong>Note</strong>: This function required the Rust standard library.
273 /// <code>no_std</code> users should use <a href="../fn.set_global_default.html">
274 /// <code>set_global_default</code></a> instead.
277 /// [`set_global_default`]: super::set_global_default
278 #[cfg(feature = "std")]
279 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
280 #[must_use = "Dropping the guard unregisters the dispatcher."]
281 pub fn set_default(dispatcher
: &Dispatch
) -> DefaultGuard
{
282 // When this guard is dropped, the default dispatcher will be reset to the
283 // prior default. Using this ensures that we always reset to the prior
284 // dispatcher even if the thread calling this function panics.
285 State
::set_default(dispatcher
.clone())
288 /// Sets this dispatch as the global default for the duration of the entire program.
289 /// Will be used as a fallback if no thread-local dispatch has been set in a thread
290 /// (using `with_default`.)
292 /// Can only be set once; subsequent attempts to set the global default will fail.
293 /// Returns `Err` if the global default has already been set.
295 /// <div class="example-wrap" style="display:inline-block"><pre class="compile_fail" style="white-space:normal;font:inherit;">
296 /// <strong>Warning</strong>: In general, libraries should <em>not</em> call
297 /// <code>set_global_default()</code>! Doing so will cause conflicts when
298 /// executables that depend on the library try to set the default later.
301 /// [span]: super::span
302 /// [`Subscriber`]: super::subscriber::Subscriber
303 /// [`Event`]: super::event::Event
304 pub fn set_global_default(dispatcher
: Dispatch
) -> Result
<(), SetGlobalDefaultError
> {
305 // if `compare_exchange` returns Result::Ok(_), then `new` has been set and
306 // `current`—now the prior value—has been returned in the `Ok()` branch.
317 let subscriber
= match dispatcher
.subscriber
{
318 Kind
::Global(s
) => s
,
319 Kind
::Scoped(s
) => unsafe {
320 // safety: this leaks the subscriber onto the heap. the
321 // reference count will always be at least 1, because the
322 // global default will never be dropped.
326 Kind
::Global(subscriber
)
329 GLOBAL_DISPATCH
= Dispatch { subscriber }
;
331 GLOBAL_INIT
.store(INITIALIZED
, Ordering
::SeqCst
);
332 EXISTS
.store(true, Ordering
::Release
);
335 Err(SetGlobalDefaultError { _no_construct: () }
)
339 /// Returns true if a `tracing` dispatcher has ever been set.
341 /// This may be used to completely elide trace points if tracing is not in use
342 /// at all or has yet to be initialized.
345 pub fn has_been_set() -> bool
{
346 EXISTS
.load(Ordering
::Relaxed
)
349 /// Returned if setting the global dispatcher fails.
350 pub struct SetGlobalDefaultError
{
354 impl fmt
::Debug
for SetGlobalDefaultError
{
355 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
356 f
.debug_tuple("SetGlobalDefaultError")
357 .field(&Self::MESSAGE
)
362 impl fmt
::Display
for SetGlobalDefaultError
{
363 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
368 #[cfg(feature = "std")]
369 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
370 impl error
::Error
for SetGlobalDefaultError {}
372 impl SetGlobalDefaultError
{
373 const MESSAGE
: &'
static str = "a global default trace dispatcher has already been set";
376 /// Executes a closure with a reference to this thread's current [dispatcher].
378 /// Note that calls to `get_default` should not be nested; if this function is
379 /// called while inside of another `get_default`, that closure will be provided
380 /// with `Dispatch::none` rather than the previously set dispatcher.
382 /// [dispatcher]: super::dispatcher::Dispatch
383 #[cfg(feature = "std")]
384 pub fn get_default
<T
, F
>(mut f
: F
) -> T
386 F
: FnMut(&Dispatch
) -> T
,
388 if SCOPED_COUNT
.load(Ordering
::Acquire
) == 0 {
389 // fast path if no scoped dispatcher has been set; just use the global
391 return f(get_global());
396 if let Some(entered
) = state
.enter() {
397 return f(&entered
.current());
402 .unwrap_or_else(|_
| f(&NONE
))
405 /// Executes a closure with a reference to this thread's current [dispatcher].
407 /// Note that calls to `get_default` should not be nested; if this function is
408 /// called while inside of another `get_default`, that closure will be provided
409 /// with `Dispatch::none` rather than the previously set dispatcher.
411 /// [dispatcher]: super::dispatcher::Dispatch
412 #[cfg(feature = "std")]
415 pub fn get_current
<T
>(f
: impl FnOnce(&Dispatch
) -> T
) -> Option
<T
> {
416 if SCOPED_COUNT
.load(Ordering
::Acquire
) == 0 {
417 // fast path if no scoped dispatcher has been set; just use the global
419 return Some(f(get_global()));
424 let entered
= state
.enter()?
;
425 Some(f(&entered
.current()))
430 /// Executes a closure with a reference to the current [dispatcher].
432 /// [dispatcher]: super::dispatcher::Dispatch
433 #[cfg(not(feature = "std"))]
435 pub fn get_current
<T
>(f
: impl FnOnce(&Dispatch
) -> T
) -> Option
<T
> {
436 Some(f(get_global()))
439 /// Executes a closure with a reference to the current [dispatcher].
441 /// [dispatcher]: super::dispatcher::Dispatch
442 #[cfg(not(feature = "std"))]
443 pub fn get_default
<T
, F
>(mut f
: F
) -> T
445 F
: FnMut(&Dispatch
) -> T
,
451 fn get_global() -> &'
static Dispatch
{
452 if GLOBAL_INIT
.load(Ordering
::SeqCst
) != INITIALIZED
{
456 // This is safe given the invariant that setting the global dispatcher
457 // also sets `GLOBAL_INIT` to `INITIALIZED`.
462 #[cfg(feature = "std")]
463 pub(crate) struct Registrar(Kind
<Weak
<dyn Subscriber
+ Send
+ Sync
>>);
466 /// Returns a new `Dispatch` that discards events and spans.
468 pub fn none() -> Self {
470 subscriber
: Kind
::Global(&NO_SUBSCRIBER
),
474 /// Returns a `Dispatch` that forwards to the given [`Subscriber`].
476 /// [`Subscriber`]: super::subscriber::Subscriber
477 pub fn new
<S
>(subscriber
: S
) -> Self
479 S
: Subscriber
+ Send
+ Sync
+ '
static,
482 subscriber
: Kind
::Scoped(Arc
::new(subscriber
)),
484 callsite
::register_dispatch(&me
);
488 #[cfg(feature = "std")]
489 pub(crate) fn registrar(&self) -> Registrar
{
490 Registrar(self.subscriber
.downgrade())
493 /// Creates a [`WeakDispatch`] from this `Dispatch`.
495 /// A [`WeakDispatch`] is similar to a [`Dispatch`], but it does not prevent
496 /// the underlying [`Subscriber`] from being dropped. Instead, it only permits
497 /// access while other references to the `Subscriber` exist. This is equivalent
498 /// to the standard library's [`Arc::downgrade`] method, but for `Dispatch`
499 /// rather than `Arc`.
501 /// The primary use for creating a [`WeakDispatch`] is to allow a `Subscriber`
502 /// to hold a cyclical reference to itself without creating a memory leak.
503 /// See [here] for details.
505 /// [`Arc::downgrade`]: std::sync::Arc::downgrade
506 /// [here]: Subscriber#avoiding-memory-leaks
507 pub fn downgrade(&self) -> WeakDispatch
{
509 subscriber
: self.subscriber
.downgrade(),
514 pub(crate) fn subscriber(&self) -> &(dyn Subscriber
+ Send
+ Sync
) {
515 match self.subscriber
{
516 Kind
::Global(s
) => s
,
517 Kind
::Scoped(ref s
) => s
.as_ref(),
521 /// Registers a new callsite with this collector, returning whether or not
522 /// the collector is interested in being notified about the callsite.
524 /// This calls the [`register_callsite`] function on the [`Subscriber`]
525 /// that this `Dispatch` forwards to.
527 /// [`Subscriber`]: super::subscriber::Subscriber
528 /// [`register_callsite`]: super::subscriber::Subscriber::register_callsite
530 pub fn register_callsite(&self, metadata
: &'
static Metadata
<'
static>) -> subscriber
::Interest
{
531 self.subscriber().register_callsite(metadata
)
534 /// Returns the highest [verbosity level][level] that this [`Subscriber`] will
535 /// enable, or `None`, if the subscriber does not implement level-based
536 /// filtering or chooses not to implement this method.
538 /// This calls the [`max_level_hint`] function on the [`Subscriber`]
539 /// that this `Dispatch` forwards to.
541 /// [level]: super::Level
542 /// [`Subscriber`]: super::subscriber::Subscriber
543 /// [`register_callsite`]: super::subscriber::Subscriber::max_level_hint
544 // TODO(eliza): consider making this a public API?
546 pub(crate) fn max_level_hint(&self) -> Option
<LevelFilter
> {
547 self.subscriber().max_level_hint()
550 /// Record the construction of a new span, returning a new [ID] for the
551 /// span being constructed.
553 /// This calls the [`new_span`] function on the [`Subscriber`] that this
554 /// `Dispatch` forwards to.
556 /// [ID]: super::span::Id
557 /// [`Subscriber`]: super::subscriber::Subscriber
558 /// [`new_span`]: super::subscriber::Subscriber::new_span
560 pub fn new_span(&self, span
: &span
::Attributes
<'_
>) -> span
::Id
{
561 self.subscriber().new_span(span
)
564 /// Record a set of values on a span.
566 /// This calls the [`record`] function on the [`Subscriber`] that this
567 /// `Dispatch` forwards to.
569 /// [`Subscriber`]: super::subscriber::Subscriber
570 /// [`record`]: super::subscriber::Subscriber::record
572 pub fn record(&self, span
: &span
::Id
, values
: &span
::Record
<'_
>) {
573 self.subscriber().record(span
, values
)
576 /// Adds an indication that `span` follows from the span with the id
579 /// This calls the [`record_follows_from`] function on the [`Subscriber`]
580 /// that this `Dispatch` forwards to.
582 /// [`Subscriber`]: super::subscriber::Subscriber
583 /// [`record_follows_from`]: super::subscriber::Subscriber::record_follows_from
585 pub fn record_follows_from(&self, span
: &span
::Id
, follows
: &span
::Id
) {
586 self.subscriber().record_follows_from(span
, follows
)
589 /// Returns true if a span with the specified [metadata] would be
592 /// This calls the [`enabled`] function on the [`Subscriber`] that this
593 /// `Dispatch` forwards to.
595 /// [metadata]: super::metadata::Metadata
596 /// [`Subscriber`]: super::subscriber::Subscriber
597 /// [`enabled`]: super::subscriber::Subscriber::enabled
599 pub fn enabled(&self, metadata
: &Metadata
<'_
>) -> bool
{
600 self.subscriber().enabled(metadata
)
603 /// Records that an [`Event`] has occurred.
605 /// This calls the [`event`] function on the [`Subscriber`] that this
606 /// `Dispatch` forwards to.
608 /// [`Event`]: super::event::Event
609 /// [`Subscriber`]: super::subscriber::Subscriber
610 /// [`event`]: super::subscriber::Subscriber::event
612 pub fn event(&self, event
: &Event
<'_
>) {
613 let subscriber
= self.subscriber();
614 if subscriber
.event_enabled(event
) {
615 subscriber
.event(event
);
619 /// Records that a span has been can_enter.
621 /// This calls the [`enter`] function on the [`Subscriber`] that this
622 /// `Dispatch` forwards to.
624 /// [`Subscriber`]: super::subscriber::Subscriber
625 /// [`enter`]: super::subscriber::Subscriber::enter
626 pub fn enter(&self, span
: &span
::Id
) {
627 self.subscriber().enter(span
);
630 /// Records that a span has been exited.
632 /// This calls the [`exit`] function on the [`Subscriber`] that this
633 /// `Dispatch` forwards to.
635 /// [`Subscriber`]: super::subscriber::Subscriber
636 /// [`exit`]: super::subscriber::Subscriber::exit
637 pub fn exit(&self, span
: &span
::Id
) {
638 self.subscriber().exit(span
);
641 /// Notifies the subscriber that a [span ID] has been cloned.
643 /// This function must only be called with span IDs that were returned by
644 /// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
645 /// this guarantee and any other libraries implementing instrumentation APIs
648 /// This calls the [`clone_span`] function on the `Subscriber` that this
649 /// `Dispatch` forwards to.
651 /// [span ID]: super::span::Id
652 /// [`Subscriber`]: super::subscriber::Subscriber
653 /// [`clone_span`]: super::subscriber::Subscriber::clone_span
654 /// [`new_span`]: super::subscriber::Subscriber::new_span
656 pub fn clone_span(&self, id
: &span
::Id
) -> span
::Id
{
657 self.subscriber().clone_span(id
)
660 /// Notifies the subscriber that a [span ID] has been dropped.
662 /// This function must only be called with span IDs that were returned by
663 /// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
664 /// this guarantee and any other libraries implementing instrumentation APIs
667 /// This calls the [`drop_span`] function on the [`Subscriber`] that this
668 /// `Dispatch` forwards to.
670 /// <pre class="compile_fail" style="white-space:normal;font:inherit;">
671 /// <strong>Deprecated</strong>: The <a href="#method.try_close"><code>
672 /// try_close</code></a> method is functionally identical, but returns
673 /// <code>true</code> if the span is now closed. It should be used
674 /// instead of this method.
677 /// [span ID]: super::span::Id
678 /// [`Subscriber`]: super::subscriber::Subscriber
679 /// [`drop_span`]: super::subscriber::Subscriber::drop_span
680 /// [`new_span`]: super::subscriber::Subscriber::new_span
681 /// [`try_close`]: Entered::try_close()
683 #[deprecated(since = "0.1.2", note = "use `Dispatch::try_close` instead")]
684 pub fn drop_span(&self, id
: span
::Id
) {
686 self.subscriber().drop_span(id
);
689 /// Notifies the subscriber that a [span ID] has been dropped, and returns
690 /// `true` if there are now 0 IDs referring to that span.
692 /// This function must only be called with span IDs that were returned by
693 /// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
694 /// this guarantee and any other libraries implementing instrumentation APIs
697 /// This calls the [`try_close`] function on the [`Subscriber`] that this
698 /// `Dispatch` forwards to.
700 /// [span ID]: super::span::Id
701 /// [`Subscriber`]: super::subscriber::Subscriber
702 /// [`try_close`]: super::subscriber::Subscriber::try_close
703 /// [`new_span`]: super::subscriber::Subscriber::new_span
704 pub fn try_close(&self, id
: span
::Id
) -> bool
{
705 self.subscriber().try_close(id
)
708 /// Returns a type representing this subscriber's view of the current span.
710 /// This calls the [`current`] function on the `Subscriber` that this
711 /// `Dispatch` forwards to.
713 /// [`current`]: super::subscriber::Subscriber::current_span
715 pub fn current_span(&self) -> span
::Current
{
716 self.subscriber().current_span()
719 /// Returns `true` if this `Dispatch` forwards to a `Subscriber` of type
722 pub fn is
<T
: Any
>(&self) -> bool
{
723 <dyn Subscriber
>::is
::<T
>(self.subscriber())
726 /// Returns some reference to the `Subscriber` this `Dispatch` forwards to
727 /// if it is of type `T`, or `None` if it isn't.
729 pub fn downcast_ref
<T
: Any
>(&self) -> Option
<&T
> {
730 <dyn Subscriber
>::downcast_ref(self.subscriber())
734 impl Default
for Dispatch
{
735 /// Returns the current default dispatcher
736 fn default() -> Self {
737 get_default(|default| default.clone())
741 impl fmt
::Debug
for Dispatch
{
742 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
743 match self.subscriber
{
744 Kind
::Scoped(ref s
) => f
745 .debug_tuple("Dispatch::Scoped")
746 .field(&format_args
!("{:p}", s
))
749 .debug_tuple("Dispatch::Global")
750 .field(&format_args
!("{:p}", s
))
756 impl<S
> From
<S
> for Dispatch
758 S
: Subscriber
+ Send
+ Sync
+ '
static,
761 fn from(subscriber
: S
) -> Self {
762 Dispatch
::new(subscriber
)
766 // === impl WeakDispatch ===
769 /// Attempts to upgrade this `WeakDispatch` to a [`Dispatch`].
771 /// Returns `None` if the referenced `Dispatch` has already been dropped.
776 /// # use tracing_core::subscriber::NoSubscriber;
777 /// # use tracing_core::dispatcher::Dispatch;
778 /// let strong = Dispatch::new(NoSubscriber::default());
779 /// let weak = strong.downgrade();
781 /// // The strong here keeps it alive, so we can still access the object.
782 /// assert!(weak.upgrade().is_some());
784 /// drop(strong); // But not any more.
785 /// assert!(weak.upgrade().is_none());
787 pub fn upgrade(&self) -> Option
<Dispatch
> {
790 .map(|subscriber
| Dispatch { subscriber }
)
794 impl fmt
::Debug
for WeakDispatch
{
795 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
796 match self.subscriber
{
797 Kind
::Scoped(ref s
) => f
798 .debug_tuple("WeakDispatch::Scoped")
799 .field(&format_args
!("{:p}", s
))
802 .debug_tuple("WeakDispatch::Global")
803 .field(&format_args
!("{:p}", s
))
809 #[cfg(feature = "std")]
811 pub(crate) fn upgrade(&self) -> Option
<Dispatch
> {
812 self.0.upgrade
().map(|subscriber
| Dispatch { subscriber }
)
816 // ===== impl State =====
818 impl Kind
<Arc
<dyn Subscriber
+ Send
+ Sync
>> {
819 fn downgrade(&self) -> Kind
<Weak
<dyn Subscriber
+ Send
+ Sync
>> {
821 Kind
::Global(s
) => Kind
::Global(*s
),
822 Kind
::Scoped(ref s
) => Kind
::Scoped(Arc
::downgrade(s
)),
827 impl Kind
<Weak
<dyn Subscriber
+ Send
+ Sync
>> {
828 fn upgrade(&self) -> Option
<Kind
<Arc
<dyn Subscriber
+ Send
+ Sync
>>> {
830 Kind
::Global(s
) => Some(Kind
::Global(*s
)),
831 Kind
::Scoped(ref s
) => Some(Kind
::Scoped(s
.upgrade()?
)),
836 // ===== impl State =====
838 #[cfg(feature = "std")]
840 /// Replaces the current default dispatcher on this thread with the provided
843 /// Dropping the returned `ResetGuard` will reset the default dispatcher to
844 /// the previous value.
846 fn set_default(new_dispatch
: Dispatch
) -> DefaultGuard
{
847 let prior
= CURRENT_STATE
849 state
.can_enter
.set(true);
850 state
.default.replace(Some(new_dispatch
))
854 EXISTS
.store(true, Ordering
::Release
);
855 SCOPED_COUNT
.fetch_add(1, Ordering
::Release
);
860 fn enter(&self) -> Option
<Entered
<'_
>> {
861 if self.can_enter
.replace(false) {
869 // ===== impl Entered =====
871 #[cfg(feature = "std")]
872 impl<'a
> Entered
<'a
> {
874 fn current(&self) -> Ref
<'a
, Dispatch
> {
875 let default = self.0.default.borrow();
876 Ref
::map(default, |default| match default {
877 Some(default) => default,
878 None
=> get_global(),
883 #[cfg(feature = "std")]
884 impl<'a
> Drop
for Entered
<'a
> {
887 self.0.can_enter
.set(true);
891 // ===== impl DefaultGuard =====
893 #[cfg(feature = "std")]
894 impl Drop
for DefaultGuard
{
897 // Replace the dispatcher and then drop the old one outside
898 // of the thread-local context. Dropping the dispatch may
899 // lead to the drop of a subscriber which, in the process,
900 // could then also attempt to access the same thread local
901 // state -- causing a clash.
902 let prev
= CURRENT_STATE
.try_with(|state
| state
.default.replace(self.0.take()));
903 SCOPED_COUNT
.fetch_sub(1, Ordering
::Release
);
911 #[cfg(feature = "std")]
912 use crate::stdlib
::sync
::atomic
::{AtomicUsize, Ordering}
;
915 metadata
::{Kind, Level, Metadata}
,
916 subscriber
::Interest
,
921 let dispatcher
= Dispatch
::new(NoSubscriber
::default());
922 assert
!(dispatcher
.is
::<NoSubscriber
>());
926 fn dispatch_downcasts() {
927 let dispatcher
= Dispatch
::new(NoSubscriber
::default());
928 assert
!(dispatcher
.downcast_ref
::<NoSubscriber
>().is_some());
932 static TEST_CALLSITE
: TestCallsite
= TestCallsite
;
933 static TEST_META
: Metadata
<'
static> = metadata
! {
935 target
: module_path
!(),
938 callsite
: &TEST_CALLSITE
,
942 impl Callsite
for TestCallsite
{
943 fn set_interest(&self, _
: Interest
) {}
944 fn metadata(&self) -> &Metadata
<'_
> {
950 #[cfg(feature = "std")]
951 fn events_dont_infinite_loop() {
952 // This test ensures that an event triggered within a subscriber
953 // won't cause an infinite loop of events.
954 struct TestSubscriber
;
955 impl Subscriber
for TestSubscriber
{
956 fn enabled(&self, _
: &Metadata
<'_
>) -> bool
{
960 fn new_span(&self, _
: &span
::Attributes
<'_
>) -> span
::Id
{
961 span
::Id
::from_u64(0xAAAA)
964 fn record(&self, _
: &span
::Id
, _
: &span
::Record
<'_
>) {}
966 fn record_follows_from(&self, _
: &span
::Id
, _
: &span
::Id
) {}
968 fn event(&self, _
: &Event
<'_
>) {
969 static EVENTS
: AtomicUsize
= AtomicUsize
::new(0);
971 EVENTS
.fetch_add(1, Ordering
::Relaxed
),
973 "event method called twice!"
975 Event
::dispatch(&TEST_META
, &TEST_META
.fields().value_set(&[]))
978 fn enter(&self, _
: &span
::Id
) {}
980 fn exit(&self, _
: &span
::Id
) {}
983 with_default(&Dispatch
::new(TestSubscriber
), || {
984 Event
::dispatch(&TEST_META
, &TEST_META
.fields().value_set(&[]))
989 #[cfg(feature = "std")]
990 fn spans_dont_infinite_loop() {
991 // This test ensures that a span created within a subscriber
992 // won't cause an infinite loop of new spans.
995 get_default(|current
| {
996 current
.new_span(&span
::Attributes
::new(
998 &TEST_META
.fields().value_set(&[]),
1003 struct TestSubscriber
;
1004 impl Subscriber
for TestSubscriber
{
1005 fn enabled(&self, _
: &Metadata
<'_
>) -> bool
{
1009 fn new_span(&self, _
: &span
::Attributes
<'_
>) -> span
::Id
{
1010 static NEW_SPANS
: AtomicUsize
= AtomicUsize
::new(0);
1012 NEW_SPANS
.fetch_add(1, Ordering
::Relaxed
),
1014 "new_span method called twice!"
1017 span
::Id
::from_u64(0xAAAA)
1020 fn record(&self, _
: &span
::Id
, _
: &span
::Record
<'_
>) {}
1022 fn record_follows_from(&self, _
: &span
::Id
, _
: &span
::Id
) {}
1024 fn event(&self, _
: &Event
<'_
>) {}
1026 fn enter(&self, _
: &span
::Id
) {}
1028 fn exit(&self, _
: &span
::Id
) {}
1031 with_default(&Dispatch
::new(TestSubscriber
), mk_span
)
1035 fn default_no_subscriber() {
1036 let default_dispatcher
= Dispatch
::default();
1037 assert
!(default_dispatcher
.is
::<NoSubscriber
>());
1040 #[cfg(feature = "std")]
1042 fn default_dispatch() {
1043 struct TestSubscriber
;
1044 impl Subscriber
for TestSubscriber
{
1045 fn enabled(&self, _
: &Metadata
<'_
>) -> bool
{
1049 fn new_span(&self, _
: &span
::Attributes
<'_
>) -> span
::Id
{
1050 span
::Id
::from_u64(0xAAAA)
1053 fn record(&self, _
: &span
::Id
, _
: &span
::Record
<'_
>) {}
1055 fn record_follows_from(&self, _
: &span
::Id
, _
: &span
::Id
) {}
1057 fn event(&self, _
: &Event
<'_
>) {}
1059 fn enter(&self, _
: &span
::Id
) {}
1061 fn exit(&self, _
: &span
::Id
) {}
1063 let guard
= set_default(&Dispatch
::new(TestSubscriber
));
1064 let default_dispatcher
= Dispatch
::default();
1065 assert
!(default_dispatcher
.is
::<TestSubscriber
>());
1068 let default_dispatcher
= Dispatch
::default();
1069 assert
!(default_dispatcher
.is
::<NoSubscriber
>());