tokio_trace_core/
dispatcher.rs

1//! Dispatches trace events to `Subscriber`s.c
2use {
3    callsite, span,
4    subscriber::{self, Subscriber},
5    Event, Metadata,
6};
7
8use std::{
9    any::Any,
10    cell::{Cell, RefCell},
11    fmt,
12    sync::{Arc, Weak},
13};
14
15/// `Dispatch` trace data to a [`Subscriber`].
16///
17/// [`Subscriber`]: ../subscriber/trait.Subscriber.html
18#[derive(Clone)]
19pub struct Dispatch {
20    subscriber: Arc<Subscriber + Send + Sync>,
21}
22
23thread_local! {
24    static CURRENT_STATE: State = State {
25        default: RefCell::new(Dispatch::none()),
26        can_enter: Cell::new(true),
27    };
28}
29
30/// The dispatch state of a thread.
31struct State {
32    /// This thread's current default dispatcher.
33    default: RefCell<Dispatch>,
34    /// Whether or not we can currently begin dispatching a trace event.
35    ///
36    /// This is set to `false` when functions such as `enter`, `exit`, `event`,
37    /// and `new_span` are called on this thread's default dispatcher, to
38    /// prevent further trace events triggered inside those functions from
39    /// creating an infinite recursion. When we finish handling a dispatch, this
40    /// is set back to `true`.
41    can_enter: Cell<bool>,
42}
43
44/// A guard that resets the current default dispatcher to the prior
45/// default dispatcher when dropped.
46struct ResetGuard(Option<Dispatch>);
47
48/// Sets this dispatch as the default for the duration of a closure.
49///
50/// The default dispatcher is used when creating a new [span] or
51/// [`Event`], _if no span is currently executing_. If a span is currently
52/// executing, new spans or events are dispatched to the subscriber that
53/// tagged that span, instead.
54///
55/// [span]: ../span/index.html
56/// [`Subscriber`]: ../subscriber/trait.Subscriber.html
57/// [`Event`]: ../event/struct.Event.html
58pub fn with_default<T>(dispatcher: &Dispatch, f: impl FnOnce() -> T) -> T {
59    // When this guard is dropped, the default dispatcher will be reset to the
60    // prior default. Using this (rather than simply resetting after calling
61    // `f`) ensures that we always reset to the prior dispatcher even if `f`
62    // panics.
63    let _guard = State::set_default(dispatcher.clone());
64    f()
65}
66/// Executes a closure with a reference to this thread's current [dispatcher].
67///
68/// Note that calls to `get_default` should not be nested; if this function is
69/// called while inside of another `get_default`, that closure will be provided
70/// with `Dispatch::none` rather than the previously set dispatcher.
71///
72/// [dispatcher]: ../dispatcher/struct.Dispatch.html
73pub fn get_default<T, F>(mut f: F) -> T
74where
75    F: FnMut(&Dispatch) -> T,
76{
77    // While this guard is active, additional calls to subscriber functions on
78    // the default dispatcher will not be able to access the dispatch context.
79    // Dropping the guard will allow the dispatch context to be re-entered.
80    struct Entered<'a>(&'a Cell<bool>);
81    impl<'a> Drop for Entered<'a> {
82        #[inline]
83        fn drop(&mut self) {
84            self.0.set(true);
85        }
86    }
87
88    CURRENT_STATE
89        .try_with(|state| {
90            if state.can_enter.replace(false) {
91                let _guard = Entered(&state.can_enter);
92                f(&state.default.borrow())
93            } else {
94                f(&Dispatch::none())
95            }
96        })
97        .unwrap_or_else(|_| f(&Dispatch::none()))
98}
99
100pub(crate) struct Registrar(Weak<Subscriber + Send + Sync>);
101
102impl Dispatch {
103    /// Returns a new `Dispatch` that discards events and spans.
104    #[inline]
105    pub fn none() -> Self {
106        Dispatch {
107            subscriber: Arc::new(NoSubscriber),
108        }
109    }
110
111    /// Returns a `Dispatch` that forwards to the given [`Subscriber`].
112    ///
113    /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
114    pub fn new<S>(subscriber: S) -> Self
115    where
116        S: Subscriber + Send + Sync + 'static,
117    {
118        let me = Dispatch {
119            subscriber: Arc::new(subscriber),
120        };
121        callsite::register_dispatch(&me);
122        me
123    }
124
125    pub(crate) fn registrar(&self) -> Registrar {
126        Registrar(Arc::downgrade(&self.subscriber))
127    }
128
129    /// Registers a new callsite with this subscriber, returning whether or not
130    /// the subscriber is interested in being notified about the callsite.
131    ///
132    /// This calls the [`register_callsite`] function on the [`Subscriber`]
133    /// that this `Dispatch` forwards to.
134    ///
135    /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
136    /// [`register_callsite`]: ../subscriber/trait.Subscriber.html#method.register_callsite
137    #[inline]
138    pub fn register_callsite(&self, metadata: &Metadata) -> subscriber::Interest {
139        self.subscriber.register_callsite(metadata)
140    }
141
142    /// Record the construction of a new span, returning a new [ID] for the
143    /// span being constructed.
144    ///
145    /// This calls the [`new_span`] function on the [`Subscriber`] that this
146    /// `Dispatch` forwards to.
147    ///
148    /// [ID]: ../span/struct.Id.html
149    /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
150    /// [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span
151    #[inline]
152    pub fn new_span(&self, span: &span::Attributes) -> span::Id {
153        self.subscriber.new_span(span)
154    }
155
156    /// Record a set of values on a span.
157    ///
158    /// This calls the [`record`] function on the [`Subscriber`] that this
159    /// `Dispatch` forwards to.
160    ///
161    /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
162    /// [`record`]: ../subscriber/trait.Subscriber.html#method.record
163    #[inline]
164    pub fn record(&self, span: &span::Id, values: &span::Record) {
165        self.subscriber.record(span, values)
166    }
167
168    /// Adds an indication that `span` follows from the span with the id
169    /// `follows`.
170    ///
171    /// This calls the [`record_follows_from`] function on the [`Subscriber`]
172    /// that this `Dispatch` forwards to.
173    ///
174    /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
175    /// [`record_follows_from`]: ../subscriber/trait.Subscriber.html#method.record_follows_from
176    #[inline]
177    pub fn record_follows_from(&self, span: &span::Id, follows: &span::Id) {
178        self.subscriber.record_follows_from(span, follows)
179    }
180
181    /// Returns true if a span with the specified [metadata] would be
182    /// recorded.
183    ///
184    /// This calls the [`enabled`] function on the [`Subscriber`] that this
185    /// `Dispatch` forwards to.
186    ///
187    /// [metadata]: ../metadata/struct.Metadata.html
188    /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
189    /// [`enabled`]: ../subscriber/trait.Subscriber.html#method.enabled
190    #[inline]
191    pub fn enabled(&self, metadata: &Metadata) -> bool {
192        self.subscriber.enabled(metadata)
193    }
194
195    /// Records that an [`Event`] has occurred.
196    ///
197    /// This calls the [`event`] function on the [`Subscriber`] that this
198    /// `Dispatch` forwards to.
199    ///
200    /// [`Event`]: ../event/struct.Event.html
201    /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
202    /// [`event`]: ../subscriber/trait.Subscriber.html#method.event
203    #[inline]
204    pub fn event(&self, event: &Event) {
205        self.subscriber.event(event)
206    }
207
208    /// Records that a span has been can_enter.
209    ///
210    /// This calls the [`enter`] function on the [`Subscriber`] that this
211    /// `Dispatch` forwards to.
212    ///
213    /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
214    /// [`event`]: ../subscriber/trait.Subscriber.html#method.event
215    #[inline]
216    pub fn enter(&self, span: &span::Id) {
217        self.subscriber.enter(span);
218    }
219
220    /// Records that a span has been exited.
221    ///
222    /// This calls the [`exit`](::Subscriber::exit) function on the `Subscriber`
223    /// that this `Dispatch` forwards to.
224    #[inline]
225    pub fn exit(&self, span: &span::Id) {
226        self.subscriber.exit(span);
227    }
228
229    /// Notifies the subscriber that a [span ID] has been cloned.
230    ///
231    /// This function is guaranteed to only be called with span IDs that were
232    /// returned by this `Dispatch`'s [`new_span`] function.
233    ///
234    /// This calls the [`clone_span`] function on the `Subscriber` that this
235    /// `Dispatch` forwards to.
236    ///
237    /// [span ID]: ../span/struct.Id.html
238    /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
239    /// [`clone_span`]: ../subscriber/trait.Subscriber.html#method.clone_span
240    /// [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span
241    #[inline]
242    pub fn clone_span(&self, id: &span::Id) -> span::Id {
243        self.subscriber.clone_span(&id)
244    }
245
246    /// Notifies the subscriber that a [span ID] has been dropped.
247    ///
248    /// This function is guaranteed to only be called with span IDs that were
249    /// returned by this `Dispatch`'s [`new_span`] function.
250    ///
251    /// This calls the [`drop_span`]  function on the [`Subscriber`] that this
252    ///  `Dispatch` forwards to.
253    ///
254    /// [span ID]: ../span/struct.Id.html
255    /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
256    /// [`clone_span`]: ../subscriber/trait.Subscriber.html#method.clone_span
257    /// [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span
258    #[inline]
259    pub fn drop_span(&self, id: span::Id) {
260        self.subscriber.drop_span(id)
261    }
262
263    /// Returns `true` if this `Dispatch` forwards to a `Subscriber` of type
264    /// `T`.
265    #[inline]
266    pub fn is<T: Any>(&self) -> bool {
267        Subscriber::is::<T>(&*self.subscriber)
268    }
269
270    /// Returns some reference to the `Subscriber` this `Dispatch` forwards to
271    /// if it is of type `T`, or `None` if it isn't.
272    #[inline]
273    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
274        Subscriber::downcast_ref(&*self.subscriber)
275    }
276}
277
278impl fmt::Debug for Dispatch {
279    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
280        f.pad("Dispatch(...)")
281    }
282}
283
284impl<S> From<S> for Dispatch
285where
286    S: Subscriber + Send + Sync + 'static,
287{
288    #[inline]
289    fn from(subscriber: S) -> Self {
290        Dispatch::new(subscriber)
291    }
292}
293
294struct NoSubscriber;
295impl Subscriber for NoSubscriber {
296    #[inline]
297    fn register_callsite(&self, _: &Metadata) -> subscriber::Interest {
298        subscriber::Interest::never()
299    }
300
301    fn new_span(&self, _: &span::Attributes) -> span::Id {
302        span::Id::from_u64(0xDEAD)
303    }
304
305    fn event(&self, _event: &Event) {}
306
307    fn record(&self, _span: &span::Id, _values: &span::Record) {}
308
309    fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
310
311    #[inline]
312    fn enabled(&self, _metadata: &Metadata) -> bool {
313        false
314    }
315
316    fn enter(&self, _span: &span::Id) {}
317    fn exit(&self, _span: &span::Id) {}
318}
319
320impl Registrar {
321    pub(crate) fn try_register(&self, metadata: &Metadata) -> Option<subscriber::Interest> {
322        self.0.upgrade().map(|s| s.register_callsite(metadata))
323    }
324
325    pub(crate) fn is_alive(&self) -> bool {
326        self.0.upgrade().is_some()
327    }
328}
329
330// ===== impl State =====
331
332impl State {
333    /// Replaces the current default dispatcher on this thread with the provided
334    /// dispatcher.Any
335    ///
336    /// Dropping the returned `ResetGuard` will reset the default dispatcher to
337    /// the previous value.
338    #[inline]
339    fn set_default(new_dispatch: Dispatch) -> ResetGuard {
340        let prior = CURRENT_STATE
341            .try_with(|state| {
342                state.can_enter.set(true);
343                state.default.replace(new_dispatch)
344            })
345            .ok();
346        ResetGuard(prior)
347    }
348}
349
350// ===== impl ResetGuard =====
351
352impl Drop for ResetGuard {
353    #[inline]
354    fn drop(&mut self) {
355        if let Some(dispatch) = self.0.take() {
356            let _ = CURRENT_STATE.try_with(|state| {
357                *state.default.borrow_mut() = dispatch;
358            });
359        }
360    }
361}
362
363#[cfg(test)]
364mod test {
365    use super::*;
366    use std::sync::atomic::{AtomicUsize, Ordering};
367    use {
368        callsite::Callsite,
369        metadata::{Kind, Level, Metadata},
370        span,
371        subscriber::{Interest, Subscriber},
372        Event,
373    };
374
375    #[test]
376    fn dispatch_is() {
377        let dispatcher = Dispatch::new(NoSubscriber);
378        assert!(dispatcher.is::<NoSubscriber>());
379    }
380
381    #[test]
382    fn dispatch_downcasts() {
383        let dispatcher = Dispatch::new(NoSubscriber);
384        assert!(dispatcher.downcast_ref::<NoSubscriber>().is_some());
385    }
386
387    struct TestCallsite;
388    static TEST_CALLSITE: TestCallsite = TestCallsite;
389    static TEST_META: Metadata<'static> = metadata! {
390        name: "test",
391        target: module_path!(),
392        level: Level::DEBUG,
393        fields: &[],
394        callsite: &TEST_CALLSITE,
395        kind: Kind::EVENT
396    };
397
398    impl Callsite for TestCallsite {
399        fn set_interest(&self, _: Interest) {}
400        fn metadata(&self) -> &Metadata {
401            &TEST_META
402        }
403    }
404
405    #[test]
406    fn events_dont_infinite_loop() {
407        // This test ensures that an event triggered within a subscriber
408        // won't cause an infinite loop of events.
409        struct TestSubscriber;
410        impl Subscriber for TestSubscriber {
411            fn enabled(&self, _: &Metadata) -> bool {
412                true
413            }
414
415            fn new_span(&self, _: &span::Attributes) -> span::Id {
416                span::Id::from_u64(0xAAAA)
417            }
418
419            fn record(&self, _: &span::Id, _: &span::Record) {}
420
421            fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
422
423            fn event(&self, _: &Event) {
424                static EVENTS: AtomicUsize = AtomicUsize::new(0);
425                assert_eq!(
426                    EVENTS.fetch_add(1, Ordering::Relaxed),
427                    0,
428                    "event method called twice!"
429                );
430                Event::dispatch(&TEST_META, &TEST_META.fields().value_set(&[]))
431            }
432
433            fn enter(&self, _: &span::Id) {}
434
435            fn exit(&self, _: &span::Id) {}
436        }
437
438        with_default(&Dispatch::new(TestSubscriber), || {
439            Event::dispatch(&TEST_META, &TEST_META.fields().value_set(&[]))
440        })
441    }
442
443    #[test]
444    fn spans_dont_infinite_loop() {
445        // This test ensures that a span created within a subscriber
446        // won't cause an infinite loop of new spans.
447
448        fn mk_span() {
449            get_default(|current| {
450                current.new_span(&span::Attributes::new(
451                    &TEST_META,
452                    &TEST_META.fields().value_set(&[]),
453                ))
454            });
455        }
456
457        struct TestSubscriber;
458        impl Subscriber for TestSubscriber {
459            fn enabled(&self, _: &Metadata) -> bool {
460                true
461            }
462
463            fn new_span(&self, _: &span::Attributes) -> span::Id {
464                static NEW_SPANS: AtomicUsize = AtomicUsize::new(0);
465                assert_eq!(
466                    NEW_SPANS.fetch_add(1, Ordering::Relaxed),
467                    0,
468                    "new_span method called twice!"
469                );
470                mk_span();
471                span::Id::from_u64(0xAAAA)
472            }
473
474            fn record(&self, _: &span::Id, _: &span::Record) {}
475
476            fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
477
478            fn event(&self, _: &Event) {}
479
480            fn enter(&self, _: &span::Id) {}
481
482            fn exit(&self, _: &span::Id) {}
483        }
484
485        with_default(&Dispatch::new(TestSubscriber), || mk_span())
486    }
487}