# Error Location Logging — Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Add source file and line number to WARN and ERROR log lines, leaving INFO/DEBUG unchanged. **Architecture:** Custom `FormatEvent` implementation that conditionally appends `[file:line]` based on log level. One new file (`logging.rs`), one modified line in `main.rs`. **Tech Stack:** `tracing_subscriber::fmt::FormatEvent`, `tracing::Level` **Spec:** `docs/superpowers/specs/2026-03-23-error-location-logging-design.md` --- ### Task 1: Create the custom formatter **Files:** - Create: `backend/src/logging.rs` - Modify: `backend/src/main.rs:6,11,30` - [ ] **Step 1: Create `backend/src/logging.rs`** ```rust //! 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) } } ``` - [ ] **Step 2: Add `mod logging;` to `main.rs`** In `backend/src/main.rs`, add the module declaration alongside `mod cli;`: ```rust mod cli; mod logging; ``` - [ ] **Step 3: Wire the formatter into tracing initialization** In `backend/src/main.rs`, replace line 30: ```rust // Before: fmt().with_env_filter(filter).init(); // After: fmt() .with_env_filter(filter) .event_format(logging::ErrorLocationFormat) .init(); ``` - [ ] **Step 4: Run tests to verify nothing breaks** Run: `cd backend && cargo test --lib` Expected: 338 tests pass (the formatter is only used in main.rs binary, not in lib tests) - [ ] **Step 5: Run the binary to verify output format** Run: `cd backend && RUST_LOG=debug cargo run -- serve 2>&1 | head -10` Expected: INFO/DEBUG lines have no `[file:line]`, but any WARN/ERROR would show it. To force an error, run without DATABASE_URL: Run: `cd backend && RUST_LOG=debug cargo run -- serve 2>&1 | head -5` Expected: An ERROR line with `[file:line]` showing the source location. - [ ] **Step 6: Commit** ```bash git add backend/src/logging.rs backend/src/main.rs git commit -m "feat: add source file:line to WARN and ERROR log lines" ```