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}