trace: prepare tokio-trace for release (#1051)

This commit is contained in:
Eliza Weisman 2019-04-22 14:15:07 -07:00 committed by Carl Lerche
parent fea1f780bc
commit 3ebca76a9a
8 changed files with 200 additions and 69 deletions

3
tokio-trace/CHANGELOG.md Normal file
View File

@ -0,0 +1,3 @@
# 0.1.0 (April 22, 2019)
- Initial release

View File

@ -1,21 +1,26 @@
[package] [package]
name = "tokio-trace" name = "tokio-trace"
version = "0.0.1" # When releasing to crates.io:
authors = ["Eliza Weisman <eliza@buoyant.io>"] # - Update html_root_url.
# - Update doc url
# - Cargo.toml
# - README.md
# - Update CHANGELOG.md.
# - Create "v0.1.x" git tag
version = "0.1.0"
authors = ["Tokio Contributors <team@tokio.rs>"]
license = "MIT" license = "MIT"
repository = "https://github.com/tokio-rs/tokio" repository = "https://github.com/tokio-rs/tokio"
homepage = "https://tokio.rs" homepage = "https://tokio.rs"
documentation = "https://docs.rs/tokio-trace/0.1.0/tokio_trace"
description = """ description = """
A scoped, structured logging and diagnostics system. A scoped, structured logging and diagnostics system.
""" """
categories = ["development-tools::debugging", "asynchronous"] categories = ["development-tools::debugging", "asynchronous"]
keywords = ["logging", "tracing"] keywords = ["logging", "tracing"]
# Not yet ready for production.
publish = false
[dependencies] [dependencies]
tokio-trace-core = { path = "./tokio-trace-core" } tokio-trace-core = "0.2"
log = { version = "0.4", optional = true } log = { version = "0.4", optional = true }
cfg-if = "0.1.7" cfg-if = "0.1.7"

View File

@ -2,7 +2,7 @@
A scoped, structured logging and diagnostics system. A scoped, structured logging and diagnostics system.
[Documentation](https://tokio-rs.github.io/tokio/doc/tokio_trace/) [Documentation](https://docs.rs/tokio-trace/0.1.0/tokio_trace/index.html)
## Overview ## Overview
@ -29,7 +29,7 @@ First, add this to your `Cargo.toml`:
```toml ```toml
[dependencies] [dependencies]
tokio-trace = { git = "https://github.com/tokio-rs/tokio" } tokio-trace = "0.1"
``` ```
Next, add this to your crate: Next, add this to your crate:

View File

@ -10,6 +10,8 @@ use Metadata;
/// Indexing a field with a string results in an iterative search that performs /// Indexing a field with a string results in an iterative search that performs
/// string comparisons. Thus, if possible, once the key for a field is known, it /// string comparisons. Thus, if possible, once the key for a field is known, it
/// should be used whenever possible. /// should be used whenever possible.
///
/// [`Field`]: ../struct.Field.html
pub trait AsField: ::sealed::Sealed { pub trait AsField: ::sealed::Sealed {
/// Attempts to convert `&self` into a `Field` with the specified `metadata`. /// Attempts to convert `&self` into a `Field` with the specified `metadata`.
/// ///

View File

@ -1,15 +1,59 @@
//! Trace verbosity level filtering.
//!
//! # Compile time filters
//!
//! Trace verbosity levels can be statically disabled at compile time via Cargo
//! features, similar to the [`log` crate]. Trace instrumentation at disabled
//! levels will be skipped and will not even be present in the resulting binary
//! unless the verbosity level is specified dynamically. This level is
//! configured separately for release and debug builds. The features are:
//!
//! * `max_level_off`
//! * `max_level_error`
//! * `max_level_warn`
//! * `max_level_info`
//! * `max_level_debug`
//! * `max_level_trace`
//! * `release_max_level_off`
//! * `release_max_level_error`
//! * `release_max_level_warn`
//! * `release_max_level_info`
//! * `release_max_level_debug`
//! * `release_max_level_trace`
//!
//! These features control the value of the `STATIC_MAX_LEVEL` constant. The
//! instrumentation macros macros check this value before recording an event or
//! constructing a span. By default, no levels are disabled.
//!
//! For example, a crate can disable trace level instrumentation in debug builds
//! and trace, debug, and info level instrumentation in release builds with the
//! following configuration:
//!
//! ```toml
//! [dependencies]
//! tokio-trace = { version = "0.1", features = ["max_level_debug", "release_max_level_warn"] }
//! ```
//!
//! [`log` crate]: https://docs.rs/log/0.4.6/log/#compile-time-filters
use std::cmp::Ordering; use std::cmp::Ordering;
use tokio_trace_core::Level; use tokio_trace_core::Level;
/// `LevelFilter` is used to statistically filter the logging messages based on its `Level`. /// A filter comparable to trace verbosity `Level`.
/// Logging messages will be discarded if its `Level` is greater than `LevelFilter`. ///
/// If a `Level` is considered less than a `LevelFilter`, it should be
/// considered disabled; if greater than or equal to the `LevelFilter`, that
/// level is enabled.
///
/// Note that this is essentially identical to the `Level` type, but with the
/// addition of an `OFF` level that completely disables all trace
/// instrumentation.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct LevelFilter(Option<Level>); pub struct LevelFilter(Option<Level>);
impl LevelFilter { impl LevelFilter {
/// The "off" level. /// The "off" level.
/// ///
/// Designates that logging should be to turned off. /// Designates that trace instrumentation should be completely disabled.
pub const OFF: LevelFilter = LevelFilter(None); pub const OFF: LevelFilter = LevelFilter(None);
/// The "error" level. /// The "error" level.
/// ///
@ -51,12 +95,17 @@ impl PartialOrd<LevelFilter> for Level {
} }
} }
/// The statically resolved maximum trace level. /// The statically configured maximum trace level.
/// ///
/// See the crate level documentation for information on how to configure this. /// See the [module-level documentation] for information on how to configure
/// this.
/// ///
/// This value is checked by the `event` macro. Code that manually calls functions on that value /// This value is checked by the `event!` and `span!` macros. Code that
/// should compare the level against this value. /// manually constructs events or spans via the `Event::record` function or
/// `Span` constructors should compare the level against this value to
/// determine if those spans or events are enabled.
///
/// [module-level documentation]: ../index.html#compile-time-filters
pub const STATIC_MAX_LEVEL: LevelFilter = MAX_LEVEL; pub const STATIC_MAX_LEVEL: LevelFilter = MAX_LEVEL;
cfg_if! { cfg_if! {

View File

@ -1,3 +1,6 @@
#![doc(html_root_url = "https://docs.rs/tokio-trace/0.1.0")]
#![deny(missing_debug_implementations, missing_docs, unreachable_pub)]
#![cfg_attr(test, deny(warnings))]
//! A scoped, structured logging and diagnostics system. //! A scoped, structured logging and diagnostics system.
//! //!
//! # Overview //! # Overview
@ -32,6 +35,20 @@
//! another context. The span in which a thread is currently executing is //! another context. The span in which a thread is currently executing is
//! referred to as the _current_ span. //! referred to as the _current_ span.
//! //!
//! For example:
//! ```
//! #[macro_use]
//! extern crate tokio_trace;
//!
//! use tokio_trace::Level;
//!
//! # fn main() {
//! span!(Level::TRACE, "my_span").enter(|| {
//! // perform some work in the context of `my_span`...
//! });
//! # }
//!```
//!
//! Spans form a tree structure — unless it is a root span, all spans have a //! 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, //! _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 //! the current span becomes the new span's parent. The total execution time of
@ -39,10 +56,43 @@
//! represented by its children. Thus, a parent span always lasts for at least //! represented by its children. Thus, a parent span always lasts for at least
//! as long as the longest-executing span in its subtree. //! 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").enter(|| {
//! // since we are now inside "root", this span is considered a child
//! // of "root":
//! span!(Level::DEBUG, "outer_child").enter(|| {
//! // this span is a child of "outer_child", which is in turn a
//! // child of "root":
//! span!(Level::TRACE, "inner_child").enter(|| {
//! // and so on...
//! });
//! });
//! });
//! # }
//!```
//!
//! In addition, data may be associated with spans. A span may have _fields_ — //! 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 //! 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 //! span; an optional name, and metadata describing the source code location
//! where the span was originally entered. //! 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, baz);
//!
//! // record a value for the field "baz" declared above:
//! my_span.record("baz", &"hello world");
//! # }
//!```
//! //!
//! ### When to use spans //! ### When to use spans
//! //!
@ -95,9 +145,22 @@
//! records emitted by unstructured logging code, but unlike a typical log line, //! records emitted by unstructured logging code, but unlike a typical log line,
//! an `Event` may occur within the context of a `Span`. Like a `Span`, it //! an `Event` may occur within the context of a `Span`. Like a `Span`, it
//! may have fields, and implicitly inherits any of the fields present on its //! may have fields, and implicitly inherits any of the fields present on its
//! parent span, and it may be linked with one or more additional //! parent span.
//! spans that are not its parent; in this case, the event is said to _follow //!
//! from_ those spans. //! For example:
//! ```
//! # #[macro_use] extern crate tokio_trace;
//! # use tokio_trace::Level;
//! # fn main() {
//! // records an event outside of any span context:
//! event!(Level::INFO, "something happened");
//!
//! span!(Level::INFO, "my_span").enter(|| {
//! // records an event within "my_span".
//! event!(Level::DEBUG, "something happened inside my_span");
//! });
//! # }
//!```
//! //!
//! Essentially, `Event`s exist to bridge the gap between traditional //! Essentially, `Event`s exist to bridge the gap between traditional
//! unstructured logging and span-based tracing. Similar to log records, they //! unstructured logging and span-based tracing. Similar to log records, they
@ -139,7 +202,7 @@
//! //!
//! ```toml //! ```toml
//! [dependencies] //! [dependencies]
//! tokio-trace = { git = "https://github.com/tokio-rs/tokio" } //! tokio-trace = "0.1"
//! ``` //! ```
//! //!
//! Next, add this to your crate: //! Next, add this to your crate:
@ -230,13 +293,13 @@
//! You can find examples showing how to use this crate in the examples //! You can find examples showing how to use this crate in the examples
//! directory. //! directory.
//! //!
//! ### In libraries //! ## In libraries
//! //!
//! Libraries should link only to the `tokio-trace` crate, and use the provided //! Libraries should link only to the `tokio-trace` crate, and use the provided
//! macros to record whatever information will be useful to downstream //! macros to record whatever information will be useful to downstream
//! consumers. //! consumers.
//! //!
//! ### In executables //! ## In executables
//! //!
//! In order to record trace events, executables have to use a `Subscriber` //! In order to record trace events, executables have to use a `Subscriber`
//! implementation compatible with `tokio-trace`. A `Subscriber` implements a //! implementation compatible with `tokio-trace`. A `Subscriber` implements a
@ -264,6 +327,7 @@
//! # fn new() -> Self { FooSubscriber } //! # fn new() -> Self { FooSubscriber }
//! # } //! # }
//! # fn main() { //! # fn main() {
//!
//! let my_subscriber = FooSubscriber::new(); //! let my_subscriber = FooSubscriber::new();
//! //!
//! tokio_trace::subscriber::with_default(my_subscriber, || { //! tokio_trace::subscriber::with_default(my_subscriber, || {
@ -299,6 +363,21 @@
//! trace tree. This is useful when a project using `tokio-trace` have //! trace tree. This is useful when a project using `tokio-trace` have
//! dependencies which use `log`. //! dependencies which use `log`.
//! //!
//!
//! ## Crate Feature Flags
//!
//! The following crate feature flags are available:
//!
//! * A set of features controlling the [static verbosity level].
//! * `log` causes trace instrumentation points to emit [`log`] records as well
//! as trace events. This is inteded for use in libraries whose users may be
//! using either `tokio-trace` or `log`.
//!
//! ```toml
//! [dependencies]
//! tokio-trace = { version = "0.1", features = ["log"] }
//! ```
//!
//! [`log`]: https://docs.rs/log/0.4.6/log/ //! [`log`]: https://docs.rs/log/0.4.6/log/
//! [`Span`]: span/struct.Span //! [`Span`]: span/struct.Span
//! [`Event`]: struct.Event.html //! [`Event`]: struct.Event.html
@ -312,6 +391,7 @@
//! [`tokio-trace-futures`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-futures //! [`tokio-trace-futures`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-futures
//! [`tokio-trace-fmt`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-fmt //! [`tokio-trace-fmt`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-fmt
//! [`tokio-trace-log`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-log //! [`tokio-trace-log`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-log
//! [static verbosity level]: level_filters/index.html#compile-time-filters
#[macro_use] #[macro_use]
extern crate cfg_if; extern crate cfg_if;
extern crate tokio_trace_core; extern crate tokio_trace_core;

View File

@ -4,7 +4,7 @@
//! //!
//! A thread of execution is said to _enter_ a span when it begins executing, //! 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 //! 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, //! entered through the [`enter`] method, which enters the target span,
//! performs a given function (either a closure or a function pointer), exits //! performs a given function (either a closure or a function pointer), exits
//! the span, and then returns the result. //! the span, and then returns the result.
//! //!
@ -68,11 +68,10 @@
//! Because spans may be entered and exited multiple times before they close, //! Because spans may be entered and exited multiple times before they close,
//! [`Subscriber`]s have separate trait methods which are called to notify them //! [`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 //! 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 //! span, [`exit`] will always be called with that span's ID to notify the
//! to notify the subscriber that the span has been exited. When span handles //! subscriber that the span has been exited. When span handles are dropped, the
//! are dropped, the [`drop_span`](::Subscriber::drop_span) method is called //! [`drop_span`] method is called with that span's ID. The subscriber may use
//! with that span's ID. The subscriber may use this to determine whether or not //! this to determine whether or not the span will be entered again.
//! the span will be entered again.
//! //!
//! If there is only a single handle with the capacity to exit a span, dropping //! 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 "close" the span, since the capacity to enter it no longer
@ -87,34 +86,20 @@
//! }); // --> Subscriber::exit(my_span) //! }); // --> Subscriber::exit(my_span)
//! //!
//! // The handle to `my_span` only lives inside of this block; when it is //! // 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. //! // dropped, the subscriber will be informed via `drop_span`.
//! //!
//! } // --> Subscriber::close(my_span) //! } // --> Subscriber::drop_span(my_span)
//! # } //! # }
//! ``` //! ```
//! //!
//! A span may be explicitly closed by dropping a handle to it, if it is the only
//! handle to that span.
//! time it is exited. For example:
//! ```
//! # #[macro_use] extern crate tokio_trace;
//! # use tokio_trace::Level;
//! # fn main() {
//! use tokio_trace::Span;
//!
//! let my_span = span!(Level::TRACE, "my_span");
//! // Drop the handle to the span.
//! drop(my_span); // --> Subscriber::drop_span(my_span)
//! # }
//! ```
//! However, if multiple handles exist, the span can still be re-entered even if //! 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 //! 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) //! been dropped, `Subscriber`s have a [`clone_span`] method, which is called
//! method, which is called every time a span handle is cloned. Combined with //! every time a span handle is cloned. Combined with `drop_span`, this may be
//! `drop_span`, this may be used to track the number of handles to a given span //! used to track the number of handles to a given span — if `drop_span` has
//! — if `drop_span` has been called one more time than the number of calls to //! been called one more time than the number of calls to `clone_span` for a
//! `clone_span` for a given ID, then no more handles to the span with that ID //! given ID, then no more handles to the span with that ID exist. The
//! exist. The subscriber may then treat it as closed. //! subscriber may then treat it as closed.
//! //!
//! # Accessing a Span's Attributes //! # Accessing a Span's Attributes
//! //!
@ -125,7 +110,12 @@
//! to the [`Subscriber`] when the span is created; it may then choose to cache //! 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. //! the data for future use, record it in some manner, or discard it completely.
//! //!
//! [`Subscriber`]: ::Subscriber //! [`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
//! [`Subscriber`]: ../subscriber/trait.Subscriber.html
//! [`Attributes`]: struct.Attributes.html
//! [`enter`]: struct.Span.html#method.enter
pub use tokio_trace_core::span::{Attributes, Id, Record}; pub use tokio_trace_core::span::{Attributes, Id, Record};
use std::{ use std::{
@ -136,6 +126,8 @@ use {dispatcher::Dispatch, field, Metadata};
/// Trait implemented by types which have a span `Id`. /// Trait implemented by types which have a span `Id`.
pub trait AsId: ::sealed::Sealed { pub trait AsId: ::sealed::Sealed {
/// Returns the `Id` of the span that `self` corresponds to, or `None` if
/// this corresponds to a disabled span.
fn as_id(&self) -> Option<&Id>; fn as_id(&self) -> Option<&Id>;
} }
@ -188,8 +180,8 @@ struct Entered<'a> {
// ===== impl Span ===== // ===== impl Span =====
impl Span { impl Span {
/// Constructs a new `Span` with the given [metadata] and set of [field /// Constructs a new `Span` with the given [metadata] and set of
/// values]. /// [field values].
/// ///
/// The new span will be constructed by the currently-active [`Subscriber`], /// The new span will be constructed by the currently-active [`Subscriber`],
/// with the current span as its parent (if one exists). /// with the current span as its parent (if one exists).
@ -197,10 +189,10 @@ impl Span {
/// After the span is constructed, [field values] and/or [`follows_from`] /// After the span is constructed, [field values] and/or [`follows_from`]
/// annotations may be added to it. /// annotations may be added to it.
/// ///
/// [metadata]: ::metadata::Metadata /// [metadata]: ../metadata
/// [`Subscriber`]: ::subscriber::Subscriber /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
/// [field values]: ::field::ValueSet /// [field values]: ../field/struct.ValueSet.html
/// [`follows_from`]: ::span::Span::follows_from /// [`follows_from`]: ../struct.Span.html#method.follows_from
#[inline] #[inline]
pub fn new(meta: &'static Metadata<'static>, values: &field::ValueSet) -> Span { pub fn new(meta: &'static Metadata<'static>, values: &field::ValueSet) -> Span {
let new_span = Attributes::new(meta, values); let new_span = Attributes::new(meta, values);
@ -213,9 +205,9 @@ impl Span {
/// After the span is constructed, [field values] and/or [`follows_from`] /// After the span is constructed, [field values] and/or [`follows_from`]
/// annotations may be added to it. /// annotations may be added to it.
/// ///
/// [metadata]: ::metadata::Metadata /// [metadata]: ../metadata
/// [field values]: ::field::ValueSet /// [field values]: ../field/struct.ValueSet.html
/// [`follows_from`]: ::span::Span::follows_from /// [`follows_from`]: ../struct.Span.html#method.follows_from
#[inline] #[inline]
pub fn new_root(meta: &'static Metadata<'static>, values: &field::ValueSet) -> Span { pub fn new_root(meta: &'static Metadata<'static>, values: &field::ValueSet) -> Span {
Self::make(meta, Attributes::new_root(meta, values)) Self::make(meta, Attributes::new_root(meta, values))
@ -227,9 +219,9 @@ impl Span {
/// After the span is constructed, [field values] and/or [`follows_from`] /// After the span is constructed, [field values] and/or [`follows_from`]
/// annotations may be added to it. /// annotations may be added to it.
/// ///
/// [metadata]: ::metadata::Metadata /// [metadata]: ../metadata
/// [field values]: ::field::ValueSet /// [field values]: ../field/struct.ValueSet.html
/// [`follows_from`]: ::span::Span::follows_from /// [`follows_from`]: ../struct.Span.html#method.follows_from
pub fn child_of<I>( pub fn child_of<I>(
parent: I, parent: I,
meta: &'static Metadata<'static>, meta: &'static Metadata<'static>,
@ -278,8 +270,8 @@ impl Span {
result result
} }
/// Returns a [`Field`](::field::Field) for the field with the given `name`, if /// Returns a [`Field`](../field/struct.Field.html) for the field with the
/// one exists, /// given `name`, if one exists,
pub fn field<Q: ?Sized>(&self, field: &Q) -> Option<field::Field> pub fn field<Q: ?Sized>(&self, field: &Q) -> Option<field::Field>
where where
Q: field::AsField, Q: field::AsField,
@ -288,7 +280,7 @@ impl Span {
} }
/// Returns true if this `Span` has a field for the given /// Returns true if this `Span` has a field for the given
/// [`Field`](::field::Field) or field name. /// [`Field`](../field/struct.Field.html) or field name.
#[inline] #[inline]
pub fn has_field<Q: ?Sized>(&self, field: &Q) -> bool pub fn has_field<Q: ?Sized>(&self, field: &Q) -> bool
where where
@ -450,7 +442,7 @@ impl Inner {
/// writing custom span handles, but should generally not be called directly /// writing custom span handles, but should generally not be called directly
/// when entering a span. /// when entering a span.
#[inline] #[inline]
fn enter<'a>(&'a self) -> Entered<'a> { fn enter(&self) -> Entered {
self.subscriber.enter(&self.id); self.subscriber.enter(&self.id);
Entered { inner: self } Entered { inner: self }
} }

View File

@ -8,9 +8,9 @@ pub use tokio_trace_core::subscriber::*;
/// executing, new spans or events are dispatched to the subscriber that /// executing, new spans or events are dispatched to the subscriber that
/// tagged that span, instead. /// tagged that span, instead.
/// ///
/// [`Span`]: ::span::Span /// [`Span`]: ../span/struct.Span.html
/// [`Subscriber`]: ::Subscriber /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
/// [`Event`]: ::Event /// [`Event`]: :../event/struct.Event.html
pub fn with_default<T, S>(subscriber: S, f: impl FnOnce() -> T) -> T pub fn with_default<T, S>(subscriber: S, f: impl FnOnce() -> T) -> T
where where
S: Subscriber + Send + Sync + 'static, S: Subscriber + Send + Sync + 'static,