From 97902d687973e48be93379903d18c574050d316c Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Mon, 17 Aug 2026 03:54:53 -0400 Subject: [PATCH] fix(drivers): overrun-meter tag keys align with the Meter's snake_case convention (driver_type/driver_instance) --- .../Observability/OtOpcUaTelemetry.cs | 19 +++++++++++++++++++ .../AbCipDriver.cs | 4 ++-- .../AbLegacyDriver.cs | 4 ++-- .../FocasDriver.cs | 4 ++-- .../ModbusDriver.cs | 4 ++-- .../ZB.MOM.WW.OtOpcUa.Driver.S7/S7Driver.cs | 4 ++-- .../ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlDriver.cs | 4 ++-- .../TwinCATDriver.cs | 4 ++-- 8 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Observability/OtOpcUaTelemetry.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Observability/OtOpcUaTelemetry.cs index 32043b0e..6187acaf 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Observability/OtOpcUaTelemetry.cs +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Observability/OtOpcUaTelemetry.cs @@ -55,6 +55,25 @@ public static class OtOpcUaTelemetry Meter.CreateCounter("otopcua.driver.poll.overrun", unit: "{overrun}", description: "Poll cycles that ran longer than the poll interval (slow success and slow failure both count — see PollGroupEngine.NoteOverrun)."); + /// + /// Tag key carrying the DriverTypeNames constant on . + /// The snake_case spelling is load-bearing, not a style choice. It is the same + /// literal key emits (DriverInstanceActor), and + /// every other instrument on this uses bare/snake_case keys + /// (event, kind, outcome, site, reason). A dotted + /// driver.type here would silently split a dashboard's "group by driver type" across + /// two key names that no single query can join. The seven poll drivers reference this const + /// rather than a literal so that can never drift back. + /// + public const string PollOverrunDriverTypeTag = "driver_type"; + + /// + /// Tag key carrying the emitting driver's instance id on . Cardinality + /// is bounded by the number of configured driver instances on the node. Snake_case for the same + /// convention reason as . + /// + public const string PollOverrunDriverInstanceTag = "driver_instance"; + // ---------------- VirtualTag / ScriptedAlarm engines ---------------- public static readonly Counter VirtualTagEval = diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipDriver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipDriver.cs index 958f9c63..931a7069 100644 --- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipDriver.cs +++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipDriver.cs @@ -166,8 +166,8 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery, // The engine owns no Meter (Core.Abstractions takes no metrics dependency), so this // closure IS the production consumer of its overrun signal. onOverrun: _ => OtOpcUaTelemetry.PollOverruns.Add(1, - new KeyValuePair("driver.type", DriverTypeNames.AbCip), - new KeyValuePair("driver.instance", driverInstanceId))); + new KeyValuePair(OtOpcUaTelemetry.PollOverrunDriverTypeTag, DriverTypeNames.AbCip), + new KeyValuePair(OtOpcUaTelemetry.PollOverrunDriverInstanceTag, driverInstanceId))); _alarmProjection = new AbCipAlarmProjection(this, _options.AlarmPollInterval, _logger); } diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/AbLegacyDriver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/AbLegacyDriver.cs index 9c3fa501..1befff77 100644 --- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/AbLegacyDriver.cs +++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/AbLegacyDriver.cs @@ -81,8 +81,8 @@ public sealed class AbLegacyDriver : IDriver, IReadable, IWritable, ITagDiscover // The engine owns no Meter (Core.Abstractions takes no metrics dependency), so this // closure IS the production consumer of its overrun signal. onOverrun: _ => OtOpcUaTelemetry.PollOverruns.Add(1, - new KeyValuePair("driver.type", DriverTypeNames.AbLegacy), - new KeyValuePair("driver.instance", driverInstanceId))); + new KeyValuePair(OtOpcUaTelemetry.PollOverrunDriverTypeTag, DriverTypeNames.AbLegacy), + new KeyValuePair(OtOpcUaTelemetry.PollOverrunDriverInstanceTag, driverInstanceId))); } /// Upper bound on the poll-loop failure backoff — adopts the S7-proven 30 s cap fleet-wide (05/STAB-8). diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/FocasDriver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/FocasDriver.cs index 1db8be35..ea5acf3b 100644 --- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/FocasDriver.cs +++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/FocasDriver.cs @@ -126,8 +126,8 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery, // The engine owns no Meter (Core.Abstractions takes no metrics dependency), so this // closure IS the production consumer of its overrun signal. onOverrun: _ => OtOpcUaTelemetry.PollOverruns.Add(1, - new KeyValuePair("driver.type", DriverTypeNames.FOCAS), - new KeyValuePair("driver.instance", driverInstanceId))); + new KeyValuePair(OtOpcUaTelemetry.PollOverrunDriverTypeTag, DriverTypeNames.FOCAS), + new KeyValuePair(OtOpcUaTelemetry.PollOverrunDriverInstanceTag, driverInstanceId))); } /// True when the supplied DriverConfig JSON carries a real body. The bootstrapper always passes diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusDriver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusDriver.cs index b598f209..e50d433a 100644 --- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusDriver.cs +++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusDriver.cs @@ -192,8 +192,8 @@ public sealed class ModbusDriver // The engine owns no Meter (Core.Abstractions takes no metrics dependency), so this // closure IS the production consumer of its overrun signal. onOverrun: _ => OtOpcUaTelemetry.PollOverruns.Add(1, - new KeyValuePair("driver.type", DriverTypeNames.Modbus), - new KeyValuePair("driver.instance", driverInstanceId))); + new KeyValuePair(OtOpcUaTelemetry.PollOverrunDriverTypeTag, DriverTypeNames.Modbus), + new KeyValuePair(OtOpcUaTelemetry.PollOverrunDriverInstanceTag, driverInstanceId))); } /// Upper bound on the poll-loop failure backoff — adopts the S7-proven 30 s cap fleet-wide (05/STAB-8). diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7/S7Driver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7/S7Driver.cs index 6fa90de0..d9c7c2ae 100644 --- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7/S7Driver.cs +++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7/S7Driver.cs @@ -74,8 +74,8 @@ public sealed class S7Driver // The engine owns no Meter (Core.Abstractions takes no metrics dependency), so this // closure IS the production consumer of its overrun signal. onOverrun: _ => OtOpcUaTelemetry.PollOverruns.Add(1, - new KeyValuePair("driver.type", DriverTypeNames.S7), - new KeyValuePair("driver.instance", driverInstanceId))); + new KeyValuePair(OtOpcUaTelemetry.PollOverrunDriverTypeTag, DriverTypeNames.S7), + new KeyValuePair(OtOpcUaTelemetry.PollOverrunDriverInstanceTag, driverInstanceId))); } // ---- ISubscribable + IHostConnectivityProbe state ---- diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlDriver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlDriver.cs index 89f39840..402ba588 100644 --- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlDriver.cs +++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlDriver.cs @@ -233,8 +233,8 @@ public sealed class SqlDriver // The engine owns no Meter (Core.Abstractions takes no metrics dependency), so this // closure IS the production consumer of its overrun signal. onOverrun: _ => OtOpcUaTelemetry.PollOverruns.Add(1, - new KeyValuePair("driver.type", DriverTypeNames.Sql), - new KeyValuePair("driver.instance", driverInstanceId))); + new KeyValuePair(OtOpcUaTelemetry.PollOverrunDriverTypeTag, DriverTypeNames.Sql), + new KeyValuePair(OtOpcUaTelemetry.PollOverrunDriverInstanceTag, driverInstanceId))); } /// diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATDriver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATDriver.cs index 6e13e39c..d79a5522 100644 --- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATDriver.cs +++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATDriver.cs @@ -83,8 +83,8 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery // The engine owns no Meter (Core.Abstractions takes no metrics dependency), so this // closure IS the production consumer of its overrun signal. onOverrun: _ => OtOpcUaTelemetry.PollOverruns.Add(1, - new KeyValuePair("driver.type", DriverTypeNames.TwinCAT), - new KeyValuePair("driver.instance", driverInstanceId))); + new KeyValuePair(OtOpcUaTelemetry.PollOverrunDriverTypeTag, DriverTypeNames.TwinCAT), + new KeyValuePair(OtOpcUaTelemetry.PollOverrunDriverInstanceTag, driverInstanceId))); } /// Upper bound on the poll-loop failure backoff — adopts the S7-proven 30 s cap fleet-wide (05/STAB-8).