tokio_trace/
span.rs

1//! Spans represent periods of time in the execution of a program.
2//!
3//! # Entering a Span
4//!
5//! A thread of execution is said to _enter_ a span when it begins executing,
6//! and _exit_ the span when it switches to another context. Spans may be
7//! entered through the [`enter`] method, which enters the target span,
8//! performs a given function (either a closure or a function pointer), exits
9//! the span, and then returns the result.
10//!
11//! Calling `enter` on a span handle enters the span that handle corresponds to,
12//! if the span exists:
13//! ```
14//! # #[macro_use] extern crate tokio_trace;
15//! # use tokio_trace::Level;
16//! # fn main() {
17//! let my_var: u64 = 5;
18//! let my_span = span!(Level::TRACE, "my_span", my_var = &my_var);
19//!
20//! my_span.enter(|| {
21//!     // perform some work in the context of `my_span`...
22//! });
23//!
24//! // Perform some work outside of the context of `my_span`...
25//!
26//! my_span.enter(|| {
27//!     // Perform some more work in the context of `my_span`.
28//! });
29//! # }
30//! ```
31//!
32//! # The Span Lifecycle
33//!
34//! Execution may enter and exit a span multiple times before that
35//! span is _closed_. Consider, for example, a future which has an associated
36//! span and enters that span every time it is polled:
37//! ```rust
38//! # extern crate tokio_trace;
39//! # extern crate futures;
40//! # use futures::{Future, Poll, Async};
41//! struct MyFuture {
42//!    // data
43//!    span: tokio_trace::Span,
44//! }
45//!
46//! impl Future for MyFuture {
47//!     type Item = ();
48//!     type Error = ();
49//!
50//!     fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
51//!         self.span.enter(|| {
52//!             // Do actual future work
53//! # Ok(Async::Ready(()))
54//!         })
55//!     }
56//! }
57//! ```
58//!
59//! If this future was spawned on an executor, it might yield one or more times
60//! before `poll` returns `Ok(Async::Ready)`. If the future were to yield, then
61//! the executor would move on to poll the next future, which may _also_ enter
62//! an associated span or series of spans. Therefore, it is valid for a span to
63//! be entered repeatedly before it completes. Only the time when that span or
64//! one of its children was the current span is considered to be time spent in
65//! that span. A span which is not executing and has not yet been closed is said
66//! to be _idle_.
67//!
68//! Because spans may be entered and exited multiple times before they close,
69//! [`Subscriber`]s have separate trait methods which are called to notify them
70//! of span exits and when span handles are dropped. When execution exits a
71//! span, [`exit`] will always be called with that span's ID to notify the
72//! subscriber that the span has been exited. When span handles are dropped, the
73//! [`drop_span`] method is called with that span's ID. The subscriber may use
74//! this to determine whether or not the span will be entered again.
75//!
76//! If there is only a single handle with the capacity to exit a span, dropping
77//! that handle "close" the span, since the capacity to enter it no longer
78//! exists. For example:
79//! ```
80//! # #[macro_use] extern crate tokio_trace;
81//! # use tokio_trace::Level;
82//! # fn main() {
83//! {
84//!     span!(Level::TRACE, "my_span").enter(|| {
85//!         // perform some work in the context of `my_span`...
86//!     }); // --> Subscriber::exit(my_span)
87//!
88//!     // The handle to `my_span` only lives inside of this block; when it is
89//!     // dropped, the subscriber will be informed via `drop_span`.
90//!
91//! } // --> Subscriber::drop_span(my_span)
92//! # }
93//! ```
94//!
95//! However, if multiple handles exist, the span can still be re-entered even if
96//! one or more is dropped. For determining when _all_ handles to a span have
97//! been dropped, `Subscriber`s have a [`clone_span`]  method, which is called
98//! every time a span handle is cloned. Combined with `drop_span`, this may be
99//! used to track the number of handles to a given span — if `drop_span` has
100//! been called one more time than the number of calls to `clone_span` for a
101//! given ID, then no more handles to the span with that ID exist. The
102//! subscriber may then treat it as closed.
103//!
104//! # Accessing a Span's Attributes
105//!
106//! The [`Attributes`] type represents a *non-entering* reference to a `Span`'s data
107//! — a set of key-value pairs (known as _fields_), a creation timestamp,
108//! a reference to the span's parent in the trace tree, and metadata describing
109//! the source code location where the span was created. This data is provided
110//! to the [`Subscriber`] when the span is created; it may then choose to cache
111//! the data for future use, record it in some manner, or discard it completely.
112//!
113//! [`clone_span`]: ../subscriber/trait.Subscriber.html#method.clone_span
114//! [`drop_span`]: ../subscriber/trait.Subscriber.html#method.drop_span
115//! [`exit`]: ../subscriber/trait.Subscriber.html#tymethod.exit
116//! [`Subscriber`]: ../subscriber/trait.Subscriber.html
117//! [`Attributes`]: struct.Attributes.html
118//! [`enter`]: struct.Span.html#method.enter
119pub use tokio_trace_core::span::{Attributes, Id, Record};
120
121use std::{
122    cmp, fmt,
123    hash::{Hash, Hasher},
124};
125use {dispatcher::Dispatch, field, Metadata};
126
127/// Trait implemented by types which have a span `Id`.
128pub trait AsId: ::sealed::Sealed {
129    /// Returns the `Id` of the span that `self` corresponds to, or `None` if
130    /// this corresponds to a disabled span.
131    fn as_id(&self) -> Option<&Id>;
132}
133
134/// A handle representing a span, with the capability to enter the span if it
135/// exists.
136///
137/// If the span was rejected by the current `Subscriber`'s filter, entering the
138/// span will silently do nothing. Thus, the handle can be used in the same
139/// manner regardless of whether or not the trace is currently being collected.
140#[derive(Clone)]
141pub struct Span {
142    /// A handle used to enter the span when it is not executing.
143    ///
144    /// If this is `None`, then the span has either closed or was never enabled.
145    inner: Option<Inner>,
146    meta: &'static Metadata<'static>,
147}
148
149/// A handle representing the capacity to enter a span which is known to exist.
150///
151/// Unlike `Span`, this type is only constructed for spans which _have_ been
152/// enabled by the current filter. This type is primarily used for implementing
153/// span handles; users should typically not need to interact with it directly.
154#[derive(Debug)]
155pub(crate) struct Inner {
156    /// The span's ID, as provided by `subscriber`.
157    id: Id,
158
159    /// The subscriber that will receive events relating to this span.
160    ///
161    /// This should be the same subscriber that provided this span with its
162    /// `id`.
163    subscriber: Dispatch,
164}
165
166/// A guard representing a span which has been entered and is currently
167/// executing.
168///
169/// This guard may be used to exit the span, returning an `Enter` to
170/// re-enter it.
171///
172/// This type is primarily used for implementing span handles; users should
173/// typically not need to interact with it directly.
174#[derive(Debug)]
175#[must_use = "once a span has been entered, it should be exited"]
176struct Entered<'a> {
177    inner: &'a Inner,
178}
179
180// ===== impl Span =====
181
182impl Span {
183    /// Constructs a new `Span` with the given [metadata] and set of
184    /// [field values].
185    ///
186    /// The new span will be constructed by the currently-active [`Subscriber`],
187    /// with the current span as its parent (if one exists).
188    ///
189    /// After the span is constructed, [field values] and/or [`follows_from`]
190    /// annotations may be added to it.
191    ///
192    /// [metadata]: ../metadata
193    /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
194    /// [field values]: ../field/struct.ValueSet.html
195    /// [`follows_from`]: ../struct.Span.html#method.follows_from
196    #[inline]
197    pub fn new(meta: &'static Metadata<'static>, values: &field::ValueSet) -> Span {
198        let new_span = Attributes::new(meta, values);
199        Self::make(meta, new_span)
200    }
201
202    /// Constructs a new `Span` as the root of its own trace tree, with the
203    /// given [metadata] and set of [field values].
204    ///
205    /// After the span is constructed, [field values] and/or [`follows_from`]
206    /// annotations may be added to it.
207    ///
208    /// [metadata]: ../metadata
209    /// [field values]: ../field/struct.ValueSet.html
210    /// [`follows_from`]: ../struct.Span.html#method.follows_from
211    #[inline]
212    pub fn new_root(meta: &'static Metadata<'static>, values: &field::ValueSet) -> Span {
213        Self::make(meta, Attributes::new_root(meta, values))
214    }
215
216    /// Constructs a new `Span` as child of the given parent span, with the
217    /// given [metadata] and set of [field values].
218    ///
219    /// After the span is constructed, [field values] and/or [`follows_from`]
220    /// annotations may be added to it.
221    ///
222    /// [metadata]: ../metadata
223    /// [field values]: ../field/struct.ValueSet.html
224    /// [`follows_from`]: ../struct.Span.html#method.follows_from
225    pub fn child_of<I>(
226        parent: I,
227        meta: &'static Metadata<'static>,
228        values: &field::ValueSet,
229    ) -> Span
230    where
231        I: AsId,
232    {
233        let new_span = match parent.as_id() {
234            Some(parent) => Attributes::child_of(parent.clone(), meta, values),
235            None => Attributes::new_root(meta, values),
236        };
237        Self::make(meta, new_span)
238    }
239
240    /// Constructs a new disabled span.
241    #[inline(always)]
242    pub fn new_disabled(meta: &'static Metadata<'static>) -> Span {
243        Span { inner: None, meta }
244    }
245
246    fn make(meta: &'static Metadata<'static>, new_span: Attributes) -> Span {
247        let attrs = &new_span;
248        let inner = ::dispatcher::get_default(move |dispatch| {
249            let id = dispatch.new_span(attrs);
250            Some(Inner::new(id, dispatch))
251        });
252        let span = Self { inner, meta };
253        span.log(format_args!("{}; {}", meta.name(), FmtAttrs(&new_span)));
254        span
255    }
256
257    /// Executes the given function in the context of this span.
258    ///
259    /// If this span is enabled, then this function enters the span, invokes
260    /// and then exits the span. If the span is disabled, `f` will still be
261    /// invoked, but in the context of the currently-executing span (if there is
262    /// one).
263    ///
264    /// Returns the result of evaluating `f`.
265    pub fn enter<F: FnOnce() -> T, T>(&self, f: F) -> T {
266        self.log(format_args!("-> {}", self.meta.name));
267        let _enter = self.inner.as_ref().map(Inner::enter);
268        let result = f();
269        self.log(format_args!("<- {}", self.meta.name));
270        result
271    }
272
273    /// Returns a [`Field`](../field/struct.Field.html) for the field with the
274    /// given `name`, if one exists,
275    pub fn field<Q: ?Sized>(&self, field: &Q) -> Option<field::Field>
276    where
277        Q: field::AsField,
278    {
279        self.metadata().and_then(|meta| field.as_field(meta))
280    }
281
282    /// Returns true if this `Span` has a field for the given
283    /// [`Field`](../field/struct.Field.html) or field name.
284    #[inline]
285    pub fn has_field<Q: ?Sized>(&self, field: &Q) -> bool
286    where
287        Q: field::AsField,
288    {
289        self.field(field).is_some()
290    }
291
292    /// Visits that the field described by `field` has the value `value`.
293    pub fn record<Q: ?Sized, V>(&self, field: &Q, value: &V) -> &Self
294    where
295        Q: field::AsField,
296        V: field::Value,
297    {
298        if let Some(field) = field.as_field(self.meta) {
299            self.record_all(
300                &self
301                    .meta
302                    .fields()
303                    .value_set(&[(&field, Some(value as &field::Value))]),
304            );
305        }
306
307        self
308    }
309
310    /// Visit all the fields in the span
311    pub fn record_all(&self, values: &field::ValueSet) -> &Self {
312        let record = Record::new(values);
313        if let Some(ref inner) = self.inner {
314            inner.record(&record);
315        }
316        self.log(format_args!("{}; {}", self.meta.name(), FmtValues(&record)));
317        self
318    }
319
320    /// Returns `true` if this span was disabled by the subscriber and does not
321    /// exist.
322    #[inline]
323    pub fn is_disabled(&self) -> bool {
324        self.inner.is_none()
325    }
326
327    /// Indicates that the span with the given ID has an indirect causal
328    /// relationship with this span.
329    ///
330    /// This relationship differs somewhat from the parent-child relationship: a
331    /// span may have any number of prior spans, rather than a single one; and
332    /// spans are not considered to be executing _inside_ of the spans they
333    /// follow from. This means that a span may close even if subsequent spans
334    /// that follow from it are still open, and time spent inside of a
335    /// subsequent span should not be included in the time its precedents were
336    /// executing. This is used to model causal relationships such as when a
337    /// single future spawns several related background tasks, et cetera.
338    ///
339    /// If this span is disabled, or the resulting follows-from relationship
340    /// would be invalid, this function will do nothing.
341    pub fn follows_from<I>(&self, from: I) -> &Self
342    where
343        I: AsId,
344    {
345        if let Some(ref inner) = self.inner {
346            if let Some(from) = from.as_id() {
347                inner.follows_from(from);
348            }
349        }
350        self
351    }
352
353    /// Returns this span's `Id`, if it is enabled.
354    pub fn id(&self) -> Option<Id> {
355        self.inner.as_ref().map(Inner::id)
356    }
357
358    /// Returns this span's `Metadata`, if it is enabled.
359    pub fn metadata(&self) -> Option<&'static Metadata<'static>> {
360        if self.inner.is_some() {
361            Some(self.meta)
362        } else {
363            None
364        }
365    }
366
367    #[cfg(feature = "log")]
368    #[inline]
369    fn log(&self, message: fmt::Arguments) {
370        use log;
371        let logger = log::logger();
372        let log_meta = log::Metadata::builder()
373            .level(level_to_log!(self.meta.level))
374            .target(self.meta.target)
375            .build();
376        if logger.enabled(&log_meta) {
377            logger.log(
378                &log::Record::builder()
379                    .metadata(log_meta)
380                    .module_path(self.meta.module_path)
381                    .file(self.meta.file)
382                    .line(self.meta.line)
383                    .args(message)
384                    .build(),
385            );
386        }
387    }
388
389    #[cfg(not(feature = "log"))]
390    #[inline]
391    fn log(&self, _: fmt::Arguments) {}
392}
393
394impl cmp::PartialEq for Span {
395    fn eq(&self, other: &Self) -> bool {
396        self.meta.callsite() == other.meta.callsite() && self.inner == other.inner
397    }
398}
399
400impl Hash for Span {
401    fn hash<H: Hasher>(&self, hasher: &mut H) {
402        self.inner.hash(hasher);
403    }
404}
405
406impl fmt::Debug for Span {
407    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
408        let mut span = f.debug_struct("Span");
409        span.field("name", &self.meta.name())
410            .field("level", &self.meta.level())
411            .field("target", &self.meta.target());
412
413        if let Some(ref inner) = self.inner {
414            span.field("id", &inner.id());
415        } else {
416            span.field("disabled", &true);
417        }
418
419        if let Some(ref path) = self.meta.module_path() {
420            span.field("module_path", &path);
421        }
422
423        if let Some(ref line) = self.meta.line() {
424            span.field("line", &line);
425        }
426
427        if let Some(ref file) = self.meta.file() {
428            span.field("file", &file);
429        }
430
431        span.finish()
432    }
433}
434
435// ===== impl Inner =====
436
437impl Inner {
438    /// Enters the span, returning a guard that may be used to exit the span and
439    /// re-enter the prior span.
440    ///
441    /// This is used internally to implement `Span::enter`. It may be used for
442    /// writing custom span handles, but should generally not be called directly
443    /// when entering a span.
444    #[inline]
445    fn enter(&self) -> Entered {
446        self.subscriber.enter(&self.id);
447        Entered { inner: self }
448    }
449
450    /// Indicates that the span with the given ID has an indirect causal
451    /// relationship with this span.
452    ///
453    /// This relationship differs somewhat from the parent-child relationship: a
454    /// span may have any number of prior spans, rather than a single one; and
455    /// spans are not considered to be executing _inside_ of the spans they
456    /// follow from. This means that a span may close even if subsequent spans
457    /// that follow from it are still open, and time spent inside of a
458    /// subsequent span should not be included in the time its precedents were
459    /// executing. This is used to model causal relationships such as when a
460    /// single future spawns several related background tasks, et cetera.
461    ///
462    /// If this span is disabled, this function will do nothing. Otherwise, it
463    /// returns `Ok(())` if the other span was added as a precedent of this
464    /// span, or an error if this was not possible.
465    fn follows_from(&self, from: &Id) {
466        self.subscriber.record_follows_from(&self.id, &from)
467    }
468
469    /// Returns the span's ID.
470    fn id(&self) -> Id {
471        self.id.clone()
472    }
473
474    fn record(&self, values: &Record) {
475        self.subscriber.record(&self.id, values)
476    }
477
478    fn new(id: Id, subscriber: &Dispatch) -> Self {
479        Inner {
480            id,
481            subscriber: subscriber.clone(),
482        }
483    }
484}
485
486impl cmp::PartialEq for Inner {
487    fn eq(&self, other: &Self) -> bool {
488        self.id == other.id
489    }
490}
491
492impl Hash for Inner {
493    fn hash<H: Hasher>(&self, state: &mut H) {
494        self.id.hash(state);
495    }
496}
497
498impl Drop for Inner {
499    fn drop(&mut self) {
500        self.subscriber.drop_span(self.id.clone());
501    }
502}
503
504impl Clone for Inner {
505    fn clone(&self) -> Self {
506        Inner {
507            id: self.subscriber.clone_span(&self.id),
508            subscriber: self.subscriber.clone(),
509        }
510    }
511}
512
513// ===== impl Entered =====
514
515impl<'a> Drop for Entered<'a> {
516    #[inline]
517    fn drop(&mut self) {
518        // Dropping the guard exits the span.
519        //
520        // Running this behaviour on drop rather than with an explicit function
521        // call means that spans may still be exited when unwinding.
522        self.inner.subscriber.exit(&self.inner.id);
523    }
524}
525
526struct FmtValues<'a>(&'a Record<'a>);
527
528impl<'a> fmt::Display for FmtValues<'a> {
529    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
530        let mut res = Ok(());
531        self.0.record(&mut |k: &field::Field, v: &fmt::Debug| {
532            res = write!(f, "{}={:?} ", k, v);
533        });
534        res
535    }
536}
537
538struct FmtAttrs<'a>(&'a Attributes<'a>);
539
540impl<'a> fmt::Display for FmtAttrs<'a> {
541    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
542        let mut res = Ok(());
543        self.0.record(&mut |k: &field::Field, v: &fmt::Debug| {
544            res = write!(f, "{}={:?} ", k, v);
545        });
546        res
547    }
548}
549
550// ===== impl AsId =====
551
552impl ::sealed::Sealed for Span {}
553
554impl AsId for Span {
555    fn as_id(&self) -> Option<&Id> {
556        self.inner.as_ref().map(|inner| &inner.id)
557    }
558}
559
560impl<'a> ::sealed::Sealed for &'a Span {}
561
562impl<'a> AsId for &'a Span {
563    fn as_id(&self) -> Option<&Id> {
564        self.inner.as_ref().map(|inner| &inner.id)
565    }
566}
567
568impl ::sealed::Sealed for Id {}
569
570impl AsId for Id {
571    fn as_id(&self) -> Option<&Id> {
572        Some(self)
573    }
574}
575
576impl<'a> ::sealed::Sealed for &'a Id {}
577
578impl<'a> AsId for &'a Id {
579    fn as_id(&self) -> Option<&Id> {
580        Some(self)
581    }
582}
583
584impl ::sealed::Sealed for Option<Id> {}
585
586impl AsId for Option<Id> {
587    fn as_id(&self) -> Option<&Id> {
588        self.as_ref()
589    }
590}
591
592impl<'a> ::sealed::Sealed for &'a Option<Id> {}
593
594impl<'a> AsId for &'a Option<Id> {
595    fn as_id(&self) -> Option<&Id> {
596        self.as_ref()
597    }
598}
599
600#[cfg(test)]
601mod test {
602    use super::*;
603
604    trait AssertSend: Send {}
605    impl AssertSend for Span {}
606
607    trait AssertSync: Sync {}
608    impl AssertSync for Span {}
609}