2019-02-19 12:15:01 -08:00
|
|
|
//! Spans represent periods of time in the execution of a program.
|
|
|
|
|
//!
|
|
|
|
|
//! # Entering a Span
|
|
|
|
|
//!
|
|
|
|
|
//! A thread of execution is said to _enter_ a span when it begins executing,
|
|
|
|
|
//! and _exit_ the span when it switches to another context. Spans may be
|
|
|
|
|
//! entered through the [`enter`](`Span::enter`) method, which enters the target span,
|
|
|
|
|
//! performs a given function (either a closure or a function pointer), exits
|
|
|
|
|
//! the span, and then returns the result.
|
|
|
|
|
//!
|
|
|
|
|
//! Calling `enter` on a span handle enters the span that handle corresponds to,
|
|
|
|
|
//! if the span exists:
|
|
|
|
|
//! ```
|
|
|
|
|
//! # #[macro_use] extern crate tokio_trace;
|
2019-04-02 19:29:23 +01:00
|
|
|
//! # use tokio_trace::Level;
|
2019-02-19 12:15:01 -08:00
|
|
|
//! # fn main() {
|
|
|
|
|
//! let my_var: u64 = 5;
|
2019-04-02 19:29:23 +01:00
|
|
|
//! let mut my_span = span!(Level::TRACE, "my_span", my_var = &my_var);
|
2019-02-19 12:15:01 -08:00
|
|
|
//!
|
|
|
|
|
//! my_span.enter(|| {
|
|
|
|
|
//! // perform some work in the context of `my_span`...
|
|
|
|
|
//! });
|
|
|
|
|
//!
|
|
|
|
|
//! // Perform some work outside of the context of `my_span`...
|
|
|
|
|
//!
|
|
|
|
|
//! my_span.enter(|| {
|
|
|
|
|
//! // Perform some more work in the context of `my_span`.
|
|
|
|
|
//! });
|
|
|
|
|
//! # }
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! # The Span Lifecycle
|
|
|
|
|
//!
|
|
|
|
|
//! Execution may enter and exit a span multiple times before that
|
|
|
|
|
//! span is _closed_. Consider, for example, a future which has an associated
|
|
|
|
|
//! span and enters that span every time it is polled:
|
|
|
|
|
//! ```rust
|
|
|
|
|
//! # extern crate tokio_trace;
|
|
|
|
|
//! # extern crate futures;
|
|
|
|
|
//! # use futures::{Future, Poll, Async};
|
2019-03-18 12:44:46 -07:00
|
|
|
//! struct MyFuture {
|
2019-02-19 12:15:01 -08:00
|
|
|
//! // data
|
2019-03-18 12:44:46 -07:00
|
|
|
//! span: tokio_trace::Span,
|
2019-02-19 12:15:01 -08:00
|
|
|
//! }
|
|
|
|
|
//!
|
2019-03-18 12:44:46 -07:00
|
|
|
//! impl Future for MyFuture {
|
2019-02-19 12:15:01 -08:00
|
|
|
//! type Item = ();
|
|
|
|
|
//! type Error = ();
|
|
|
|
|
//!
|
|
|
|
|
//! fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
|
|
|
//! self.span.enter(|| {
|
|
|
|
|
//! // Do actual future work
|
|
|
|
|
//! # Ok(Async::Ready(()))
|
|
|
|
|
//! })
|
|
|
|
|
//! }
|
|
|
|
|
//! }
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! If this future was spawned on an executor, it might yield one or more times
|
|
|
|
|
//! before `poll` returns `Ok(Async::Ready)`. If the future were to yield, then
|
|
|
|
|
//! the executor would move on to poll the next future, which may _also_ enter
|
|
|
|
|
//! an associated span or series of spans. Therefore, it is valid for a span to
|
|
|
|
|
//! be entered repeatedly before it completes. Only the time when that span or
|
|
|
|
|
//! one of its children was the current span is considered to be time spent in
|
|
|
|
|
//! that span. A span which is not executing and has not yet been closed is said
|
|
|
|
|
//! to be _idle_.
|
|
|
|
|
//!
|
|
|
|
|
//! Because spans may be entered and exited multiple times before they close,
|
|
|
|
|
//! [`Subscriber`]s have separate trait methods which are called to notify them
|
|
|
|
|
//! of span exits and when span handles are dropped. When execution exits a
|
|
|
|
|
//! span, [`exit`](::Subscriber::exit) will always be called with that span's ID
|
|
|
|
|
//! to notify the subscriber that the span has been exited. When span handles
|
|
|
|
|
//! are dropped, the [`drop_span`](::Subscriber::drop_span) method is called
|
|
|
|
|
//! with that span's ID. The subscriber may use this to determine whether or not
|
|
|
|
|
//! the span will be entered again.
|
|
|
|
|
//!
|
|
|
|
|
//! If there is only a single handle with the capacity to exit a span, dropping
|
|
|
|
|
//! that handle "close" the span, since the capacity to enter it no longer
|
|
|
|
|
//! exists. For example:
|
|
|
|
|
//! ```
|
|
|
|
|
//! # #[macro_use] extern crate tokio_trace;
|
2019-04-02 19:29:23 +01:00
|
|
|
//! # use tokio_trace::Level;
|
2019-02-19 12:15:01 -08:00
|
|
|
//! # fn main() {
|
|
|
|
|
//! {
|
2019-04-02 19:29:23 +01:00
|
|
|
//! span!(Level::TRACE, "my_span").enter(|| {
|
2019-02-19 12:15:01 -08:00
|
|
|
//! // perform some work in the context of `my_span`...
|
|
|
|
|
//! }); // --> Subscriber::exit(my_span)
|
|
|
|
|
//!
|
|
|
|
|
//! // The handle to `my_span` only lives inside of this block; when it is
|
|
|
|
|
//! // dropped, the subscriber will be informed that `my_span` has closed.
|
|
|
|
|
//!
|
|
|
|
|
//! } // --> Subscriber::close(my_span)
|
|
|
|
|
//! # }
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
2019-03-18 12:44:46 -07:00
|
|
|
//! A span may be explicitly closed by dropping a handle to it, if it is the only
|
|
|
|
|
//! handle to that span.
|
2019-02-19 12:15:01 -08:00
|
|
|
//! time it is exited. For example:
|
|
|
|
|
//! ```
|
|
|
|
|
//! # #[macro_use] extern crate tokio_trace;
|
2019-04-02 19:29:23 +01:00
|
|
|
//! # use tokio_trace::Level;
|
2019-02-19 12:15:01 -08:00
|
|
|
//! # fn main() {
|
|
|
|
|
//! use tokio_trace::Span;
|
|
|
|
|
//!
|
2019-04-02 19:29:23 +01:00
|
|
|
//! let my_span = span!(Level::TRACE, "my_span");
|
2019-03-18 12:44:46 -07:00
|
|
|
//! // Drop the handle to the span.
|
|
|
|
|
//! drop(my_span); // --> Subscriber::drop_span(my_span)
|
2019-02-19 12:15:01 -08:00
|
|
|
//! # }
|
|
|
|
|
//! ```
|
|
|
|
|
//! However, if multiple handles exist, the span can still be re-entered even if
|
|
|
|
|
//! one or more is dropped. For determining when _all_ handles to a span have
|
|
|
|
|
//! been dropped, `Subscriber`s have a [`clone_span`](::Subscriber::clone_span)
|
|
|
|
|
//! method, which is called every time a span handle is cloned. Combined with
|
|
|
|
|
//! `drop_span`, this may be used to track the number of handles to a given span
|
|
|
|
|
//! — if `drop_span` has been called one more time than the number of calls to
|
|
|
|
|
//! `clone_span` for a given ID, then no more handles to the span with that ID
|
|
|
|
|
//! exist. The subscriber may then treat it as closed.
|
|
|
|
|
//!
|
|
|
|
|
//! # Accessing a Span's Attributes
|
|
|
|
|
//!
|
|
|
|
|
//! The [`Attributes`] type represents a *non-entering* reference to a `Span`'s data
|
|
|
|
|
//! — a set of key-value pairs (known as _fields_), a creation timestamp,
|
|
|
|
|
//! a reference to the span's parent in the trace tree, and metadata describing
|
|
|
|
|
//! the source code location where the span was created. This data is provided
|
|
|
|
|
//! to the [`Subscriber`] when the span is created; it may then choose to cache
|
|
|
|
|
//! the data for future use, record it in some manner, or discard it completely.
|
|
|
|
|
//!
|
|
|
|
|
//! [`Subscriber`]: ::Subscriber
|
2019-03-07 12:41:10 -08:00
|
|
|
pub use tokio_trace_core::span::{Attributes, Id, Record};
|
2019-02-19 12:15:01 -08:00
|
|
|
|
|
|
|
|
use std::{
|
|
|
|
|
cmp, fmt,
|
|
|
|
|
hash::{Hash, Hasher},
|
|
|
|
|
};
|
2019-03-26 16:43:05 -07:00
|
|
|
use {dispatcher::Dispatch, field, Metadata};
|
2019-02-19 12:15:01 -08:00
|
|
|
|
2019-04-01 11:42:29 -07:00
|
|
|
/// Trait implemented by types which have a span `Id`.
|
|
|
|
|
pub trait AsId: ::sealed::Sealed {
|
|
|
|
|
fn as_id(&self) -> Option<&Id>;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-19 12:15:01 -08:00
|
|
|
/// A handle representing a span, with the capability to enter the span if it
|
|
|
|
|
/// exists.
|
|
|
|
|
///
|
|
|
|
|
/// If the span was rejected by the current `Subscriber`'s filter, entering the
|
|
|
|
|
/// span will silently do nothing. Thus, the handle can be used in the same
|
|
|
|
|
/// manner regardless of whether or not the trace is currently being collected.
|
2019-03-26 16:43:05 -07:00
|
|
|
#[derive(Clone)]
|
2019-03-18 12:44:46 -07:00
|
|
|
pub struct Span {
|
2019-02-19 12:15:01 -08:00
|
|
|
/// A handle used to enter the span when it is not executing.
|
|
|
|
|
///
|
|
|
|
|
/// If this is `None`, then the span has either closed or was never enabled.
|
2019-03-26 16:43:05 -07:00
|
|
|
inner: Option<Inner>,
|
|
|
|
|
meta: &'static Metadata<'static>,
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A handle representing the capacity to enter a span which is known to exist.
|
|
|
|
|
///
|
|
|
|
|
/// Unlike `Span`, this type is only constructed for spans which _have_ been
|
|
|
|
|
/// enabled by the current filter. This type is primarily used for implementing
|
|
|
|
|
/// span handles; users should typically not need to interact with it directly.
|
|
|
|
|
#[derive(Debug)]
|
2019-03-26 16:43:05 -07:00
|
|
|
pub(crate) struct Inner {
|
2019-02-19 12:15:01 -08:00
|
|
|
/// The span's ID, as provided by `subscriber`.
|
|
|
|
|
id: Id,
|
|
|
|
|
|
|
|
|
|
/// The subscriber that will receive events relating to this span.
|
|
|
|
|
///
|
|
|
|
|
/// This should be the same subscriber that provided this span with its
|
|
|
|
|
/// `id`.
|
|
|
|
|
subscriber: Dispatch,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A guard representing a span which has been entered and is currently
|
|
|
|
|
/// executing.
|
|
|
|
|
///
|
|
|
|
|
/// This guard may be used to exit the span, returning an `Enter` to
|
|
|
|
|
/// re-enter it.
|
|
|
|
|
///
|
|
|
|
|
/// This type is primarily used for implementing span handles; users should
|
|
|
|
|
/// typically not need to interact with it directly.
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
#[must_use = "once a span has been entered, it should be exited"]
|
2019-03-26 16:43:05 -07:00
|
|
|
struct Entered {
|
|
|
|
|
inner: Inner,
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ===== impl Span =====
|
|
|
|
|
|
2019-03-18 12:44:46 -07:00
|
|
|
impl Span {
|
2019-03-01 11:29:11 -08:00
|
|
|
/// Constructs a new `Span` with the given [metadata] and set of [field
|
|
|
|
|
/// values].
|
2019-02-19 12:15:01 -08:00
|
|
|
///
|
|
|
|
|
/// The new span will be constructed by the currently-active [`Subscriber`],
|
|
|
|
|
/// with the current span as its parent (if one exists).
|
|
|
|
|
///
|
|
|
|
|
/// After the span is constructed, [field values] and/or [`follows_from`]
|
|
|
|
|
/// annotations may be added to it.
|
|
|
|
|
///
|
|
|
|
|
/// [metadata]: ::metadata::Metadata
|
|
|
|
|
/// [`Subscriber`]: ::subscriber::Subscriber
|
|
|
|
|
/// [field values]: ::field::ValueSet
|
|
|
|
|
/// [`follows_from`]: ::span::Span::follows_from
|
|
|
|
|
#[inline]
|
2019-03-18 12:44:46 -07:00
|
|
|
pub fn new(meta: &'static Metadata<'static>, values: &field::ValueSet) -> Span {
|
2019-03-01 11:29:11 -08:00
|
|
|
let new_span = Attributes::new(meta, values);
|
|
|
|
|
Self::make(meta, new_span)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Constructs a new `Span` as the root of its own trace tree, with the
|
|
|
|
|
/// given [metadata] and set of [field values].
|
|
|
|
|
///
|
|
|
|
|
/// After the span is constructed, [field values] and/or [`follows_from`]
|
|
|
|
|
/// annotations may be added to it.
|
|
|
|
|
///
|
|
|
|
|
/// [metadata]: ::metadata::Metadata
|
|
|
|
|
/// [field values]: ::field::ValueSet
|
|
|
|
|
/// [`follows_from`]: ::span::Span::follows_from
|
|
|
|
|
#[inline]
|
2019-03-18 12:44:46 -07:00
|
|
|
pub fn new_root(meta: &'static Metadata<'static>, values: &field::ValueSet) -> Span {
|
2019-03-01 11:29:11 -08:00
|
|
|
Self::make(meta, Attributes::new_root(meta, values))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Constructs a new `Span` as child of the given parent span, with the
|
|
|
|
|
/// given [metadata] and set of [field values].
|
|
|
|
|
///
|
|
|
|
|
/// After the span is constructed, [field values] and/or [`follows_from`]
|
|
|
|
|
/// annotations may be added to it.
|
|
|
|
|
///
|
|
|
|
|
/// [metadata]: ::metadata::Metadata
|
|
|
|
|
/// [field values]: ::field::ValueSet
|
|
|
|
|
/// [`follows_from`]: ::span::Span::follows_from
|
2019-03-18 12:44:46 -07:00
|
|
|
pub fn child_of<I>(
|
|
|
|
|
parent: I,
|
|
|
|
|
meta: &'static Metadata<'static>,
|
|
|
|
|
values: &field::ValueSet,
|
|
|
|
|
) -> Span
|
2019-03-01 11:29:11 -08:00
|
|
|
where
|
2019-04-01 11:42:29 -07:00
|
|
|
I: AsId,
|
2019-03-01 11:29:11 -08:00
|
|
|
{
|
2019-04-01 11:42:29 -07:00
|
|
|
let new_span = match parent.as_id() {
|
|
|
|
|
Some(parent) => Attributes::child_of(parent.clone(), meta, values),
|
2019-03-01 11:29:11 -08:00
|
|
|
None => Attributes::new_root(meta, values),
|
|
|
|
|
};
|
|
|
|
|
Self::make(meta, new_span)
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Constructs a new disabled span.
|
|
|
|
|
#[inline(always)]
|
2019-03-26 16:43:05 -07:00
|
|
|
pub fn new_disabled(meta: &'static Metadata<'static>) -> Span {
|
|
|
|
|
Span { inner: None, meta }
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-18 12:44:46 -07:00
|
|
|
fn make(meta: &'static Metadata<'static>, new_span: Attributes) -> Span {
|
2019-03-26 16:43:05 -07:00
|
|
|
let attrs = &new_span;
|
|
|
|
|
let inner = ::dispatcher::get_default(move |dispatch| {
|
|
|
|
|
let id = dispatch.new_span(attrs);
|
|
|
|
|
Some(Inner::new(id, dispatch))
|
2019-03-01 11:29:11 -08:00
|
|
|
});
|
2019-03-26 16:43:05 -07:00
|
|
|
let span = Self { inner, meta };
|
|
|
|
|
span.log(format_args!("{}; {}", meta.name(), FmtAttrs(&new_span)));
|
|
|
|
|
span
|
2019-03-01 11:29:11 -08:00
|
|
|
}
|
|
|
|
|
|
2019-02-19 12:15:01 -08:00
|
|
|
/// Executes the given function in the context of this span.
|
|
|
|
|
///
|
|
|
|
|
/// If this span is enabled, then this function enters the span, invokes
|
|
|
|
|
/// and then exits the span. If the span is disabled, `f` will still be
|
|
|
|
|
/// invoked, but in the context of the currently-executing span (if there is
|
|
|
|
|
/// one).
|
|
|
|
|
///
|
|
|
|
|
/// Returns the result of evaluating `f`.
|
|
|
|
|
pub fn enter<F: FnOnce() -> T, T>(&mut self, f: F) -> T {
|
2019-03-26 16:43:05 -07:00
|
|
|
self.log(format_args!("-> {}", self.meta.name));
|
|
|
|
|
let result = match self.inner.take() {
|
2019-03-11 15:29:00 -07:00
|
|
|
Some(inner) => {
|
2019-02-19 12:15:01 -08:00
|
|
|
let guard = inner.enter();
|
|
|
|
|
let result = f();
|
2019-03-18 12:44:46 -07:00
|
|
|
self.inner = Some(guard.exit());
|
2019-02-19 12:15:01 -08:00
|
|
|
result
|
2019-03-11 15:29:00 -07:00
|
|
|
}
|
2019-02-19 12:15:01 -08:00
|
|
|
None => f(),
|
2019-03-26 16:43:05 -07:00
|
|
|
};
|
|
|
|
|
self.log(format_args!("<- {}", self.meta.name));
|
|
|
|
|
result
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns a [`Field`](::field::Field) for the field with the given `name`, if
|
|
|
|
|
/// one exists,
|
2019-04-01 11:42:29 -07:00
|
|
|
pub fn field<Q: ?Sized>(&self, field: &Q) -> Option<field::Field>
|
2019-02-19 12:15:01 -08:00
|
|
|
where
|
2019-04-01 11:42:29 -07:00
|
|
|
Q: field::AsField,
|
2019-02-19 12:15:01 -08:00
|
|
|
{
|
2019-04-01 11:42:29 -07:00
|
|
|
self.metadata().and_then(|meta| field.as_field(meta))
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns true if this `Span` has a field for the given
|
|
|
|
|
/// [`Field`](::field::Field) or field name.
|
2019-04-01 11:42:29 -07:00
|
|
|
#[inline]
|
2019-02-19 12:15:01 -08:00
|
|
|
pub fn has_field<Q: ?Sized>(&self, field: &Q) -> bool
|
|
|
|
|
where
|
|
|
|
|
Q: field::AsField,
|
|
|
|
|
{
|
2019-04-01 11:42:29 -07:00
|
|
|
self.field(field).is_some()
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-07 12:41:10 -08:00
|
|
|
/// Visits that the field described by `field` has the value `value`.
|
2019-02-19 12:15:01 -08:00
|
|
|
pub fn record<Q: ?Sized, V>(&mut self, field: &Q, value: &V) -> &mut Self
|
|
|
|
|
where
|
|
|
|
|
Q: field::AsField,
|
|
|
|
|
V: field::Value,
|
|
|
|
|
{
|
2019-03-26 16:43:05 -07:00
|
|
|
if let Some(field) = field.as_field(self.meta) {
|
|
|
|
|
self.record_all(
|
|
|
|
|
&self
|
|
|
|
|
.meta
|
|
|
|
|
.fields()
|
|
|
|
|
.value_set(&[(&field, Some(value as &field::Value))]),
|
|
|
|
|
);
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
2019-03-26 16:43:05 -07:00
|
|
|
|
2019-02-19 12:15:01 -08:00
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-07 12:41:10 -08:00
|
|
|
/// Visit all the fields in the span
|
2019-02-19 12:15:01 -08:00
|
|
|
pub fn record_all(&mut self, values: &field::ValueSet) -> &mut Self {
|
2019-03-26 16:43:05 -07:00
|
|
|
let record = Record::new(values);
|
2019-02-19 12:15:01 -08:00
|
|
|
if let Some(ref mut inner) = self.inner {
|
2019-03-26 16:43:05 -07:00
|
|
|
inner.record(&record);
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
2019-03-26 16:43:05 -07:00
|
|
|
self.log(format_args!("{}; {}", self.meta.name(), FmtValues(&record)));
|
2019-02-19 12:15:01 -08:00
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns `true` if this span was disabled by the subscriber and does not
|
|
|
|
|
/// exist.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn is_disabled(&self) -> bool {
|
2019-03-18 12:44:46 -07:00
|
|
|
self.inner.is_none()
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Indicates that the span with the given ID has an indirect causal
|
|
|
|
|
/// relationship with this span.
|
|
|
|
|
///
|
|
|
|
|
/// This relationship differs somewhat from the parent-child relationship: a
|
|
|
|
|
/// span may have any number of prior spans, rather than a single one; and
|
|
|
|
|
/// spans are not considered to be executing _inside_ of the spans they
|
|
|
|
|
/// follow from. This means that a span may close even if subsequent spans
|
|
|
|
|
/// that follow from it are still open, and time spent inside of a
|
|
|
|
|
/// subsequent span should not be included in the time its precedents were
|
|
|
|
|
/// executing. This is used to model causal relationships such as when a
|
|
|
|
|
/// single future spawns several related background tasks, et cetera.
|
|
|
|
|
///
|
|
|
|
|
/// If this span is disabled, or the resulting follows-from relationship
|
|
|
|
|
/// would be invalid, this function will do nothing.
|
2019-04-01 11:42:29 -07:00
|
|
|
pub fn follows_from<I>(&self, from: I) -> &Self
|
|
|
|
|
where
|
|
|
|
|
I: AsId,
|
|
|
|
|
{
|
2019-02-19 12:15:01 -08:00
|
|
|
if let Some(ref inner) = self.inner {
|
2019-04-01 11:42:29 -07:00
|
|
|
if let Some(from) = from.as_id() {
|
|
|
|
|
inner.follows_from(from);
|
|
|
|
|
}
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns this span's `Id`, if it is enabled.
|
|
|
|
|
pub fn id(&self) -> Option<Id> {
|
|
|
|
|
self.inner.as_ref().map(Inner::id)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns this span's `Metadata`, if it is enabled.
|
2019-03-18 12:44:46 -07:00
|
|
|
pub fn metadata(&self) -> Option<&'static Metadata<'static>> {
|
2019-03-26 16:43:05 -07:00
|
|
|
if self.inner.is_some() {
|
|
|
|
|
Some(self.meta)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "log")]
|
|
|
|
|
#[inline]
|
|
|
|
|
fn log(&self, message: fmt::Arguments) {
|
|
|
|
|
use log;
|
|
|
|
|
let logger = log::logger();
|
|
|
|
|
let log_meta = log::Metadata::builder()
|
|
|
|
|
.level(level_to_log!(self.meta.level))
|
|
|
|
|
.target(self.meta.target)
|
|
|
|
|
.build();
|
|
|
|
|
if logger.enabled(&log_meta) {
|
|
|
|
|
logger.log(
|
|
|
|
|
&log::Record::builder()
|
|
|
|
|
.metadata(log_meta)
|
|
|
|
|
.module_path(self.meta.module_path)
|
|
|
|
|
.file(self.meta.file)
|
|
|
|
|
.line(self.meta.line)
|
|
|
|
|
.args(message)
|
|
|
|
|
.build(),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(not(feature = "log"))]
|
|
|
|
|
#[inline]
|
|
|
|
|
fn log(&self, _: fmt::Arguments) {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl cmp::PartialEq for Span {
|
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
|
self.meta.callsite() == other.meta.callsite() && self.inner == other.inner
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Hash for Span {
|
|
|
|
|
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
|
|
|
|
self.inner.hash(hasher);
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-26 16:43:05 -07:00
|
|
|
impl fmt::Debug for Span {
|
2019-02-19 12:15:01 -08:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
|
let mut span = f.debug_struct("Span");
|
2019-03-26 16:43:05 -07:00
|
|
|
span.field("name", &self.meta.name())
|
|
|
|
|
.field("level", &self.meta.level())
|
|
|
|
|
.field("target", &self.meta.target());
|
|
|
|
|
|
2019-02-19 12:15:01 -08:00
|
|
|
if let Some(ref inner) = self.inner {
|
2019-03-26 16:43:05 -07:00
|
|
|
span.field("id", &inner.id());
|
2019-02-19 12:15:01 -08:00
|
|
|
} else {
|
2019-03-26 16:43:05 -07:00
|
|
|
span.field("disabled", &true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Some(ref path) = self.meta.module_path() {
|
|
|
|
|
span.field("module_path", &path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Some(ref line) = self.meta.line() {
|
|
|
|
|
span.field("line", &line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Some(ref file) = self.meta.file() {
|
|
|
|
|
span.field("file", &file);
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
2019-03-26 16:43:05 -07:00
|
|
|
|
|
|
|
|
span.finish()
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ===== impl Inner =====
|
|
|
|
|
|
2019-03-26 16:43:05 -07:00
|
|
|
impl Inner {
|
2019-02-19 12:15:01 -08:00
|
|
|
/// Enters the span, returning a guard that may be used to exit the span and
|
|
|
|
|
/// re-enter the prior span.
|
|
|
|
|
///
|
|
|
|
|
/// This is used internally to implement `Span::enter`. It may be used for
|
|
|
|
|
/// writing custom span handles, but should generally not be called directly
|
|
|
|
|
/// when entering a span.
|
2019-03-26 16:43:05 -07:00
|
|
|
fn enter(self) -> Entered {
|
2019-02-19 12:15:01 -08:00
|
|
|
self.subscriber.enter(&self.id);
|
|
|
|
|
Entered { inner: self }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Indicates that the span with the given ID has an indirect causal
|
|
|
|
|
/// relationship with this span.
|
|
|
|
|
///
|
|
|
|
|
/// This relationship differs somewhat from the parent-child relationship: a
|
|
|
|
|
/// span may have any number of prior spans, rather than a single one; and
|
|
|
|
|
/// spans are not considered to be executing _inside_ of the spans they
|
|
|
|
|
/// follow from. This means that a span may close even if subsequent spans
|
|
|
|
|
/// that follow from it are still open, and time spent inside of a
|
|
|
|
|
/// subsequent span should not be included in the time its precedents were
|
|
|
|
|
/// executing. This is used to model causal relationships such as when a
|
|
|
|
|
/// single future spawns several related background tasks, et cetera.
|
|
|
|
|
///
|
|
|
|
|
/// If this span is disabled, this function will do nothing. Otherwise, it
|
|
|
|
|
/// returns `Ok(())` if the other span was added as a precedent of this
|
|
|
|
|
/// span, or an error if this was not possible.
|
|
|
|
|
fn follows_from(&self, from: &Id) {
|
|
|
|
|
self.subscriber.record_follows_from(&self.id, &from)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the span's ID.
|
|
|
|
|
fn id(&self) -> Id {
|
|
|
|
|
self.id.clone()
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-26 16:43:05 -07:00
|
|
|
fn record(&mut self, values: &Record) {
|
|
|
|
|
self.subscriber.record(&self.id, values)
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-26 16:43:05 -07:00
|
|
|
fn new(id: Id, subscriber: &Dispatch) -> Self {
|
2019-02-19 12:15:01 -08:00
|
|
|
Inner {
|
|
|
|
|
id,
|
|
|
|
|
subscriber: subscriber.clone(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-26 16:43:05 -07:00
|
|
|
impl cmp::PartialEq for Inner {
|
2019-02-19 12:15:01 -08:00
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
|
self.id == other.id
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-26 16:43:05 -07:00
|
|
|
impl Hash for Inner {
|
2019-02-19 12:15:01 -08:00
|
|
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
|
|
|
self.id.hash(state);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-26 16:43:05 -07:00
|
|
|
impl Drop for Inner {
|
2019-02-19 12:15:01 -08:00
|
|
|
fn drop(&mut self) {
|
|
|
|
|
self.subscriber.drop_span(self.id.clone());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-26 16:43:05 -07:00
|
|
|
impl Clone for Inner {
|
2019-02-19 12:15:01 -08:00
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
Inner {
|
|
|
|
|
id: self.subscriber.clone_span(&self.id),
|
|
|
|
|
subscriber: self.subscriber.clone(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ===== impl Entered =====
|
|
|
|
|
|
2019-03-26 16:43:05 -07:00
|
|
|
impl Entered {
|
2019-02-19 12:15:01 -08:00
|
|
|
/// Exit the `Entered` guard, returning an `Inner` handle that may be used
|
2019-03-18 12:44:46 -07:00
|
|
|
/// to re-enter the span.
|
2019-03-26 16:43:05 -07:00
|
|
|
fn exit(self) -> Inner {
|
2019-02-19 12:15:01 -08:00
|
|
|
self.inner.subscriber.exit(&self.inner.id);
|
2019-03-18 12:44:46 -07:00
|
|
|
self.inner
|
2019-02-19 12:15:01 -08:00
|
|
|
}
|
|
|
|
|
}
|
2019-03-26 16:43:05 -07:00
|
|
|
|
|
|
|
|
struct FmtValues<'a>(&'a Record<'a>);
|
|
|
|
|
|
|
|
|
|
impl<'a> fmt::Display for FmtValues<'a> {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
|
let mut res = Ok(());
|
|
|
|
|
self.0.record(&mut |k: &field::Field, v: &fmt::Debug| {
|
|
|
|
|
res = write!(f, "{}={:?} ", k, v);
|
|
|
|
|
});
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct FmtAttrs<'a>(&'a Attributes<'a>);
|
|
|
|
|
|
|
|
|
|
impl<'a> fmt::Display for FmtAttrs<'a> {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
|
let mut res = Ok(());
|
|
|
|
|
self.0.record(&mut |k: &field::Field, v: &fmt::Debug| {
|
|
|
|
|
res = write!(f, "{}={:?} ", k, v);
|
|
|
|
|
});
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-01 11:42:29 -07:00
|
|
|
|
|
|
|
|
// ===== impl AsId =====
|
|
|
|
|
|
|
|
|
|
impl ::sealed::Sealed for Span {}
|
|
|
|
|
|
|
|
|
|
impl AsId for Span {
|
|
|
|
|
fn as_id(&self) -> Option<&Id> {
|
|
|
|
|
self.inner.as_ref().map(|inner| &inner.id)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> ::sealed::Sealed for &'a Span {}
|
|
|
|
|
|
|
|
|
|
impl<'a> AsId for &'a Span {
|
|
|
|
|
fn as_id(&self) -> Option<&Id> {
|
|
|
|
|
self.inner.as_ref().map(|inner| &inner.id)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ::sealed::Sealed for Id {}
|
|
|
|
|
|
|
|
|
|
impl AsId for Id {
|
|
|
|
|
fn as_id(&self) -> Option<&Id> {
|
|
|
|
|
Some(self)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> ::sealed::Sealed for &'a Id {}
|
|
|
|
|
|
|
|
|
|
impl<'a> AsId for &'a Id {
|
|
|
|
|
fn as_id(&self) -> Option<&Id> {
|
|
|
|
|
Some(self)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ::sealed::Sealed for Option<Id> {}
|
|
|
|
|
|
|
|
|
|
impl AsId for Option<Id> {
|
|
|
|
|
fn as_id(&self) -> Option<&Id> {
|
|
|
|
|
self.as_ref()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> ::sealed::Sealed for &'a Option<Id> {}
|
|
|
|
|
|
|
|
|
|
impl<'a> AsId for &'a Option<Id> {
|
|
|
|
|
fn as_id(&self) -> Option<&Id> {
|
|
|
|
|
self.as_ref()
|
|
|
|
|
}
|
|
|
|
|
}
|