1use tracing::Subscriber;
3use tracing_subscriber::EnvFilter;
4use tracing_subscriber::fmt::{FormatEvent, FormatFields, FormattedFields};
5use tracing_subscriber::registry::LookupSpan;
6
7#[expect(
8 missing_docs,
9 reason = "This is internal code. This struct needs to be pub for some reason for the Formatter impl to work in staged code?"
10)]
11pub struct Formatter;
12
13impl<S, N> FormatEvent<S, N> for Formatter
14where
15 S: Subscriber + for<'a> LookupSpan<'a>,
16 N: for<'a> FormatFields<'a> + 'static,
17{
18 fn format_event(
19 &self,
20 ctx: &tracing_subscriber::fmt::FmtContext<'_, S, N>,
21 mut writer: tracing_subscriber::fmt::format::Writer<'_>,
22 event: &tracing::Event<'_>,
23 ) -> std::fmt::Result {
24 use colored::Colorize;
25
26 let metadata = event.metadata();
27
28 if writer.has_ansi_escapes() {
29 write!(
30 &mut writer,
31 "{} {} {}{} {} {}:{}: ",
32 chrono::Utc::now()
33 .format("%Y-%m-%dT%H:%M:%S%.f%:z")
34 .to_string()
35 .magenta()
36 .underline()
37 .on_white(),
38 metadata.level().as_str().red(),
39 std::thread::current()
40 .name()
41 .unwrap_or("unnamed-thread")
42 .blue(),
43 format!("({:?})", std::thread::current().id()).blue(),
44 metadata.target().green(),
46 metadata.file().unwrap_or("unknown-file").red(),
47 format!("{}", metadata.line().unwrap_or(0)).red(),
48 )?;
49 } else {
50 write!(
51 &mut writer,
52 "{} {} {}{:?} {} {}:{}: ",
53 chrono::Utc::now().format("%Y-%m-%dT%H:%M:%S%.f%:z"),
54 metadata.level().as_str().red(),
55 std::thread::current().name().unwrap_or("unnamed-thread"),
56 std::thread::current().id(),
57 metadata.target(),
59 metadata.file().unwrap_or("unknown-file"),
60 metadata.line().unwrap_or(0),
61 )?;
62 }
63
64 if let Some(scope) = ctx.event_scope() {
65 for span in scope.from_root() {
66 if writer.has_ansi_escapes() {
67 write!(writer, "{}", span.name().purple())?;
68 } else {
69 write!(writer, "{}", span.name())?;
70 }
71
72 let ext = span.extensions();
73 let fields = &ext.get::<FormattedFields<N>>().unwrap();
74
75 if !fields.is_empty() {
76 if writer.has_ansi_escapes() {
77 write!(writer, "{{{}}}", fields.cyan())?;
78 } else {
79 write!(writer, "{{{}}}", fields)?;
80 }
81 }
82
83 write!(writer, ": ")?;
84 }
85 }
86
87 if writer.has_ansi_escapes() {
88 write!(writer, "{}: ", metadata.name().yellow().bold().underline())?;
89 } else {
90 write!(writer, "{}: ", metadata.name())?;
91 }
92
93 ctx.field_format().format_fields(writer.by_ref(), event)?;
94
95 writeln!(writer)
96 }
97}
98
99pub fn initialize_tracing() {
101 let rust_log = std::env::var("RUST_LOG").unwrap_or_else(|err| {
102 match err {
103 std::env::VarError::NotPresent => {
104 "error".to_string()
106 }
107 std::env::VarError::NotUnicode(v) => {
108 eprintln!(
110 "RUST_LOG is not unicode, defaulting to 'error' directive: {:?}",
111 v
112 );
113 "error".to_string()
114 }
115 }
116 });
117
118 let filter = EnvFilter::try_new(&rust_log).unwrap_or_else(|err| {
119 eprintln!("Failed to parse RUST_LOG: {}, err: {:?}", rust_log, err);
121 "error".to_string().parse().unwrap()
122 });
123
124 initialize_tracing_with_filter(filter)
125}
126
127pub fn initialize_tracing_with_filter(filter: EnvFilter) {
130 use tracing::subscriber::set_global_default;
131 use tracing_subscriber::fmt::format::FmtSpan;
132 use tracing_subscriber::prelude::*;
133 use tracing_subscriber::{Layer, fmt, registry};
134
135 set_global_default(
136 registry().with(
137 fmt::layer()
138 .with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
139 .event_format(Formatter)
140 .with_filter(filter.clone()),
141 ),
142 )
143 .unwrap();
144
145 #[expect(
146 non_snake_case,
147 reason = "this variable represents an env var which is in all caps"
148 )]
149 let RUST_LOG = std::env::var("RUST_LOG");
150
151 tracing::trace!(name: "Tracing Initialized", ?RUST_LOG, ?filter);
152}