//! Custom log formatter that includes source file and line for WARN/ERROR events. use std::fmt; use tracing::{Event, Level, Subscriber}; use tracing_subscriber::fmt::format::{self, FormatEvent, FormatFields}; use tracing_subscriber::fmt::FmtContext; use tracing_subscriber::registry::LookupSpan; /// Event formatter that appends `[file:line]` to WARN and ERROR log lines. /// /// INFO, DEBUG, and TRACE events use the default format without source location. pub struct ErrorLocationFormat; impl FormatEvent for ErrorLocationFormat where S: Subscriber + for<'a> LookupSpan<'a>, N: for<'a> FormatFields<'a> + 'static, { fn format_event( &self, ctx: &FmtContext<'_, S, N>, mut writer: format::Writer<'_>, event: &Event<'_>, ) -> fmt::Result { let metadata = event.metadata(); let level = metadata.level(); let timestamp = chrono::Utc::now().format("%Y-%m-%dT%H:%M:%S%.6fZ"); // Write: timestamp + level + target write!(writer, "{} {:>5} {}", timestamp, level, metadata.target())?; // Append [file:line] for WARN and ERROR only if *level <= Level::WARN { if let (Some(file), Some(line)) = (metadata.file(), metadata.line()) { write!(writer, " [{}:{}]", file, line)?; } } write!(writer, ": ")?; // Write the event fields (message, structured fields) ctx.format_fields(writer.by_ref(), event)?; writeln!(writer) } }