Skip to content

Commit

Permalink
subscriber: make ANSI and not-ANSI formatting consistent
Browse files Browse the repository at this point in the history
Currently, the `tracing-subscriber` crate's `fmt` module has two
separate `fmt::Display` impls for its' `FmtCtx` and `FullCtx` types,
depending on whether the feature flag that enables ANSI colors is set.
Since a lot of the `fmt::Display` implementations doesn't have anything
to do with ANSI colors, this means that we have a lot of repeated code,
and in order to keep the formatting consistent, we have to keep these
implementations in sync manually. There are currently some
inconsistencies in formatting with ANSI colors on and off, implying that
we have failed to do that.

This commit simplifies the situation significantly by consolidating the
`fmt::Display` impls into one implementation, and only feature flagging
the code that actually needs to be different. We do this by introducing
a `Style` type which exposes no-op versions of methods with the same
names as the `ansi-term` crate's `Style` when ANSI formatting is
disabled. Now, the conditional logic is hidden in the function that
returns a `Style`, and the rest of the `fmt::Display` implementations
can be agnostic of ANSI colors. In release mode, `rustc` should be able
to optimize out the no-op methods and empty struct entirely.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
  • Loading branch information
hawkw committed Feb 3, 2020
1 parent eba1adb commit 506a482
Showing 1 changed file with 34 additions and 62 deletions.
96 changes: 34 additions & 62 deletions tracing-subscriber/src/fmt/format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,53 +488,33 @@ where
pub(crate) fn new(ctx: &'a FmtContext<'_, S, N>) -> Self {
Self { ctx }
}
}

#[cfg(feature = "ansi")]
impl<'a, S, N: 'a> fmt::Display for FmtCtx<'a, S, N>
where
S: Subscriber + for<'lookup> LookupSpan<'lookup>,
N: for<'writer> FormatFields<'writer> + 'static,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut seen = false;
self.ctx.visit_spans(|span| {
if seen {
f.pad(":")?;
}
seen = true;

let metadata = span.metadata();
fn bold(&self) -> Style {
#[cfg(feature = "ansi")]
{
if self.ansi {
write!(f, "{}", Style::new().bold().paint(metadata.name()))?;
} else {
write!(f, "{}", metadata.name())?;
return Style::new().bold();
}

Ok(()) as fmt::Result
})?;
if seen {
f.pad(" ")?;
}
Ok(())

Style::new()
}
}

#[cfg(not(feature = "ansi"))]
impl<'a, S, N> fmt::Display for FmtCtx<'a, S, N>
impl<'a, S, N: 'a> fmt::Display for FmtCtx<'a, S, N>
where
S: Subscriber + for<'lookup> LookupSpan<'lookup>,
N: for<'writer> FormatFields<'writer> + 'static,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let bold = self.bold();
let mut seen = false;

self.ctx.visit_spans(|span| {
if seen {
f.pad(":")?;
}
seen = true;
write!(f, "{}", span.name())
write!(f, "{}:", bold.paint(span.metadata().name()))
})?;

if seen {
f.pad(" ")?;
}
Expand Down Expand Up @@ -566,33 +546,39 @@ where
pub(crate) fn new(ctx: &'a FmtContext<'a, S, N>) -> Self {
Self { ctx }
}

fn bold(&self) -> Style {
#[cfg(feature = "ansi")] {
if self.ansi {
return Style::new().bold();
}
}


Style::new()
}
}

#[cfg(feature = "ansi")]
impl<'a, S, N> fmt::Display for FullCtx<'a, S, N>
where
S: Subscriber + for<'lookup> LookupSpan<'lookup>,
N: for<'writer> FormatFields<'writer> + 'static,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let bold = self.bold();
let mut seen = false;
let style = if self.ansi {
Style::new().bold()
} else {
Style::new()
};

self.ctx.visit_spans(|span| {
let metadata = span.metadata();
write!(f, "{}", style.paint(metadata.name()))?;
write!(f, "{}", bold.paint(span.metadata().name()))?;
seen = true;

let ext = span.extensions();
let data = &ext
let fields = &ext
.get::<FormattedFields<N>>()
.expect("Unable to find FormattedFields in extensions; this is a bug");
write!(f, "{}{}{}", style.paint("{"), data, style.paint("}"))?;
":".fmt(f)
write!(f, "{}{}{}:", bold.paint("{"), fields, bold.paint("}"))
})?;

if seen {
f.pad(" ")?;
}
Expand All @@ -601,27 +587,13 @@ where
}

#[cfg(not(feature = "ansi"))]
impl<'a, S, N> fmt::Display for FullCtx<'a, S, N>
where
S: Subscriber + for<'lookup> LookupSpan<'lookup>,
N: for<'writer> FormatFields<'writer> + 'static,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut seen = false;
self.ctx.visit_spans(|span| {
write!(f, "{}", span.name())?;
seen = true;
struct Style;

let fields = span.fields();
if !fields.is_empty() {
write!(f, "{{{}}}", fields)?;
}
":".fmt(f)
})?;
if seen {
f.pad(" ")?;
}
Ok(())
#[cfg(not(feature = "ansi"))]
impl Style {
fn new() -> Self { Style }
fn paint(&self, d: impl fmt::Display) -> impl fmt::Display {
d
}
}

Expand Down

0 comments on commit 506a482

Please sign in to comment.