mirror of
https://github.com/tokio-rs/tracing.git
synced 2025-10-01 15:00:33 +00:00
This backports PR #1067 to v0.1.x. Since this has already been approved on master, I'm just going to go ahead and merge it when CI passes. ## Motivation Currently, the `tracing_subscriber::fmt` module contains only single-line event formatters. Some users have requested a human-readable, pretty-printing event formatter optimized for aesthetics. ## Solution This branch adds a new `Pretty` formatter which uses an _excessively_ pretty output format. It's neither compact, single-line oriented, nor easily machine-readable, but it looks _quite_ nice, in my opinion. This is well suited for local development or potentially for user-facing logs in a CLI application. Additionally, I tried to improve the docs for the different formatters currently provided, including example output. Check out [the Netlify preview][1]! [1]: https://deploy-preview-1067--tracing-rs.netlify.app/tracing_subscriber/fmt/index.html#formatters Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This commit is contained in:
parent
3bc2fd35e6
commit
8bdc6c367d
21
examples/examples/fmt-json.rs
Normal file
21
examples/examples/fmt-json.rs
Normal file
@ -0,0 +1,21 @@
|
||||
#![deny(rust_2018_idioms)]
|
||||
#[path = "fmt/yak_shave.rs"]
|
||||
mod yak_shave;
|
||||
|
||||
fn main() {
|
||||
tracing_subscriber::fmt()
|
||||
.json()
|
||||
.with_max_level(tracing::Level::TRACE)
|
||||
.with_current_span(false)
|
||||
.init();
|
||||
|
||||
let number_of_yaks = 3;
|
||||
// this creates a new event, outside of any spans.
|
||||
tracing::info!(number_of_yaks, "preparing to shave yaks");
|
||||
|
||||
let number_shaved = yak_shave::shave_all(number_of_yaks);
|
||||
tracing::info!(
|
||||
all_yaks_shaved = number_shaved == number_of_yaks,
|
||||
"yak shaving completed"
|
||||
);
|
||||
}
|
23
examples/examples/fmt-pretty.rs
Normal file
23
examples/examples/fmt-pretty.rs
Normal file
@ -0,0 +1,23 @@
|
||||
#![deny(rust_2018_idioms)]
|
||||
#[path = "fmt/yak_shave.rs"]
|
||||
mod yak_shave;
|
||||
|
||||
fn main() {
|
||||
tracing_subscriber::fmt()
|
||||
.pretty()
|
||||
.with_thread_names(true)
|
||||
// enable everything
|
||||
.with_max_level(tracing::Level::TRACE)
|
||||
// sets this to be the default, global collector for this application.
|
||||
.init();
|
||||
|
||||
let number_of_yaks = 3;
|
||||
// this creates a new event, outside of any spans.
|
||||
tracing::info!(number_of_yaks, "preparing to shave yaks");
|
||||
|
||||
let number_shaved = yak_shave::shave_all(number_of_yaks);
|
||||
tracing::info!(
|
||||
all_yaks_shaved = number_shaved == number_of_yaks,
|
||||
"yak shaving completed"
|
||||
);
|
||||
}
|
@ -1,23 +1,20 @@
|
||||
#![deny(rust_2018_idioms)]
|
||||
use tracing::{info, Level};
|
||||
|
||||
#[path = "fmt/yak_shave.rs"]
|
||||
mod yak_shave;
|
||||
|
||||
fn main() {
|
||||
tracing_subscriber::fmt()
|
||||
// all spans/events with a level higher than DEBUG (e.g, info, warn, etc.)
|
||||
// will be written to stdout.
|
||||
.with_max_level(Level::DEBUG)
|
||||
// sets this to be the default, global subscriber for this application.
|
||||
// enable everything
|
||||
.with_max_level(tracing::Level::TRACE)
|
||||
// sets this to be the default, global collector for this application.
|
||||
.init();
|
||||
|
||||
let number_of_yaks = 3;
|
||||
// this creates a new event, outside of any spans.
|
||||
info!(number_of_yaks, "preparing to shave yaks");
|
||||
tracing::info!(number_of_yaks, "preparing to shave yaks");
|
||||
|
||||
let number_shaved = yak_shave::shave_all(number_of_yaks);
|
||||
info!(
|
||||
tracing::info!(
|
||||
all_yaks_shaved = number_shaved == number_of_yaks,
|
||||
"yak shaving completed."
|
||||
);
|
||||
|
@ -1,38 +1,38 @@
|
||||
use std::{error::Error, io};
|
||||
use tracing::{debug, error, info, span, warn, Level};
|
||||
use tracing::{debug, error, info, span, trace, warn, Level};
|
||||
|
||||
// the `#[tracing::instrument]` attribute creates and enters a span
|
||||
// every time the instrumented function is called. The span is named after the
|
||||
// the function or method. Paramaters passed to the function are recorded as fields.
|
||||
#[tracing::instrument]
|
||||
pub fn shave(yak: usize) -> Result<(), Box<dyn Error + 'static>> {
|
||||
// this creates an event at the DEBUG log level with two fields:
|
||||
// this creates an event at the TRACE log level with two fields:
|
||||
// - `excitement`, with the key "excitement" and the value "yay!"
|
||||
// - `message`, with the key "message" and the value "hello! I'm gonna shave a yak."
|
||||
//
|
||||
// unlike other fields, `message`'s shorthand initialization is just the string itself.
|
||||
debug!(excitement = "yay!", "hello! I'm gonna shave a yak.");
|
||||
trace!(excitement = "yay!", "hello! I'm gonna shave a yak");
|
||||
if yak == 3 {
|
||||
warn!("could not locate yak!");
|
||||
warn!("could not locate yak");
|
||||
// note that this is intended to demonstrate `tracing`'s features, not idiomatic
|
||||
// error handling! in a library or application, you should consider returning
|
||||
// a dedicated `YakError`. libraries like snafu or thiserror make this easy.
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "shaving yak failed!").into());
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "missing yak").into());
|
||||
} else {
|
||||
debug!("yak shaved successfully");
|
||||
trace!("yak shaved successfully");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn shave_all(yaks: usize) -> usize {
|
||||
// Constructs a new span named "shaving_yaks" at the TRACE level,
|
||||
// Constructs a new span named "shaving_yaks" at the INFO level,
|
||||
// and a field whose key is "yaks". This is equivalent to writing:
|
||||
//
|
||||
// let span = span!(Level::TRACE, "shaving_yaks", yaks = yaks);
|
||||
// let span = span!(Level::INFO, "shaving_yaks", yaks = yaks);
|
||||
//
|
||||
// local variables (`yaks`) can be used as field values
|
||||
// without an assignment, similar to struct initializers.
|
||||
let span = span!(Level::TRACE, "shaving_yaks", yaks);
|
||||
let span = span!(Level::INFO, "shaving_yaks", yaks);
|
||||
let _enter = span.enter();
|
||||
|
||||
info!("shaving yaks");
|
||||
@ -40,16 +40,16 @@ pub fn shave_all(yaks: usize) -> usize {
|
||||
let mut yaks_shaved = 0;
|
||||
for yak in 1..=yaks {
|
||||
let res = shave(yak);
|
||||
debug!(yak, shaved = res.is_ok());
|
||||
debug!(target: "yak_events", yak, shaved = res.is_ok());
|
||||
|
||||
if let Err(ref error) = res {
|
||||
// Like spans, events can also use the field initialization shorthand.
|
||||
// In this instance, `yak` is the field being initalized.
|
||||
error!(yak, error = error.as_ref(), "failed to shave yak!");
|
||||
error!(yak, error = error.as_ref(), "failed to shave yak");
|
||||
} else {
|
||||
yaks_shaved += 1;
|
||||
}
|
||||
debug!(yaks_shaved);
|
||||
trace!(yaks_shaved);
|
||||
}
|
||||
|
||||
yaks_shaved
|
||||
|
@ -367,6 +367,19 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the layer being built to use an [excessively pretty, human-readable formatter](crate::fmt::format::Pretty).
|
||||
#[cfg(feature = "ansi")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "ansi")))]
|
||||
pub fn pretty(self) -> Layer<S, format::Pretty, format::Format<format::Pretty, T>, W> {
|
||||
Layer {
|
||||
fmt_event: self.fmt_event.pretty(),
|
||||
fmt_fields: format::Pretty::default(),
|
||||
fmt_span: self.fmt_span,
|
||||
make_writer: self.make_writer,
|
||||
_inner: self._inner,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the layer being built to use a [JSON formatter](../fmt/format/struct.Json.html).
|
||||
///
|
||||
/// The full format includes fields from all entered spans.
|
||||
|
@ -24,12 +24,18 @@ use ansi_term::{Colour, Style};
|
||||
|
||||
#[cfg(feature = "json")]
|
||||
mod json;
|
||||
|
||||
use fmt::{Debug, Display};
|
||||
#[cfg(feature = "json")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
|
||||
pub use json::*;
|
||||
|
||||
#[cfg(feature = "ansi")]
|
||||
mod pretty;
|
||||
#[cfg(feature = "ansi")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "ansi")))]
|
||||
pub use pretty::*;
|
||||
|
||||
use fmt::{Debug, Display};
|
||||
|
||||
/// A type that can format a tracing `Event` for a `fmt::Write`.
|
||||
///
|
||||
/// `FormatEvent` is primarily used in the context of [`fmt::Subscriber`] or [`fmt::Layer`]. Each time an event is
|
||||
@ -214,6 +220,25 @@ impl<F, T> Format<F, T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Use an excessively pretty, human-readable output format.
|
||||
///
|
||||
/// See [`Pretty`].
|
||||
///
|
||||
/// Note that this requires the "ansi" feature to be enabled.
|
||||
#[cfg(feature = "ansi")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "ansi")))]
|
||||
pub fn pretty(self) -> Format<Pretty, T> {
|
||||
Format {
|
||||
format: Pretty::default(),
|
||||
timer: self.timer,
|
||||
ansi: self.ansi,
|
||||
display_target: self.display_target,
|
||||
display_level: self.display_level,
|
||||
display_thread_id: self.display_thread_id,
|
||||
display_thread_name: self.display_thread_name,
|
||||
}
|
||||
}
|
||||
|
||||
/// Use the full JSON format.
|
||||
///
|
||||
/// The full format includes fields from all entered spans.
|
||||
@ -521,6 +546,7 @@ where
|
||||
}
|
||||
|
||||
// === impl FormatFields ===
|
||||
|
||||
impl<'writer, M> FormatFields<'writer> for M
|
||||
where
|
||||
M: MakeOutput<&'writer mut dyn fmt::Write, fmt::Result>,
|
||||
@ -622,10 +648,7 @@ impl<'a> field::Visit for DefaultVisitor<'a> {
|
||||
|
||||
fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
|
||||
if let Some(source) = value.source() {
|
||||
self.record_debug(
|
||||
field,
|
||||
&format_args!("{} {}.source={}", value, field, source),
|
||||
)
|
||||
self.record_debug(field, &format_args!("{}, {}: {}", value, field, source))
|
||||
} else {
|
||||
self.record_debug(field, &format_args!("{}", value))
|
||||
}
|
||||
|
339
tracing-subscriber/src/fmt/format/pretty.rs
Normal file
339
tracing-subscriber/src/fmt/format/pretty.rs
Normal file
@ -0,0 +1,339 @@
|
||||
use super::*;
|
||||
use crate::{
|
||||
field::{VisitFmt, VisitOutput},
|
||||
fmt::fmt_layer::{FmtContext, FormattedFields},
|
||||
registry::LookupSpan,
|
||||
};
|
||||
|
||||
use std::{
|
||||
fmt::{self, Write},
|
||||
iter,
|
||||
};
|
||||
use tracing_core::{
|
||||
field::{self, Field},
|
||||
Event, Level, Subscriber,
|
||||
};
|
||||
|
||||
#[cfg(feature = "tracing-log")]
|
||||
use tracing_log::NormalizeEvent;
|
||||
|
||||
use ansi_term::{Colour, Style};
|
||||
|
||||
/// An excessively pretty, human-readable event formatter.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Pretty {
|
||||
display_location: bool,
|
||||
}
|
||||
|
||||
/// The [visitor] produced by [`Pretty`]'s [`MakeVisitor`] implementation.
|
||||
///
|
||||
/// [visitor]: ../../field/trait.Visit.html
|
||||
/// [`DefaultFields`]: struct.DefaultFields.html
|
||||
/// [`MakeVisitor`]: ../../field/trait.MakeVisitor.html
|
||||
pub struct PrettyVisitor<'a> {
|
||||
writer: &'a mut dyn Write,
|
||||
is_empty: bool,
|
||||
style: Style,
|
||||
result: fmt::Result,
|
||||
}
|
||||
|
||||
// === impl Pretty ===
|
||||
|
||||
impl Default for Pretty {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
display_location: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pretty {
|
||||
fn style_for(level: &Level) -> Style {
|
||||
match *level {
|
||||
Level::TRACE => Style::new().fg(Colour::Purple),
|
||||
Level::DEBUG => Style::new().fg(Colour::Blue),
|
||||
Level::INFO => Style::new().fg(Colour::Green),
|
||||
Level::WARN => Style::new().fg(Colour::Yellow),
|
||||
Level::ERROR => Style::new().fg(Colour::Red),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets whether the event's source code location is displayed.
|
||||
///
|
||||
/// This defaults to `true`.
|
||||
pub fn with_source_location(self, display_location: bool) -> Self {
|
||||
Self {
|
||||
display_location,
|
||||
..self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Format<Pretty, T> {
|
||||
/// Sets whether or not the source code location from which an event
|
||||
/// originated is displayed.
|
||||
///
|
||||
/// This defaults to `true`.
|
||||
pub fn with_source_location(mut self, display_location: bool) -> Self {
|
||||
self.format = self.format.with_source_location(display_location);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, N, T> FormatEvent<C, N> for Format<Pretty, T>
|
||||
where
|
||||
C: Subscriber + for<'a> LookupSpan<'a>,
|
||||
N: for<'a> FormatFields<'a> + 'static,
|
||||
T: FormatTime,
|
||||
{
|
||||
fn format_event(
|
||||
&self,
|
||||
ctx: &FmtContext<'_, C, N>,
|
||||
writer: &mut dyn fmt::Write,
|
||||
event: &Event<'_>,
|
||||
) -> fmt::Result {
|
||||
#[cfg(feature = "tracing-log")]
|
||||
let normalized_meta = event.normalized_metadata();
|
||||
#[cfg(feature = "tracing-log")]
|
||||
let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
|
||||
#[cfg(not(feature = "tracing-log"))]
|
||||
let meta = event.metadata();
|
||||
write!(writer, " ")?;
|
||||
time::write(&self.timer, writer, true)?;
|
||||
|
||||
let style = if self.display_level {
|
||||
Pretty::style_for(meta.level())
|
||||
} else {
|
||||
Style::new()
|
||||
};
|
||||
|
||||
if self.display_target {
|
||||
let bold = style.bold();
|
||||
write!(
|
||||
writer,
|
||||
"{}{}{}: ",
|
||||
bold.prefix(),
|
||||
meta.target(),
|
||||
bold.infix(style)
|
||||
)?;
|
||||
}
|
||||
let mut v = PrettyVisitor::new(writer, true).with_style(style);
|
||||
event.record(&mut v);
|
||||
v.finish()?;
|
||||
writer.write_char('\n')?;
|
||||
|
||||
let dimmed = Style::new().dimmed().italic();
|
||||
let thread = self.display_thread_name || self.display_thread_id;
|
||||
if let (true, Some(file), Some(line)) =
|
||||
(self.format.display_location, meta.file(), meta.line())
|
||||
{
|
||||
write!(
|
||||
writer,
|
||||
" {} {}:{}{}",
|
||||
dimmed.paint("at"),
|
||||
file,
|
||||
line,
|
||||
dimmed.paint(if thread { " " } else { "\n" })
|
||||
)?;
|
||||
} else if thread {
|
||||
write!(writer, " ")?;
|
||||
}
|
||||
|
||||
if thread {
|
||||
write!(writer, "{} ", dimmed.paint("on"))?;
|
||||
let thread = std::thread::current();
|
||||
if self.display_thread_name {
|
||||
if let Some(name) = thread.name() {
|
||||
write!(writer, "{}", name)?;
|
||||
if self.display_thread_id {
|
||||
write!(writer, " ({:?})", thread.id())?;
|
||||
}
|
||||
} else if !self.display_thread_id {
|
||||
write!(writer, " {:?}", thread.id())?;
|
||||
}
|
||||
} else if self.display_thread_id {
|
||||
write!(writer, " {:?}", thread.id())?;
|
||||
}
|
||||
writer.write_char('\n')?;
|
||||
}
|
||||
|
||||
let bold = Style::new().bold();
|
||||
let span = event
|
||||
.parent()
|
||||
.and_then(|id| ctx.span(&id))
|
||||
.or_else(|| ctx.lookup_current());
|
||||
|
||||
let scope = span.into_iter().flat_map(|span| {
|
||||
let parents = span.parents();
|
||||
iter::once(span).chain(parents)
|
||||
});
|
||||
|
||||
for span in scope {
|
||||
let meta = span.metadata();
|
||||
if self.display_target {
|
||||
write!(
|
||||
writer,
|
||||
" {} {}::{}",
|
||||
dimmed.paint("in"),
|
||||
meta.target(),
|
||||
bold.paint(meta.name()),
|
||||
)?;
|
||||
} else {
|
||||
write!(
|
||||
writer,
|
||||
" {} {}",
|
||||
dimmed.paint("in"),
|
||||
bold.paint(meta.name()),
|
||||
)?;
|
||||
}
|
||||
|
||||
let ext = span.extensions();
|
||||
let fields = &ext
|
||||
.get::<FormattedFields<N>>()
|
||||
.expect("Unable to find FormattedFields in extensions; this is a bug");
|
||||
if !fields.is_empty() {
|
||||
write!(writer, " {} {}", dimmed.paint("with"), fields)?;
|
||||
}
|
||||
writer.write_char('\n')?;
|
||||
}
|
||||
|
||||
writer.write_char('\n')
|
||||
}
|
||||
}
|
||||
|
||||
impl<'writer> FormatFields<'writer> for Pretty {
|
||||
fn format_fields<R: RecordFields>(
|
||||
&self,
|
||||
writer: &'writer mut dyn fmt::Write,
|
||||
fields: R,
|
||||
) -> fmt::Result {
|
||||
let mut v = PrettyVisitor::new(writer, true);
|
||||
fields.record(&mut v);
|
||||
v.finish()
|
||||
}
|
||||
|
||||
fn add_fields(&self, current: &'writer mut String, fields: &span::Record<'_>) -> fmt::Result {
|
||||
let empty = current.is_empty();
|
||||
let mut v = PrettyVisitor::new(current, empty);
|
||||
fields.record(&mut v);
|
||||
v.finish()
|
||||
}
|
||||
}
|
||||
|
||||
// === impl PrettyVisitor ===
|
||||
|
||||
impl<'a> PrettyVisitor<'a> {
|
||||
/// Returns a new default visitor that formats to the provided `writer`.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `writer`: the writer to format to.
|
||||
/// - `is_empty`: whether or not any fields have been previously written to
|
||||
/// that writer.
|
||||
pub fn new(writer: &'a mut dyn Write, is_empty: bool) -> Self {
|
||||
Self {
|
||||
writer,
|
||||
is_empty,
|
||||
style: Style::default(),
|
||||
result: Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn with_style(self, style: Style) -> Self {
|
||||
Self { style, ..self }
|
||||
}
|
||||
|
||||
fn maybe_pad(&mut self) {
|
||||
if self.is_empty {
|
||||
self.is_empty = false;
|
||||
} else {
|
||||
self.result = write!(self.writer, ", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> field::Visit for PrettyVisitor<'a> {
|
||||
fn record_str(&mut self, field: &Field, value: &str) {
|
||||
if self.result.is_err() {
|
||||
return;
|
||||
}
|
||||
|
||||
if field.name() == "message" {
|
||||
self.record_debug(field, &format_args!("{}", value))
|
||||
} else {
|
||||
self.record_debug(field, &value)
|
||||
}
|
||||
}
|
||||
|
||||
fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
|
||||
if let Some(source) = value.source() {
|
||||
let bold = self.style.bold();
|
||||
self.record_debug(
|
||||
field,
|
||||
&format_args!(
|
||||
"{}, {}{}.source{}: {}",
|
||||
value,
|
||||
bold.prefix(),
|
||||
field,
|
||||
bold.infix(self.style),
|
||||
source,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
self.record_debug(field, &format_args!("{}", value))
|
||||
}
|
||||
}
|
||||
|
||||
fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
|
||||
if self.result.is_err() {
|
||||
return;
|
||||
}
|
||||
let bold = self.style.bold();
|
||||
self.maybe_pad();
|
||||
self.result = match field.name() {
|
||||
"message" => write!(self.writer, "{}{:?}", self.style.prefix(), value,),
|
||||
// Skip fields that are actually log metadata that have already been handled
|
||||
#[cfg(feature = "tracing-log")]
|
||||
name if name.starts_with("log.") => Ok(()),
|
||||
name if name.starts_with("r#") => write!(
|
||||
self.writer,
|
||||
"{}{}{}: {:?}",
|
||||
bold.prefix(),
|
||||
&name[2..],
|
||||
bold.infix(self.style),
|
||||
value
|
||||
),
|
||||
name => write!(
|
||||
self.writer,
|
||||
"{}{}{}: {:?}",
|
||||
bold.prefix(),
|
||||
name,
|
||||
bold.infix(self.style),
|
||||
value
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VisitOutput<fmt::Result> for PrettyVisitor<'a> {
|
||||
fn finish(self) -> fmt::Result {
|
||||
write!(self.writer, "{}", self.style.suffix())?;
|
||||
self.result
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VisitFmt for PrettyVisitor<'a> {
|
||||
fn writer(&mut self) -> &mut dyn fmt::Write {
|
||||
self.writer
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Debug for PrettyVisitor<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("PrettyVisitor")
|
||||
.field("writer", &format_args!("<dyn fmt::Write>"))
|
||||
.field("is_empty", &self.is_empty)
|
||||
.field("result", &self.result)
|
||||
.field("style", &self.style)
|
||||
.finish()
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@
|
||||
//!
|
||||
//! ## Filtering Events with Environment Variables
|
||||
//!
|
||||
//! The default subscriber installed by `init` enables you to filter events
|
||||
//! The default collector installed by `init` enables you to filter events
|
||||
//! at runtime using environment variables (using the [`EnvFilter`]).
|
||||
//!
|
||||
//! The filter syntax is a superset of the [`env_logger`] syntax.
|
||||
@ -52,12 +52,148 @@
|
||||
//! You can create one by calling:
|
||||
//!
|
||||
//! ```rust
|
||||
//! let subscriber = tracing_subscriber::fmt()
|
||||
//! let collector = tracing_subscriber::fmt()
|
||||
//! // ... add configuration
|
||||
//! .finish();
|
||||
//! ```
|
||||
//!
|
||||
//! You can find the configuration methods for [`FmtSubscriber`] in [`fmtBuilder`].
|
||||
//! You can find the configuration methods for [`FmtSubscriber`] in
|
||||
//! [`SubscriberBuilder`].
|
||||
//!
|
||||
//! ### Formatters
|
||||
//!
|
||||
//! The output format used by the layer and subscriber in this module is
|
||||
//! represented by implementing the [`FormatEvent`] trait, and can be
|
||||
//! customized. This module provides a number of formatter implementations:
|
||||
//!
|
||||
//! * [`format::Full`]: The default formatter. This emits human-readable,
|
||||
//! single-line logs for each event that occurs, with the current span context
|
||||
//! displayed before the formatted representation of the event.
|
||||
//!
|
||||
//! For example:
|
||||
//! <pre><font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 1.59s
|
||||
//! <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt`
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#4E9A06"> INFO</font> fmt: preparing to shave yaks number_of_yaks=3
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#4E9A06"> INFO</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: shaving yaks
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=1<b>}</b>: fmt::yak_shave: hello! I'm gonna shave a yak excitement="yay!"
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=1<b>}</b>: fmt::yak_shave: yak shaved successfully
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: yak_events: yak=1 shaved=true
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: yaks_shaved=1
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=2<b>}</b>: fmt::yak_shave: hello! I'm gonna shave a yak excitement="yay!"
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=2<b>}</b>: fmt::yak_shave: yak shaved successfully
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: yak_events: yak=2 shaved=true
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: yaks_shaved=2
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=3<b>}</b>: fmt::yak_shave: hello! I'm gonna shave a yak excitement="yay!"
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#C4A000"> WARN</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=3<b>}</b>: fmt::yak_shave: could not locate yak
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: yak_events: yak=3 shaved=false
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#CC0000">ERROR</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: failed to shave yak yak=3 error=missing yak
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: yaks_shaved=2
|
||||
//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#4E9A06"> INFO</font> fmt: yak shaving completed all_yaks_shaved=false
|
||||
//! </pre>
|
||||
//!
|
||||
//! * [`format::Pretty`]: Emits excessively pretty, multi-line logs, optimized
|
||||
//! for human readability. This is primarily intended to be used in local
|
||||
//! development and debugging, or for command-line applications, where
|
||||
//! automated analysis and compact storage of logs is less of a priority than
|
||||
//! readability and visual appeal.
|
||||
//!
|
||||
//! For example:
|
||||
//! <pre><font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 1.61s
|
||||
//! <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt-pretty`
|
||||
//! Oct 24 12:57:29.386 <font color="#4E9A06"><b>fmt_pretty</b></font><font color="#4E9A06">: preparing to shave yaks, </font><font color="#4E9A06"><b>number_of_yaks</b></font><font color="#4E9A06">: 3</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt-pretty.rs:16<font color="#AAAAAA"><i> on</i></font> main
|
||||
//!
|
||||
//! Oct 24 12:57:29.386 <font color="#4E9A06"><b>fmt_pretty::yak_shave</b></font><font color="#4E9A06">: shaving yaks</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:38<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
|
||||
//!
|
||||
//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I'm gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: "yay!"</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:14<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 1
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
|
||||
//!
|
||||
//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: yak shaved successfully</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:22<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 1
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
|
||||
//!
|
||||
//! Oct 24 12:57:29.387 <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 1, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: true</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:43<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
|
||||
//!
|
||||
//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 1</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:52<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
|
||||
//!
|
||||
//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I'm gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: "yay!"</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:14<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 2
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
|
||||
//!
|
||||
//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: yak shaved successfully</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:22<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 2
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
|
||||
//!
|
||||
//! Oct 24 12:57:29.387 <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 2, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: true</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:43<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
|
||||
//!
|
||||
//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 2</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:52<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
|
||||
//!
|
||||
//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I'm gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: "yay!"</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:14<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 3
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
|
||||
//!
|
||||
//! Oct 24 12:57:29.387 <font color="#C4A000"><b>fmt_pretty::yak_shave</b></font><font color="#C4A000">: could not locate yak</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:16<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 3
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
|
||||
//!
|
||||
//! Oct 24 12:57:29.387 <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 3, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: false</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:43<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
|
||||
//!
|
||||
//! Oct 24 12:57:29.387 <font color="#CC0000"><b>fmt_pretty::yak_shave</b></font><font color="#CC0000">: failed to shave yak, </font><font color="#CC0000"><b>yak</b></font><font color="#CC0000">: 3, </font><font color="#CC0000"><b>error</b></font><font color="#CC0000">: missing yak</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:48<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
|
||||
//!
|
||||
//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 2</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:52<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
|
||||
//!
|
||||
//! Oct 24 12:57:29.387 <font color="#4E9A06"><b>fmt_pretty</b></font><font color="#4E9A06">: yak shaving completed, </font><font color="#4E9A06"><b>all_yaks_shaved</b></font><font color="#4E9A06">: false</font>
|
||||
//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt-pretty.rs:19<font color="#AAAAAA"><i> on</i></font> main
|
||||
//! </pre>
|
||||
//!
|
||||
//! * [`format::Json`]: Outputs newline-delimited JSON logs. This is intended
|
||||
//! for production use with systems where structured logs are consumed as JSON
|
||||
//! by analysis and viewing tools. The JSON output, as seen below, is *not*
|
||||
//! optimized for human readability.
|
||||
//!
|
||||
//! For example:
|
||||
//! <pre><font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 1.58s
|
||||
//! <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt-json`
|
||||
//! {"timestamp":"Oct 24 13:00:00.873","level":"INFO","fields":{"message":"preparing to shave yaks","number_of_yaks":3},"target":"fmt_json"}
|
||||
//! {"timestamp":"Oct 24 13:00:00.874","level":"INFO","fields":{"message":"shaving yaks"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"}]}
|
||||
//! {"timestamp":"Oct 24 13:00:00.874","level":"TRACE","fields":{"message":"hello! I'm gonna shave a yak","excitement":"yay!"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":"1","name":"shave"}]}
|
||||
//! {"timestamp":"Oct 24 13:00:00.874","level":"TRACE","fields":{"message":"yak shaved successfully"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":"1","name":"shave"}]}
|
||||
//! {"timestamp":"Oct 24 13:00:00.874","level":"DEBUG","fields":{"yak":1,"shaved":true},"target":"yak_events","spans":[{"yaks":3,"name":"shaving_yaks"}]}
|
||||
//! {"timestamp":"Oct 24 13:00:00.874","level":"TRACE","fields":{"yaks_shaved":1},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"}]}
|
||||
//! {"timestamp":"Oct 24 13:00:00.874","level":"TRACE","fields":{"message":"hello! I'm gonna shave a yak","excitement":"yay!"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":"2","name":"shave"}]}
|
||||
//! {"timestamp":"Oct 24 13:00:00.874","level":"TRACE","fields":{"message":"yak shaved successfully"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":"2","name":"shave"}]}
|
||||
//! {"timestamp":"Oct 24 13:00:00.874","level":"DEBUG","fields":{"yak":2,"shaved":true},"target":"yak_events","spans":[{"yaks":3,"name":"shaving_yaks"}]}
|
||||
//! {"timestamp":"Oct 24 13:00:00.874","level":"TRACE","fields":{"yaks_shaved":2},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"}]}
|
||||
//! {"timestamp":"Oct 24 13:00:00.874","level":"TRACE","fields":{"message":"hello! I'm gonna shave a yak","excitement":"yay!"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":"3","name":"shave"}]}
|
||||
//! {"timestamp":"Oct 24 13:00:00.875","level":"WARN","fields":{"message":"could not locate yak"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"},{"yak":"3","name":"shave"}]}
|
||||
//! {"timestamp":"Oct 24 13:00:00.875","level":"DEBUG","fields":{"yak":3,"shaved":false},"target":"yak_events","spans":[{"yaks":3,"name":"shaving_yaks"}]}
|
||||
//! {"timestamp":"Oct 24 13:00:00.875","level":"ERROR","fields":{"message":"failed to shave yak","yak":3,"error":"missing yak"},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"}]}
|
||||
//! {"timestamp":"Oct 24 13:00:00.875","level":"TRACE","fields":{"yaks_shaved":2},"target":"fmt_json::yak_shave","spans":[{"yaks":3,"name":"shaving_yaks"}]}
|
||||
//! {"timestamp":"Oct 24 13:00:00.875","level":"INFO","fields":{"message":"yak shaving completed","all_yaks_shaved":false},"target":"fmt_json"}
|
||||
//! </pre>
|
||||
//!
|
||||
//! ### Filters
|
||||
//!
|
||||
@ -116,7 +252,7 @@
|
||||
//! [`EnvFilter`]: ../filter/struct.EnvFilter.html
|
||||
//! [`env_logger`]: https://docs.rs/env_logger/
|
||||
//! [`filter`]: ../filter/index.html
|
||||
//! [`fmtBuilder`]: ./struct.SubscriberBuilder.html
|
||||
//! [`SubscriberBuilder`]: ./struct.SubscriberBuilder.html
|
||||
//! [`FmtSubscriber`]: ./struct.Subscriber.html
|
||||
//! [`Subscriber`]:
|
||||
//! https://docs.rs/tracing/latest/tracing/trait.Subscriber.html
|
||||
@ -200,7 +336,7 @@ pub struct SubscriberBuilder<
|
||||
/// .with_target(false)
|
||||
/// .with_timer(tracing_subscriber::fmt::time::uptime())
|
||||
/// .with_level(true)
|
||||
/// // Set the subscriber as the default.
|
||||
/// // Set the collector as the default.
|
||||
/// .init();
|
||||
/// ```
|
||||
///
|
||||
@ -211,11 +347,11 @@ pub struct SubscriberBuilder<
|
||||
///
|
||||
/// fn init_subscriber() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
||||
/// tracing_subscriber::fmt()
|
||||
/// // Configure the subscriber to emit logs in JSON format.
|
||||
/// // Configure the collector to emit logs in JSON format.
|
||||
/// .json()
|
||||
/// // Configure the subscriber to flatten event fields in the output JSON objects.
|
||||
/// // Configure the collector to flatten event fields in the output JSON objects.
|
||||
/// .flatten_event(true)
|
||||
/// // Set the subscriber as the default, returning an error if this fails.
|
||||
/// // Set the collector as the default, returning an error if this fails.
|
||||
/// .try_init()?;
|
||||
///
|
||||
/// Ok(())
|
||||
@ -572,7 +708,7 @@ where
|
||||
|
||||
/// Sets the subscriber being built to use a less verbose formatter.
|
||||
///
|
||||
/// See [`format::Compact`](../fmt/format/struct.Compact.html).
|
||||
/// See [`format::Compact`].
|
||||
pub fn compact(self) -> SubscriberBuilder<N, format::Format<format::Compact, T>, F, W>
|
||||
where
|
||||
N: for<'writer> FormatFields<'writer> + 'static,
|
||||
@ -583,6 +719,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the subscriber being built to use an [excessively pretty, human-readable formatter](crate::fmt::format::Pretty).
|
||||
#[cfg(feature = "ansi")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "ansi")))]
|
||||
pub fn pretty(
|
||||
self,
|
||||
) -> SubscriberBuilder<format::Pretty, format::Format<format::Pretty, T>, F, W> {
|
||||
SubscriberBuilder {
|
||||
filter: self.filter,
|
||||
inner: self.inner.pretty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the subscriber being built to use a JSON formatter.
|
||||
///
|
||||
/// See [`format::Json`](../fmt/format/struct.Json.html)
|
||||
@ -617,7 +765,7 @@ impl<T, F, W> SubscriberBuilder<format::JsonFields, format::Format<format::Json,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets whether or not the JSON layer being built will include the current span
|
||||
/// Sets whether or not the JSON subscriber being built will include the current span
|
||||
/// in formatted events.
|
||||
///
|
||||
/// See [`format::Json`](../fmt/format/struct.Json.html)
|
||||
@ -631,7 +779,7 @@ impl<T, F, W> SubscriberBuilder<format::JsonFields, format::Format<format::Json,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets whether or not the JSON layer being built will include a list (from
|
||||
/// Sets whether or not the JSON subscriber being built will include a list (from
|
||||
/// root to leaf) of all currently entered spans in formatted events.
|
||||
///
|
||||
/// See [`format::Json`](../fmt/format/struct.Json.html)
|
||||
|
@ -95,6 +95,12 @@
|
||||
unused_parens,
|
||||
while_true
|
||||
)]
|
||||
// Using struct update syntax when a struct has no additional fields avoids
|
||||
// a potential source change if additional fields are added to the struct in the
|
||||
// future, reducing diff noise. Allow this even though clippy considers it
|
||||
// "needless".
|
||||
#![allow(clippy::needless_update)]
|
||||
|
||||
use tracing_core::span::Id;
|
||||
|
||||
#[macro_use]
|
||||
|
Loading…
x
Reference in New Issue
Block a user