Adopt AddZbSerilog (Telemetry.Serilog 0.2.0) with MinimumLevelGovernor + ConfigureLogger #94

Closed
opened 2026-11-09 13:42:33 -05:00 by dohertj2 · 1 comment
Owner

ZB.MOM.WW.Telemetry.Serilog 0.2.0 (scadaproj#12, main 1ab5ca0 — not yet published to the feed) adds AddZbSerilog(builder, configure, configureSerilog) with ZbSerilogOptions.MinimumLevelGovernor and ConfigureLogger, built to match ScadaBridge's own LoggerConfigurationFactory (min-level key after ReadFrom.Configuration, standby active-node filter). Once 0.2.0 is published, switch ScadaBridge from its own factory to AddZbSerilog using those two hooks, and verify level governance + the standby filter are unchanged (tests + a rig boot log check). Blocked on publishing Telemetry 0.2.0.

ZB.MOM.WW.Telemetry.Serilog 0.2.0 (scadaproj#12, main 1ab5ca0 — not yet published to the feed) adds `AddZbSerilog(builder, configure, configureSerilog)` with `ZbSerilogOptions.MinimumLevelGovernor` and `ConfigureLogger`, built to match ScadaBridge's own `LoggerConfigurationFactory` (min-level key after ReadFrom.Configuration, standby active-node filter). Once 0.2.0 is published, switch ScadaBridge from its own factory to AddZbSerilog using those two hooks, and verify level governance + the standby filter are unchanged (tests + a rig boot log check). Blocked on publishing Telemetry 0.2.0.
dohertj2 added the type:followuppriority:p3blockedcross-repo labels 2026-11-09 13:42:33 -05:00
Author
Owner

Done — ScadaBridge main 2d2e9f35.

Library: ZB.MOM.WW.Telemetry + ZB.MOM.WW.Telemetry.Serilog 0.2.0 published to the Gitea feed 2026-11-12. Both were packed from scadaproj 01c6dc1 (the 0.2.0 code from 1ab5ca0 plus the corrected RepositoryUrl, before the unpublished 0.2.1 commit). Their tests were green in Release (12 + 30). The SHA256 of the feed download matches the local pack:

  • ZB.MOM.WW.Telemetry.0.2.0.nupkg: 71749cb3c34a0d0aba3eca43a6c12398b427f494e8c4c6f216db0be7d3ab40dc
  • ZB.MOM.WW.Telemetry.Serilog.0.2.0.nupkg: 2aef391e7ab28061c5b3365c62c73e5c972ba8bcecd88bd0e0471550cfcc40c0

Change: ScadaBridgeLogging builds the process logger with AddZbSerilog(..., s => { s.MinimumLevelGovernor = ...; s.ConfigureLogger = ...; }).

  • Governor: reads ScadaBridge:Logging:MinimumLevel and runs after ReadFrom.Configuration, so it outranks Serilog:MinimumLevel. It never returns null. Override:* entries still apply, and the one-shot warnings are unchanged.
  • ConfigureLogger: adds the standby active-node filter, the configured SiteId/NodeRole/NodeHostname (the shared lib stamps NodeHostname from MachineName and skips empty values, so an overwriting enricher keeps the configured values), FromLogContext and ExecutionLogCaptureSink.
  • Static logger: AddZbSerilog runs on a small pre-host builder, and Program installs the result as the static Log.Logger. Both web hosts keep UseSerilog(). That leaves one logger and one file-sink handle per process. The startup banner, pre-host Fatal, SerilogAkkaLogger and the post-dispose shutdown/Fatal lines all keep working. The host's own AddZbSerilog registration would not set Log.Logger, and the container would dispose the logger.
  • LoggerConfigurationFactory is deleted; nothing else used it.
  • Telemetry pins go from 0.1.0 to 0.2.0.

Tests (Release): the existing logging, standby-filter and file-sink tests now run through the new pipeline. New ScadaBridgeLoggingParityTests cover:

  • ScadaBridge level beats a more verbose Serilog level
  • the floor never defers to the Serilog key
  • Override:* still applies
  • the warning fires once
  • configured identity, including NodeHostname != MachineName and an empty SiteId
  • the exact property set of a plain line
  • trace_id/span_id

Mutation check: five mutations, and each one fails tests:

  • governor returns null: 6 fail
  • filter removed: 1 fails
  • identity enricher removed: 2 fail
  • FromLogContext removed: 2 fail
  • capture sink removed: 1 fails

Host.Tests: 695/695 after the rebase. Whole solution: 11,196 passed. The 185 CentralUI.PlaywrightTests failures are all environmental: ECONNREFUSED ws://localhost:3000, no Playwright browser server running.

Rig boot check: I built the image from this commit and recreated all 8 nodes plus Traefik with the main checkout's compose file, central-a and central-b together.

  • All 8 nodes are running with 0 restarts and 0 FTL.
  • Levels: 0 DBG/VRB lines at MinimumLevel=Information. The console format [HH:mm:ss LVL] [Central/scadabridge-central-b] is the same as before.
  • Standby filter: central-b answered 503 on /health/active (45 503 responses in its file log since the new boot) and site-a-b answered 503 on 10 out of 10 probes. Neither logged a Health check active-node line. central-b still logs its genuine akka-cluster Unhealthy ERR, just as the old build did, which shows the filter is still keyed on the check name.
  • Sinks: the file sink is still logs/scadabridge-20261112.log, the same file as the previous boot.
  • Akka lines reach Serilog.
Done — ScadaBridge `main` **`2d2e9f35`**. **Library:** `ZB.MOM.WW.Telemetry` + `ZB.MOM.WW.Telemetry.Serilog` **0.2.0 published** to the Gitea feed 2026-11-12. Both were packed from scadaproj `01c6dc1` (the 0.2.0 code from `1ab5ca0` plus the corrected RepositoryUrl, before the unpublished 0.2.1 commit). Their tests were green in Release (12 + 30). The SHA256 of the feed download matches the local pack: - `ZB.MOM.WW.Telemetry.0.2.0.nupkg`: `71749cb3c34a0d0aba3eca43a6c12398b427f494e8c4c6f216db0be7d3ab40dc` - `ZB.MOM.WW.Telemetry.Serilog.0.2.0.nupkg`: `2aef391e7ab28061c5b3365c62c73e5c972ba8bcecd88bd0e0471550cfcc40c0` **Change:** `ScadaBridgeLogging` builds the process logger with `AddZbSerilog(..., s => { s.MinimumLevelGovernor = ...; s.ConfigureLogger = ...; })`. - **Governor:** reads `ScadaBridge:Logging:MinimumLevel` and runs after `ReadFrom.Configuration`, so it outranks `Serilog:MinimumLevel`. It never returns null. `Override:*` entries still apply, and the one-shot warnings are unchanged. - **ConfigureLogger:** adds the standby `active-node` filter, the configured `SiteId`/`NodeRole`/`NodeHostname` (the shared lib stamps `NodeHostname` from `MachineName` and skips empty values, so an overwriting enricher keeps the configured values), `FromLogContext` and `ExecutionLogCaptureSink`. - **Static logger:** `AddZbSerilog` runs on a small pre-host builder, and `Program` installs the result as the static `Log.Logger`. Both web hosts keep `UseSerilog()`. That leaves one logger and one file-sink handle per process. The startup banner, pre-host `Fatal`, `SerilogAkkaLogger` and the post-dispose shutdown/`Fatal` lines all keep working. The host's own `AddZbSerilog` registration would not set `Log.Logger`, and the container would dispose the logger. - `LoggerConfigurationFactory` is deleted; nothing else used it. - Telemetry pins go from 0.1.0 to 0.2.0. **Tests (Release):** the existing logging, standby-filter and file-sink tests now run through the new pipeline. New `ScadaBridgeLoggingParityTests` cover: - ScadaBridge level beats a more verbose Serilog level - the floor never defers to the Serilog key - `Override:*` still applies - the warning fires once - configured identity, including `NodeHostname` != `MachineName` and an empty `SiteId` - the exact property set of a plain line - `trace_id`/`span_id` Mutation check: five mutations, and each one fails tests: - governor returns null: 6 fail - filter removed: 1 fails - identity enricher removed: 2 fail - `FromLogContext` removed: 2 fail - capture sink removed: 1 fails Host.Tests: 695/695 after the rebase. Whole solution: 11,196 passed. The 185 `CentralUI.PlaywrightTests` failures are all environmental: `ECONNREFUSED ws://localhost:3000`, no Playwright browser server running. **Rig boot check:** I built the image from this commit and recreated all 8 nodes plus Traefik with the main checkout's compose file, central-a and central-b together. - All 8 nodes are running with 0 restarts and 0 FTL. - Levels: 0 DBG/VRB lines at `MinimumLevel=Information`. The console format `[HH:mm:ss LVL] [Central/scadabridge-central-b]` is the same as before. - Standby filter: central-b answered 503 on `/health/active` (45 503 responses in its file log since the new boot) and site-a-b answered 503 on 10 out of 10 probes. Neither logged a `Health check active-node` line. central-b still logs its genuine `akka-cluster` Unhealthy ERR, just as the old build did, which shows the filter is still keyed on the check name. - Sinks: the file sink is still `logs/scadabridge-20261112.log`, the same file as the previous boot. - Akka lines reach Serilog.
Sign in to join this conversation.