mirror of
https://github.com/tokio-rs/tracing.git
synced 2025-11-11 10:54:15 +00:00
## Motivation
The `tracing-fmt` crate crate currently uses a `NewVisitor` trait to
abstract over constructing field visitors of different types or with
different configurations:
d51d4d69d8/tracing-fmt/src/lib.rs (L192-L196)
There have been other use-cases where having this abstraction seems
valuable. For example, issue #73 is a proposal for adding utilities for
wrapping a visitor to skip a set of excluded field names. A `MakeVisitor`
abstraction would allow us to provide much more ergonomic APIs for
composing this kind of visitor behaviour.
Additionally, the current trait in `tracing-fmt` is tied pretty closely
to `tracing-fmt- specific behaviour. A generalized version of this trait
should be generic over the input type used to build the visitor.
## Solution
This PR adds a new `MakeVisitor` trait in `tracing-subscriber`.
`MakeVisitor` generalizes the `NewVisitor` trait in `tracing-fmt` to
represent constructing visitors for arbitrary targets. In addition, I've
added some additional traits representing common patterns for visitors,
such as those that format to a `fmt::Write` instance or write to an IO
stream, or those that produce output once a set of fields have been
visited. I've also added some extension traits & combinators to make
composing visitors easier, and to demonstrate that the trait in this
branch can be used for implementing this kind of wrapper.
I've also rewritten the `tracing-fmt` crate to use the new
`tracing-subscriber::MakeVisitor` trait rather than its homegrown
`fmt`-specifc version.
Closes: #240
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
71 lines
1.9 KiB
Rust
71 lines
1.9 KiB
Rust
#![deny(rust_2018_idioms)]
|
|
use tracing::{debug, error, info, span, trace, warn, Level};
|
|
|
|
#[tracing::instrument]
|
|
fn shave(yak: usize) -> bool {
|
|
debug!(
|
|
message = "hello! I'm gonna shave a yak.",
|
|
excitement = "yay!"
|
|
);
|
|
if yak == 3 {
|
|
warn!(target: "yak_events", "could not locate yak!");
|
|
false
|
|
} else {
|
|
trace!(target: "yak_events", "yak shaved successfully");
|
|
true
|
|
}
|
|
}
|
|
|
|
fn shave_all(yaks: usize) -> usize {
|
|
let span = span!(Level::TRACE, "shaving_yaks", yaks_to_shave = yaks);
|
|
let _enter = span.enter();
|
|
|
|
info!("shaving yaks");
|
|
|
|
let mut num_shaved = 0;
|
|
for yak in 1..=yaks {
|
|
let shaved = shave(yak);
|
|
trace!(target: "yak_events", yak, shaved);
|
|
|
|
if !shaved {
|
|
error!(message = "failed to shave yak!", yak);
|
|
} else {
|
|
num_shaved += 1;
|
|
}
|
|
|
|
trace!(target: "yak_events", yaks_shaved = num_shaved);
|
|
}
|
|
|
|
num_shaved
|
|
}
|
|
|
|
fn main() {
|
|
use tracing_fmt::format;
|
|
use tracing_subscriber::prelude::*;
|
|
|
|
let formatter =
|
|
// Construct a custom formatter for `Debug` fields
|
|
format::debug_fn(|writer, field, value| write!(writer, "{}: {:?}", field, value))
|
|
// Use `tracing-subscriber`'s extension traits to add delimiters
|
|
// between fields, and ensure that fields named "message" are
|
|
// formatted using fmt::Display.
|
|
.display_messages()
|
|
.delimited(", ");
|
|
|
|
let subscriber = tracing_fmt::FmtSubscriber::builder()
|
|
.fmt_fields(formatter)
|
|
.finish();
|
|
|
|
tracing::subscriber::with_default(subscriber, || {
|
|
let number_of_yaks = 3;
|
|
debug!("preparing to shave {} yaks", number_of_yaks);
|
|
|
|
let number_shaved = shave_all(number_of_yaks);
|
|
|
|
debug!(
|
|
message = "yak shaving completed.",
|
|
all_yaks_shaved = number_shaved == number_of_yaks,
|
|
);
|
|
});
|
|
}
|