mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-09-08 00:00:13 +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:
@@ -4,7 +4,11 @@ mod support;
|
||||
|
||||
use self::support::*;
|
||||
use std::thread;
|
||||
use tokio_trace::{field::display, subscriber::with_default, Level, Span};
|
||||
use tokio_trace::{
|
||||
field::{debug, display},
|
||||
subscriber::with_default,
|
||||
Level, Span,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn handles_to_the_same_span_are_equal() {
|
||||
@@ -547,3 +551,61 @@ fn contextual_child() {
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_shorthand() {
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span::mock().named("my_span").with_field(
|
||||
field::mock("my_field")
|
||||
.with_value(&display("hello world"))
|
||||
.only(),
|
||||
),
|
||||
)
|
||||
.done()
|
||||
.run_with_handle();
|
||||
with_default(subscriber, || {
|
||||
span!(Level::TRACE, "my_span", my_field = %"hello world");
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn debug_shorthand() {
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span::mock().named("my_span").with_field(
|
||||
field::mock("my_field")
|
||||
.with_value(&debug("hello world"))
|
||||
.only(),
|
||||
),
|
||||
)
|
||||
.done()
|
||||
.run_with_handle();
|
||||
with_default(subscriber, || {
|
||||
span!(Level::TRACE, "my_span", my_field = ?"hello world");
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn both_shorthands() {
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span::mock().named("my_span").with_field(
|
||||
field::mock("display_field")
|
||||
.with_value(&display("hello world"))
|
||||
.and(field::mock("debug_field").with_value(&debug("hello world")))
|
||||
.only(),
|
||||
),
|
||||
)
|
||||
.done()
|
||||
.run_with_handle();
|
||||
with_default(subscriber, || {
|
||||
span!(Level::TRACE, "my_span", display_field = %"hello world", debug_field = ?"hello world");
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user