From 110cb08c151141cfffda7ea21968f74cb1a91649 Mon Sep 17 00:00:00 2001 From: Gus Wynn Date: Thu, 31 Mar 2022 11:30:16 -0700 Subject: [PATCH] tracing: add `span_enabled!` and `event_enabled!` macros (#1900) ## Motivation Closes #1892 ## Solution This branch adds new `span_enabled!` and `event_enabled!` macros. I went withe sharing as much of the macro as possible. The new macros were implemented by adding a `kind:` parameter to `enabled!`, and invoking `enabled!` with the appropriate `kind:` argument. This means in the docs, the macro only shows the `($($rest:tt)*)=> (...)` variant, but I think linking to the `enabled!` docs should be fine. Also, I find the macro pattern part of rustdoc to be very hard to understand, and I think many people dont look at it. Co-authored-by: Eliza Weisman --- tracing/src/macros.rs | 118 ++++++++++++++++++++++++++++++++++++--- tracing/tests/enabled.rs | 37 ++++++++++-- tracing/tests/macros.rs | 32 ++++++++++- 3 files changed, 174 insertions(+), 13 deletions(-) diff --git a/tracing/src/macros.rs b/tracing/src/macros.rs index 0d52c4cdec..0a599c6bb7 100644 --- a/tracing/src/macros.rs +++ b/tracing/src/macros.rs @@ -807,6 +807,70 @@ macro_rules! event { ); } +/// Tests whether an event with the specified level and target would be enabled. +/// +/// This is similar to [`enabled!`], but queries the current subscriber specifically for +/// an event, whereas [`enabled!`] queries for an event _or_ span. +/// +/// See the documentation for [`enabled!]` for more details on using this macro. +/// See also [`span_enabled!`]. +/// +/// # Examples +/// +/// ```rust +/// # use tracing::{event_enabled, Level}; +/// if event_enabled!(target: "my_crate", Level::DEBUG) { +/// // some expensive work... +/// } +/// // simpler +/// if event_enabled!(Level::DEBUG) { +/// // some expensive work... +/// } +/// // with fields +/// if event_enabled!(Level::DEBUG, foo_field) { +/// // some expensive work... +/// } +/// ``` +/// +#[macro_export] +macro_rules! event_enabled { + ($($rest:tt)*)=> ( + $crate::enabled!(kind: $crate::metadata::Kind::EVENT, $($rest)*) + ) +} + +/// Tests whether a span with the specified level and target would be enabled. +/// +/// This is similar to [`enabled!`], but queries the current subscriber specifically for +/// an event, whereas [`enabled!`] queries for an event _or_ span. +/// +/// See the documentation for [`enabled!]` for more details on using this macro. +/// See also [`span_enabled!`]. +/// +/// # Examples +/// +/// ```rust +/// # use tracing::{span_enabled, Level}; +/// if span_enabled!(target: "my_crate", Level::DEBUG) { +/// // some expensive work... +/// } +/// // simpler +/// if span_enabled!(Level::DEBUG) { +/// // some expensive work... +/// } +/// // with fields +/// if span_enabled!(Level::DEBUG, foo_field) { +/// // some expensive work... +/// } +/// ``` +/// +#[macro_export] +macro_rules! span_enabled { + ($($rest:tt)*)=> ( + $crate::enabled!(kind: $crate::metadata::Kind::SPAN, $($rest)*) + ) +} + /// Checks whether a span or event is [enabled] based on the provided [metadata]. /// /// [enabled]: crate::Subscriber::enabled @@ -884,9 +948,21 @@ macro_rules! event { /// } /// ``` /// +/// # Alternatives +/// +/// `enabled!` queries subscribers with [`Metadata`] where +/// [`is_event`] and [`is_span`] both return `false`. Alternatively, +/// use [`event_enabled!`] or [`span_enabled!`] to ensure one of these +/// returns true. +/// +/// +/// [`Metadata`]: crate::Metadata +/// [`is_event`]: crate::Metadata::is_event +/// [`is_span`]: crate::Metadata::is_span +/// #[macro_export] macro_rules! enabled { - (target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ({ + (kind: $kind:expr, target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ({ if $crate::level_enabled!($lvl) { use $crate::__macro_support::Callsite as _; static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { @@ -896,7 +972,7 @@ macro_rules! enabled { ":", line!() ), - kind: $crate::metadata::Kind::HINT, + kind: $kind.hint(), target: $target, level: $lvl, fields: $($fields)* @@ -913,20 +989,35 @@ macro_rules! enabled { } }); // Just target and level + (kind: $kind:expr, target: $target:expr, $lvl:expr ) => ( + $crate::enabled!(kind: $kind, target: $target, $lvl, { }) + ); (target: $target:expr, $lvl:expr ) => ( - $crate::enabled!(target: $target, $lvl, { }) + $crate::enabled!(kind: $crate::metadata::Kind::HINT, target: $target, $lvl, { }) ); - // These two cases handle fields with no values + // These four cases handle fields with no values + (kind: $kind:expr, target: $target:expr, $lvl:expr, $($field:tt)*) => ( + $crate::enabled!( + kind: $kind, + target: $target, + $lvl, + { $($field)*} + ) + ); (target: $target:expr, $lvl:expr, $($field:tt)*) => ( $crate::enabled!( + kind: $crate::metadata::Kind::HINT, target: $target, $lvl, { $($field)*} ) ); - ($lvl:expr, $($field:tt)*) => ( + + // Level and field case + (kind: $kind:expr, $lvl:expr, $($field:tt)*) => ( $crate::enabled!( + kind: $kind, target: module_path!(), $lvl, { $($field)*} @@ -934,8 +1025,21 @@ macro_rules! enabled { ); // Simplest `enabled!` case - ( $lvl:expr ) => ( - $crate::enabled!(target: module_path!(), $lvl, { }) + (kind: $kind:expr, $lvl:expr) => ( + $crate::enabled!(kind: $kind, target: module_path!(), $lvl, { }) + ); + ($lvl:expr) => ( + $crate::enabled!(kind: $crate::metadata::Kind::HINT, target: module_path!(), $lvl, { }) + ); + + // Fallthrough from above + ($lvl:expr, $($field:tt)*) => ( + $crate::enabled!( + kind: $crate::metadata::Kind::HINT, + target: module_path!(), + $lvl, + { $($field)*} + ) ); } diff --git a/tracing/tests/enabled.rs b/tracing/tests/enabled.rs index 1a41a87a3e..c756cb4c25 100644 --- a/tracing/tests/enabled.rs +++ b/tracing/tests/enabled.rs @@ -4,7 +4,7 @@ use tracing_mock::*; #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[test] fn level_and_target() { - let (subscriber, handle) = subscriber::mock() + let subscriber = subscriber::mock() .with_filter(|meta| { if meta.target() == "debug_module" { meta.level() <= &Level::DEBUG @@ -13,12 +13,41 @@ fn level_and_target() { } }) .done() - .run_with_handle(); + .run(); - tracing::subscriber::set_global_default(subscriber).unwrap(); + let _guard = tracing::subscriber::set_default(subscriber); assert!(tracing::enabled!(target: "debug_module", Level::DEBUG)); assert!(tracing::enabled!(Level::ERROR)); assert!(!tracing::enabled!(Level::DEBUG)); - handle.assert_finished(); +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] +#[test] +fn span_and_event() { + let subscriber = subscriber::mock() + .with_filter(|meta| { + if meta.target() == "debug_module" { + meta.level() <= &Level::DEBUG + } else if meta.is_span() { + meta.level() <= &Level::TRACE + } else if meta.is_event() { + meta.level() <= &Level::DEBUG + } else { + meta.level() <= &Level::INFO + } + }) + .done() + .run(); + + let _guard = tracing::subscriber::set_default(subscriber); + + // Ensure that the `_event` and `_span` alternatives work corretly + assert!(!tracing::event_enabled!(Level::TRACE)); + assert!(tracing::event_enabled!(Level::DEBUG)); + assert!(tracing::span_enabled!(Level::TRACE)); + + // target variants + assert!(tracing::span_enabled!(target: "debug_module", Level::DEBUG)); + assert!(tracing::event_enabled!(target: "debug_module", Level::DEBUG)); } diff --git a/tracing/tests/macros.rs b/tracing/tests/macros.rs index 0a32ebfc3f..a9679a3e94 100644 --- a/tracing/tests/macros.rs +++ b/tracing/tests/macros.rs @@ -1,7 +1,7 @@ #![deny(warnings)] use tracing::{ - callsite, debug, debug_span, enabled, error, error_span, event, info, info_span, span, trace, - trace_span, warn, warn_span, Level, + callsite, debug, debug_span, enabled, error, error_span, event, event_enabled, info, info_span, + span, span_enabled, trace, trace_span, warn, warn_span, Level, }; // Tests that macros work across various invocation syntax. @@ -348,6 +348,34 @@ fn enabled() { enabled!(target: "rando", Level::DEBUG, field); } +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] +#[test] +fn span_enabled() { + span_enabled!(Level::DEBUG, foo, bar.baz, quux,); + span_enabled!(Level::DEBUG, message); + span_enabled!(Level::INFO, foo, bar.baz, quux, message,); + span_enabled!(Level::INFO, foo, bar., message,); + span_enabled!(Level::DEBUG, foo); + + span_enabled!(Level::DEBUG); + span_enabled!(target: "rando", Level::DEBUG); + span_enabled!(target: "rando", Level::DEBUG, field); +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] +#[test] +fn event_enabled() { + event_enabled!(Level::DEBUG, foo, bar.baz, quux,); + event_enabled!(Level::DEBUG, message); + event_enabled!(Level::INFO, foo, bar.baz, quux, message,); + event_enabled!(Level::INFO, foo, bar., message,); + event_enabled!(Level::DEBUG, foo); + + event_enabled!(Level::DEBUG); + event_enabled!(target: "rando", Level::DEBUG); + event_enabled!(target: "rando", Level::DEBUG, field); +} + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[test] fn locals_with_message() {