diff --git a/tracing/src/lib.rs b/tracing/src/lib.rs index c1c6d2fa98..58baa95659 100644 --- a/tracing/src/lib.rs +++ b/tracing/src/lib.rs @@ -319,6 +319,19 @@ //! # } //!``` //! +//! Constant expressions can also be used as field names. Constants +//! must be enclosed in curly braces (`{}`) to indicate that the *value* +//! of the constant is to be used as the field name, rather than the +//! constant's name. For example: +//! ``` +//! # use tracing::{span, Level}; +//! # fn main() { +//! const RESOURCE_NAME: &str = "foo"; +//! // this span will have the field `foo = "some_id"` +//! span!(Level::TRACE, "get", { RESOURCE_NAME } = "some_id"); +//! # } +//!``` +//! //! The `?` sigil is shorthand that specifies a field should be recorded using //! its [`fmt::Debug`] implementation: //! ``` diff --git a/tracing/src/macros.rs b/tracing/src/macros.rs index 082be6dd46..31890b69ee 100644 --- a/tracing/src/macros.rs +++ b/tracing/src/macros.rs @@ -24,7 +24,7 @@ macro_rules! span { (target: $target:expr, parent: $parent:expr, $lvl:expr, $name:expr, $($fields:tt)*) => { { use $crate::__macro_support::Callsite as _; - static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { + static __CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { name: $name, kind: $crate::metadata::Kind::SPAN, target: $target, @@ -33,10 +33,10 @@ macro_rules! span { }; let mut interest = $crate::collect::Interest::never(); if $crate::level_enabled!($lvl) - && { interest = CALLSITE.interest(); !interest.is_never() } - && CALLSITE.is_enabled(interest) + && { interest = __CALLSITE.interest(); !interest.is_never() } + && __CALLSITE.is_enabled(interest) { - let meta = CALLSITE.metadata(); + let meta = __CALLSITE.metadata(); // span with explicit parent $crate::Span::child_of( $parent, @@ -44,9 +44,9 @@ macro_rules! span { &$crate::valueset!(meta.fields(), $($fields)*), ) } else { - let span = CALLSITE.disabled_span(); + let span = __CALLSITE.disabled_span(); $crate::if_log_enabled! { $lvl, { - span.record_all(&$crate::valueset!(CALLSITE.metadata().fields(), $($fields)*)); + span.record_all(&$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); }}; span } @@ -55,7 +55,7 @@ macro_rules! span { (target: $target:expr, $lvl:expr, $name:expr, $($fields:tt)*) => { { use $crate::__macro_support::{Callsite as _, Registration}; - static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { + static __CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { name: $name, kind: $crate::metadata::Kind::SPAN, target: $target, @@ -65,19 +65,19 @@ macro_rules! span { let mut interest = $crate::collect::Interest::never(); if $crate::level_enabled!($lvl) - && { interest = CALLSITE.interest(); !interest.is_never() } - && CALLSITE.is_enabled(interest) + && { interest = __CALLSITE.interest(); !interest.is_never() } + && __CALLSITE.is_enabled(interest) { - let meta = CALLSITE.metadata(); + let meta = __CALLSITE.metadata(); // span with contextual parent $crate::Span::new( meta, &$crate::valueset!(meta.fields(), $($fields)*), ) } else { - let span = CALLSITE.disabled_span(); + let span = __CALLSITE.disabled_span(); $crate::if_log_enabled! { $lvl, { - span.record_all(&$crate::valueset!(CALLSITE.metadata().fields(), $($fields)*)); + span.record_all(&$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); }}; span } @@ -587,7 +587,7 @@ macro_rules! event { // Name / target / parent. (name: $name:expr, target: $target:expr, parent: $parent:expr, $lvl:expr, { $($fields:tt)* } )=> ({ use $crate::__macro_support::Callsite as _; - static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { + static __CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { name: $name, kind: $crate::metadata::Kind::EVENT, target: $target, @@ -596,29 +596,29 @@ macro_rules! event { }; let enabled = $crate::level_enabled!($lvl) && { - let interest = CALLSITE.interest(); - !interest.is_never() && CALLSITE.is_enabled(interest) + let interest = __CALLSITE.interest(); + !interest.is_never() && __CALLSITE.is_enabled(interest) }; if enabled { (|value_set: $crate::field::ValueSet| { $crate::__tracing_log!( $lvl, - CALLSITE, + __CALLSITE, &value_set ); - let meta = CALLSITE.metadata(); + let meta = __CALLSITE.metadata(); // event with explicit parent $crate::Event::child_of( $parent, meta, &value_set ); - })($crate::valueset!(CALLSITE.metadata().fields(), $($fields)*)); + })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); } else { $crate::__tracing_log!( $lvl, - CALLSITE, - &$crate::valueset!(CALLSITE.metadata().fields(), $($fields)*) + __CALLSITE, + &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) ); } }); @@ -641,7 +641,7 @@ macro_rules! event { // Name / target. (name: $name:expr, target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ({ use $crate::__macro_support::Callsite as _; - static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { + static __CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { name: $name, kind: $crate::metadata::Kind::EVENT, target: $target, @@ -649,12 +649,12 @@ macro_rules! event { fields: $($fields)* }; let enabled = $crate::level_enabled!($lvl) && { - let interest = CALLSITE.interest(); - !interest.is_never() && CALLSITE.is_enabled(interest) + let interest = __CALLSITE.interest(); + !interest.is_never() && __CALLSITE.is_enabled(interest) }; if enabled { (|value_set: $crate::field::ValueSet| { - let meta = CALLSITE.metadata(); + let meta = __CALLSITE.metadata(); // event with contextual parent $crate::Event::dispatch( meta, @@ -662,15 +662,15 @@ macro_rules! event { ); $crate::__tracing_log!( $lvl, - CALLSITE, + __CALLSITE, &value_set ); - })($crate::valueset!(CALLSITE.metadata().fields(), $($fields)*)); + })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); } else { $crate::__tracing_log!( $lvl, - CALLSITE, - &$crate::valueset!(CALLSITE.metadata().fields(), $($fields)*) + __CALLSITE, + &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) ); } }); @@ -692,7 +692,7 @@ macro_rules! event { // Target / parent. (target: $target:expr, parent: $parent:expr, $lvl:expr, { $($fields:tt)* } )=> ({ use $crate::__macro_support::Callsite as _; - static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { + static __CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { name: concat!( "event ", file!(), @@ -706,29 +706,29 @@ macro_rules! event { }; let enabled = $crate::level_enabled!($lvl) && { - let interest = CALLSITE.interest(); - !interest.is_never() && CALLSITE.is_enabled(interest) + let interest = __CALLSITE.interest(); + !interest.is_never() && __CALLSITE.is_enabled(interest) }; if enabled { (|value_set: $crate::field::ValueSet| { $crate::__tracing_log!( $lvl, - CALLSITE, + __CALLSITE, &value_set ); - let meta = CALLSITE.metadata(); + let meta = __CALLSITE.metadata(); // event with explicit parent $crate::Event::child_of( $parent, meta, &value_set ); - })($crate::valueset!(CALLSITE.metadata().fields(), $($fields)*)); + })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); } else { $crate::__tracing_log!( $lvl, - CALLSITE, - &$crate::valueset!(CALLSITE.metadata().fields(), $($fields)*) + __CALLSITE, + &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) ); } }); @@ -750,7 +750,7 @@ macro_rules! event { // Name / parent. (name: $name:expr, parent: $parent:expr, $lvl:expr, { $($fields:tt)* } )=> ({ use $crate::__macro_support::Callsite as _; - static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { + static __CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { name: $name, kind: $crate::metadata::Kind::EVENT, target: module_path!(), @@ -759,29 +759,29 @@ macro_rules! event { }; let enabled = $crate::level_enabled!($lvl) && { - let interest = CALLSITE.interest(); - !interest.is_never() && CALLSITE.is_enabled(interest) + let interest = __CALLSITE.interest(); + !interest.is_never() && __CALLSITE.is_enabled(interest) }; if enabled { (|value_set: $crate::field::ValueSet| { $crate::__tracing_log!( $lvl, - CALLSITE, + __CALLSITE, &value_set ); - let meta = CALLSITE.metadata(); + let meta = __CALLSITE.metadata(); // event with explicit parent $crate::Event::child_of( $parent, meta, &value_set ); - })($crate::valueset!(CALLSITE.metadata().fields(), $($fields)*)); + })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); } else { $crate::__tracing_log!( $lvl, - CALLSITE, - &$crate::valueset!(CALLSITE.metadata().fields(), $($fields)*) + __CALLSITE, + &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) ); } }); @@ -803,7 +803,7 @@ macro_rules! event { // Name. (name: $name:expr, $lvl:expr, { $($fields:tt)* } )=> ({ use $crate::__macro_support::Callsite as _; - static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { + static __CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { name: $name, kind: $crate::metadata::Kind::EVENT, target: module_path!(), @@ -811,12 +811,12 @@ macro_rules! event { fields: $($fields)* }; let enabled = $crate::level_enabled!($lvl) && { - let interest = CALLSITE.interest(); - !interest.is_never() && CALLSITE.is_enabled(interest) + let interest = __CALLSITE.interest(); + !interest.is_never() && __CALLSITE.is_enabled(interest) }; if enabled { (|value_set: $crate::field::ValueSet| { - let meta = CALLSITE.metadata(); + let meta = __CALLSITE.metadata(); // event with contextual parent $crate::Event::dispatch( meta, @@ -824,15 +824,15 @@ macro_rules! event { ); $crate::__tracing_log!( $lvl, - CALLSITE, + __CALLSITE, &value_set ); - })($crate::valueset!(CALLSITE.metadata().fields(), $($fields)*)); + })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); } else { $crate::__tracing_log!( $lvl, - CALLSITE, - &$crate::valueset!(CALLSITE.metadata().fields(), $($fields)*) + __CALLSITE, + &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) ); } }); @@ -853,7 +853,7 @@ macro_rules! event { // Target. (target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ({ use $crate::__macro_support::Callsite as _; - static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { + static __CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { name: concat!( "event ", file!(), @@ -866,12 +866,12 @@ macro_rules! event { fields: $($fields)* }; let enabled = $crate::level_enabled!($lvl) && { - let interest = CALLSITE.interest(); - !interest.is_never() && CALLSITE.is_enabled(interest) + let interest = __CALLSITE.interest(); + !interest.is_never() && __CALLSITE.is_enabled(interest) }; if enabled { (|value_set: $crate::field::ValueSet| { - let meta = CALLSITE.metadata(); + let meta = __CALLSITE.metadata(); // event with contextual parent $crate::Event::dispatch( meta, @@ -879,15 +879,15 @@ macro_rules! event { ); $crate::__tracing_log!( $lvl, - CALLSITE, + __CALLSITE, &value_set ); - })($crate::valueset!(CALLSITE.metadata().fields(), $($fields)*)); + })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); } else { $crate::__tracing_log!( $lvl, - CALLSITE, - &$crate::valueset!(CALLSITE.metadata().fields(), $($fields)*) + __CALLSITE, + &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) ); } }); @@ -1183,7 +1183,7 @@ macro_rules! enabled { (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! { + static __CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { name: concat!( "enabled ", file!(), @@ -1195,9 +1195,9 @@ macro_rules! enabled { level: $lvl, fields: $($fields)* }; - let interest = CALLSITE.interest(); - if !interest.is_never() && CALLSITE.is_enabled(interest) { - let meta = CALLSITE.metadata(); + let interest = __CALLSITE.interest(); + if !interest.is_never() && __CALLSITE.is_enabled(interest) { + let meta = __CALLSITE.metadata(); $crate::dispatch::get_default(|current| current.enabled(meta)) } else { false @@ -2709,20 +2709,20 @@ macro_rules! callsite { fields: $($fields:tt)* ) => {{ use $crate::__macro_support::{MacroCallsite, Registration}; - static META: $crate::Metadata<'static> = { + static __META: $crate::Metadata<'static> = { $crate::metadata! { name: $name, target: $target, level: $lvl, fields: $crate::fieldset!( $($fields)* ), - callsite: &CALLSITE, + callsite: &__CALLSITE, kind: $kind, } }; - static REG: Registration = Registration::new(&CALLSITE); - static CALLSITE: MacroCallsite = MacroCallsite::new(&META, ®); - CALLSITE.register(); - &CALLSITE + static REG: Registration = Registration::new(&__CALLSITE); + static __CALLSITE: MacroCallsite = MacroCallsite::new(&__META, ®); + __CALLSITE.register(); + &__CALLSITE }}; } @@ -2761,19 +2761,19 @@ macro_rules! callsite2 { fields: $($fields:tt)* ) => {{ use $crate::__macro_support::{MacroCallsite, Registration}; - static META: $crate::Metadata<'static> = { + static __META: $crate::Metadata<'static> = { $crate::metadata! { name: $name, target: $target, level: $lvl, fields: $crate::fieldset!( $($fields)* ), - callsite: &CALLSITE, + callsite: &__CALLSITE, kind: $kind, } }; - static REG: Registration = Registration::new(&CALLSITE); + static REG: Registration = Registration::new(&__CALLSITE); - MacroCallsite::new(&META, ®) + MacroCallsite::new(&__META, ®) }}; } @@ -2923,6 +2923,47 @@ macro_rules! valueset { ) }; + // Handle constant names + (@ { $(,)* $($out:expr),* }, $next:expr, { $k:expr } = ?$val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, Some(&debug(&$val) as &dyn Value)) }, + $next, + $($rest)* + ) + }; + (@ { $(,)* $($out:expr),* }, $next:expr, { $k:expr } = %$val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, Some(&display(&$val) as &dyn Value)) }, + $next, + $($rest)* + ) + }; + (@ { $(,)* $($out:expr),* }, $next:expr, { $k:expr } = $val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, Some(&$val as &dyn Value)) }, + $next, + $($rest)* + ) + }; + (@ { $(,)* $($out:expr),* }, $next:expr, { $k:expr } = ?$val:expr) => { + $crate::valueset!( + @ { $($out),*, (&$next, Some(&debug(&$val) as &dyn Value)) }, + $next, + ) + }; + (@ { $(,)* $($out:expr),* }, $next:expr, { $k:expr } = %$val:expr) => { + $crate::valueset!( + @ { $($out),*, (&$next, Some(&display(&$val) as &dyn Value)) }, + $next, + ) + }; + (@ { $(,)* $($out:expr),* }, $next:expr, { $k:expr } = $val:expr) => { + $crate::valueset!( + @ { $($out),*, (&$next, Some(&$val as &dyn Value)) }, + $next, + ) + }; + // Remainder is unparsable, but exists --- must be format args! (@ { $(,)* $($out:expr),* }, $next:expr, $($rest:tt)+) => { $crate::valueset!(@ { (&$next, ::core::option::Option::Some(&format_args!($($rest)+) as &dyn Value)), $($out),* }, $next, ) @@ -2992,6 +3033,17 @@ macro_rules! fieldset { $crate::fieldset!(@ { $($out),*, $k } $($rest)*) }; + // Handle constant names + (@ { $(,)* $($out:expr),* } { $k:expr } = ?$val:expr, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $k } $($rest)*) + }; + (@ { $(,)* $($out:expr),* } { $k:expr } = %$val:expr, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $k } $($rest)*) + }; + (@ { $(,)* $($out:expr),* } { $k:expr } = $val:expr, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $k } $($rest)*) + }; + // Remainder is unparseable, but exists --- must be format args! (@ { $(,)* $($out:expr),* } $($rest:tt)+) => { $crate::fieldset!(@ { "message", $($out),*, }) @@ -3045,7 +3097,7 @@ macro_rules! __tracing_log { if level <= log::max_level() { let log_meta = log::Metadata::builder() .level(level) - .target(CALLSITE.metadata().target()) + .target(__CALLSITE.metadata().target()) .build(); let logger = log::logger(); if logger.enabled(&log_meta) { diff --git a/tracing/tests/event.rs b/tracing/tests/event.rs index 7e4f87c6d3..55594ea913 100644 --- a/tracing/tests/event.rs +++ b/tracing/tests/event.rs @@ -401,3 +401,45 @@ fn string_field() { handle.assert_finished(); } + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] +#[test] +fn constant_field_name() { + let expect_event = || { + expect::event().with_fields( + expect::field("foo") + .with_value(&"bar") + .and(expect::field("constant string").with_value(&"also works")) + .and(expect::field("foo.bar").with_value(&"baz")) + .and(expect::field("message").with_value(&debug(format_args!("quux")))) + .only(), + ) + }; + let (collector, handle) = collector::mock() + .event(expect_event()) + .event(expect_event()) + .only() + .run_with_handle(); + + with_default(collector, || { + const FOO: &str = "foo"; + tracing::event!( + Level::INFO, + { std::convert::identity(FOO) } = "bar", + { "constant string" } = "also works", + foo.bar = "baz", + "quux" + ); + tracing::event!( + Level::INFO, + { + { std::convert::identity(FOO) } = "bar", + { "constant string" } = "also works", + foo.bar = "baz", + }, + "quux" + ); + }); + + handle.assert_finished(); +} diff --git a/tracing/tests/span.rs b/tracing/tests/span.rs index 14c4417cb6..62a9fe6145 100644 --- a/tracing/tests/span.rs +++ b/tracing/tests/span.rs @@ -836,3 +836,33 @@ fn both_shorthands() { handle.assert_finished(); } + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] +#[test] +fn constant_field_name() { + let (collector, handle) = collector::mock() + .new_span( + expect::span().named("my_span").with_field( + expect::field("foo") + .with_value(&"bar") + .and(expect::field("constant string").with_value(&"also works")) + .and(expect::field("foo.bar").with_value(&"baz")) + .only(), + ), + ) + .only() + .run_with_handle(); + + with_default(collector, || { + const FOO: &str = "foo"; + tracing::span!( + Level::TRACE, + "my_span", + { std::convert::identity(FOO) } = "bar", + { "constant string" } = "also works", + foo.bar = "baz", + ); + }); + + handle.assert_finished(); +}