diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriver.cs index 2cc822b6..d5ea6e49 100644 --- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriver.cs +++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriver.cs @@ -1128,6 +1128,7 @@ public sealed class GalaxyDriver private void OnAlarmFeedTransition(object? sender, GalaxyAlarmTransition transition) { GalaxyAlarmSubscriptionHandle? handle; + int subCount; lock (_alarmHandlersLock) { // Pick the earliest-registered handle as the event owner. The server routes @@ -1137,10 +1138,17 @@ public sealed class GalaxyDriver // subscription remains — HashSet.First() was unstable across mutations // (Driver.Galaxy-006 fix). _alarmSubscriptions is a List, so [0] is always // the earliest-registered handle. - handle = _alarmSubscriptions.Count > 0 - ? _alarmSubscriptions[0] - : null; + subCount = _alarmSubscriptions.Count; + handle = subCount > 0 ? _alarmSubscriptions[0] : null; } + // Native-alarm delivery observability (was a black box): one line per feed transition with the + // resolved alarm ref, the live subscription count, and whether it fans out to OnAlarmEvent. Debug + // so a flapping galaxy doesn't flood prod, but available on demand to answer "is the feed + // delivering / is the subscription un-gating it" — the exact question this driver couldn't answer + // before the SubscribeAlarmsAsync wiring fix. + _logger.LogDebug( + "GalaxyDriver alarm feed: {Kind} {Ref} (subs={Subs}, fanout={Fanout})", + transition.TransitionKind, transition.AlarmFullReference, subCount, handle is not null); if (handle is null) return; var args = new AlarmEventArgs(