use std::{fmt::Write, io::Write as _};
use colored::{Color, Colorize};
use smallstr::SmallString;
use tracing::{
span::{Attributes, Id, Record},
Event, Subscriber,
};
use tracing_subscriber::{fmt::MakeWriter, layer::Context, registry::LookupSpan, Layer};
use crate::log::{now_string, short_path, write_call, LogLevelExt, SimpleEventVisitor};
pub(super) struct SimplePrettyLayer<W> {
make_writer: W,
}
impl<W> SimplePrettyLayer<W> {
pub(super) fn new(
make_writer: W,
) -> Self {
Self { make_writer }
}
}
impl<S, W> Layer<S> for SimplePrettyLayer<W>
where
S: Subscriber + for<'l> LookupSpan<'l>,
W: for<'w> MakeWriter<'w> + Send + Sync + 'static,
{
fn on_new_span(
&self,
_attributes: &Attributes<'_>,
_id: &Id,
_tracing_context: Context<'_, S>,
) {}
fn on_record(
&self,
_id: &Id,
_values: &Record<'_>,
_tracing_context: Context<'_, S>,
) {}
fn on_event(
&self,
event: &Event<'_>,
tracing_context: Context<'_, S>,
) {
let meta = event.metadata();
let mut event_visitor = SimpleEventVisitor::new(&tracing_context);
event.record(&mut event_visitor);
let mut out = String::with_capacity(512);
let mut line: SmallString<[u8; 16]> = SmallString::new();
let _ = write!(&mut line, "{}", meta.line().unwrap_or_default());
let _ = writeln!(
out,
"{:<5} {} {}{}{}",
meta.level().colored(),
now_string().color(Color::BrightBlack),
short_path(meta.file().unwrap_or("<unknown>"), 3).color(Color::BrightBlack),
":".color(Color::BrightBlack),
line.color(Color::BrightBlack),
);
if event_visitor.chain.is_empty() {
if let Some(
message,
) = &event_visitor.message && !message.is_empty() {
let _ = writeln!(
out,
"{} {}",
"\\_".color(meta.level().color()),
message.color(meta.level().color())
);
}
} else {
if let Some(
message,
) = &event_visitor.message && !message.is_empty() {
let _ = writeln!(
out,
"{} {}",
"|-".color(meta.level().color()),
message.color(meta.level().color())
);
}
}
let last_idx = event_visitor
.chain
.iter()
.rposition(|chain_link| {
if let Some(
message,
) = &chain_link.message && !message.is_empty() {
true
} else {
false
}
});
for (i, link) in event_visitor.chain.iter().enumerate() {
if let Some(
frame,
) = &link.frame {
write_call(
&mut out,
meta.level(),
frame.name,
&frame.file,
frame.line,
Some(&frame.fields),
);
}
if let Some(
message,
) = &link.message {
if Some(i) == last_idx {
let _ = writeln!(
out,
"{} {}",
"\\_".color(meta.level().color()),
message.color(meta.level().color())
);
} else {
let _ = writeln!(
out,
"{} {}",
"|-".color(meta.level().color()),
message.color(meta.level().color())
);
}
}
}
let mut w = self.make_writer.make_writer_for(meta);
let _ = w.write_all(out.as_bytes());
}
}