b5f120c370
scadabridge_site_connection_up never counted data connections. It counts open central->site gRPC subscriber streams (Debug View + the site-wide alarm feed), so it correctly reads 0 on a healthy site nobody is watching — and the name invited reading it as device health. That misreading has already cost a live debugging session: register row 48's 'connection_up is 0 on all six site nodes' was healthy steady state, not the fault it was diagnosed as. Two halves, per the row: RENAME. scadabridge.site.connection.up -> scadabridge.site.stream.subscribers.active (helpers SiteConnectionOpened/Closed -> SiteStreamSubscriberOpened/Closed), and the instrument gains the unit:"1" the other gauges already carried. Every reference updated: the gRPC server, both test suites, Component-Communication.md, components/Commons.md, docker/README.md and docker/seed-live-probe.sh. A test now pins the new name AND asserts the old one is gone, so it cannot creep back. NEW. scadabridge.site.data_connections.connected / .total — the first exported data-connection signal (the state existed on the health report and in the CLI, but never as a metric). connected < total is the alert condition; neither number alone separates 'a device is down' from 'nothing is configured', which is why the denominator ships with the numerator. Sourcing is deliberate on two counts. It is fed by the DCL at its four state transitions rather than derived from the health report, so the metric survives a dead report pipeline — the exact failure the 'metrics stale' flag exists to catch, and a derived gauge would go blind at the same moment. And it uses a static registry reached through ScadaBridgeTelemetry (the SiteConnectionOpened precedent) rather than a DI-injected holder: the DCL actors already take ISiteHealthCollector through their constructors, and threading a second dependency through both would ripple into every test that builds them. It also keeps SiteHealthCollector untouched, which matters right now — another agent is concurrently editing that file for the tag-resolution path. Removal is wired too: an undeployed connection leaves the registry, so it stops counting toward the total instead of latching connected < total on forever. Both gauges read 0 on the standby (connections open on the active node only) — healthy, documented, and called out in the docs so it does not become the next site_connection_up. No ObservedMeters allowlist change: all three instruments ride the existing ZB.MOM.WW.ScadaBridge meter. (An unlisted meter exports nothing, silently.) Tests: Commons 711 passed (9 new, delta-based against a baseline with unique per-test connection names, so they do not inherit the register row 32 QueueDepthGaugeTests static-state flake); Communication 717; DCL 319.
36 lines
1.2 KiB
C#
36 lines
1.2 KiB
C#
using ZB.MOM.WW.ScadaBridge.Commons.Observability;
|
|
|
|
namespace ZB.MOM.WW.ScadaBridge.Host.Tests;
|
|
|
|
/// <summary>
|
|
/// Infrastructure-free guards for <see cref="ScadaBridgeTelemetry"/>: the meter name is the
|
|
/// stable value registered with OTel, and the emit helpers are safe to call (they are no-op
|
|
/// until follow-on tasks wire real emit points and a listener attaches).
|
|
/// </summary>
|
|
public class ScadaBridgeTelemetryTests
|
|
{
|
|
[Fact]
|
|
public void MeterName_IsStableValue()
|
|
{
|
|
Assert.Equal("ZB.MOM.WW.ScadaBridge", ScadaBridgeTelemetry.MeterName);
|
|
}
|
|
|
|
[Fact]
|
|
public void EmitHelpers_DoNotThrow()
|
|
{
|
|
var ex = Record.Exception(() =>
|
|
{
|
|
ScadaBridgeTelemetry.RecordDeploymentApplied();
|
|
ScadaBridgeTelemetry.RecordInboundApiRequest("X");
|
|
ScadaBridgeTelemetry.SiteStreamSubscriberOpened();
|
|
ScadaBridgeTelemetry.SiteStreamSubscriberClosed();
|
|
ScadaBridgeTelemetry.LiveAlarmAggregatorStarted();
|
|
ScadaBridgeTelemetry.LiveAlarmAggregatorStopped();
|
|
ScadaBridgeTelemetry.RecordLiveAlarmStreamReconnect();
|
|
ScadaBridgeTelemetry.SetQueueDepthProvider(() => 5);
|
|
});
|
|
|
|
Assert.Null(ex);
|
|
}
|
|
}
|