use std::fmt;
use tracing::{Event, Level, Subscriber};
use tracing_subscriber::fmt::format::Writer;
use tracing_subscriber::fmt::{FmtContext, FormatEvent, FormatFields};
use tracing_subscriber::registry::LookupSpan;
const RESET: &str = "\x1b[0m";
const BOLD: &str = "\x1b[1m";
const DIM: &str = "\x1b[2m";
const GREEN: &str = "\x1b[32m";
const YELLOW: &str = "\x1b[33m";
const RED: &str = "\x1b[91m"; const CYAN: &str = "\x1b[36m";
const MAGENTA: &str = "\x1b[35m";
pub struct PrettyLog {
pub colors: bool,
}
impl<S, N> FormatEvent<S, N> for PrettyLog
where
S: Subscriber + for<'a> LookupSpan<'a>,
N: for<'a> FormatFields<'a> + 'static,
{
fn format_event(
&self,
ctx: &FmtContext<'_, S, N>,
mut writer: Writer<'_>,
event: &Event<'_>,
) -> fmt::Result {
let level = *event.metadata().level();
let target = event.metadata().target();
let now = chrono::Local::now();
let time_str = now.format("%H:%M").to_string();
if self.colors {
write!(writer, "{DIM}{time_str}{RESET} ")?;
} else {
write!(writer, "{time_str} ")?;
}
let (color, badge) = match level {
Level::ERROR => (RED, "ERROR"),
Level::WARN => (YELLOW, "WARN "),
Level::INFO => (GREEN, "INFO "),
Level::DEBUG => (CYAN, "DEBUG"),
Level::TRACE => (MAGENTA, "TRACE"),
};
if self.colors {
write!(writer, "{BOLD}{color}{badge}{RESET} ")?;
} else {
write!(writer, "{badge} ")?;
}
ctx.format_fields(writer.by_ref(), event)?;
let skip_target = target.is_empty()
|| target == "udb"
|| target.starts_with("tokio::")
|| target.starts_with("hyper::")
|| target.starts_with("h2::")
|| target.starts_with("tower::");
if !skip_target {
if self.colors {
write!(writer, " {DIM}[{target}]{RESET}")?;
} else {
write!(writer, " [{target}]")?;
}
}
if let Some(scope) = ctx.event_scope() {
for span in scope.from_root() {
let ext = span.extensions();
if let Some(fields) = ext.get::<tracing_subscriber::fmt::FormattedFields<N>>()
&& !fields.is_empty()
{
if self.colors {
write!(writer, " {DIM}{fields}{RESET}")?
} else {
write!(writer, " {fields}")?
}
}
}
}
writeln!(writer)
}
}