mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-07 00:00:09 +02:00
trace: Improve documentation (#1148)
This commit is contained in:
committed by
David Barsky
parent
06c473e628
commit
448302c3d4
+7
-152
@@ -24,12 +24,12 @@
|
||||
//!
|
||||
//! # Core Concepts
|
||||
//!
|
||||
//! The core of `tokio-trace`'s API is composed of `Event`s, `Span`s, and
|
||||
//! `Subscriber`s. We'll cover these in turn.
|
||||
//! The core of `tokio-trace`'s API is composed of _spans_, _events_ and
|
||||
//! _subscribers_. We'll cover these in turn.
|
||||
//!
|
||||
//! ## `Span`s
|
||||
//! ## Spans
|
||||
//!
|
||||
//! A [`Span`] represents a _period of time_ during which a program was executing
|
||||
//! A [`span`] represents a _period of time_ during which a program was executing
|
||||
//! in some context. A thread of execution is said to _enter_ a span when it
|
||||
//! begins executing in that context, and to _exit_ the span when switching to
|
||||
//! another context. The span in which a thread is currently executing is
|
||||
@@ -49,153 +49,7 @@
|
||||
//! # }
|
||||
//!```
|
||||
//!
|
||||
//! The [`in_scope`] method may be used to execute a closure inside a
|
||||
//! span:
|
||||
//!
|
||||
//! ```
|
||||
//! # #[macro_use] extern crate tokio_trace;
|
||||
//! # use tokio_trace::Level;
|
||||
//! # fn main() {
|
||||
//! # let span = span!(Level::TRACE, "my_span");
|
||||
//! span.in_scope(|| {
|
||||
//! // perform some more work in the context of `my_span`...
|
||||
//! });
|
||||
//! # }
|
||||
//!```
|
||||
//!
|
||||
//! Spans form a tree structure — unless it is a root span, all spans have a
|
||||
//! _parent_, and may have one or more _children_. When a new span is created,
|
||||
//! the current span becomes the new span's parent. The total execution time of
|
||||
//! a span consists of the time spent in that span and in the entire subtree
|
||||
//! represented by its children. Thus, a parent span always lasts for at least
|
||||
//! as long as the longest-executing span in its subtree.
|
||||
//!
|
||||
//! ```
|
||||
//! # #[macro_use] extern crate tokio_trace;
|
||||
//! # use tokio_trace::Level;
|
||||
//! # fn main() {
|
||||
//! // this span is considered the "root" of a new trace tree:
|
||||
//! span!(Level::INFO, "root").in_scope(|| {
|
||||
//! // since we are now inside "root", this span is considered a child
|
||||
//! // of "root":
|
||||
//! span!(Level::DEBUG, "outer_child").in_scope(|| {
|
||||
//! // this span is a child of "outer_child", which is in turn a
|
||||
//! // child of "root":
|
||||
//! span!(Level::TRACE, "inner_child").in_scope(|| {
|
||||
//! // and so on...
|
||||
//! });
|
||||
//! });
|
||||
//! });
|
||||
//! # }
|
||||
//!```
|
||||
//!
|
||||
//! In addition, data may be associated with spans. A span may have _fields_ —
|
||||
//! a set of key-value pairs describing the state of the program during that
|
||||
//! span; an optional name, and metadata describing the source code location
|
||||
//! where the span was originally entered.
|
||||
//! ```
|
||||
//! # #[macro_use] extern crate tokio_trace;
|
||||
//! # use tokio_trace::Level;
|
||||
//! # fn main() {
|
||||
//! // construct a new span with three fields:
|
||||
//! // - "foo", with a value of 42,
|
||||
//! // - "bar", with the value "false"
|
||||
//! // - "baz", with no initial value
|
||||
//! let my_span = span!(Level::INFO, "my_span", foo = 42, bar = false);
|
||||
//!
|
||||
// TODO(#1138): determine a new syntax for uninitialized span fields, and
|
||||
// re-enable this.
|
||||
// //! // record a value for the field "baz" declared above:
|
||||
// //! my_span.record("baz", &"hello world");
|
||||
//! # }
|
||||
//!```
|
||||
//!
|
||||
//! As shorthand, local variables may be used as field values without an
|
||||
//! assignment, similar to [struct initializers]. For example:
|
||||
//! ```
|
||||
//! # #[macro_use]
|
||||
//! # extern crate tokio_trace;
|
||||
//! # use tokio_trace::Level;
|
||||
//! # fn main() {
|
||||
//! let user = "ferris";
|
||||
//!
|
||||
//! span!(Level::TRACE, "login", user);
|
||||
//! // is equivalent to:
|
||||
//! span!(Level::TRACE, "login", user = user);
|
||||
//! # }
|
||||
//!```
|
||||
//!
|
||||
//! The [`field::display`] and [`field::debug`] functions are used to record
|
||||
//! fields on spans or events using their `fmt::Display` and `fmt::Debug`
|
||||
//! implementations (rather than as typed data). This may be used in lieu of
|
||||
//! custom `Value` implementations for complex or user-defined types.
|
||||
//!
|
||||
//! In addition, the span and event macros permit the use of the `%` and `?`
|
||||
//! sigils as shorthand for `field::display` and `field::debug`, respectively.
|
||||
//! For example:
|
||||
//!
|
||||
//! ```
|
||||
//! # #[macro_use]
|
||||
//! # extern crate tokio_trace;
|
||||
//! # use tokio_trace::{Level, field};
|
||||
//! # fn main() {
|
||||
//! #[derive(Debug)]
|
||||
//! struct MyStruct {
|
||||
//! my_field: &'static str,
|
||||
//! }
|
||||
//!
|
||||
//! let my_struct = MyStruct {
|
||||
//! my_field: "Hello world!"
|
||||
//! };
|
||||
//!
|
||||
//! span!(Level::TRACE,"my_span", ?my_struct, %my_struct.my_field);
|
||||
//! // is equivalent to:
|
||||
//! span!(Level::TRACE, "my_span", my_struct = field::debug(&my_struct), my_struct.my_field = field::display(&my_struct.my_field));
|
||||
//! # }
|
||||
//!```
|
||||
//!
|
||||
//! ### When to use spans
|
||||
//!
|
||||
//! As a rule of thumb, spans should be used to represent discrete units of work
|
||||
//! (e.g., a given request's lifetime in a server) or periods of time spent in a
|
||||
//! given context (e.g., time spent interacting with an instance of an external
|
||||
//! system, such as a database).
|
||||
//!
|
||||
//! Which scopes in a program correspond to new spans depend somewhat on user
|
||||
//! intent. For example, consider the case of a loop in a program. Should we
|
||||
//! construct one span and perform the entire loop inside of that span, like:
|
||||
//! ```rust
|
||||
//! # #[macro_use] extern crate tokio_trace;
|
||||
//! # use tokio_trace::Level;
|
||||
//! # fn main() {
|
||||
//! # let n = 1;
|
||||
//! let span = span!(Level::TRACE, "my_loop");
|
||||
//! let _enter = span.enter();
|
||||
//! for i in 0..n {
|
||||
//! # let _ = i;
|
||||
//! // ...
|
||||
//! }
|
||||
//! # }
|
||||
//! ```
|
||||
//! Or, should we create a new span for each iteration of the loop, as in:
|
||||
//! ```rust
|
||||
//! # #[macro_use] extern crate tokio_trace;
|
||||
//! # use tokio_trace::Level;
|
||||
//! # fn main() {
|
||||
//! # let n = 1u64;
|
||||
//! for i in 0..n {
|
||||
//! let span = span!(Level::TRACE, "my_loop", iteration = i);
|
||||
//! let _enter = span.enter();
|
||||
//! // ...
|
||||
//! }
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! Depending on the circumstances, we might want to do either, or both. For
|
||||
//! example, if we want to know how long was spent in the loop overall, we would
|
||||
//! create a single span around the entire loop; whereas if we wanted to know how
|
||||
//! much time was spent in each individual iteration, we would enter a new span
|
||||
//! on every iteration.
|
||||
//! The [`span` module]'s documentation provides further details on how to use spans.
|
||||
//!
|
||||
//! ## Events
|
||||
//!
|
||||
@@ -462,7 +316,8 @@
|
||||
//! ```
|
||||
//!
|
||||
//! [`log`]: https://docs.rs/log/0.4.6/log/
|
||||
//! [`Span`]: span/struct.Span.html
|
||||
//! [`span`]: span/index.html
|
||||
//! [`span` module]: span/index.html
|
||||
//! [`in_scope`]: span/struct.Span.html#method.in_scope
|
||||
//! [`Event`]: struct.Event.html
|
||||
//! [`Subscriber`]: subscriber/trait.Subscriber.html
|
||||
|
||||
+182
-36
@@ -2,43 +2,31 @@
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Creating a new span with no fields:
|
||||
/// Creating a new span:
|
||||
/// ```
|
||||
/// # #[macro_use]
|
||||
/// # extern crate tokio_trace;
|
||||
/// # use tokio_trace::Level;
|
||||
/// #[macro_use]
|
||||
/// extern crate tokio_trace;
|
||||
/// use tokio_trace::Level;
|
||||
/// # fn main() {
|
||||
/// let span = span!(Level::TRACE, "my span");
|
||||
/// span.in_scope(|| {
|
||||
/// // do work inside the span...
|
||||
/// });
|
||||
/// let _enter = span.enter();
|
||||
/// // do work inside the span...
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Creating a span with custom target:
|
||||
/// ## Recording Fields
|
||||
///
|
||||
/// Span fields are written using the syntax `key = value`.
|
||||
/// ```
|
||||
/// # #[macro_use]
|
||||
/// # extern crate tokio_trace;
|
||||
/// # #[macro_use] extern crate tokio_trace;
|
||||
/// # use tokio_trace::Level;
|
||||
/// # fn main() {
|
||||
/// span!(Level::TRACE, target: "app_span", "my span");
|
||||
/// // construct a new span with two fields:
|
||||
/// // - "foo", with a value of 42,
|
||||
/// // - "bar", with the value "false"
|
||||
/// let my_span = span!(Level::INFO, "my_span", foo = 42, bar = false);
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// # Fields
|
||||
///
|
||||
/// Creating a span with fields:
|
||||
/// ```
|
||||
/// # #[macro_use]
|
||||
/// # extern crate tokio_trace;
|
||||
/// # use tokio_trace::Level;
|
||||
/// # fn main() {
|
||||
/// span!(Level::TRACE, "my span", foo = 2, bar = "a string").in_scope(|| {
|
||||
/// // do work inside the span...
|
||||
/// });
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Note that a trailing comma on the final field is valid:
|
||||
/// ```
|
||||
/// # #[macro_use]
|
||||
@@ -46,10 +34,10 @@
|
||||
/// # use tokio_trace::Level;
|
||||
/// # fn main() {
|
||||
/// span!(
|
||||
/// Level::TRACE,
|
||||
/// "my span",
|
||||
/// foo = 2,
|
||||
/// bar = "a string",
|
||||
/// Level::INFO,
|
||||
/// "my_span",
|
||||
/// foo = 42,
|
||||
/// bar = false,
|
||||
/// );
|
||||
/// # }
|
||||
/// ```
|
||||
@@ -69,7 +57,7 @@
|
||||
/// # }
|
||||
///```
|
||||
///
|
||||
/// Field names can include dots:
|
||||
/// Field names can include dots, but should not be terminated by them:
|
||||
/// ```
|
||||
/// # #[macro_use]
|
||||
/// # extern crate tokio_trace;
|
||||
@@ -116,7 +104,7 @@
|
||||
// /// # }
|
||||
// /// ```
|
||||
// ///
|
||||
/// The `?` sigil is shorthand for `field::debug`:
|
||||
/// The `?` sigil is shorthand for [`field::debug`]:
|
||||
/// ```
|
||||
/// # #[macro_use]
|
||||
/// # extern crate tokio_trace;
|
||||
@@ -132,11 +120,13 @@
|
||||
/// };
|
||||
///
|
||||
/// // `my_struct` will be recorded using its `fmt::Debug` implementation.
|
||||
/// let my_span = span!(Level::TRACE, "my span", foo = ?my_struct);
|
||||
/// span!(Level::TRACE, "my span", foo = ?my_struct);
|
||||
/// // is equivalent to:
|
||||
/// span!(Level::TRACE, "my span", foo = tokio_trace::field::debug(&my_struct));
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// The `%` character is shorthand for `field::display`:
|
||||
/// The `%` character is shorthand for [`field::display`]:
|
||||
/// ```
|
||||
/// # #[macro_use]
|
||||
/// # extern crate tokio_trace;
|
||||
@@ -151,11 +141,13 @@
|
||||
/// # field: "Hello world!"
|
||||
/// # };
|
||||
/// // `my_struct.field` will be recorded using its `fmt::Display` implementation.
|
||||
/// let my_span = span!(Level::TRACE, "my span", foo = %my_struct.field);
|
||||
/// span!(Level::TRACE, "my span", foo = %my_struct.field);
|
||||
/// // is equivalent to:
|
||||
/// span!(Level::TRACE, "my span", foo = tokio_trace::field::display(&my_struct.field));
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// The `display` and `debug` sigils may also be used with local variable shorthand:
|
||||
/// The `%` and `?` sigils may also be used with local variable shorthand:
|
||||
/// ```
|
||||
/// # #[macro_use]
|
||||
/// # extern crate tokio_trace;
|
||||
@@ -190,7 +182,76 @@
|
||||
/// );
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ## Setting Span Attributes
|
||||
///
|
||||
/// In addition to the level and name of the span, which are required, the
|
||||
/// [target] and [parent span] may be overridden. For example:
|
||||
///
|
||||
/// Creating a span with custom target:
|
||||
/// ```
|
||||
/// # #[macro_use]
|
||||
/// # extern crate tokio_trace;
|
||||
/// # use tokio_trace::Level;
|
||||
/// # fn main() {
|
||||
/// span!(Level::TRACE, target: "app_span", "my span");
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Creating a span with an explicit parent:
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate tokio_trace;
|
||||
/// # use tokio_trace::Level;
|
||||
/// # fn main() {
|
||||
/// // Create, but do not enter, a span called "foo".
|
||||
/// let foo = span!(Level::INFO, "foo");
|
||||
///
|
||||
/// // Create and enter a span called "bar".
|
||||
/// let bar = span!(Level::INFO, "bar");
|
||||
/// let _enter = bar.enter();
|
||||
///
|
||||
/// // Although we have currently entered "bar", "baz"'s parent span
|
||||
/// // will be "foo".
|
||||
/// let baz = span!(Level::INFO, parent: &foo, "baz");
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Creating a span _without_ a parent:
|
||||
///
|
||||
///```rust
|
||||
/// # #[macro_use] extern crate tokio_trace;
|
||||
/// # use tokio_trace::Level;
|
||||
/// # fn main() {
|
||||
/// let foo = span!(Level::INFO, "foo");
|
||||
/// let _enter = foo.enter();
|
||||
///
|
||||
/// // Although we have currently entered "foo", "bar" will be created
|
||||
/// // as the root of its own trace tree:
|
||||
/// let bar = span!(Level::INFO, parent: None, "bar");
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Both the parent and target may be overridden simultaenously:
|
||||
///
|
||||
///```rust
|
||||
/// # #[macro_use] extern crate tokio_trace;
|
||||
/// # use tokio_trace::Level;
|
||||
/// # fn main() {
|
||||
/// let foo = span!(Level::INFO, "foo");
|
||||
//
|
||||
/// let bar = span!(Level::INFO, target: "bar_events", parent: &foo, "bar");
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// By default, the module path to the current Rust module will be used
|
||||
/// as the target, and the parent will be [determined contextually].
|
||||
///
|
||||
/// [struct initializers]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#using-the-field-init-shorthand-when-variables-and-fields-have-the-same-name
|
||||
/// [target]: struct.Metadata.html#method.target
|
||||
/// [parent span]: span/struct.Attributes.html#method.parent
|
||||
/// [determined contextually]: span/struct.Attributes.html#method.is_contextual
|
||||
/// [`field::debug`]: field/fn.display.html
|
||||
/// [`field::display`]: field/fn.display.html
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! span {
|
||||
($lvl:expr, target: $target:expr, parent: $parent:expr, $name:expr) => {
|
||||
@@ -300,9 +361,26 @@ macro_rules! span {
|
||||
|
||||
/// Constructs a span at the trace level.
|
||||
///
|
||||
/// [Fields] and [attributes] are set using the same syntax as the [`span!`]
|
||||
/// macro.
|
||||
///
|
||||
/// [attributes]: macro.span.html#setting-span-attributes
|
||||
/// [Fields]: macro.span.html#recording-fields
|
||||
/// [`span!`]: macro.span.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate tokio_trace;
|
||||
/// # use tokio_trace::Level;
|
||||
/// # fn main() {
|
||||
/// trace_span!("my_span");
|
||||
/// // is equivalent to:
|
||||
/// span!(Level::TRACE, "my_span");
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use]
|
||||
/// # extern crate tokio_trace;
|
||||
/// # fn main() {
|
||||
@@ -362,9 +440,26 @@ macro_rules! trace_span {
|
||||
|
||||
/// Constructs a span at the debug level.
|
||||
///
|
||||
/// [Fields] and [attributes] are set using the same syntax as the [`span!`]
|
||||
/// macro.
|
||||
///
|
||||
/// [attributes]: macro.span.html#setting-span-attributes
|
||||
/// [Fields]: macro.span.html#recording-fields
|
||||
/// [`span!`]: macro.span.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate tokio_trace;
|
||||
/// # use tokio_trace::Level;
|
||||
/// # fn main() {
|
||||
/// debug_span!("my_span");
|
||||
/// // is equivalent to:
|
||||
/// span!(Level::DEBUG, "my_span");
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use]
|
||||
/// # extern crate tokio_trace;
|
||||
/// # fn main() {
|
||||
@@ -424,9 +519,26 @@ macro_rules! debug_span {
|
||||
|
||||
/// Constructs a span at the info level.
|
||||
///
|
||||
/// [Fields] and [attributes] are set using the same syntax as the [`span!`]
|
||||
/// macro.
|
||||
///
|
||||
/// [attributes]: macro.span.html#setting-span-attributes
|
||||
/// [Fields]: macro.span.html#recording-fields
|
||||
/// [`span!`]: macro.span.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate tokio_trace;
|
||||
/// # use tokio_trace::Level;
|
||||
/// # fn main() {
|
||||
/// info_span!("my_span");
|
||||
/// // is equivalent to:
|
||||
/// span!(Level::INFO, "my_span");
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use]
|
||||
/// # extern crate tokio_trace;
|
||||
/// # fn main() {
|
||||
@@ -486,9 +598,26 @@ macro_rules! info_span {
|
||||
|
||||
/// Constructs a span at the warn level.
|
||||
///
|
||||
/// [Fields] and [attributes] are set using the same syntax as the [`span!`]
|
||||
/// macro.
|
||||
///
|
||||
/// [attributes]: macro.span.html#setting-span-attributes
|
||||
/// [Fields]: macro.span.html#recording-fields
|
||||
/// [`span!`]: macro.span.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate tokio_trace;
|
||||
/// # use tokio_trace::Level;
|
||||
/// # fn main() {
|
||||
/// info_span!("my_span");
|
||||
/// // is equivalent to:
|
||||
/// span!(Level::INFO, "my_span");
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use]
|
||||
/// # extern crate tokio_trace;
|
||||
/// # fn main() {
|
||||
@@ -547,9 +676,26 @@ macro_rules! warn_span {
|
||||
}
|
||||
/// Constructs a span at the error level.
|
||||
///
|
||||
/// [Fields] and [attributes] are set using the same syntax as the [`span!`]
|
||||
/// macro.
|
||||
///
|
||||
/// [attributes]: macro.span.html#setting-span-attributes
|
||||
/// [Fields]: macro.span.html#recording-fields
|
||||
/// [`span!`]: macro.span.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate tokio_trace;
|
||||
/// # use tokio_trace::Level;
|
||||
/// # fn main() {
|
||||
/// error_span!("my_span");
|
||||
/// // is equivalent to:
|
||||
/// span!(Level::ERROR, "my_span");
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use]
|
||||
/// # extern crate tokio_trace;
|
||||
/// # fn main() {
|
||||
|
||||
+185
-18
@@ -1,6 +1,51 @@
|
||||
//! Spans represent periods of time in the execution of a program.
|
||||
//! Spans represent periods of time in which a program was executing in a
|
||||
//! particular context.
|
||||
//!
|
||||
//! # Entering a Span
|
||||
//! A span consists of [fields], user-defined key-value pairs of arbitrary data
|
||||
//! that describe the context the span represents, and [metadata], a fixed set
|
||||
//! of attributes that describe all `tokio-trace` spans and events. Each span is
|
||||
//! assigned an [`Id` ] by the subscriber that uniquely identifies it in relation
|
||||
//! to other spans.
|
||||
//!
|
||||
//! # Creating Spans
|
||||
//!
|
||||
//! Spans are created using the [`span!`] macro. This macro is invoked with a
|
||||
//! [verbosity level], followed by a set of attributes whose default values
|
||||
//! the user whishes to override, a string literal providing the span's name,
|
||||
//! and finally, between zero and 32 fields.
|
||||
//!
|
||||
//! For example:
|
||||
//! ```rust
|
||||
//! #[macro_use]
|
||||
//! extern crate tokio_trace;
|
||||
//! use tokio_trace::Level;
|
||||
//!
|
||||
//! # fn main() {
|
||||
//! /// Construct a new span at the `INFO` level named "my_span", with a single
|
||||
//! /// field named answer , with the value `42`.
|
||||
//! let my_span = span!(Level::INFO, "my_span", answer = 42);
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! The documentation for the [`span!`] macro provides additional examples of
|
||||
//! the various options that exist when creating spans.
|
||||
//!
|
||||
//! The [`trace_span!`], [`debug_span!`], [`info_span!`], [`warn_span!`], and
|
||||
//! [`error_span!`] exist as shorthand for constructing spans at various
|
||||
//! verbosity levels.
|
||||
//!
|
||||
//! ## Recording Span Creation
|
||||
//!
|
||||
//! The [`Attributes`] type contains data associated with a span, and is
|
||||
//! provided to the [`Subscriber`] when a new span is created. It contains
|
||||
//! the span's metadata, the ID of the span's parent if one was explicitly set,
|
||||
//! and any fields whose values were recorded when the span was constructed.
|
||||
//! The subscriber may then choose to cache the data for future use, record
|
||||
//! it in some manner, or discard it completely.
|
||||
//!
|
||||
//! # The Span Lifecycle
|
||||
//!
|
||||
//! ## 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
|
||||
@@ -13,13 +58,15 @@
|
||||
//! # use tokio_trace::Level;
|
||||
//! # fn main() {
|
||||
//! let my_var: u64 = 5;
|
||||
//! let my_span = span!(Level::TRACE, "my_span", my_var = &my_var);
|
||||
//! let my_span = span!(Level::TRACE, "my_span", my_var);
|
||||
//!
|
||||
//! // `my_span` exists but has not been entered.
|
||||
//!
|
||||
//! // Enter `my_span`...
|
||||
//! let _enter = my_span.enter();
|
||||
//!
|
||||
//! // Perform some work inside of the context of `my_span`...
|
||||
//! // Dropping the `_enter` guard will exit the span.
|
||||
//! # }
|
||||
//!```
|
||||
//!
|
||||
@@ -44,11 +91,86 @@
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! **Note:** Since entering a span takes `&self`, and `Span`s are `Clone`,
|
||||
//! `Send`, and `Sync`, it is entirely valid for multiple threads to enter the
|
||||
//! same span concurrently.
|
||||
//!
|
||||
//! # The Span Lifecycle
|
||||
//! ## Span Relationships
|
||||
//!
|
||||
//! Execution may enter and exit a span multiple times before that
|
||||
//! span is _closed_. Consider, for example, a future which has an associated
|
||||
//! Spans form a tree structure — unless it is a root span, all spans have a
|
||||
//! _parent_, and may have one or more _children_. When a new span is created,
|
||||
//! the current span becomes the new span's parent. The total execution time of
|
||||
//! a span consists of the time spent in that span and in the entire subtree
|
||||
//! represented by its children. Thus, a parent span always lasts for at least
|
||||
//! as long as the longest-executing span in its subtree.
|
||||
//!
|
||||
//! ```
|
||||
//! # #[macro_use] extern crate tokio_trace;
|
||||
//! # use tokio_trace::Level;
|
||||
//! # fn main() {
|
||||
//! // this span is considered the "root" of a new trace tree:
|
||||
//! span!(Level::INFO, "root").in_scope(|| {
|
||||
//! // since we are now inside "root", this span is considered a child
|
||||
//! // of "root":
|
||||
//! span!(Level::DEBUG, "outer_child").in_scope(|| {
|
||||
//! // this span is a child of "outer_child", which is in turn a
|
||||
//! // child of "root":
|
||||
//! span!(Level::TRACE, "inner_child").in_scope(|| {
|
||||
//! // and so on...
|
||||
//! });
|
||||
//! });
|
||||
//! // another span created here would also be a child of "root".
|
||||
//! });
|
||||
//! # }
|
||||
//!```
|
||||
//!
|
||||
//! In addition, the parent of a span may be explicitly specified in
|
||||
//! the `span!` macro. For example:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # #[macro_use] extern crate tokio_trace;
|
||||
//! # use tokio_trace::Level;
|
||||
//! # fn main() {
|
||||
//! // Create, but do not enter, a span called "foo".
|
||||
//! let foo = span!(Level::INFO, "foo");
|
||||
//!
|
||||
//! // Create and enter a span called "bar".
|
||||
//! let bar = span!(Level::INFO, "bar");
|
||||
//! let _enter = bar.enter();
|
||||
//!
|
||||
//! // Although we have currently entered "bar", "baz"'s parent span
|
||||
//! // will be "foo".
|
||||
//! let baz = span!(Level::INFO, parent: &foo, "baz");
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! A child span should typically be considered _part_ of its parent. For
|
||||
//! example, if a subscriber is recording the length of time spent in various
|
||||
//! spans, it should generally include the time spent in a span's children as
|
||||
//! part of that span's duration.
|
||||
//!
|
||||
//! In addition to having zero or one parent, a span may also _follow from_ any
|
||||
//! number of other spans. This indicates a causal relationship between the span
|
||||
//! and the spans that it follows from, but a follower is *not* typically
|
||||
//! considered part of the duration of the span it follows. Unlike the parent, a
|
||||
//! span may record that it follows from another span after it is created, using
|
||||
//! the [`follows_from`] method.
|
||||
//!
|
||||
//! As an example, consider a listener task in a server. As the listener accepts
|
||||
//! incoming connections, it spawns new tasks that handle those connections. We
|
||||
//! might want to have a span representing the listener, and instrument each
|
||||
//! spawned handler task with its own span. We would want our instrumentation to
|
||||
//! record that the handler tasks were spawned as a result of the listener task.
|
||||
//! However, we might not consider the handler tasks to be _part_ of the time
|
||||
//! spent in the listener task, so we would not consider those spans children of
|
||||
//! the listener span. Instead, we would record that the handler tasks follow
|
||||
//! from the listener, recording the causal relationship but treating the spans
|
||||
//! as separate durations.
|
||||
//!
|
||||
//! ## Closing Spans
|
||||
//!
|
||||
//! 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;
|
||||
@@ -64,10 +186,9 @@
|
||||
//! type Error = ();
|
||||
//!
|
||||
//! fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
//! self.span.in_scope(|| {
|
||||
//! // Do actual future work
|
||||
//! let _enter = self.span.enter();
|
||||
//! // Do actual future work...
|
||||
//! # Ok(Async::Ready(()))
|
||||
//! })
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
@@ -90,7 +211,7 @@
|
||||
//! 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
|
||||
//! that handle "closes" the span, since the capacity to enter it no longer
|
||||
//! exists. For example:
|
||||
//! ```
|
||||
//! # #[macro_use] extern crate tokio_trace;
|
||||
@@ -117,15 +238,60 @@
|
||||
//! 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
|
||||
//! # When to use spans
|
||||
//!
|
||||
//! 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.
|
||||
//! As a rule of thumb, spans should be used to represent discrete units of work
|
||||
//! (e.g., a given request's lifetime in a server) or periods of time spent in a
|
||||
//! given context (e.g., time spent interacting with an instance of an external
|
||||
//! system, such as a database).
|
||||
//!
|
||||
//! Which scopes in a program correspond to new spans depend somewhat on user
|
||||
//! intent. For example, consider the case of a loop in a program. Should we
|
||||
//! construct one span and perform the entire loop inside of that span, like:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # #[macro_use] extern crate tokio_trace;
|
||||
//! # use tokio_trace::Level;
|
||||
//! # fn main() {
|
||||
//! # let n = 1;
|
||||
//! let span = span!(Level::TRACE, "my_loop");
|
||||
//! let _enter = span.enter();
|
||||
//! for i in 0..n {
|
||||
//! # let _ = i;
|
||||
//! // ...
|
||||
//! }
|
||||
//! # }
|
||||
//! ```
|
||||
//! Or, should we create a new span for each iteration of the loop, as in:
|
||||
//! ```rust
|
||||
//! # #[macro_use] extern crate tokio_trace;
|
||||
//! # use tokio_trace::Level;
|
||||
//! # fn main() {
|
||||
//! # let n = 1u64;
|
||||
//! for i in 0..n {
|
||||
//! let span = span!(Level::TRACE, "my_loop", iteration = i);
|
||||
//! let _enter = span.enter();
|
||||
//! // ...
|
||||
//! }
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! Depending on the circumstances, we might want to do either, or both. For
|
||||
//! example, if we want to know how long was spent in the loop overall, we would
|
||||
//! create a single span around the entire loop; whereas if we wanted to know how
|
||||
//! much time was spent in each individual iteration, we would enter a new span
|
||||
//! on every iteration.
|
||||
//!
|
||||
//! [fields]: ../field/index.html
|
||||
//! [metadata]: ../struct.Metadata.html
|
||||
//! [`Id`]: struct.Id.html
|
||||
//! [verbosity level]: ../struct.Level.html
|
||||
//! [`span!`]: ../macro.span.html
|
||||
//! [`trace_span!`]: ../macro.trace_span.html
|
||||
//! [`debug_span!`]: ../macro.debug_span.html
|
||||
//! [`info_span!`]: ../macro.info_span.html
|
||||
//! [`warn_span!`]: ../macro.warn_span.html
|
||||
//! [`error_span!`]: ../macro.error_span.html
|
||||
//! [`clone_span`]: ../subscriber/trait.Subscriber.html#method.clone_span
|
||||
//! [`drop_span`]: ../subscriber/trait.Subscriber.html#method.drop_span
|
||||
//! [`exit`]: ../subscriber/trait.Subscriber.html#tymethod.exit
|
||||
@@ -133,7 +299,8 @@
|
||||
//! [`Attributes`]: struct.Attributes.html
|
||||
//! [`enter`]: struct.Span.html#method.enter
|
||||
//! [`in_scope`]: struct.Span.html#method.in_scope
|
||||
//! [`guard`]: struct.Entered.html
|
||||
//! [`follows_from`]: struct.Span.html#method.follows_from
|
||||
//! [guard]: struct.Entered.html
|
||||
pub use tokio_trace_core::span::{Attributes, Id, Record};
|
||||
|
||||
use std::{
|
||||
|
||||
@@ -7,8 +7,21 @@ use std::fmt;
|
||||
|
||||
/// Metadata describing a [span] or [event].
|
||||
///
|
||||
/// This includes the source code location where the span occurred, the names of
|
||||
/// its fields, et cetera.
|
||||
/// All spans and events have the following metadata:
|
||||
/// - A [name], represented as a static string.
|
||||
/// - A [target], a string that categorizes part of the system where the span
|
||||
/// or event occurred. The `tokio_trace` macros default to using the module
|
||||
/// path where the span or event originated as the target, but it may be
|
||||
/// overridden.
|
||||
/// - A [verbosity level].
|
||||
/// - The names of the [fields] defined by the span or event.
|
||||
/// - Whether the metadata corresponds to a span or event.
|
||||
///
|
||||
/// In addition, the following optional metadata describing the source code
|
||||
/// location where the span or event originated _may_ be provided:
|
||||
/// - The [file name]
|
||||
/// - The [line number]
|
||||
/// - The [module path]
|
||||
///
|
||||
/// Metadata is used by [`Subscriber`]s when filtering spans and events, and it
|
||||
/// may also be used as part of their data payload.
|
||||
@@ -20,14 +33,22 @@ use std::fmt;
|
||||
/// filtering is based on metadata, rather than on the constructed span.
|
||||
///
|
||||
/// **Note**: Although instances of `Metadata` cannot be compared directly, they
|
||||
/// provide a method [`Metadata::id()`] which returns an an opaque [callsite
|
||||
/// identifier] which uniquely identifies the callsite where the metadata
|
||||
/// originated. This can be used for determining if two Metadata correspond to
|
||||
/// provide a method [`id`] which returns an an opaque [callsite identifier]
|
||||
/// which uniquely identifies the callsite where the metadata originated.
|
||||
/// This can be used for determining if two Metadata correspond to
|
||||
/// the same callsite.
|
||||
///
|
||||
/// [span]: ../span
|
||||
/// [span]: ../span/index.html
|
||||
/// [event]: ../event/index.html
|
||||
/// [name]: #method.name
|
||||
/// [target]: #method.target
|
||||
/// [fields]: #method.fields
|
||||
/// [verbosity level]: #method.level
|
||||
/// [file name]: #method.file
|
||||
/// [line number]: #method.line
|
||||
/// [module path]: #method.module
|
||||
/// [`Subscriber`]: ../subscriber/trait.Subscriber.html
|
||||
/// [`Metadata::id()`]: struct.Metadata.html#method.id
|
||||
/// [`id`]: struct.Metadata.html#method.id
|
||||
/// [callsite identifier]: ../callsite/struct.Identifier.html
|
||||
// TODO: When `const fn` is stable, make this type's fields private.
|
||||
pub struct Metadata<'a> {
|
||||
@@ -136,7 +157,7 @@ pub struct Metadata<'a> {
|
||||
pub kind: Kind,
|
||||
}
|
||||
|
||||
/// Indicate whether the callsite is a span or event.
|
||||
/// Indicates whether the callsite is a span or event.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Kind(KindInner);
|
||||
|
||||
@@ -175,12 +196,12 @@ impl<'a> Metadata<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the set of fields on the described span.
|
||||
/// Returns the names of the fields on the described span or event.
|
||||
pub fn fields(&self) -> &field::FieldSet {
|
||||
&self.fields
|
||||
}
|
||||
|
||||
/// Returns the level of verbosity of the described span.
|
||||
/// Returns the level of verbosity of the described span or event.
|
||||
pub fn level(&self) -> &Level {
|
||||
&self.level
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user