Files
scadaproj/ZB.MOM.WW.Telemetry/CLAUDE.md
T

7.2 KiB

ZB.MOM.WW.Telemetry

Observability libraries for the ZB.MOM.WW SCADA family (OtOpcUa, MxAccessGateway, ScadaBridge). These are libraries, not a service — each package is linked directly into the consuming application at build time. There is no central telemetry process; instrumentation runs in-process alongside the application.

The library normalizes the three-project observability surface: a shared OpenTelemetry Resource driven by a single identity triple (service.name / site.id / node.role), standard instrumentation wiring, Prometheus and OTLP export, and a Serilog bootstrap with enrichers and TraceContextEnricher for trace↔log correlation.

Built at 0.1.0, published to the Gitea NuGet feed, and adopted across all three apps on 2026-06-01 (branch feat/adopt-zb-telemetry per repo, behaviour-preserving). MxAccessGateway's MEL→Serilog migration + metrics export both landed in this pass — they were not actually done beforehand despite the earlier claim. ScadaBridge keeps its LoggerConfigurationFactory (min-level governance) and only adds the shared TraceContextEnricher; it does not call AddZbSerilog. Per-repo result + deferred follow-ons tracked in ~/Desktop/scadaproj/components/observability/GAPS.md.


Packages

Package Responsibilities Key Dependencies
ZB.MOM.WW.Telemetry AddZbTelemetry — wires OTel SDK (metrics + tracing), populates shared Resource (service.name, service.namespace, service.version, site.id, node.role, host.name), registers caller-supplied Meters/ActivitySources, adds standard instrumentation (ASP.NET Core, HttpClient, gRPC client, runtime, process), Prometheus always-on exporter, OTLP additive overlay. app.MapZbMetrics() — mounts /metrics. ZbTelemetryOptions — the single options object shared by both packages. Microsoft.AspNetCore.App (framework ref), OpenTelemetry.* stack
ZB.MOM.WW.Telemetry.Serilog AddZbSerilog — shared two-stage Serilog bootstrap: ReadFrom.Configuration-driven sinks, MinimumLevel.Is(Information) default (config-overridable), SiteId/NodeRole/NodeHostname enrichers from ZbTelemetryOptions, TraceContextEnricher (writes trace_id/span_id from Activity.Current), ILogRedactor seam (per-project sensitive-field redaction via RedactionEnricher). Does NOT freeze Log.Logger — safe for multi-host/test scenarios. ZB.MOM.WW.Telemetry, Serilog.* stack

Consumer matrix

Consumer ZB.MOM.WW.Telemetry (core) ZB.MOM.WW.Telemetry.Serilog
OtOpcUa ✅ adopted ✅ adopted (AddZbSerilog)
MxAccessGateway ✅ adopted (GatewayMetrics exported) ✅ adopted (MEL→Serilog migrated in this pass)
ScadaBridge ✅ adopted (both roots) ⚠️ referenced for TraceContextEnricher only — keeps LoggerConfigurationFactory, does not call AddZbSerilog

All three adopted on 2026-06-01 (branch feat/adopt-zb-telemetry per repo). ScadaBridge's logging deviates: it keeps its own LoggerConfigurationFactory (min-level governance contract) and only adds the shared TraceContextEnricher. See components/observability/GAPS.md for the full result.


Build, test, and pack commands

# From ZB.MOM.WW.Telemetry/

# Build
dotnet build ZB.MOM.WW.Telemetry.slnx
dotnet build ZB.MOM.WW.Telemetry.slnx -c Release

# Test (no external dependencies — no running OTel collector, no Serilog backend required)
dotnet test ZB.MOM.WW.Telemetry.slnx

# Pack (two .nupkg files land in artifacts/)
dotnet pack ZB.MOM.WW.Telemetry.slnx -c Release -o ./artifacts

All test assemblies run offline:

Assembly Tests
ZB.MOM.WW.Telemetry.Tests 7
ZB.MOM.WW.Telemetry.Serilog.Tests 12
Total 19

GeneratePackageOnBuild is off — pack explicitly with the command above.


Status

Built at 0.1.0, published to the Gitea NuGet feed, and adopted across all three apps on 2026-06-01 (branch feat/adopt-zb-telemetry per repo, behaviour-preserving). MxAccessGateway's MEL→Serilog migration and metrics export both landed in this pass (not beforehand, despite the earlier claim). Deferred follow-ons (MxGateway ms→s + Meter rename, ScadaBridge app instruments

  • Site-node HTTP/1.1 metrics listener, OTLP wiring) are tracked in the component backlog:
  • ~/Desktop/scadaproj/components/observability/GAPS.md — adoption status + deferred follow-ons

Design documentation:

  • ~/Desktop/scadaproj/components/observability/spec/SPEC.md — normalized observability target
  • ~/Desktop/scadaproj/components/observability/spec/METRIC-CONVENTIONS.md — metric naming reference
  • ~/Desktop/scadaproj/components/observability/shared-contract/ZB.MOM.WW.Telemetry.md — proposed shared-library API
  • ~/Desktop/scadaproj/components/observability/current-state/ — per-project current state (code-verified)

Index history (migrated from the scadaproj root CLAUDE.md)

Moved verbatim out of the scadaproj root CLAUDE.md on 2026-09-03 so it loads only when needed. This file is now the authoritative place for this history — append new entries here and keep the root index row short.

Narrative

The observability component is fully populated: a normalized spec, a metric-conventions reference, a shared-contract, three current-state docs, and an adoption GAPS backlog. Shared = OTel Resource (service.name/site.id/node.role identity triple) + standard instrumentation (ASP.NET Core, HttpClient, gRPC client, runtime, process) + Prometheus always-on exporter + OTLP opt-in

  • Serilog two-stage bootstrap + SiteId/NodeRole/NodeHostname enrichers + TraceContextEnricher (trace_id/span_id)
  • ILogRedactor seam; left per-project = application Meters/ActivitySources, sink config, per-operation enrichers, and redaction policies.

The shared library is built and lives in this repo at ZB.MOM.WW.Telemetry/ (.NET 10; 2 packages — ZB.MOM.WW.Telemetry, ZB.MOM.WW.Telemetry.Serilog; 34 tests (verified 2026-07-18); dotnet pack → 2 nupkgs @ 0.1.0). Adopted across all three apps on 2026-06-01 (branch feat/adopt-zb-telemetry per repo, behaviour-preserving): AddZbTelemetry (Resource + standard instrumentation + Prometheus /metrics) everywhere; OtOpcUa + MxGateway on AddZbSerilog (MxGateway's MEL→Serilog migration + metrics export both landed in this pass — they were not actually done beforehand despite an earlier claim); ScadaBridge keeps its LoggerConfigurationFactory (min-level governance) and only adds the shared TraceContextEnricher. Deferred: MxGateway ms→s + Meter rename, ScadaBridge app instruments + Site-node HTTP/1.1 metrics listener, OTLP wiring. Per-repo result tracked in components/observability/GAPS.md. Build/test from ZB.MOM.WW.Telemetry/: dotnet test. Consumer matrix: all three apps consume both packages after adoption (OtOpcUa, MxGateway Server, ScadaBridge Host + any instrumented project).