mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-09-08 00:00:13 +02:00
trace: Add shorthand syntax for local fields (#1103)
## Motivation
A common pattern in `tokio-trace` is to use the value of a local
variable as a field on a span or event. Currently, this requires code
like:
```rust
info!(foo = foo);
```
which is not particularly ergonomic given how commonly this occurs.
Struct initializers support a shorthand syntax for fields where the name
of the field is the same as a local variable, and `tokio-trace` should
as well.
## Solution
This branch adds support for syntax like
```rust
let foo = ...;
info!(foo);
```
and
```rust
let foo = Foo {
bar: ...,
...
};
info!(foo.bar)
```
to the `tokio-trace` span and event macros. This syntax also works with
the `Debug` and `Display` field shorthand.
The span macros previously used a field name with no value to indicate
an uninitialized field. A new issue, #1138, has been opened for finding a
replacement syntax for uninitialized fields. Until then, the `tokio-trace`
macros will no longer provide a way to create fields without values,
although the `-core` API will continue to support this.
Closes #1062
Signed-off-by: Eliza Weisman <[email protected]>
This commit is contained in:
@@ -394,6 +394,26 @@ fn error() {
|
||||
error!(target: "foo_events", { foo = 2, bar.baz = 78, }, "quux");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn field_shorthand_only() {
|
||||
#[derive(Debug)]
|
||||
struct Position {
|
||||
x: f32,
|
||||
y: f32,
|
||||
}
|
||||
let pos = Position {
|
||||
x: 3.234,
|
||||
y: -1.223,
|
||||
};
|
||||
|
||||
trace!(?pos.x, ?pos.y);
|
||||
debug!(?pos.x, ?pos.y);
|
||||
info!(?pos.x, ?pos.y);
|
||||
warn!(?pos.x, ?pos.y);
|
||||
error!(?pos.x, ?pos.y);
|
||||
event!(Level::TRACE, ?pos.x, ?pos.y);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn callsite_macro_api() {
|
||||
// This test should catch any inadvertant breaking changes
|
||||
|
||||
@@ -391,13 +391,17 @@ fn move_field_out_of_struct() {
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
// TODO(#1138): determine a new syntax for uninitialized span fields, and
|
||||
// re-enable these.
|
||||
/*
|
||||
#[test]
|
||||
fn add_field_after_new_span() {
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span::mock()
|
||||
.named("foo")
|
||||
.with_field(field::mock("bar").with_value(&5).only()),
|
||||
.with_field(field::mock("bar").with_value(&5)
|
||||
.and(field::mock("baz").with_value).only()),
|
||||
)
|
||||
.record(
|
||||
span::mock().named("foo"),
|
||||
@@ -410,7 +414,7 @@ fn add_field_after_new_span() {
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
let span = span!(Level::TRACE, "foo", bar = 5, baz);
|
||||
let span = span!(Level::TRACE, "foo", bar = 5, baz = false);
|
||||
span.record("baz", &true);
|
||||
span.in_scope(|| {})
|
||||
});
|
||||
@@ -437,7 +441,73 @@ fn add_fields_only_after_new_span() {
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
let span = span!(Level::TRACE, "foo", bar, baz);
|
||||
let span = span!(Level::TRACE, "foo", bar = _, baz = _);
|
||||
span.record("bar", &5);
|
||||
span.record("baz", &true);
|
||||
span.in_scope(|| {})
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
*/
|
||||
|
||||
#[test]
|
||||
fn record_new_value_for_field() {
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span::mock().named("foo").with_field(
|
||||
field::mock("bar")
|
||||
.with_value(&5)
|
||||
.and(field::mock("baz").with_value(&false))
|
||||
.only(),
|
||||
),
|
||||
)
|
||||
.record(
|
||||
span::mock().named("foo"),
|
||||
field::mock("baz").with_value(&true).only(),
|
||||
)
|
||||
.enter(span::mock().named("foo"))
|
||||
.exit(span::mock().named("foo"))
|
||||
.drop_span(span::mock().named("foo"))
|
||||
.done()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
let span = span!(Level::TRACE, "foo", bar = 5, baz = false);
|
||||
span.record("baz", &true);
|
||||
span.in_scope(|| {})
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_new_values_for_fields() {
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span::mock().named("foo").with_field(
|
||||
field::mock("bar")
|
||||
.with_value(&4)
|
||||
.and(field::mock("baz").with_value(&false))
|
||||
.only(),
|
||||
),
|
||||
)
|
||||
.record(
|
||||
span::mock().named("foo"),
|
||||
field::mock("bar").with_value(&5).only(),
|
||||
)
|
||||
.record(
|
||||
span::mock().named("foo"),
|
||||
field::mock("baz").with_value(&true).only(),
|
||||
)
|
||||
.enter(span::mock().named("foo"))
|
||||
.exit(span::mock().named("foo"))
|
||||
.drop_span(span::mock().named("foo"))
|
||||
.done()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
let span = span!(Level::TRACE, "foo", bar = 4, baz = false);
|
||||
span.record("bar", &5);
|
||||
span.record("baz", &true);
|
||||
span.in_scope(|| {})
|
||||
|
||||
Reference in New Issue
Block a user