tokio_trace_core/
subscriber.rs

1//! Subscribers collect and record trace data.
2use {span, Event, Metadata};
3
4use std::{
5    any::{Any, TypeId},
6    ptr,
7};
8
9/// Trait representing the functions required to collect trace data.
10///
11/// Crates that provide implementations of methods for collecting or recording
12/// trace data should implement the `Subscriber` interface. This trait is
13/// intended to represent fundamental primitives for collecting trace events and
14/// spans — other libraries may offer utility functions and types to make
15/// subscriber implementations more modular or improve the ergonomics of writing
16/// subscribers.
17///
18/// A subscriber is responsible for the following:
19/// - Registering new spans as they are created, and providing them with span
20///   IDs. Implicitly, this means the subscriber may determine the strategy for
21///   determining span equality.
22/// - Recording the attachment of field values and follows-from annotations to
23///   spans.
24/// - Filtering spans and events, and determining when those filters must be
25///   invalidated.
26/// - Observing spans as they are entered, exited, and closed, and events as
27///   they occur.
28///
29/// When a span is entered or exited, the subscriber is provided only with the
30/// [ID] with which it tagged that span when it was created. This means
31/// that it is up to the subscriber to determine whether and how span _data_ —
32/// the fields and metadata describing the span — should be stored. The
33/// [`new_span`] function is called when a new span is created, and at that
34/// point, the subscriber _may_ choose to store the associated data if it will
35/// be referenced again. However, if the data has already been recorded and will
36/// not be needed by the implementations of `enter` and `exit`, the subscriber
37/// may freely discard that data without allocating space to store it.
38///
39/// [ID]: ../span/struct.Id.html
40/// [`new_span`]: trait.Subscriber.html#method.new_span
41pub trait Subscriber: 'static {
42    // === Span registry methods ==============================================
43
44    /// Registers a new callsite with this subscriber, returning whether or not
45    /// the subscriber is interested in being notified about the callsite.
46    ///
47    /// By default, this function assumes that the subscriber's [filter]
48    /// represents an unchanging view of its interest in the callsite. However,
49    /// if this is not the case, subscribers may override this function to
50    /// indicate different interests, or to implement behaviour that should run
51    /// once for every callsite.
52    ///
53    /// This function is guaranteed to be called at least once per callsite on
54    /// every active subscriber. The subscriber may store the keys to fields it
55    /// cares about in order to reduce the cost of accessing fields by name,
56    /// preallocate storage for that callsite, or perform any other actions it
57    /// wishes to perform once for each callsite.
58    ///
59    /// The subscriber should then return an [`Interest`], indicating
60    /// whether it is interested in being notified about that callsite in the
61    /// future. This may be `Always` indicating that the subscriber always
62    /// wishes to be notified about the callsite, and its filter need not be
63    /// re-evaluated; `Sometimes`, indicating that the subscriber may sometimes
64    /// care about the callsite but not always (such as when sampling), or
65    /// `Never`, indicating that the subscriber never wishes to be notified about
66    /// that callsite. If all active subscribers return `Never`, a callsite will
67    /// never be enabled unless a new subscriber expresses interest in it.
68    ///
69    /// `Subscriber`s which require their filters to be run every time an event
70    /// occurs or a span is entered/exited should return `Interest::sometimes`.
71    /// If a subscriber returns `Interest::sometimes`, then its' [`enabled`] method
72    /// will be called every time an event or span is created from that callsite.
73    ///
74    /// For example, suppose a sampling subscriber is implemented by
75    /// incrementing a counter every time `enabled` is called and only returning
76    /// `true` when the counter is divisible by a specified sampling rate. If
77    /// that subscriber returns `Interest::always` from `register_callsite`, then
78    /// the filter will not be re-evaluated once it has been applied to a given
79    /// set of metadata. Thus, the counter will not be incremented, and the span
80    /// or event that correspands to the metadata will never be `enabled`.
81    ///
82    /// `Subscriber`s that need to change their filters occasionally should call
83    /// [`rebuild_interest_cache`] to re-evaluate `register_callsite` for all
84    /// callsites.
85    ///
86    /// Similarly, if a `Subscriber` has a filtering strategy that can be
87    /// changed dynamically at runtime, it would need to re-evaluate that filter
88    /// if the cached results have changed.
89    ///
90    /// A subscriber which manages fanout to multiple other subscribers
91    /// should proxy this decision to all of its child subscribers,
92    /// returning `Interest::never` only if _all_ such children return
93    /// `Interest::never`. If the set of subscribers to which spans are
94    /// broadcast may change dynamically, the subscriber should also never
95    /// return `Interest::Never`, as a new subscriber may be added that _is_
96    /// interested.
97    ///
98    /// # Notes
99    /// This function may be called again when a new subscriber is created or
100    /// when the registry is invalidated.
101    ///
102    /// If a subscriber returns `Interest::never` for a particular callsite, it
103    /// _may_ still see spans and events originating from that callsite, if
104    /// another subscriber expressed interest in it.
105    ///
106    /// [filter]: #method.enabled
107    /// [metadata]: ../metadata/struct.Metadata.html
108    /// [`Interest`]: struct.Interest.html
109    /// [`enabled`]: #method.enabled
110    /// [`rebuild_interest_cache`]: ../callsite/fn.rebuild_interest_cache.html
111    fn register_callsite(&self, metadata: &Metadata) -> Interest {
112        match self.enabled(metadata) {
113            true => Interest::always(),
114            false => Interest::never(),
115        }
116    }
117
118    /// Returns true if a span or event with the specified [metadata] would be
119    /// recorded.
120    ///
121    /// By default, it is assumed that this filter needs only be evaluated once
122    /// for each callsite, so it is called by [`register_callsite`] when each
123    /// callsite is registered. The result is used to determine if the subscriber
124    /// is always [interested] or never interested in that callsite. This is intended
125    /// primarily as an optimization, so that expensive filters (such as those
126    /// involving string search, et cetera) need not be re-evaluated.
127    ///
128    /// However, if the subscriber's interest in a particular span or event may
129    /// change, or depends on contexts only determined dynamically at runtime,
130    /// then the `register_callsite` method should be overridden to return
131    /// [`Interest::sometimes`]. In that case, this function will be called every
132    /// time that span or event occurs.
133    ///
134    /// [metadata]: ../metadata/struct.Metadata.html
135    /// [interested]: struct.Interest.html
136    /// [`Interest::sometimes`]: struct.Interest.html#method.sometimes
137    /// [`register_callsite`]: #method.register_callsite
138    fn enabled(&self, metadata: &Metadata) -> bool;
139
140    /// Visit the construction of a new span, returning a new [span ID] for the
141    /// span being constructed.
142    ///
143    /// The provided [`Attributes`] contains any field values that were provided
144    /// when the span was created. The subscriber may pass a [visitor] to the
145    /// `Attributes`' [`record` method] to record these values.
146    ///
147    /// IDs are used to uniquely identify spans and events within the context of a
148    /// subscriber, so span equality will be based on the returned ID. Thus, if
149    /// the subscriber wishes for all spans with the same metadata to be
150    /// considered equal, it should return the same ID every time it is given a
151    /// particular set of metadata. Similarly, if it wishes for two separate
152    /// instances of a span with the same metadata to *not* be equal, it should
153    /// return a distinct ID every time this function is called, regardless of
154    /// the metadata.
155    ///
156    /// Note that the subscriber is free to assign span IDs based on whatever
157    /// scheme it sees fit. Any guarantees about uniqueness, ordering, or ID
158    /// reuse are left up to the subscriber implementation to determine.
159    ///
160    /// [span ID]: ../span/struct.Id.html
161    /// [`Attributes`]: ../span/struct.Attributes.html
162    /// [visitor]: ../field/trait.Visit.html
163    /// [`record` method]: ../span/struct.Attributes.html#method.record
164    fn new_span(&self, span: &span::Attributes) -> span::Id;
165
166    // === Notification methods ===============================================
167
168    /// Record a set of values on a span.
169    ///
170    /// This method will be invoked when value is recorded on a span.
171    /// Recording multiple values for the same field is possible,
172    /// but the actual behaviour is defined by the subscriber implementation.
173    ///
174    /// Keep in mind that a span might not provide a value
175    /// for each field it declares.
176    ///
177    /// The subscriber is expected to provide a [visitor] to the `Record`'s
178    /// [`record` method] in order to record the added values.
179    ///
180    /// # Example
181    ///  "foo = 3" will be recorded when [`record`] is called on the
182    /// `Attributes` passed to `new_span`.
183    /// Since values are not provided for the `bar` and `baz` fields,
184    /// the span's `Metadata` will indicate that it _has_ those fields,
185    /// but values for them won't be recorded at this time.
186    ///
187    /// ```rust,ignore
188    /// #[macro_use]
189    /// extern crate tokio_trace;
190    ///
191    /// let mut span = span!("my_span", foo = 3, bar, baz);
192    ///
193    /// // `Subscriber::record` will be called with a `Record`
194    /// // containing "bar = false"
195    /// span.record("bar", &false);
196    ///
197    /// // `Subscriber::record` will be called with a `Record`
198    /// // containing "baz = "a string""
199    /// span.record("baz", &"a string");
200    /// ```
201    ///
202    /// [visitor]: ../field/trait.Visit.html
203    /// [`record`]: ../span/struct.Attributes.html#method.record
204    /// [`record` method]: ../span/struct.Record.html#method.record
205    fn record(&self, span: &span::Id, values: &span::Record);
206
207    /// Adds an indication that `span` follows from the span with the id
208    /// `follows`.
209    ///
210    /// This relationship differs somewhat from the parent-child relationship: a
211    /// span may have any number of prior spans, rather than a single one; and
212    /// spans are not considered to be executing _inside_ of the spans they
213    /// follow from. This means that a span may close even if subsequent spans
214    /// that follow from it are still open, and time spent inside of a
215    /// subsequent span should not be included in the time its precedents were
216    /// executing. This is used to model causal relationships such as when a
217    /// single future spawns several related background tasks, et cetera.
218    ///
219    /// If the subscriber has spans corresponding to the given IDs, it should
220    /// record this relationship in whatever way it deems necessary. Otherwise,
221    /// if one or both of the given span IDs do not correspond to spans that the
222    /// subscriber knows about, or if a cyclical relationship would be created
223    /// (i.e., some span _a_ which proceeds some other span _b_ may not also
224    /// follow from _b_), it may silently do nothing.
225    fn record_follows_from(&self, span: &span::Id, follows: &span::Id);
226
227    /// Records that an [`Event`] has occurred.
228    ///
229    /// This method will be invoked when an Event is constructed by
230    /// the `Event`'s [`dispatch` method]. For example, this happens internally
231    /// when an event macro from `tokio-trace` is called.
232    ///
233    /// The key difference between this method and `record` is that `record` is
234    /// called when a value is recorded for a field defined by a span,
235    /// while `event` is called when a new event occurs.
236    ///
237    /// The provided `Event` struct contains any field values attached to the
238    /// event. The subscriber may pass a [visitor] to the `Event`'s
239    /// [`record` method] to record these values.
240    ///
241    /// [`Event`]: ../event/struct.Event.html
242    /// [visitor]: ../field/trait.Visit.html
243    /// [`record` method]: ../event/struct.Event.html#method.record
244    /// [`dispatch` method]: ../event/struct.Event.html#method.dispatch
245    fn event(&self, event: &Event);
246
247    /// Records that a span has been entered.
248    ///
249    /// When entering a span, this method is called to notify the subscriber
250    /// that the span has been entered. The subscriber is provided with the
251    /// [span ID] of the entered span, and should update any internal state
252    /// tracking the current span accordingly.
253    ///
254    /// [span ID]: ../span/struct.Id.html
255    fn enter(&self, span: &span::Id);
256
257    /// Records that a span has been exited.
258    ///
259    /// When entering a span, this method is called to notify the subscriber
260    /// that the span has been exited. The subscriber is provided with the
261    /// [span ID] of the exited span, and should update any internal state
262    /// tracking the current span accordingly.
263    ///
264    /// Exiting a span does not imply that the span will not be re-entered.
265    ///
266    /// [span ID]: ../span/struct.Id.html
267    fn exit(&self, span: &span::Id);
268
269    /// Notifies the subscriber that a [span ID] has been cloned.
270    ///
271    /// This function is guaranteed to only be called with span IDs that were
272    /// returned by this subscriber's `new_span` function.
273    ///
274    /// Note that the default implementation of this function this is just the
275    /// identity function, passing through the identifier. However, it can be
276    /// used in conjunction with [`drop_span`] to track the number of handles
277    /// capable of `enter`ing a span. When all the handles have been dropped
278    /// (i.e., `drop_span` has been called one more time than `clone_span` for a
279    /// given ID), the subscriber may assume that the span will not be entered
280    /// again. It is then free to deallocate storage for data associated with
281    /// that span, write data from that span to IO, and so on.
282    ///
283    /// For more unsafe situations, however, if `id` is itself a pointer of some
284    /// kind this can be used as a hook to "clone" the pointer, depending on
285    /// what that means for the specified pointer.
286    ///
287    /// [span ID]: ../span/struct.Id.html
288    /// [`drop_span`]: trait.Subscriber.html#method.drop_span
289    fn clone_span(&self, id: &span::Id) -> span::Id {
290        id.clone()
291    }
292
293    /// Notifies the subscriber that a [span ID] has been dropped.
294    ///
295    /// This function is guaranteed to only be called with span IDs that were
296    /// returned by this subscriber's `new_span` function.
297    ///
298    /// It's guaranteed that if this function has been called once more than the
299    /// number of times `clone_span` was called with the same `id`, then no more
300    /// spans using that `id` exist. This means that it can be used in
301    /// conjunction with [`clone_span`] to track the number of handles
302    /// capable of `enter`ing a span. When all the handles have been dropped
303    /// (i.e., `drop_span` has been called one more time than `clone_span` for a
304    /// given ID), the subscriber may assume that the span will not be entered
305    /// again. It is then free to deallocate storage for data associated with
306    /// that span, write data from that span to IO, and so on.
307    ///
308    /// **Note**: since this function is called when spans are dropped,
309    /// implementations should ensure that they are unwind-safe. Panicking from
310    /// inside of a `drop_span` function may cause a double panic, if the span
311    /// was dropped due to a thread unwinding.
312    ///
313    /// [span ID]: ../span/struct.Id.html
314    /// [`clone_span`]: trait.Subscriber.html#method.clone_span
315    fn drop_span(&self, id: span::Id) {
316        let _ = id;
317    }
318
319    // === Downcasting methods ================================================
320
321    /// If `self` is the same type as the provided `TypeId`, returns an untyped
322    /// `*const` pointer to that type. Otherwise, returns `None`.
323    ///
324    /// If you wish to downcast a `Subscriber`, it is strongly advised to use
325    /// the safe API provided by [`downcast_ref`] instead.
326    ///
327    /// This API is required for `downcast_raw` to be a trait method; a method
328    /// signature like [`downcast_ref`] (with a generic type parameter) is not
329    /// object-safe, and thus cannot be a trait method for `Subscriber`. This
330    /// means that if we only exposed `downcast_ref`, `Subscriber`
331    /// implementations could not override the downcasting behavior
332    ///
333    /// This method may be overridden by "fan out" or "chained" subscriber
334    /// implementations which consist of multiple composed types. Such
335    /// subscribers might allow `downcast_raw` by returning references to those
336    /// component if they contain components with the given `TypeId`.
337    ///
338    /// # Safety
339    ///
340    /// The [`downcast_ref`] method expects that the pointer returned by
341    /// `downcast_raw` is non-null and points to a valid instance of the type
342    /// with the provided `TypeId`. Failure to ensure this will result in
343    /// undefined behaviour, so implementing `downcast_raw` is unsafe.
344    ///
345    /// [`downcast_ref`]: #method.downcast_ref
346    unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> {
347        if id == TypeId::of::<Self>() {
348            Some(self as *const Self as *const ())
349        } else {
350            None
351        }
352    }
353}
354
355impl Subscriber {
356    /// Returns `true` if this `Subscriber` is the same type as `T`.
357    pub fn is<T: Any>(&self) -> bool {
358        self.downcast_ref::<T>().is_some()
359    }
360
361    /// Returns some reference to this `Subscriber` value if it is of type `T`,
362    /// or `None` if it isn't.
363    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
364        unsafe {
365            let raw = self.downcast_raw(TypeId::of::<T>())?;
366            if raw == ptr::null() {
367                None
368            } else {
369                Some(&*(raw as *const _))
370            }
371        }
372    }
373}
374
375/// Indicates a [`Subscriber`]'s interest in a particular callsite.
376///
377/// `Subscriber`s return an `Interest` from their [`register_callsite`] methods
378/// in order to determine whether that span should be enabled or disabled.
379///
380/// [`Subscriber`] trait.Subscriber.html
381/// [clone_span]: trait.Subscriber.html#method.register_callsite
382#[derive(Clone, Debug)]
383pub struct Interest(InterestKind);
384
385#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
386enum InterestKind {
387    Never = 0,
388    Sometimes = 1,
389    Always = 2,
390}
391
392impl Interest {
393    /// Returns an `Interest` indicating that the subscriber is never interested
394    /// in being notified about a callsite.
395    ///
396    /// If all active subscribers are `never()` interested in a callsite, it will
397    /// be completely disabled unless a new subscriber becomes active.
398    #[inline]
399    pub fn never() -> Self {
400        Interest(InterestKind::Never)
401    }
402
403    /// Returns an `Interest` indicating  the subscriber is sometimes interested
404    /// in being notified about a callsite.
405    ///
406    /// If all active subscribers are `sometimes` or `never` interested in a
407    /// callsite, the currently active subscriber will be asked to filter that
408    /// callsite every time it creates a span. This will be the case until a new
409    /// subscriber expresses that it is `always` interested in the callsite.
410    #[inline]
411    pub fn sometimes() -> Self {
412        Interest(InterestKind::Sometimes)
413    }
414
415    /// Returns an `Interest` indicating  the subscriber is always interested in
416    /// being notified about a callsite.
417    ///
418    /// If any subscriber expresses that it is `always()` interested in a given
419    /// callsite, then the callsite will always be enabled.
420    #[inline]
421    pub fn always() -> Self {
422        Interest(InterestKind::Always)
423    }
424
425    /// Returns `true` if the subscriber is never interested in being notified
426    /// about this callsite.
427    #[inline]
428    pub fn is_never(&self) -> bool {
429        match self.0 {
430            InterestKind::Never => true,
431            _ => false,
432        }
433    }
434
435    /// Returns `true` if the subscriber is sometimes interested in being notified
436    /// about this callsite.
437    #[inline]
438    pub fn is_sometimes(&self) -> bool {
439        match self.0 {
440            InterestKind::Sometimes => true,
441            _ => false,
442        }
443    }
444
445    /// Returns `true` if the subscriber is always interested in being notified
446    /// about this callsite.
447    #[inline]
448    pub fn is_always(&self) -> bool {
449        match self.0 {
450            InterestKind::Always => true,
451            _ => false,
452        }
453    }
454
455    /// Returns the common interest between these two Interests.
456    ///
457    /// The common interest is defined as the least restrictive, so if one
458    /// interest is `never` and the other is `always` the common interest is
459    /// `always`.
460    pub(crate) fn and(self, rhs: Interest) -> Self {
461        match rhs.0 {
462            // If the added interest is `never()`, don't change anything —
463            // either a different subscriber added a higher interest, which we
464            // want to preserve, or the interest is 0 anyway (as it's
465            // initialized to 0).
466            InterestKind::Never => self,
467            // If the interest is `sometimes()`, that overwrites a `never()`
468            // interest, but doesn't downgrade an `always()` interest.
469            InterestKind::Sometimes if self.0 == InterestKind::Never => rhs,
470            // If the interest is `always()`, we overwrite the current interest,
471            // as always() is the highest interest level and should take
472            // precedent.
473            InterestKind::Always => rhs,
474            _ => self,
475        }
476    }
477}