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