diff --git a/README.md b/README.md index 78e49e4470..34391af59d 100644 --- a/README.md +++ b/README.md @@ -41,11 +41,20 @@ idiomatic `tracing`.) In order to record trace events, executables have to use a `Subscriber` implementation compatible with `tracing`. A `Subscriber` implements a way of -collecting trace data, such as by logging it to standard output. [`tracing_subscriber`](https://docs.rs/tracing-subscriber/)'s -[`fmt` module](https://docs.rs/tracing-subscriber/0.2.6/tracing_subscriber/fmt/index.html) provides reasonable defaults. -Additionally, `tracing-subscriber` is able to consume messages emitted by `log`-instrumented libraries and modules. +collecting trace data, such as by logging it to standard output. +[`tracing_subscriber`]'s [`fmt` module][fmt] provides a subscriber for logging +traces with reasonable defaults. Additionally, `tracing-subscriber` is able to +consume messages emitted by `log`-instrumented libraries and modules. -The simplest way to use a subscriber is to call the `set_global_default` function. +To use `tracing-subscriber`, add the following to your `Cargo.toml`: + +```toml +[dependencies] +tracing = "0.1" +tracing-subscriber = "0.2" +``` + +To set a global subscriber for the entire program, use the `set_global_default` function: ```rust use tracing::{info, Level}; @@ -57,8 +66,11 @@ fn main() { // all spans/events with a level higher than TRACE (e.g, debug, info, warn, etc.) // will be written to stdout. .with_max_level(Level::TRACE) - // completes the builder and sets the constructed `Subscriber` as the default. - .init(); + // completes the builder + .finish(); + // and sets the constructed `Subscriber` as the default. + tracing::subscriber::set_global_default(subscriber) + .expect("no global subscriber has been set") let number_of_yaks = 3; // this creates a new event, outside of any spans. @@ -72,11 +84,9 @@ fn main() { } ``` -```toml -[dependencies] -tracing = "0.1" -tracing-subscriber = "0.2.6" -``` +[`tracing-subscriber`]: https://docs.rs/tracing-subscriber/ +[fmt]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/index.html +[`set_global_default`]: https://docs.rs/tracing/latest/tracing/subscriber/fn.set_global_default.html This subscriber will be used as the default in all threads for the remainder of the duration of the program, similar to how loggers work in the `log` crate. @@ -186,10 +196,9 @@ conflicts when executables try to set the default later. ### In Asynchronous Code If you are instrumenting code that make use of -[`std::future::Future`](https://doc.rust-lang.org/stable/std/future/trait.Future.html) -or async/await, be sure to use the -[`tracing-futures`](https://docs.rs/tracing-futures) crate. This is needed -because the following example _will not_ work: +[`std::future::Future`][std-future] or async/await, be sure to use the +[`tracing-futures`] crate. This is needed because the following example _will +not_ work: ```rust async { @@ -202,10 +211,10 @@ The span guard `_s` will not exit until the future generated by the `async` bloc Since futures and spans can be entered and exited _multiple_ times without them completing, the span remains entered for as long as the future exists, rather than being entered only when it is polled, leading to very confusing and incorrect output. -For more details, see [the documentation on closing spans](https://tracing.rs/tracing/span/index.html#closing-spans). +For more details, see [the documentation on closing spans][closing]. There are two ways to instrument asynchronous code. The first is through the -[`Future::instrument`](https://docs.rs/tracing-futures/0.2.1/tracing_futures/trait.Instrument.html#method.instrument) combinator: +[`Future::instrument`] combinator: ```rust use tracing_futures::Instrument; @@ -222,9 +231,7 @@ my_future `Future::instrument` attaches a span to the future, ensuring that the span's lifetime is as long as the future's. -The second, and preferred, option is through the -[`#[instrument]`](https://docs.rs/tracing/0.1.11/tracing/attr.instrument.html) -attribute: +The second, and preferred, option is through the [`#[instrument]`] attribute: ```rust use tracing::{info, instrument}; @@ -242,6 +249,13 @@ async fn write(stream: &mut TcpStream) -> io::Result { Under the hood, the `#[instrument]` macro performs same the explicit span attachment that `Future::instrument` does. +[std-future]: https://doc.rust-lang.org/stable/std/future/trait.Future.html +[`tracing-futures`]: https://docs.rs/tracing-futures +[closing]: https://docs.rs/tracing/latest/span/index.html#closing-spans +[`Future::instrument`]: https://docs.rs/tracing-futures/latest/tracing_futures/trait.Instrument.html#method.instrument +[`#[instrument]`]: https://docs.rs/tracing/0.1.11/tracing/attr.instrument.html + + ## Getting Help First, see if the answer to your question can be found in the API documentation. diff --git a/tracing-core/src/dispatcher.rs b/tracing-core/src/dispatcher.rs index 6e76d823ab..d37f5fb387 100644 --- a/tracing-core/src/dispatcher.rs +++ b/tracing-core/src/dispatcher.rs @@ -108,9 +108,16 @@ //! // `my_subscriber` is now the default //! ``` //! -//! **Note**: the thread-local scoped dispatcher (`with_default`) requires the -//! Rust standard library. `no_std` users should use [`set_global_default`] +//!
+//!
Note
+//!
+//!
+//!
+//! Note:the thread-local scoped dispatcher with_default
+//! requires the Rust standard library. no_std users should use
+//! set_global_default
 //! instead.
+//! 
//! //! Finally, `tokio` users should note that versions of `tokio` >= 0.1.22 //! support an `experimental-tracing` feature flag. When this flag is enabled, @@ -204,8 +211,15 @@ pub struct DefaultGuard(Option); /// The default dispatcher is used when creating a new [span] or /// [`Event`]. /// -/// **Note**: This function requires the Rust standard library. `no_std` users -/// should use [`set_global_default`] instead. +///
+///
Note
+///
+///
+///
+/// Note: This function required the Rust standard library.
+/// no_std users should use 
+/// set_global_default instead.
+/// 
/// /// [span]: ../span/index.html /// [`Subscriber`]: ../subscriber/trait.Subscriber.html @@ -225,8 +239,15 @@ pub fn with_default(dispatcher: &Dispatch, f: impl FnOnce() -> T) -> T { /// Sets the dispatch as the default dispatch for the duration of the lifetime /// of the returned DefaultGuard /// -/// **Note**: This function required the Rust standard library. `no_std` users -/// should use [`set_global_default`] instead. +///
+///
Note
+///
+///
+///
+/// Note: This function required the Rust standard library.
+/// no_std users should use 
+/// set_global_default instead.
+/// 
/// /// [`set_global_default`]: ../fn.set_global_default.html #[cfg(feature = "std")] @@ -246,8 +267,14 @@ pub fn set_default(dispatcher: &Dispatch) -> DefaultGuard { /// Can only be set once; subsequent attempts to set the global default will fail. /// Returns `Err` if the global default has already been set. /// -/// Note: Libraries should *NOT* call `set_global_default()`! That will cause conflicts when -/// executables try to set them later. +/// +///
+///
⚠ ️Warning
+///
+/// Warning: In general, libraries should not call
+/// set_global_default()! Doing so will cause conflicts when
+/// executables that depend on the library try to set the default later.
+/// 
/// /// [span]: ../span/index.html /// [`Subscriber`]: ../subscriber/trait.Subscriber.html @@ -525,8 +552,14 @@ impl Dispatch { /// This calls the [`drop_span`] function on the [`Subscriber`] that this /// `Dispatch` forwards to. /// - /// **Note:** the [`try_close`] function is functionally identical, but - /// returns `true` if the span is now closed. + ///
+ ///
⚠ ️Warning
+ ///
+ ///
+    /// Deprecated: The try_close
+    /// method is functionally identical, but returns true if the span is now closed.
+    /// It should be used instead of this method.
+    /// 
/// /// [span ID]: ../span/struct.Id.html /// [`Subscriber`]: ../subscriber/trait.Subscriber.html diff --git a/tracing-core/src/field.rs b/tracing-core/src/field.rs index 73ccbf16b5..7ead482cdc 100644 --- a/tracing-core/src/field.rs +++ b/tracing-core/src/field.rs @@ -169,8 +169,15 @@ pub struct Iter { /// `examples/counters.rs`, which demonstrates a very simple metrics system /// implemented using `tracing`. /// -/// **Note:** the `record_error` trait method is only available when the Rust -/// standard library is present, as it requires the `std::error::Error` trait. +///
+///
Note
+///
+///
+///
+/// Note: The record_error trait method is only
+/// available when the Rust standard library is present, as it requires the `
+/// std::error::Error trait.
+/// 
/// /// [`Value`]: trait.Value.html /// [recorded]: trait.Value.html#method.record @@ -202,8 +209,15 @@ pub trait Visit { /// Records a type implementing `Error`. /// - /// **Note**: this is only enabled when the Rust standard library is + ///
+ ///
Note
+ ///
+ ///
+ ///
+ ///
+    /// Note: This is only enabled when the Rust standard library is
     /// present.
+    /// 
#[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) { @@ -604,11 +618,20 @@ impl FieldSet { /// Returns `true` if `self` contains the given `field`. /// - /// **Note**: If `field` shares a name with a field in this `FieldSet`, but - /// was created by a `FieldSet` with a different callsite, this `FieldSet` - /// does _not_ contain it. This is so that if two separate span callsites - /// define a field named "foo", the `Field` corresponding to "foo" for each + ///
+ ///
Note
+ ///
+ ///
+ ///
+ ///
+    /// Note: If field shares a name with a field
+    /// in this FieldSet, but was created by a FieldSet
+    /// with a different callsite, this FieldSet does not
+    /// contain it. This is so that if two separate span callsites define a field
+    /// named "foo", the Field corresponding to "foo" for each
     /// of those callsites are not equivalent.
+    /// 
+ ///
pub fn contains(&self, field: &Field) -> bool { field.callsite() == self.callsite() && field.i <= self.len() } diff --git a/tracing-core/src/metadata.rs b/tracing-core/src/metadata.rs index 27fc77cba2..11562f946d 100644 --- a/tracing-core/src/metadata.rs +++ b/tracing-core/src/metadata.rs @@ -29,11 +29,18 @@ use crate::stdlib::{fmt, str::FromStr}; /// _significantly_ lower than that of creating the actual span. Therefore, /// filtering is based on metadata, rather than on the constructed span. /// -/// **Note**: Although instances of `Metadata` cannot be compared directly, they -/// provide a method [`id`] which returns an opaque [callsite identifier] -/// which uniquely identifies the callsite where the metadata originated. -/// This can be used for determining if two Metadata correspond to +///
+///
Note
+///
+///
+///
+/// Note: Although instances of Metadata cannot
+/// be compared directly, they provide a method 
+/// id, returning an opaque 
+/// callsite identifier  which uniquely identifies the callsite where the metadata
+/// originated. This can be used to determine if two Metadata correspond to
 /// the same callsite.
+/// 
/// /// [span]: ../span/index.html /// [event]: ../event/index.html diff --git a/tracing-core/src/span.rs b/tracing-core/src/span.rs index df529ee9d2..517233b403 100644 --- a/tracing-core/src/span.rs +++ b/tracing-core/src/span.rs @@ -60,7 +60,13 @@ enum CurrentInner { impl Id { /// Constructs a new span ID from the given `u64`. /// - /// **Note**: Span IDs must be greater than zero. + ///
+ ///
Note
+ ///
+ ///
+ ///
+ ///
+    /// Note: Span IDs must be greater than zero.
/// /// # Panics /// - If the provided `u64` is 0 diff --git a/tracing-subscriber/src/layer.rs b/tracing-subscriber/src/layer.rs index ebad54182f..05609f68ca 100644 --- a/tracing-subscriber/src/layer.rs +++ b/tracing-subscriber/src/layer.rs @@ -212,13 +212,24 @@ where /// By default, this returns [`Interest::always()`] if [`self.enabled`] returns /// true, or [`Interest::never()`] if it returns false. /// - /// **Note:** This method (and [`Layer::enabled`]) determine whether a - /// span or event is globally enabled, _not_ whether the individual layer - /// will be notified about that span or event. This is intended to be used + ///
+ ///
Note
+ ///
+ ///
+ ///
+ ///
+    /// Note: This method (and 
+    /// Layer::enabled) determine whether a span or event is
+    /// globally enabled, not whether the individual layer will be
+    /// notified about that span or event. This is intended to be used
     /// by layers that implement filtering for the entire stack. Layers which do
     /// not wish to be notified about certain spans or events but do not wish to
     /// globally disable them should ignore those spans or events in their
-    /// [`on_event`], [`on_enter`], [`on_exit`], and other notification methods.
+    /// on_event,
+    /// on_enter,
+    /// on_exit, and other notification
+    /// methods.
+    /// 
/// /// See [the trait-level documentation] for more information on filtering /// with `Layer`s. @@ -254,13 +265,24 @@ where /// By default, this always returns `true`, allowing the wrapped subscriber /// to choose to disable the span. /// - /// **Note:** This method (and [`Layer::register_callsite`]) determine whether a - /// span or event is globally enabled, _not_ whether the individual layer - /// will be notified about that span or event. This is intended to be used + ///
+ ///
Note
+ ///
+ ///
+ ///
+ ///
+    /// Note: This method (and 
+    /// Layer::register_callsite) determine whether a span or event is
+    /// globally enabled, not whether the individual layer will be
+    /// notified about that span or event. This is intended to be used
     /// by layers that implement filtering for the entire stack. Layers which do
     /// not wish to be notified about certain spans or events but do not wish to
     /// globally disable them should ignore those spans or events in their
-    /// [`on_event`], [`on_enter`], [`on_exit`], and other notification methods.
+    /// on_event,
+    /// on_enter,
+    /// on_exit, and other notification
+    /// methods.
+    /// 
/// /// /// See [the trait-level documentation] for more information on filtering @@ -848,15 +870,20 @@ impl<'a, S: Subscriber> Context<'a, S> { /// If this returns `None`, then no span exists for that ID (either it has /// closed or the ID is invalid). /// - /// **Note**: This requires the wrapped subscriber to implement the - /// [`LookupSpan`] trait. `Layer` implementations that wish to use this - /// function can bound their `Subscriber` type parameter with + ///
+ ///
Note
+ ///
+ ///
+ ///
+ ///
+    /// Note: This requires the wrapped subscriber to implement the
+    /// LookupSpan trait.
+    /// Layer implementations that wish to use this
+    /// function can bound their Subscriber type parameter with:
+    /// 
/// ```rust,ignore - /// where S: Subscriber + for<'a> LookupSpan<'a>, + /// where S: Subscriber + for<'a> LookupSpan<'a>,` /// ``` - /// or similar. - /// - /// [`LookupSpan`]: ../registry/trait.LookupSpan.html #[inline] #[cfg(feature = "registry")] #[cfg_attr(docsrs, doc(cfg(feature = "registry")))] @@ -873,13 +900,20 @@ impl<'a, S: Subscriber> Context<'a, S> { /// If this returns `None`, then no span exists for that ID (either it has /// closed or the ID is invalid). /// - /// **Note**: This requires the wrapped subscriber to implement the - /// [`LookupSpan`] trait. `Layer` implementations that wish to use this - /// function can bound their `Subscriber` type parameter with + ///
+ ///
Note
+ ///
+ ///
+ ///
+ ///
+    /// Note: This requires the wrapped subscriber to implement the
+    /// LookupSpan trait.
+    /// Layer implementations that wish to use this
+    /// function can bound their Subscriber type parameter with:
+    /// 
/// ```rust,ignore - /// where S: Subscriber + for<'span> LookupSpan<'span>, + /// where S: Subscriber + for<'a> LookupSpan<'a>,` /// ``` - /// or similar. /// /// [stored data]: ../registry/struct.SpanRef.html /// [`LookupSpan`]: ../registry/trait.LookupSpan.html @@ -895,13 +929,20 @@ impl<'a, S: Subscriber> Context<'a, S> { /// Returns `true` if an active span exists for the given `Id`. /// - /// **Note**: This requires the wrapped subscriber to implement the - /// [`LookupSpan`] trait. `Layer` implementations that wish to use this - /// function can bound their `Subscriber` type parameter with + ///
+ ///
Note
+ ///
+ ///
+ ///
+ ///
+    /// Note: This requires the wrapped subscriber to implement the
+    /// LookupSpan trait.
+    /// Layer implementations that wish to use this
+    /// function can bound their Subscriber type parameter with:
+    /// 
/// ```rust,ignore - /// where S: Subscriber + for<'a> LookupSpan<'a>, + /// where S: Subscriber + for<'a> LookupSpan<'a>,` /// ``` - /// or similar. /// /// [`LookupSpan`]: ../registry/trait.LookupSpan.html #[inline] @@ -919,13 +960,20 @@ impl<'a, S: Subscriber> Context<'a, S> { /// /// If this returns `None`, then we are not currently within a span. /// - /// **Note**: This requires the wrapped subscriber to implement the - /// [`LookupSpan`] trait. `Layer` implementations that wish to use this - /// function can bound their `Subscriber` type parameter with + ///
+ ///
Note
+ ///
+ ///
+ ///
+ ///
+    /// Note: This requires the wrapped subscriber to implement the
+    /// LookupSpan trait.
+    /// Layer implementations that wish to use this
+    /// function can bound their Subscriber type parameter with:
+    /// 
/// ```rust,ignore - /// where S: Subscriber + for<'span> LookupSpan<'span>, + /// where S: Subscriber + for<'a> LookupSpan<'a>,` /// ``` - /// or similar. /// /// [stored data]: ../registry/struct.SpanRef.html /// [`LookupSpan`]: ../registry/trait.LookupSpan.html @@ -954,13 +1002,20 @@ impl<'a, S: Subscriber> Context<'a, S> { /// /// If this iterator is empty, then there are no spans in the current context /// - /// **Note**: This requires the wrapped subscriber to implement the - /// [`LookupSpan`] trait. `Layer` implementations that wish to use this - /// function can bound their `Subscriber` type parameter with + ///
+ ///
Note
+ ///
+ ///
+ ///
+ ///
+    /// Note: This requires the wrapped subscriber to implement the
+    /// LookupSpan trait.
+    /// Layer implementations that wish to use this
+    /// function can bound their Subscriber type parameter with:
+    /// 
/// ```rust,ignore - /// where S: Subscriber + for<'span> LookupSpan<'span>, + /// where S: Subscriber + for<'a> LookupSpan<'a>,` /// ``` - /// or similar. /// /// [stored data]: ../registry/struct.SpanRef.html /// [`LookupSpan`]: ../registry/trait.LookupSpan.html diff --git a/tracing-subscriber/src/registry/mod.rs b/tracing-subscriber/src/registry/mod.rs index 3f3421de1e..4eae69ba0b 100644 --- a/tracing-subscriber/src/registry/mod.rs +++ b/tracing-subscriber/src/registry/mod.rs @@ -94,13 +94,20 @@ pub trait LookupSpan<'a> { /// Returns the [`SpanData`] for a given `Id`, if it exists. /// - /// **Note**: users of the `LookupSpan` trait should typically call the - /// [`span`] method rather than this method. The `span` method is - /// implemented by calling `span_data`, but returns a reference which is + ///
+ ///
Note
+ ///
+ ///
+ ///
+ ///
+    /// Note: users of the LookupSpan trait should
+    /// typically call the span method rather
+    /// than this method. The span method is implemented by
+    /// calling span_data, but returns a reference which is
     /// capable of performing more sophisiticated queries.
+    /// 
/// /// [`SpanData`]: trait.SpanData.html - /// [`span`]: #method.span fn span_data(&'a self, id: &Id) -> Option; /// Returns a [`SpanRef`] for the span with the given `Id`, if it exists. diff --git a/tracing/src/dispatcher.rs b/tracing/src/dispatcher.rs index 83579c61c6..ea9feec83c 100644 --- a/tracing/src/dispatcher.rs +++ b/tracing/src/dispatcher.rs @@ -107,10 +107,16 @@ //! //! // `my_subscriber` is now the default //! ``` -//! -//! **Note**: the thread-local scoped dispatcher (`with_default`) requires the -//! Rust standard library. `no_std` users should use [`set_global_default`] +//!
+//!
Note
+//!
+//!
//! //! Finally, `tokio` users should note that versions of `tokio` >= 0.1.22 //! support an `experimental-tracing` feature flag. When this flag is enabled, diff --git a/tracing/src/field.rs b/tracing/src/field.rs index 5b683e012a..2514336585 100644 --- a/tracing/src/field.rs +++ b/tracing/src/field.rs @@ -5,13 +5,19 @@ use crate::Metadata; /// Trait implemented to allow a type to be used as a field key. /// -/// **Note**: Although this is implemented for both the [`Field`] type *and* any -/// type that can be borrowed as an `&str`, only `Field` allows _O_(1) access. +///
+///
Note
+///
+///
+///
+/// Note: Although this is implemented for both the
+/// Field type and any
+/// type that can be borrowed as an &str, only Field
+/// allows O(1) access.
 /// 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
 /// should be used whenever possible.
-///
-/// [`Field`]: ./struct.Field.html
+/// 
pub trait AsField: crate::sealed::Sealed { /// Attempts to convert `&self` into a `Field` with the specified `metadata`. /// diff --git a/tracing/src/lib.rs b/tracing/src/lib.rs index ec91df8776..f32f67fc7b 100644 --- a/tracing/src/lib.rs +++ b/tracing/src/lib.rs @@ -49,11 +49,21 @@ //! The [`span` module][span]'s documentation provides further details on how to //! use spans. //! +//!
+//!
⚠ ️Warning
+//!
+//!     Warning: In asynchronous code that uses async/await syntax,
+//!     Span::enter may produce incorrect traces if the returned drop
+//!     guard is held across an await point. See
+//!     the method documentation
+//!     for details.
+//! 
+//! //! ## Events //! //! An [`Event`] represents a _moment_ in time. It signifies something that //! happened while a trace was being recorded. `Event`s are comparable to the log -//! records emitted by unstructured logging code, but unlike a typical log line, +//! records emitted by unstructured logging code, but unlike a typical log line,``s //! an `Event` may occur within the context of a span. //! //! For example: @@ -160,8 +170,15 @@ //! # fn main() {} //! ``` //! -//! **Note**: using `#[instrument]` on `async fn`s requires the -//! [`tracing-futures`] crate as a dependency, as well. +//!
+//!
Note
+//!
+//!
+//!
+//!     Note: Using #[instrument] on
+//!     async fns requires the 
+//!     tracing-futures crate as a dependency as well.
+//! 
//! //! You can find more examples showing how to use this crate [here][examples]. //! @@ -537,8 +554,13 @@ //! # } //! ``` //! -//! **Note:** Libraries should *NOT* call `set_global_default()`! That will -//! cause conflicts when executables try to set the default later. +//!
+//!
⚠ ️Warning
+//!
+//! Warning: In general, libraries should not call
+//! set_global_default()! Doing so will cause conflicts when
+//! executables that depend on the library try to set the default later.
+//! 
//! //! This subscriber will be used as the default in all threads for the //! remainder of the duration of the program, similar to setting the logger @@ -695,9 +717,15 @@ //! [`tracing-bunyan-formatter`]: https://crates.io/crates/tracing-bunyan-formatter //! [bunyan]: https://github.com/trentm/node-bunyan //! -//! **Note:** that some of the ecosystem crates are currently unreleased and -//! undergoing active development. They may be less stable than `tracing` and -//! `tracing-core`. +//!
+//!
Note
+//!
+//!
+//!
+//! Note: Some of these ecosystem crates are currently
+//! unreleased and/or in earlier stages of development. They may be less stable
+//! than tracing and tracing-core.
+//! 
//! //! ## Crate Feature Flags //! @@ -708,8 +736,6 @@ //! as trace events, if a default `tracing` subscriber has not been set. This //! is intended for use in libraries whose users may be using either `tracing` //! or `log`. -//! **Note:** `log` support will not work when `tracing` is renamed in `Cargo.toml`, -//! due to oddities in macro expansion. //! * `log-always`: Emit `log` records from all `tracing` spans and events, even //! a `tracing` subscriber has been set. This should be set only by //! applications which intend to collect traces and logs separately; if an @@ -729,7 +755,15 @@ //! //! *Compiler support: requires rustc 1.39+* //! -//! **Note**:`tracing`'s `no_std` support requires `liballoc`. +//!
+//!
Note
+//!
+//!
+//!
+//! Note: tracing's no_std support
+//! requires liballoc.
+//! 
+//!
//! //! [`log`]: https://docs.rs/log/0.4.6/log/ //! [span]: span/index.html diff --git a/tracing/src/span.rs b/tracing/src/span.rs index fdf1eca239..c3b022fc1e 100644 --- a/tracing/src/span.rs +++ b/tracing/src/span.rs @@ -76,6 +76,16 @@ //! // Dropping the `_enter` guard will exit the span. //!``` //! +//!
+//!
⚠ ️Warning
+//!
+//!     Warning: In asynchronous code that uses async/await syntax,
+//!     Span::enter may produce incorrect traces if the returned drop
+//!     guard is held across an await point. See
+//!     the method documentation
+//!     for details.
+//! 
+//! //! `in_scope` takes a closure or function pointer and executes it inside the //! span. //! ``` @@ -95,9 +105,16 @@ //! }); //! ``` //! -//! **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 +//!
+//!
Note
+//!
+//!
+//!
+//! Note: Since entering a span takes &selfSpans are Clone, Send, and
+//! Sync, it is entirely valid for multiple threads to enter the
 //! same span concurrently.
+//! 
//! //! ## Span Relationships //! @@ -505,7 +522,132 @@ impl Span { /// /// If this span is enabled by the current subscriber, then this function will /// call [`Subscriber::enter`] with the span's [`Id`], and dropping the guard - /// will call [`Subscriber::exit`]. If the span is disabled, this does nothing. + /// will call [`Subscriber::exit`]. If the span is disabled, this does + /// nothing. + /// + /// # In Asynchronous Code + /// + /// **Warning**: in asynchronous code that uses [async/await syntax][syntax], + /// `Span::enter` should be used very carefully or avoided entirely. Holding + /// the drop guard returned by `Span::enter` across `.await` points will + /// result in incorrect traces. + /// + /// For example, + /// + /// ``` + /// # use tracing::info_span; + /// # async fn some_other_async_function() {} + /// async fn my_async_function() { + /// let span = info_span!("my_async_function"); + /// + /// // THIS WILL RESULT IN INCORRECT TRACES + /// let _enter = span.enter(); + /// some_other_async_function().await; + /// + /// // ... + /// } + /// ``` + /// + /// The drop guard returned by `Span::enter` exits the span when it is + /// dropped. When an async function or async block yields at an `.await` + /// point, the current scope is _exited_, but values in that scope are + /// **not** dropped (because the async block will eventually resume + /// execution from that await point). This means that _another_ task will + /// begin executing while _remaining_ in the entered span. This results in + /// an incorrect trace. + /// + /// Instead of using `Span::enter` in asynchronous code, prefer the + /// following: + /// + /// * To enter a span for a synchronous section of code within an async + /// block or function, prefer [`Span::in_scope`]. Since `in_scope` takes a + /// synchronous closure and exits the span when the closure returns, the + /// span will always be exited before the next await point. For example: + /// ``` + /// # use tracing::info_span; + /// # async fn some_other_async_function(_: ()) {} + /// async fn my_async_function() { + /// let span = info_span!("my_async_function"); + /// + /// let some_value = span.in_scope(|| { + /// // run some synchronous code inside the span... + /// }); + /// + /// // This is okay! The span has already been exited before we reach + /// // the await point. + /// some_other_async_function(some_value).await; + /// + /// // ... + /// } + /// ``` + /// * For instrumenting asynchronous code, the [`tracing-futures` crate] + /// provides the [`Future::instrument` combinator][instrument] for + /// attaching a span to a future (async function or block). This will + /// enter the span _every_ time the future is polled, and exit it whenever + /// the future yields. + /// + /// `Instrument` can be used with an async block inside an async function: + /// ```ignore + /// # use tracing::info_span; + /// use tracing_futures::Instrument; + /// + /// # async fn some_other_async_function() {} + /// async fn my_async_function() { + /// let span = info_span!("my_async_function"); + /// async move { + /// // This is correct! If we yield here, the span will be exited, + /// // and re-entered when we resume. + /// some_other_async_function().await; + /// + /// //more asynchronous code inside the span... + /// + /// } + /// // instrument the async block with the span... + /// .instrument(span) + /// // ...and await it. + /// .await + /// } + /// ``` + /// + /// It can also be used to instrument calls to async functions at the + /// callsite: + /// ```ignore + /// # use tracing::debug_span; + /// use tracing_futures::Instrument; + /// + /// # async fn some_other_async_function() {} + /// async fn my_async_function() { + /// let some_value = some_other_async_function() + /// .instrument(debug_span!("some_other_async_function")) + /// .await; + /// + /// // ... + /// } + /// ``` + /// + /// * Finally, if your crate depends on the `tracing-futures` crate, the + /// [`#[instrument]` attribute macro][attr] will automatically generate + /// correct code when used on an async function: + /// + /// ```ignore + /// # async fn some_other_async_function() {} + /// #[tracing::instrument(level = "info")] + /// async fn my_async_function() { + /// + /// // This is correct! If we yield here, the span will be exited, + /// // and re-entered when we resume. + /// some_other_async_function().await; + /// + /// // ... + /// + /// } + /// ``` + /// + /// [syntax]: https://rust-lang.github.io/async-book/01_getting_started/04_async_await_primer.html + /// [`Span::in_scope`]: #method.in_scope + /// [`tracing-futures` crate]: https://docs.rs/tracing-futures/ + /// [instrument]: https://docs.rs/tracing-futures/latest/tracing_futures/trait.Instrument.html + /// [attr]: ../../attr.instrument.html /// /// # Examples /// @@ -680,11 +822,18 @@ impl Span { /// } /// ``` /// - /// **Note**: The fields associated with a span are part of its [`Metadata`]. - /// The [`Metadata`] describing a particular span is constructed statically when the span is - /// created and cannot be extended later to add new fields. - /// Therefore, you cannot record a value for a field that was not specified when the span - /// was created: + ///
+ ///
Note
+ ///
+ ///
+ ///
+    /// Note: The fields associated with a span are part of its
+    /// Metadata.
+    /// The Metadata. describing a particular
+    /// span is constructed statically when the span is created and cannot be extended later to
+    /// add new fields. Therefore, you cannot record a value for a field that was not specified
+    /// when the span was created:
+ /// /// ``` /// use tracing::{trace_span, field}; /// @@ -704,6 +853,7 @@ impl Span { /// // This `record` call will indeed replace field::Empty with "you will be remembered". /// span.record("parting", &"you will be remembered"); /// ``` + /// /// [`field::Empty`]: ../field/struct.Empty.html /// [`Metadata`]: ../struct.Metadata.html pub fn record(&self, field: &Q, value: &V) -> &Self