mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-30 00:00:16 +02:00
trace: Add shorthand for field::display and field::debug (#1088)
## Motivation In `tokio-trace`, field values may be recorded as either a subset of Rust primitive types or as `fmt::Display` and `fmt::Debug` implementations. Currently, `tokio-trace` provides the `field::display` and `field::debug` functions which wrap a type with a type that implements `Value` using the wrapped type's `fmt::Display` or `fmt::Debug` implementation. However, importing and using these functions adds unnecessary boilerplate. In #1081, @jonhoo suggested adding shorthand syntax to the macros, similar to that used by the `slog` crate, as a solution for the wordiness of the current API. ## Solution This branch adds `?` and `%` sigils to field values in the span and event macros, which expand to the `field::debug` and `field::display` wrappers, respectively. The shorthand sigils may be used in any position where the macros take a field value. For example: ```rust trace_span!("foo", my_field = ?something, ...); // shorthand for `debug` info!(foo = %value, bar = false, ...) // shorthand for `display` ``` Adding this shorthand required a fairly large change to how field key-value pairs are handled by the macros --- since `%foo` and `%foo` are not valid Rust expressions, we can no longer match repeated `$ident = $expr` patterns, and must now match field lists as repeated token trees. The inner helper macros for constructing `FieldSet`s and `ValueSet`s have to parse the token trees recursively. This added a decent chunk of complexity, but fortunately we have a large number of compile tests for the macros and I'm quite confident that all existing invocations will still work. Closes #1081 Signed-off-by: Eliza Weisman <[email protected]>
This commit is contained in:
+40
-3
@@ -94,6 +94,40 @@
|
||||
//! # }
|
||||
//!```
|
||||
//!
|
||||
//! The [`field::display`] and [`field::debug`] functions are used to record
|
||||
//! fields on spans or events using their `fmt::Display` and `fmt::Debug`
|
||||
//! implementations (rather than as typed data). This may be used in lieu of
|
||||
//! custom `Value` implementations for complex or user-defined types.
|
||||
//!
|
||||
//! In addition, the span and event macros permit the use of the `%` and `?`
|
||||
//! sigils as shorthand for `field::display` and `field::debug`, respectively.
|
||||
//! For example:
|
||||
//!
|
||||
//! ```
|
||||
//! # #[macro_use]
|
||||
//! # extern crate tokio_trace;
|
||||
//! # use tokio_trace::Level;
|
||||
//! # fn main() {
|
||||
//! #[derive(Debug)]
|
||||
//! struct MyStruct {
|
||||
//! my_field: &'static str,
|
||||
//! }
|
||||
//!
|
||||
//! let my_struct = MyStruct {
|
||||
//! my_field: "Hello world!"
|
||||
//! };
|
||||
//!
|
||||
//! let my_span = span!(
|
||||
//! Level::TRACE,
|
||||
//! "my_span",
|
||||
//! // `my_struct` will be recorded using its `fmt::Debug` implementation.
|
||||
//! my_struct = ?my_struct,
|
||||
//! // `my_field` will be recorded using the implementation of `fmt::Display` for `&str`.
|
||||
//! my_struct.my_field = %my_struct.my_field,
|
||||
//! );
|
||||
//! # }
|
||||
//!```
|
||||
//!
|
||||
//! ### When to use spans
|
||||
//!
|
||||
//! As a rule of thumb, spans should be used to represent discrete units of work
|
||||
@@ -254,7 +288,8 @@
|
||||
//! ```rust
|
||||
//! #[macro_use]
|
||||
//! extern crate tokio_trace;
|
||||
//! use tokio_trace::{field, Level};
|
||||
//! use tokio_trace::Level;
|
||||
//!
|
||||
//! # #[derive(Debug)] pub struct Yak(String);
|
||||
//! # impl Yak { fn shave(&mut self, _: u32) {} }
|
||||
//! # fn find_a_razor() -> Result<u32, u32> { Ok(1) }
|
||||
@@ -262,7 +297,7 @@
|
||||
//! pub fn shave_the_yak(yak: &mut Yak) {
|
||||
//! // Create a new span for this invocation of `shave_the_yak`, annotated
|
||||
//! // with the yak being shaved as a *field* on the span.
|
||||
//! span!(Level::TRACE, "shave_the_yak", yak = field::debug(&yak)).enter(|| {
|
||||
//! span!(Level::TRACE, "shave_the_yak", yak = ?yak).enter(|| {
|
||||
//! // Since the span is annotated with the yak, it is part of the context
|
||||
//! // for everything happening inside the span. Therefore, we don't need
|
||||
//! // to add it to the message for this event, as the `log` crate does.
|
||||
@@ -274,7 +309,7 @@
|
||||
//! // We can add the razor as a field rather than formatting it
|
||||
//! // as part of the message, allowing subscribers to consume it
|
||||
//! // in a more structured manner:
|
||||
//! info!({ razor = field::display(razor) }, "Razor located");
|
||||
//! info!({ razor = %razor }, "Razor located");
|
||||
//! yak.shave(razor);
|
||||
//! break;
|
||||
//! }
|
||||
@@ -387,6 +422,8 @@
|
||||
//! [`exit`]: subscriber/trait.Subscriber.html#tymethod.exit
|
||||
//! [`enabled`]: subscriber/trait.Subscriber.html#tymethod.enabled
|
||||
//! [metadata]: struct.Metadata.html
|
||||
//! [`field::display`]: field/fn.display.html
|
||||
//! [`field::debug`]: field/fn.debug.html
|
||||
//! [`tokio-trace-nursery`]: https://github.com/tokio-rs/tokio-trace-nursery
|
||||
//! [`tokio-trace-futures`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-futures
|
||||
//! [`tokio-trace-fmt`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-fmt
|
||||
|
||||
+404
-451
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user