From 6fe75d77e70118d1a7ea57da3e06183b427b8fae Mon Sep 17 00:00:00 2001 From: oabrivard Date: Mon, 23 Mar 2026 09:32:19 +0100 Subject: [PATCH] feat: add source file:line to WARN and ERROR log lines Co-Authored-By: Claude Sonnet 4.6 --- backend/src/logging.rs | 46 ++++++++++++++++++++++++++++++++++++++++++ backend/src/main.rs | 6 +++++- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 backend/src/logging.rs diff --git a/backend/src/logging.rs b/backend/src/logging.rs new file mode 100644 index 0000000..847acb4 --- /dev/null +++ b/backend/src/logging.rs @@ -0,0 +1,46 @@ +//! 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) + } +} diff --git a/backend/src/main.rs b/backend/src/main.rs index 7360825..c6b0916 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -4,6 +4,7 @@ //! and starts the HTTP server. Also supports the `create-admin` CLI subcommand. mod cli; +mod logging; use anyhow::Context; use clap::Parser; @@ -27,7 +28,10 @@ async fn main() -> anyhow::Result<()> { // Initialize tracing let filter = EnvFilter::try_from_default_env() .unwrap_or_else(|_| EnvFilter::new("info,ai_synth_backend=debug")); - fmt().with_env_filter(filter).init(); + fmt() + .with_env_filter(filter) + .event_format(logging::ErrorLocationFormat) + .init(); let cli = Cli::parse();