feat: migrate DB error logging onto the generic OCORE MultiLogger SQL sink
Playwright Tests / test (push) Canceled after 0s

Retires Fuchs_intranet.debug_log() and every direct EXECUTE [dbo].[fds__admin_logdebug]
call in favor of a single path: ILogger. A new SQL log sink (OCORE.MultiLogger.SqlLoggerProvider,
gated by Fuchs:Logging:SqlSink:Enabled, default on) mirrors every _logger.LogWarning/-Error/
-Critical call into [dbo].[fds__debuglog] via a new fds__admin_logdebug_ext proc, at Warning+.

- Program.cs registers the sink and RequestLogScopeMiddleware (request id/path/authenticated
  user, pushed after UseAuthentication) so every log line in a request — including ones written
  deep inside OCORE's SQL helpers — is attributed automatically.
- FIS_SQLOptions, IntranetController.Do's catch-all, PdfPreviewAsync, and the banking-upload
  handlers now log once, with an explicit EventId preserving the exact CodeReference text the
  retired debug_log() calls used to write, so existing dashboards/queries over fds__debuglog
  keep working unchanged.
- Fuchs_DataService/FdsMfr.cs's FdsSqlOptions had the identical double-write hazard (it's hosted
  in the same process per ADR 0010) — the original 2026-09-16 log review's mfr__getSchema/
  fds__getUpdateableRequests deadlock rows came from exactly this class. Fixed the same way.
- fds__debuglog gains LogLevel/Machine/Category/Account/AuthUser/IsDebug columns; the legacy
  fds__admin_logdebug proc is left in place unused, not dropped.
- FdsDebug.DebugLog (Fuchs_DataService's other ~9 call sites) deliberately left on its direct
  DB-write path — no ILogger call sits alongside it there, so no duplication risk today.

See ADR 0024 (supersedes 0023) and Docs/Concepts/error-logging-pipeline.md.

New tests: ErrorLoggingTests (FIS_SQLOptions), FdsSqlOptionsTests, RequestLogScopeMiddlewareTests.
694/694 pass (the 4 PdfPipelineTests failures seen under full-suite parallel runs are a
pre-existing, unrelated PdfSharp global-font-resolver test-isolation flake — they pass both
individually and in most full-suite runs).

Bumps the OCORE submodule to 3137b56 (SQL sink hardening: redaction matches short fragments
as whole identifier segments, per-entry-tolerant serialization, lazy dataSerialized, opt-in
SqlLoggerOptions.IncludeCategory, LogEntry.Category/AuthUser capture).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Stefan
2026-09-16 17:20:06 +02:00
co-authored by Claude Sonnet 5
parent a1e6002c3b
commit bcf1f2dbb6
23 changed files with 757 additions and 225 deletions
+2 -1
View File
@@ -68,8 +68,9 @@
## Observability
- Use **OpenTelemetry**. The app's instrumentation is centralised in `Fuchs/Observability/FuchsTelemetry.cs` (one `ActivitySource` + one `Meter`).
- When adding a meaningful operation: start an activity (`FuchsTelemetry.StartActivity(...)`), record the relevant counter/histogram, and log entry/result/timing/errors via the injected `ILogger<T>`. Prefer structured logging (named placeholders), never string interpolation in log messages.
- When adding a meaningful operation: start an activity (`FuchsTelemetry.StartActivity(...)`), record the relevant counter/histogram, and log entry/result/timing/errors via the injected `ILogger<T>`. Prefer structured logging (named placeholders), never string interpolation in log messages — and never `{@Foo}`: plain `Microsoft.Extensions.Logging` (unlike Serilog) does not strip the `@`, it becomes a literal part of the key.
- Tracing/metrics are always collected; OTLP export is opt-in via `Fuchs:Telemetry:OtlpEndpoint`. Don't add exporters that fail hard when no collector is present.
- **DB log sink (ADR 0024):** every `_logger.LogWarning`/`-Error`/`-Critical` call additionally lands in `[dbo].[fds__debuglog]` via the OCORE MultiLogger SQL sink (`fds__admin_logdebug_ext`), gated by `Fuchs:Logging:SqlSink:Enabled` (default on). `RequestLogScopeMiddleware` (`Fuchs/Logging/`) attributes every log line in a request to a request id/path/authenticated user automatically. Give a log call an explicit `EventId` (its `Name` becomes the row's `CodeReference`) when the call site should be individually greppable — see `FIS_SQLOptions`, `IntranetController.Do`'s catch-all, `PdfPreviewAsync`, and the banking-upload handlers for the pattern. Do not also call the retired `Fuchs_intranet.debug_log` — one `ILogger` call is the single write path; a second explicit DB write duplicates the row.
## Testing
- xUnit in `Fuchs.Tests`. Testing must be **extensive**, not superficial: