diff --git a/tracing-core/src/field.rs b/tracing-core/src/field.rs index 988336914..69544f9f3 100644 --- a/tracing-core/src/field.rs +++ b/tracing-core/src/field.rs @@ -876,7 +876,7 @@ impl FieldSet { /// [`Identifier`]: super::callsite::Identifier /// [`Callsite`]: super::callsite::Callsite #[inline] - pub(crate) fn callsite(&self) -> callsite::Identifier { + pub(crate) const fn callsite(&self) -> callsite::Identifier { callsite::Identifier(self.callsite.0) } @@ -949,6 +949,16 @@ impl FieldSet { } } + pub(crate) const fn fake_field(&self) -> Field { + Field { + i: usize::MAX, + fields: FieldSet { + names: self.names, + callsite: self.callsite(), + }, + } + } + /// Returns the number of fields in this `FieldSet`. #[inline] pub fn len(&self) -> usize { diff --git a/tracing-core/src/metadata.rs b/tracing-core/src/metadata.rs index cac6d7a0a..308b8529e 100644 --- a/tracing-core/src/metadata.rs +++ b/tracing-core/src/metadata.rs @@ -330,6 +330,14 @@ impl<'a> Metadata<'a> { pub fn is_span(&self) -> bool { self.kind.is_span() } + + /// Generate a fake field that will never match a real field. + /// + /// Used via valueset to fill in for unknown fields. + #[doc(hidden)] + pub const fn private_fake_field(&self) -> field::Field { + self.fields.fake_field() + } } impl fmt::Debug for Metadata<'_> { diff --git a/tracing/src/lib.rs b/tracing/src/lib.rs index 2a058e533..f8ac83f1e 100644 --- a/tracing/src/lib.rs +++ b/tracing/src/lib.rs @@ -1127,6 +1127,18 @@ pub mod __macro_support { .finish() } } + + static CALLSITE: crate::callsite::DefaultCallsite = + crate::callsite::DefaultCallsite::new(&META); + static META: crate::Metadata<'static> = crate::metadata! { + name: "__fake_tracing_callsite", + target: module_path!(), + level: crate::Level::TRACE, + fields: crate::fieldset!(), + callsite: &CALLSITE, + kind: crate::metadata::Kind::SPAN, + }; + pub static FAKE_FIELD: crate::field::Field = META.private_fake_field(); } #[cfg(feature = "log")] diff --git a/tracing/src/macros.rs b/tracing/src/macros.rs index 6e6bc2f56..14481c0a1 100644 --- a/tracing/src/macros.rs +++ b/tracing/src/macros.rs @@ -41,12 +41,12 @@ macro_rules! span { $crate::Span::child_of( $parent, meta, - &$crate::valueset!(meta.fields(), $($fields)*), + &$crate::valueset_all!(meta.fields(), $($fields)*), ) } else { let span = $crate::__macro_support::__disabled_span(__CALLSITE.metadata()); $crate::if_log_enabled! { $lvl, { - span.record_all(&$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + span.record_all(&$crate::valueset_all!(__CALLSITE.metadata().fields(), $($fields)*)); }}; span } @@ -71,12 +71,12 @@ macro_rules! span { // span with contextual parent $crate::Span::new( meta, - &$crate::valueset!(meta.fields(), $($fields)*), + &$crate::valueset_all!(meta.fields(), $($fields)*), ) } else { let span = $crate::__macro_support::__disabled_span(__CALLSITE.metadata()); $crate::if_log_enabled! { $lvl, { - span.record_all(&$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + span.record_all(&$crate::valueset_all!(__CALLSITE.metadata().fields(), $($fields)*)); }}; span } @@ -642,12 +642,12 @@ macro_rules! event { meta, &value_set ); - })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + })($crate::valueset_all!(__CALLSITE.metadata().fields(), $($fields)*)); } else { $crate::__tracing_log!( $lvl, __CALLSITE, - &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) + &$crate::valueset_all!(__CALLSITE.metadata().fields(), $($fields)*) ); } }); @@ -694,12 +694,12 @@ macro_rules! event { __CALLSITE, &value_set ); - })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + })($crate::valueset_all!(__CALLSITE.metadata().fields(), $($fields)*)); } else { $crate::__tracing_log!( $lvl, __CALLSITE, - &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) + &$crate::valueset_all!(__CALLSITE.metadata().fields(), $($fields)*) ); } }); @@ -752,12 +752,12 @@ macro_rules! event { meta, &value_set ); - })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + })($crate::valueset_all!(__CALLSITE.metadata().fields(), $($fields)*)); } else { $crate::__tracing_log!( $lvl, __CALLSITE, - &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) + &$crate::valueset_all!(__CALLSITE.metadata().fields(), $($fields)*) ); } }); @@ -805,12 +805,12 @@ macro_rules! event { meta, &value_set ); - })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + })($crate::valueset_all!(__CALLSITE.metadata().fields(), $($fields)*)); } else { $crate::__tracing_log!( $lvl, __CALLSITE, - &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) + &$crate::valueset_all!(__CALLSITE.metadata().fields(), $($fields)*) ); } }); @@ -856,12 +856,12 @@ macro_rules! event { __CALLSITE, &value_set ); - })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + })($crate::valueset_all!(__CALLSITE.metadata().fields(), $($fields)*)); } else { $crate::__tracing_log!( $lvl, __CALLSITE, - &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) + &$crate::valueset_all!(__CALLSITE.metadata().fields(), $($fields)*) ); } }); @@ -911,12 +911,12 @@ macro_rules! event { __CALLSITE, &value_set ); - })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + })($crate::valueset_all!(__CALLSITE.metadata().fields(), $($fields)*)); } else { $crate::__tracing_log!( $lvl, __CALLSITE, - &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) + &$crate::valueset_all!(__CALLSITE.metadata().fields(), $($fields)*) ); } }); @@ -2811,7 +2811,7 @@ macro_rules! level_enabled { #[doc(hidden)] #[macro_export] -macro_rules! valueset { +macro_rules! valueset_all { // === base case === (@ { $(,)* $($val:expr),* $(,)* } $(,)*) => { @@ -2823,148 +2823,148 @@ macro_rules! valueset { // TODO(#1138): determine a new syntax for uninitialized span fields, and // re-enable this. // (@{ $(,)* $($out:expr),* }, $($k:ident).+ = _, $($rest:tt)*) => { - // $crate::valueset!(@ { $($out),*, (None) }, $($rest)*) + // $crate::valueset_all!(@ { $($out),*, (None) }, $($rest)*) // }; (@ { $(,)* $($out:expr),* }, $($k:ident).+ = ?$val:expr, $($rest:tt)*) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$crate::field::debug(&$val) as &dyn $crate::field::Value)) }, $($rest)* ) }; (@ { $(,)* $($out:expr),* }, $($k:ident).+ = %$val:expr, $($rest:tt)*) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$crate::field::display(&$val) as &dyn $crate::field::Value)) }, $($rest)* ) }; (@ { $(,)* $($out:expr),* }, $($k:ident).+ = $val:expr, $($rest:tt)*) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$val as &dyn $crate::field::Value)) }, $($rest)* ) }; (@ { $(,)* $($out:expr),* }, $($k:ident).+, $($rest:tt)*) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$($k).+ as &dyn $crate::field::Value)) }, $($rest)* ) }; (@ { $(,)* $($out:expr),* }, ?$($k:ident).+, $($rest:tt)*) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$crate::field::debug(&$($k).+) as &dyn $crate::field::Value)) }, $($rest)* ) }; (@ { $(,)* $($out:expr),* }, %$($k:ident).+, $($rest:tt)*) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$crate::field::display(&$($k).+) as &dyn $crate::field::Value)) }, $($rest)* ) }; (@ { $(,)* $($out:expr),* }, $($k:ident).+ = ?$val:expr) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$crate::field::debug(&$val) as &dyn $crate::field::Value)) }, ) }; (@ { $(,)* $($out:expr),* }, $($k:ident).+ = %$val:expr) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$crate::field::display(&$val) as &dyn $crate::field::Value)) }, ) }; (@ { $(,)* $($out:expr),* }, $($k:ident).+ = $val:expr) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$val as &dyn $crate::field::Value)) }, ) }; (@ { $(,)* $($out:expr),* }, $($k:ident).+) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$($k).+ as &dyn $crate::field::Value)) }, ) }; (@ { $(,)* $($out:expr),* }, ?$($k:ident).+) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$crate::field::debug(&$($k).+) as &dyn $crate::field::Value)) }, ) }; (@ { $(,)* $($out:expr),* }, %$($k:ident).+) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$crate::field::display(&$($k).+) as &dyn $crate::field::Value)) }, ) }; // Handle literal names (@ { $(,)* $($out:expr),* }, $k:literal = ?$val:expr, $($rest:tt)*) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$crate::field::debug(&$val) as &dyn $crate::field::Value)) }, $($rest)* ) }; (@ { $(,)* $($out:expr),* }, $k:literal = %$val:expr, $($rest:tt)*) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$crate::field::display(&$val) as &dyn $crate::field::Value)) }, $($rest)* ) }; (@ { $(,)* $($out:expr),* }, $k:literal = $val:expr, $($rest:tt)*) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$val as &dyn $crate::field::Value)) }, $($rest)* ) }; (@ { $(,)* $($out:expr),* }, $k:literal = ?$val:expr) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$crate::field::debug(&$val) as &dyn $crate::field::Value)) }, ) }; (@ { $(,)* $($out:expr),* }, $k:literal = %$val:expr) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$crate::field::display(&$val) as &dyn $crate::field::Value)) }, ) }; (@ { $(,)* $($out:expr),* }, $k:literal = $val:expr) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, ($crate::__macro_support::Option::Some(&$val as &dyn $crate::field::Value)) }, ) }; // Handle constant names (@ { $(,)* $($out:expr),* }, { $k:expr } = ?$val:expr, $($rest:tt)*) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, (Some(&$crate::field::debug(&$val) as &dyn $crate::field::Value)) }, $($rest)* ) }; (@ { $(,)* $($out:expr),* }, { $k:expr } = %$val:expr, $($rest:tt)*) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, (Some(&$crate::field::display(&$val) as &dyn $crate::field::Value)) }, $($rest)* ) }; (@ { $(,)* $($out:expr),* }, { $k:expr } = $val:expr, $($rest:tt)*) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, (Some(&$val as &dyn $crate::field::Value)) }, $($rest)* ) }; (@ { $(,)* $($out:expr),* }, { $k:expr } = ?$val:expr) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, (Some(&$crate::field::debug(&$val) as &dyn $crate::field::Value)) }, ) }; (@ { $(,)* $($out:expr),* }, { $k:expr } = %$val:expr) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, (Some(&$crate::field::display(&$val) as &dyn $crate::field::Value)) }, ) }; (@ { $(,)* $($out:expr),* }, { $k:expr } = $val:expr) => { - $crate::valueset!( + $crate::valueset_all!( @ { $($out),*, (Some(&$val as &dyn $crate::field::Value)) }, ) }; // Remainder is unparsable, but exists --- must be format args! (@ { $(,)* $($out:expr),* }, $($rest:tt)+) => { - $crate::valueset!(@ { ($crate::__macro_support::Option::Some(&$crate::__macro_support::format_args!($($rest)+) as &dyn $crate::field::Value)), $($out),* },) + $crate::valueset_all!(@ { ($crate::__macro_support::Option::Some(&$crate::__macro_support::format_args!($($rest)+) as &dyn $crate::field::Value)), $($out),* },) }; // === entry === @@ -2974,7 +2974,7 @@ macro_rules! valueset { // This import statement CANNOT be removed as it will break existing use cases. // See #831, #2332, #3424 for the last times we tried. use $crate::field::{debug, display, Value}; - $fields.value_set_all($crate::valueset!( + $fields.value_set_all($crate::valueset_all!( @ { }, $($kvs)+ )) @@ -2987,6 +2987,179 @@ macro_rules! valueset { }; } +#[doc(hidden)] +#[macro_export] +macro_rules! valueset { + + // === base case === + (@ $fields:expr, { $(,)* $(($field:expr, $val:expr)),* $(,)* } $(,)*) => {{ + &[ + $(( + $fields.field($field).as_ref().unwrap_or(&$crate::__macro_support::FAKE_FIELD), + $crate::__macro_support::Option::Some(&$val as &dyn $crate::field::Value), + ),)* + ] + }}; + + // === recursive case (more tts) === + + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, $($k:ident).+ = ?$val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($crate::__tracing_stringify!($($k).+), $crate::field::debug(&$val)) }, + $($rest)* + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, $($k:ident).+ = %$val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($crate::__tracing_stringify!($($k).+), $crate::field::display(&$val)) }, + $($rest)* + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, $($k:ident).+ = $val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($crate::__tracing_stringify!($($k).+), $val) }, + $($rest)* + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, $($k:ident).+, $($rest:tt)*) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($crate::__tracing_stringify!($($k).+), $($k).+) }, + $($rest)* + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, ?$($k:ident).+, $($rest:tt)*) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($crate::__tracing_stringify!($($k).+), $crate::field::debug(&$($k).+)) }, + $($rest)* + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, %$($k:ident).+, $($rest:tt)*) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($crate::__tracing_stringify!($($k).+), $crate::field::display(&$($k).+)) }, + $($rest)* + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, $($k:ident).+ = ?$val:expr) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($crate::__tracing_stringify!($($k).+), $crate::field::debug(&$val)) }, + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, $($k:ident).+ = %$val:expr) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($crate::__tracing_stringify!($($k).+), $crate::field::display(&$val)) }, + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, $($k:ident).+ = $val:expr) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($crate::__tracing_stringify!($($k).+), $val) }, + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, $($k:ident).+) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($crate::__tracing_stringify!($($k).+), $($k).+) }, + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, ?$($k:ident).+) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($crate::__tracing_stringify!($($k).+), $crate::field::debug(&$($k).+)) }, + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, %$($k:ident).+) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($crate::__tracing_stringify!($($k).+), $crate::field::display(&$($k).+)) }, + ) + }; + + // Handle literal names + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, $k:literal = ?$val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($k, $crate::field::debug(&$val)) }, + $($rest)* + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, $k:literal = %$val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($k, $crate::field::display(&$val)) }, + $($rest)* + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, $k:literal = $val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($k, $val) }, + $($rest)* + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, $k:literal = ?$val:expr) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($k, $crate::field::debug(&$val)) }, + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, $k:literal = %$val:expr) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($k, $crate::field::display(&$val)) }, + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, $k:literal = $val:expr) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($k, $val) }, + ) + }; + + // Handle constant names + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, { $k:expr } = ?$val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($k, $crate::field::debug(&$val)) }, + $($rest)* + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, { $k:expr } = %$val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($k, $crate::field::display(&$val)) }, + $($rest)* + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, { $k:expr } = $val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($k, $val) }, + $($rest)* + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, { $k:expr } = ?$val:expr) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($k, $crate::field::debug(&$val)) }, + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, { $k:expr } = %$val:expr) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($k, $crate::field::display(&$val)) }, + ) + }; + (@ $fields:expr, { $(,)* $(($field:expr, $out:expr)),* }, { $k:expr } = $val:expr) => { + $crate::valueset!( + @ $fields, { $(($field, $out)),*, ($k, $val) }, + ) + }; + + // === entry === + ($fields:expr, $($kvs:tt)+) => { + { + #[allow(unused_imports)] + // This import statement CANNOT be removed as it will break existing use cases. + // See #831, #2332, #3424 for the last times we tried. + use $crate::field::{debug, display, Value}; + $fields.value_set($crate::valueset!( + @ $fields, { }, + $($kvs)+ + )) + } + }; + ($fields:expr,) => { + { + $fields.value_set(&[]) + } + }; +} + #[doc(hidden)] #[macro_export] macro_rules! fieldset { diff --git a/tracing/tests/span.rs b/tracing/tests/span.rs index b9a1d148d..2561b4fc0 100644 --- a/tracing/tests/span.rs +++ b/tracing/tests/span.rs @@ -630,7 +630,6 @@ fn record_all_macro_records_new_values_for_fields() { expect::span().named("foo"), expect::field("bar") .with_value(&5) - .and(expect::field("baz").with_value(&"BAZ")) .and(expect::field("qux").with_value(&display("qux"))) .and(expect::field("quux").with_value(&debug("QuuX"))) .only(), @@ -650,7 +649,122 @@ fn record_all_macro_records_new_values_for_fields() { qux = Empty, quux = Empty ); - record_all!(span, bar = 5, baz = "BAZ", qux = %"qux", quux = ?"QuuX"); + record_all!(span, bar = 5, qux = %"qux", quux = ?"QuuX", unknown = "unknown"); + span.in_scope(|| {}) + }); + + handle.assert_finished(); +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] +#[test] +fn record_all_macro_records_all_fields() { + let (subscriber, handle) = subscriber::mock() + .new_span( + expect::span() + .named("foo") + .with_fields(expect::field("bar")), + ) + .record( + expect::span().named("foo"), + expect::field("bar") + .with_value(&5) + .and(expect::field("baz").with_value(&6)) + .and(expect::field("qux").with_value(&display("qux"))) + .and(expect::field("quux").with_value(&debug("QuuX"))) + .only(), + ) + .enter(expect::span().named("foo")) + .exit(expect::span().named("foo")) + .drop_span(expect::span().named("foo")) + .only() + .run_with_handle(); + + with_default(subscriber, || { + let span = tracing::span!( + Level::TRACE, + "foo", + bar = 1, + baz = 2, + qux = Empty, + quux = Empty + ); + record_all!(span, bar = 5, baz = 6, qux = %"qux", quux = ?"QuuX"); + span.in_scope(|| {}) + }); + + handle.assert_finished(); +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] +#[test] +fn record_all_macro_records_all_fields_different_order() { + let (subscriber, handle) = subscriber::mock() + .new_span( + expect::span() + .named("foo") + .with_fields(expect::field("bar")), + ) + .record( + expect::span().named("foo"), + expect::field("bar") + .with_value(&5) + .and(expect::field("baz").with_value(&6)) + .and(expect::field("qux").with_value(&display("qux"))) + .and(expect::field("quux").with_value(&debug("QuuX"))) + .only(), + ) + .enter(expect::span().named("foo")) + .exit(expect::span().named("foo")) + .drop_span(expect::span().named("foo")) + .only() + .run_with_handle(); + + with_default(subscriber, || { + let span = tracing::span!( + Level::TRACE, + "foo", + bar = 1, + baz = 2, + qux = Empty, + quux = Empty + ); + record_all!(span, qux = %"qux", baz = 6, bar = 5, quux = ?"QuuX"); + span.in_scope(|| {}) + }); + + handle.assert_finished(); +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] +#[test] +fn record_all_macro_unknown_field() { + let (subscriber, handle) = subscriber::mock() + .new_span( + expect::span() + .named("foo") + .with_fields(expect::field("bar")), + ) + .record( + expect::span().named("foo"), + tracing_mock::field::ExpectedFields::default().only(), + ) + .enter(expect::span().named("foo")) + .exit(expect::span().named("foo")) + .drop_span(expect::span().named("foo")) + .only() + .run_with_handle(); + + with_default(subscriber, || { + let span = tracing::span!( + Level::TRACE, + "foo", + bar = 1, + baz = 2, + qux = Empty, + quux = Empty + ); + record_all!(span, unknown = "unknown"); span.in_scope(|| {}) });