From 8cc41bf9c5e3a7f2bc92ae319bd23e3100ae3b2b Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 27 Oct 2022 12:20:11 -0700 Subject: [PATCH] attributes: improve docs; tests for using Levels in `#[instrument]` (#2350) This branch adds documentation and tests noting that the `#[instrument]` macro accepts `tracing::Level` directly. Using `tracing::Level` directly allows for IDE autocomplete and earlier detection of typos. The documentation for tracing-attributes was also rewritten to remove the usage of the second-person perspective, making it more consistent with the rest of tracing's documentation. Co-authored-by: David Barsky ; Conflicts: ; tracing-attributes/Cargo.toml ; tracing-attributes/src/lib.rs --- tracing-attributes/Cargo.toml | 2 +- tracing-attributes/src/lib.rs | 65 ++++++++++---------------- tracing-attributes/tests/err.rs | 12 ++--- tracing-attributes/tests/instrument.rs | 2 +- tracing-attributes/tests/levels.rs | 46 ++++++++++++++++++ tracing-attributes/tests/ret.rs | 8 ++-- tracing-core/src/field.rs | 1 + tracing-flame/src/lib.rs | 3 +- tracing-futures/src/executor/mod.rs | 2 - tracing/src/field.rs | 1 + 10 files changed, 85 insertions(+), 57 deletions(-) diff --git a/tracing-attributes/Cargo.toml b/tracing-attributes/Cargo.toml index d6e3adb807..8e41eb31d0 100644 --- a/tracing-attributes/Cargo.toml +++ b/tracing-attributes/Cargo.toml @@ -47,7 +47,7 @@ quote = "1" tracing = { path = "../tracing", version = "0.1.35" } tracing-mock = { path = "../tracing-mock", features = ["tokio-test"] } tracing-subscriber = { path = "../tracing-subscriber", version = "0.3.0", features = ["env-filter"] } -tokio-test = { version = "0.3.0" } +tokio-test = "0.4.2" tracing-core = { path = "../tracing-core", version = "0.1.28"} async-trait = "0.1.56" trybuild = "1.0.64" diff --git a/tracing-attributes/src/lib.rs b/tracing-attributes/src/lib.rs index 00e24d0163..462b53dca5 100644 --- a/tracing-attributes/src/lib.rs +++ b/tracing-attributes/src/lib.rs @@ -12,7 +12,7 @@ //! //! ## Usage //! -//! First, add this to your `Cargo.toml`: +//! In the `Cargo.toml`: //! //! ```toml //! [dependencies] @@ -24,7 +24,7 @@ //! called. For example: //! //! ``` -//! use tracing_attributes::instrument; +//! use tracing::instrument; //! //! #[instrument] //! pub fn my_function(my_arg: usize) { @@ -204,16 +204,17 @@ mod expand; /// /// # Adding Fields /// -/// Additional fields (key-value pairs with arbitrary data) may be added to the -/// generated span using the `fields` argument on the `#[instrument]` macro. Any +/// Additional fields (key-value pairs with arbitrary data) can be passed to +/// to the generated span through the `fields` argument on the +/// `#[instrument]` macro. Strings, integers or boolean literals are accepted values +/// for each field. The name of the field must be a single valid Rust +/// identifier, nested (dotted) field names are not supported. Any /// Rust expression can be used as a field value in this manner. These /// expressions will be evaluated at the beginning of the function's body, so /// arguments to the function may be used in these expressions. Field names may /// also be specified *without* values. Doing so will result in an [empty field] /// whose value may be recorded later within the function body. /// -/// This supports the same [field syntax] as the `span!` and `event!` macros. -/// /// Note that overlap between the names of fields and (non-skipped) arguments /// will result in a compile error. /// @@ -323,11 +324,15 @@ mod expand; /// Setting the level for the generated span: /// ``` /// # use tracing_attributes::instrument; -/// #[instrument(level = "debug")] +/// # use tracing::Level; +/// #[instrument(level = Level::DEBUG)] /// pub fn my_function() { /// // ... /// } /// ``` +/// Levels can be specified either with [`Level`] constants, literal strings +/// (e.g., `"debug"`, `"info"`) or numerically (1—5, corresponding to [`Level::TRACE`]—[`Level::ERROR`]). +/// /// Overriding the generated span's name: /// ``` /// # use tracing_attributes::instrument; @@ -398,7 +403,7 @@ mod expand; /// } /// ``` /// -/// To add an additional context to the span, pass key-value pairs to `fields`: +/// To add additional context to the span, pass key-value pairs to `fields`: /// /// ``` /// # use tracing_attributes::instrument; @@ -426,7 +431,8 @@ mod expand; /// /// ``` /// # use tracing_attributes::instrument; -/// #[instrument(ret(level = "warn"))] +/// # use tracing::Level; +/// #[instrument(ret(level = Level::WARN))] /// fn my_function() -> i32 { /// 42 /// } @@ -447,8 +453,8 @@ mod expand; /// } /// ``` /// -/// If the function returns a `Result` and `E` implements `std::fmt::Display`, you can add -/// `err` or `err(Display)` to emit error events when the function returns `Err`: +/// If the function returns a `Result` and `E` implements `std::fmt::Display`, adding +/// `err` or `err(Display)` will emit error events when the function returns `Err`: /// /// ``` /// # use tracing_attributes::instrument; @@ -458,11 +464,12 @@ mod expand; /// } /// ``` /// -/// Similarly, you can override the level of the `err` event: +/// Similarly, overriding the level of the `err` event : /// /// ``` /// # use tracing_attributes::instrument; -/// #[instrument(err(level = "info"))] +/// # use tracing::Level; +/// #[instrument(err(level = Level::INFO))] /// fn my_function(arg: usize) -> Result<(), std::io::Error> { /// Ok(()) /// } @@ -470,7 +477,7 @@ mod expand; /// /// By default, error values will be recorded using their `std::fmt::Display` implementations. /// If an error implements `std::fmt::Debug`, it can be recorded using its `Debug` implementation -/// instead, by writing `err(Debug)`: +/// instead by writing `err(Debug)`: /// /// ``` /// # use tracing_attributes::instrument; @@ -529,33 +536,6 @@ mod expand; /// } /// ``` /// -/// Note than on `async-trait` <= 0.1.43, references to the `Self` -/// type inside the `fields` argument were only allowed when the instrumented -/// function is a method (i.e., the function receives `self` as an argument). -/// For example, this *used to not work* because the instrument function -/// didn't receive `self`: -/// ``` -/// # use tracing::instrument; -/// use async_trait::async_trait; -/// -/// #[async_trait] -/// pub trait Bar { -/// async fn bar(); -/// } -/// -/// #[derive(Debug)] -/// struct BarImpl(usize); -/// -/// #[async_trait] -/// impl Bar for BarImpl { -/// #[instrument(fields(tmp = std::any::type_name::()))] -/// async fn bar() {} -/// } -/// ``` -/// Instead, you should manually rewrite any `Self` types as the type for -/// which you implement the trait: `#[instrument(fields(tmp = std::any::type_name::()))]` -/// (or maybe you can just bump `async-trait`). -/// /// [span]: https://docs.rs/tracing/latest/tracing/span/index.html /// [name]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.name /// [target]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.target @@ -567,6 +547,9 @@ mod expand; /// [`follows_from`]: https://docs.rs/tracing/latest/tracing/struct.Span.html#method.follows_from /// [`tracing`]: https://github.com/tokio-rs/tracing /// [`fmt::Debug`]: std::fmt::Debug +/// [`Level`]: https://docs.rs/tracing/latest/tracing/struct.Level.html +/// [`Level::TRACE`]: https://docs.rs/tracing/latest/tracing/struct.Level.html#associatedconstant.TRACE +/// [`Level::ERROR`]: https://docs.rs/tracing/latest/tracing/struct.Level.html#associatedconstant.ERROR #[proc_macro_attribute] pub fn instrument( args: proc_macro::TokenStream, diff --git a/tracing-attributes/tests/err.rs b/tracing-attributes/tests/err.rs index a030138407..deb2f1d59d 100644 --- a/tracing-attributes/tests/err.rs +++ b/tracing-attributes/tests/err.rs @@ -240,7 +240,7 @@ fn err_info() -> Result { #[test] fn test_err_info() { let span = span::mock().named("err_info"); - let (collector, handle) = collector::mock() + let (subscriber, handle) = subscriber::mock() .new_span(span.clone()) .enter(span.clone()) .event(event::mock().at_level(Level::INFO)) @@ -248,7 +248,7 @@ fn test_err_info() { .drop_span(span) .done() .run_with_handle(); - with_default(collector, || err_info().ok()); + with_default(subscriber, || err_info().ok()); handle.assert_finished(); } @@ -260,7 +260,7 @@ fn err_dbg_info() -> Result { #[test] fn test_err_dbg_info() { let span = span::mock().named("err_dbg_info"); - let (collector, handle) = collector::mock() + let (subscriber, handle) = subscriber::mock() .new_span(span.clone()) .enter(span.clone()) .event( @@ -277,7 +277,7 @@ fn test_err_dbg_info() { .drop_span(span) .done() .run_with_handle(); - with_default(collector, || err_dbg_info().ok()); + with_default(subscriber, || err_dbg_info().ok()); handle.assert_finished(); } @@ -289,7 +289,7 @@ fn err_warn_info() -> Result { #[test] fn test_err_warn_info() { let span = span::mock().named("err_warn_info").at_level(Level::WARN); - let (collector, handle) = collector::mock() + let (subscriber, handle) = subscriber::mock() .new_span(span.clone()) .enter(span.clone()) .event(event::mock().at_level(Level::INFO)) @@ -297,6 +297,6 @@ fn test_err_warn_info() { .drop_span(span) .done() .run_with_handle(); - with_default(collector, || err_warn_info().ok()); + with_default(subscriber, || err_warn_info().ok()); handle.assert_finished(); } diff --git a/tracing-attributes/tests/instrument.rs b/tracing-attributes/tests/instrument.rs index 7686927488..b215b8455d 100644 --- a/tracing-attributes/tests/instrument.rs +++ b/tracing-attributes/tests/instrument.rs @@ -17,7 +17,7 @@ fn override_everything() { #[instrument(target = "my_target", level = "debug")] fn my_fn() {} - #[instrument(level = "debug", target = "my_target")] + #[instrument(level = Level::DEBUG, target = "my_target")] fn my_other_fn() {} let span = span::mock() diff --git a/tracing-attributes/tests/levels.rs b/tracing-attributes/tests/levels.rs index b074ea4f28..94fc7e85a2 100644 --- a/tracing-attributes/tests/levels.rs +++ b/tracing-attributes/tests/levels.rs @@ -94,3 +94,49 @@ fn numeric_levels() { handle.assert_finished(); } + +#[test] +fn enum_levels() { + #[instrument(level = Level::TRACE)] + fn trace() {} + + #[instrument(level = Level::DEBUG)] + fn debug() {} + + #[instrument(level = tracing::Level::INFO)] + fn info() {} + + #[instrument(level = Level::WARN)] + fn warn() {} + + #[instrument(level = Level::ERROR)] + fn error() {} + let (subscriber, handle) = subscriber::mock() + .new_span(span::mock().named("trace").at_level(Level::TRACE)) + .enter(span::mock().named("trace").at_level(Level::TRACE)) + .exit(span::mock().named("trace").at_level(Level::TRACE)) + .new_span(span::mock().named("debug").at_level(Level::DEBUG)) + .enter(span::mock().named("debug").at_level(Level::DEBUG)) + .exit(span::mock().named("debug").at_level(Level::DEBUG)) + .new_span(span::mock().named("info").at_level(Level::INFO)) + .enter(span::mock().named("info").at_level(Level::INFO)) + .exit(span::mock().named("info").at_level(Level::INFO)) + .new_span(span::mock().named("warn").at_level(Level::WARN)) + .enter(span::mock().named("warn").at_level(Level::WARN)) + .exit(span::mock().named("warn").at_level(Level::WARN)) + .new_span(span::mock().named("error").at_level(Level::ERROR)) + .enter(span::mock().named("error").at_level(Level::ERROR)) + .exit(span::mock().named("error").at_level(Level::ERROR)) + .done() + .run_with_handle(); + + with_default(subscriber, || { + trace(); + debug(); + info(); + warn(); + error(); + }); + + handle.assert_finished(); +} diff --git a/tracing-attributes/tests/ret.rs b/tracing-attributes/tests/ret.rs index c29c87ea8a..f20b66797c 100644 --- a/tracing-attributes/tests/ret.rs +++ b/tracing-attributes/tests/ret.rs @@ -262,7 +262,7 @@ fn ret_warn_info() -> i32 { #[test] fn test_warn_info() { let span = span::mock().named("ret_warn_info").at_level(Level::WARN); - let (collector, handle) = collector::mock() + let (subscriber, handle) = subscriber::mock() .new_span(span.clone()) .enter(span.clone()) .event( @@ -275,7 +275,7 @@ fn test_warn_info() { .done() .run_with_handle(); - with_default(collector, ret_warn_info); + with_default(subscriber, ret_warn_info); handle.assert_finished(); } @@ -287,7 +287,7 @@ fn ret_dbg_warn() -> i32 { #[test] fn test_dbg_warn() { let span = span::mock().named("ret_dbg_warn").at_level(Level::INFO); - let (collector, handle) = collector::mock() + let (subscriber, handle) = subscriber::mock() .new_span(span.clone()) .enter(span.clone()) .event( @@ -300,6 +300,6 @@ fn test_dbg_warn() { .done() .run_with_handle(); - with_default(collector, ret_dbg_warn); + with_default(subscriber, ret_dbg_warn); handle.assert_finished(); } diff --git a/tracing-core/src/field.rs b/tracing-core/src/field.rs index e103c75a9d..7e2c26b1d7 100644 --- a/tracing-core/src/field.rs +++ b/tracing-core/src/field.rs @@ -315,6 +315,7 @@ pub trait Visit { /// 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)) { diff --git a/tracing-flame/src/lib.rs b/tracing-flame/src/lib.rs index 51dd436d34..145d2be90f 100644 --- a/tracing-flame/src/lib.rs +++ b/tracing-flame/src/lib.rs @@ -133,8 +133,7 @@ while_true )] -pub use error::Error; - +use error::Error; use error::Kind; use once_cell::sync::Lazy; use std::cell::Cell; diff --git a/tracing-futures/src/executor/mod.rs b/tracing-futures/src/executor/mod.rs index 442b523b84..ced3b5a460 100644 --- a/tracing-futures/src/executor/mod.rs +++ b/tracing-futures/src/executor/mod.rs @@ -1,7 +1,5 @@ #[cfg(feature = "futures-01")] mod futures_01; -#[cfg(feature = "futures-01")] -pub use self::futures_01::*; #[cfg(feature = "futures_preview")] mod futures_preview; diff --git a/tracing/src/field.rs b/tracing/src/field.rs index b3f9fbdfca..886c53a916 100644 --- a/tracing/src/field.rs +++ b/tracing/src/field.rs @@ -126,6 +126,7 @@ use crate::Metadata; /// string comparisons. Thus, if possible, once the key for a field is known, it /// should be used whenever possible. /// +/// pub trait AsField: crate::sealed::Sealed { /// Attempts to convert `&self` into a `Field` with the specified `metadata`. ///