1use std::fmt;
2
3use jiff::Timestamp;
4use owo_colors::OwoColorize;
5use tracing::{Event, Subscriber};
6use tracing_subscriber::fmt::format::Writer;
7use tracing_subscriber::fmt::{FmtContext, FormatEvent, FormatFields};
8use tracing_subscriber::registry::LookupSpan;
9
10pub struct UvFormat {
12 pub display_timestamp: bool,
13 pub display_level: bool,
14 pub show_spans: bool,
15}
16
17impl Default for UvFormat {
18 fn default() -> Self {
20 Self {
21 display_timestamp: false,
22 display_level: true,
23 show_spans: false,
24 }
25 }
26}
27
28impl<S, N> FormatEvent<S, N> for UvFormat
30where
31 S: Subscriber + for<'a> LookupSpan<'a>,
32 N: for<'a> FormatFields<'a> + 'static,
33{
34 fn format_event(
35 &self,
36 ctx: &FmtContext<'_, S, N>,
37 mut writer: Writer<'_>,
38 event: &Event<'_>,
39 ) -> fmt::Result {
40 let meta = event.metadata();
41 let ansi = writer.has_ansi_escapes();
42
43 if self.display_timestamp {
44 if ansi {
45 write!(writer, "{} ", Timestamp::now().dimmed())?;
46 } else {
47 write!(writer, "{} ", Timestamp::now())?;
48 }
49 }
50
51 if self.display_level {
52 let level = meta.level();
53 if ansi {
55 match *level {
56 tracing::Level::TRACE => write!(writer, "{} ", level.purple())?,
57 tracing::Level::DEBUG => write!(writer, "{} ", level.blue())?,
58 tracing::Level::INFO => write!(writer, "{} ", level.green())?,
59 tracing::Level::WARN => write!(writer, "{} ", level.yellow())?,
60 tracing::Level::ERROR => write!(writer, "{} ", level.red())?,
61 }
62 } else {
63 write!(writer, "{level} ")?;
64 }
65 }
66
67 if self.show_spans {
68 let span = event.parent();
69 let mut seen = false;
70
71 let span = span
72 .and_then(|id| ctx.span(id))
73 .or_else(|| ctx.lookup_current());
74
75 let scope = span.into_iter().flat_map(|span| span.scope().from_root());
76
77 for span in scope {
78 seen = true;
79 if ansi {
80 write!(writer, "{}:", span.metadata().name().bold())?;
81 } else {
82 write!(writer, "{}:", span.metadata().name())?;
83 }
84 }
85
86 if seen {
87 writer.write_char(' ')?;
88 }
89 }
90
91 ctx.field_format().format_fields(writer.by_ref(), event)?;
92
93 writeln!(writer)
94 }
95}