feat(health): show all cluster nodes (online/offline, primary/standby) in health dashboard
Add NodeStatus record, IClusterNodeProvider interface, and AkkaClusterNodeProvider that queries Akka cluster membership for all site-role nodes. HealthReportSender populates ClusterNodes before each report. UI shows a row per node with hostname, Online/Offline badge, and Primary/Standby badge. Falls back to single-node display if ClusterNodes is not populated.
This commit is contained in:
@@ -18,6 +18,7 @@ public class HealthReportSender : BackgroundService
|
||||
private readonly ILogger<HealthReportSender> _logger;
|
||||
private readonly string _siteId;
|
||||
private readonly StoreAndForwardStorage? _sfStorage;
|
||||
private readonly IClusterNodeProvider? _clusterNodeProvider;
|
||||
private long _sequenceNumber;
|
||||
|
||||
public HealthReportSender(
|
||||
@@ -26,7 +27,8 @@ public class HealthReportSender : BackgroundService
|
||||
IOptions<HealthMonitoringOptions> options,
|
||||
ILogger<HealthReportSender> logger,
|
||||
ISiteIdentityProvider siteIdentityProvider,
|
||||
StoreAndForwardStorage? sfStorage = null)
|
||||
StoreAndForwardStorage? sfStorage = null,
|
||||
IClusterNodeProvider? clusterNodeProvider = null)
|
||||
{
|
||||
_collector = collector;
|
||||
_transport = transport;
|
||||
@@ -34,6 +36,7 @@ public class HealthReportSender : BackgroundService
|
||||
_logger = logger;
|
||||
_siteId = siteIdentityProvider.SiteId;
|
||||
_sfStorage = sfStorage;
|
||||
_clusterNodeProvider = clusterNodeProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -58,6 +61,15 @@ public class HealthReportSender : BackgroundService
|
||||
if (!_collector.IsActiveNode)
|
||||
continue;
|
||||
|
||||
if (_clusterNodeProvider != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_collector.SetClusterNodes(_clusterNodeProvider.GetClusterNodes());
|
||||
}
|
||||
catch { /* Non-fatal */ }
|
||||
}
|
||||
|
||||
if (_sfStorage != null)
|
||||
{
|
||||
try
|
||||
|
||||
12
src/ScadaLink.HealthMonitoring/IClusterNodeProvider.cs
Normal file
12
src/ScadaLink.HealthMonitoring/IClusterNodeProvider.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using ScadaLink.Commons.Messages.Health;
|
||||
|
||||
namespace ScadaLink.HealthMonitoring;
|
||||
|
||||
/// <summary>
|
||||
/// Provides cluster node status information for health reporting.
|
||||
/// Implemented by the Host project which has access to the Akka.NET actor system.
|
||||
/// </summary>
|
||||
public interface IClusterNodeProvider
|
||||
{
|
||||
IReadOnlyList<NodeStatus> GetClusterNodes();
|
||||
}
|
||||
@@ -21,6 +21,7 @@ public interface ISiteHealthCollector
|
||||
void SetInstanceCounts(int deployed, int enabled, int disabled);
|
||||
void SetParkedMessageCount(int count);
|
||||
void SetNodeHostname(string hostname);
|
||||
void SetClusterNodes(IReadOnlyList<Commons.Messages.Health.NodeStatus> nodes);
|
||||
void SetActiveNode(bool isActive);
|
||||
bool IsActiveNode { get; }
|
||||
SiteHealthReport CollectReport(string siteId);
|
||||
|
||||
@@ -21,6 +21,7 @@ public class SiteHealthCollector : ISiteHealthCollector
|
||||
private int _deployedInstanceCount, _enabledInstanceCount, _disabledInstanceCount;
|
||||
private int _parkedMessageCount;
|
||||
private volatile string _nodeHostname = "";
|
||||
private volatile IReadOnlyList<Commons.Messages.Health.NodeStatus>? _clusterNodes;
|
||||
private volatile bool _isActiveNode;
|
||||
|
||||
/// <summary>
|
||||
@@ -94,6 +95,8 @@ public class SiteHealthCollector : ISiteHealthCollector
|
||||
|
||||
public void SetNodeHostname(string hostname) => _nodeHostname = hostname;
|
||||
|
||||
public void SetClusterNodes(IReadOnlyList<Commons.Messages.Health.NodeStatus> nodes) => _clusterNodes = nodes;
|
||||
|
||||
/// <summary>
|
||||
/// Set the current store-and-forward buffer depths snapshot.
|
||||
/// Called before report collection with data from the S&F service.
|
||||
@@ -159,6 +162,7 @@ public class SiteHealthCollector : ISiteHealthCollector
|
||||
NodeHostname: _nodeHostname,
|
||||
DataConnectionEndpoints: connectionEndpoints,
|
||||
DataConnectionTagQuality: tagQuality,
|
||||
ParkedMessageCount: Interlocked.CompareExchange(ref _parkedMessageCount, 0, 0));
|
||||
ParkedMessageCount: Interlocked.CompareExchange(ref _parkedMessageCount, 0, 0),
|
||||
ClusterNodes: _clusterNodes?.ToList());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user