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:
Eliza Weisman
2019-06-09 13:16:35 -07:00
committed by GitHub
parent 8d0f102de8
commit 41ca9a43de
5 changed files with 567 additions and 98 deletions
+73 -3
View File
@@ -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(|| {})