--- status: Accepted date: 2026-07-03 applyTo: - "Fuchs/Logging/**" - "Fuchs/Program.cs" supersededBy: "" --- # 0003 — The solution is equipped with structured diagnostic logging ## Context Diagnosing issues in a deployed intranet instance requires a durable, inspectable log of what the application did, independent of whether an OpenTelemetry collector is attached (see [0004](0004-opentelemetry-observability.md)) — logging must work out-of-the-box on every environment with zero external dependencies. ## Decision - `Fuchs/Logging/FuchsLoggerProvider.cs` implements a custom `ILoggerProvider`/`ILogger` registered via `builder.Logging.AddFuchsLogging()` in `Program.cs`, with `SetMinimumLevel(LogLevel.Debug)`. - Every log line always goes to `Debug.WriteLine` **and** to a rolling text file under `/logs/` — `AppLog.txt` for `Debug`/`Information`/`Warning`, `ErrorLog.txt` for `Error`/`Critical` — so a failure investigation never depends on a debugger being attached. - Log lines are structured with timestamp, level tag, category, message, and (when present) the exception message + stack trace on continuation lines. - Database logging (`fuchs__admin_logdebug`) is **prepared but disabled** by default (`FuchsLoggerProvider.DatabaseLoggingEnabled = false`) — flip it on only where DB-durable diagnostics are specifically needed, since it adds a DB round-trip per log call. - All logger calls elsewhere in the codebase use `ILogger` injected via DI with **structured** placeholders (`_logger.LogInformation("Sent {InvoiceNumber} to {Email}", ...)`), never interpolated strings — this is enforced project-wide (see Coding Standards / Observability in `CLAUDE.md`). - File writes are best-effort: `AppendToFile` swallows its own exceptions — a logging failure must never crash or interrupt the operation being logged. ## Consequences - New code must inject `ILogger` and log entry/result/timing/errors for meaningful operations (see [0004](0004-opentelemetry-observability.md) for the matching tracing/metrics requirement) rather than adding ad-hoc `Console.WriteLine`/`Debug.Print` calls. - Because logs always write to `logs/AppLog.txt` and `ErrorLog.txt` regardless of telemetry configuration, these files are the first place to check when OTLP export isn't configured for an environment. - Enabling `DatabaseLoggingEnabled` is a deliberate, explicit choice per environment, not a default — it has a per-call DB cost. ## Alternatives considered - **Third-party logging framework (Serilog/NLog)**: rejected for now to avoid an extra dependency for a need the in-box `ILogger` abstraction plus a small custom provider already satisfies; revisit if requirements (e.g. structured JSON sinks, log shipping) outgrow this.