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