snarkos_cli/helpers/
dynamic_format.rs1use std::sync::{
17 Arc,
18 atomic::{AtomicBool, Ordering},
19};
20
21use time::{
22 OffsetDateTime,
23 format_description::{self, OwnedFormatItem},
24};
25use tracing::{Event, Subscriber};
26use tracing_subscriber::{
27 fmt::{FmtContext, FormatEvent, FormatFields, format::Writer},
28 registry::LookupSpan,
29};
30
31pub struct DynamicFormatter {
33 dim_format: DimFormat,
34 default_format: tracing_subscriber::fmt::format::Format,
35 dim: Arc<AtomicBool>,
37}
38
39impl<S, N> FormatEvent<S, N> for DynamicFormatter
40where
41 S: Subscriber + for<'a> LookupSpan<'a>,
42 N: for<'a> FormatFields<'a> + 'static,
43{
44 fn format_event(&self, ctx: &FmtContext<'_, S, N>, writer: Writer<'_>, event: &Event<'_>) -> std::fmt::Result {
45 if self.dim.load(Ordering::Relaxed) {
46 self.dim_format.format_event(ctx, writer, event)
47 } else {
48 self.default_format.format_event(ctx, writer, event)
49 }
50 }
51}
52
53impl DynamicFormatter {
54 pub fn new(dim: Arc<AtomicBool>) -> Self {
55 let dim_format = DimFormat::new();
56 let default_format = tracing_subscriber::fmt::format::Format::default();
57 Self { dim_format, default_format, dim }
58 }
59}
60
61struct DimFormat {
62 fmt: OwnedFormatItem,
63}
64
65impl DimFormat {
69 fn new() -> Self {
70 let format =
71 format_description::parse_owned::<2>("[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond digits:6]Z")
72 .expect("failed to set timestampt format");
73 Self { fmt: format }
74 }
75}
76
77impl<S, N> FormatEvent<S, N> for DimFormat
78where
79 S: Subscriber + for<'a> LookupSpan<'a>,
80 N: for<'a> FormatFields<'a> + 'static,
81{
82 fn format_event(&self, ctx: &FmtContext<'_, S, N>, mut writer: Writer<'_>, event: &Event<'_>) -> std::fmt::Result {
84 if writer.has_ansi_escapes() {
86 write!(writer, "\x1b[2m")?;
87 }
88
89 let date_time = OffsetDateTime::now_utc();
90 write!(writer, "{} ", date_time.format(&self.fmt).map_err(|_| std::fmt::Error)?)?;
91
92 let meta = event.metadata();
93 let fmt_level = match *meta.level() {
94 tracing::Level::ERROR => "ERROR",
95 tracing::Level::WARN => "WARN ",
96 tracing::Level::INFO => "INFO ",
97 tracing::Level::DEBUG => "DEBUG",
98 tracing::Level::TRACE => "TRACE",
99 };
100 write!(writer, "{fmt_level}")?;
101
102 write!(writer, "{}: ", meta.target())?;
103
104 ctx.format_fields(writer.by_ref(), event)?;
105
106 if writer.has_ansi_escapes() {
108 write!(writer, "\x1b[0m")?;
109 }
110 writeln!(writer)
111 }
112}