Skip to content

Commit ee82cf9

Browse files
tracing: fix record_all panic (#3432)
## Motivation This seems to be a result of the new `valueset!` optimisations combined with this new `record_all!` feature. In fact, the `record_all!` feature never worked with a set of fields differnt to all a span's fields in the correct order. The following code panics ```rust #[test] fn tracing_bug() { let span = tracing::info_span!("example", foo=1, bar=2); tracing::record_all!(span, foo=3); } ``` ## Solution This is horrible. We rename `valueset!` to `valueset_all!`, then we re-introduce the original `valueset!` with some notable changes. The new `valueset!` doesn't use fields from the fieldset iterator, it instead uses `FieldSet::field(...)` to find the correct field. If the field isn't found, we set a fallback field that will be ignored (callsites are not equal). Fixes #3431
1 parent 9978c36 commit ee82cf9

File tree

5 files changed

+364
-47
lines changed

5 files changed

+364
-47
lines changed

tracing-core/src/field.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ impl FieldSet {
876876
/// [`Identifier`]: super::callsite::Identifier
877877
/// [`Callsite`]: super::callsite::Callsite
878878
#[inline]
879-
pub(crate) fn callsite(&self) -> callsite::Identifier {
879+
pub(crate) const fn callsite(&self) -> callsite::Identifier {
880880
callsite::Identifier(self.callsite.0)
881881
}
882882

@@ -949,6 +949,16 @@ impl FieldSet {
949949
}
950950
}
951951

952+
pub(crate) const fn fake_field(&self) -> Field {
953+
Field {
954+
i: usize::MAX,
955+
fields: FieldSet {
956+
names: self.names,
957+
callsite: self.callsite(),
958+
},
959+
}
960+
}
961+
952962
/// Returns the number of fields in this `FieldSet`.
953963
#[inline]
954964
pub fn len(&self) -> usize {

tracing-core/src/metadata.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,14 @@ impl<'a> Metadata<'a> {
330330
pub fn is_span(&self) -> bool {
331331
self.kind.is_span()
332332
}
333+
334+
/// Generate a fake field that will never match a real field.
335+
///
336+
/// Used via valueset to fill in for unknown fields.
337+
#[doc(hidden)]
338+
pub const fn private_fake_field(&self) -> field::Field {
339+
self.fields.fake_field()
340+
}
333341
}
334342

335343
impl fmt::Debug for Metadata<'_> {

tracing/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,18 @@ pub mod __macro_support {
11271127
.finish()
11281128
}
11291129
}
1130+
1131+
static CALLSITE: crate::callsite::DefaultCallsite =
1132+
crate::callsite::DefaultCallsite::new(&META);
1133+
static META: crate::Metadata<'static> = crate::metadata! {
1134+
name: "__fake_tracing_callsite",
1135+
target: module_path!(),
1136+
level: crate::Level::TRACE,
1137+
fields: crate::fieldset!(),
1138+
callsite: &CALLSITE,
1139+
kind: crate::metadata::Kind::SPAN,
1140+
};
1141+
pub static FAKE_FIELD: crate::field::Field = META.private_fake_field();
11301142
}
11311143

11321144
#[cfg(feature = "log")]

0 commit comments

Comments
 (0)