c72271aa8a
Claude-Session: https://claude.ai/code/session_01Wzg6NUCWHipSexLs2cgRFv
107 lines
7.2 KiB
Markdown
107 lines
7.2 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
# 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`](components/observability/spec/SPEC.md),
|
|
a [`metric-conventions`](components/observability/spec/METRIC-CONVENTIONS.md) reference, a
|
|
[`shared-contract`](components/observability/shared-contract/ZB.MOM.WW.Telemetry.md), three
|
|
[`current-state`](components/observability/current-state/) docs, and an adoption [`GAPS`](components/observability/GAPS.md)
|
|
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/`](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`](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).
|