diff --git a/tracing-attributes/tests/fields.rs b/tracing-attributes/tests/fields.rs index e789dfddbd..70649eea6b 100644 --- a/tracing-attributes/tests/fields.rs +++ b/tracing-attributes/tests/fields.rs @@ -31,6 +31,11 @@ fn fn_clashy_expr_field2(s: &str) { let _ = s; } +#[instrument(fields(s = &s))] +fn fn_string(s: String) { + let _ = s; +} + #[derive(Debug)] struct HasField { my_field: &'static str, @@ -134,6 +139,14 @@ fn empty_field() { }); } +#[test] +fn string_field() { + let span = span::mock().with_field(mock("s").with_value(&"hello world").only()); + run_test(span, || { + fn_string(String::from("hello world")); + }); +} + fn run_test T, T>(span: NewSpan, fun: F) { let (collector, handle) = collector::mock() .new_span(span) diff --git a/tracing-core/src/field.rs b/tracing-core/src/field.rs index 39979ab2af..651064b156 100644 --- a/tracing-core/src/field.rs +++ b/tracing-core/src/field.rs @@ -503,6 +503,18 @@ where } } +#[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] +impl crate::sealed::Sealed for alloc::string::String {} + +#[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] +impl Value for alloc::string::String { + fn record(&self, key: &Field, visitor: &mut dyn Visit) { + visitor.record_str(key, self.as_str()) + } +} + impl fmt::Debug for dyn Value { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // We are only going to be recording the field value, so we don't diff --git a/tracing/tests/event.rs b/tracing/tests/event.rs index 3db6c68cfd..7f0d7eae16 100644 --- a/tracing/tests/event.rs +++ b/tracing/tests/event.rs @@ -367,3 +367,27 @@ fn explicit_child_at_levels() { handle.assert_finished(); } + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] +#[test] +fn string_field() { + let (collector, handle) = collector::mock() + .event(event::mock().with_fields(field::mock("my_string").with_value(&"hello").only())) + .event( + event::mock().with_fields(field::mock("my_string").with_value(&"hello world!").only()), + ) + .done() + .run_with_handle(); + with_default(collector, || { + let mut my_string = String::from("hello"); + + tracing::event!(Level::INFO, my_string); + + // the string is not moved by using it as a field! + my_string.push_str(" world!"); + + tracing::event!(Level::INFO, my_string); + }); + + handle.assert_finished(); +}