b350fba233
LocalDbReplicationHealthCheck reports Healthy when replication is default-OFF or LocalDb is absent (admin-only graphs) - so a plain node is never degraded by it - Degraded when configured-but-disconnected, connected-with-unknown-backlog (a failed oplog poll must not read as zero), or connected-with-backlog past the threshold. Never Unhealthy: a replication fault does not stop the node serving its address space. Pure decision core is table-tested; registered unconditionally via a factory so AddOtOpcUaHealth keeps its no-arg signature and resolves ISyncStatus optionally. Adds LocalDbMetrics.MeterName to the observability allowlist. o.Meters is a strict allowlist with no wildcard, so the localdb.sync.* / localdb.oplog.depth series were otherwise silently absent from /metrics - the omission a ScadaBridge live gate caught.
70 lines
3.2 KiB
C#
70 lines
3.2 KiB
C#
using Microsoft.AspNetCore.Routing;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
|
using Microsoft.Extensions.Options;
|
|
using ZB.MOM.WW.Health;
|
|
using ZB.MOM.WW.Health.Akka;
|
|
using ZB.MOM.WW.Health.EntityFrameworkCore;
|
|
using ZB.MOM.WW.LocalDb.Replication;
|
|
using ZB.MOM.WW.OtOpcUa.Configuration;
|
|
using ZB.MOM.WW.OtOpcUa.Host.Configuration;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Host.Health;
|
|
|
|
public static class HealthEndpoints
|
|
{
|
|
/// <summary>
|
|
/// Registers the shared ZB.MOM.WW health probes. Tier semantics preserved: configdb + akka on
|
|
/// ready+active; admin-leader on active only.
|
|
/// </summary>
|
|
/// <param name="services">The service collection to register the health checks on.</param>
|
|
/// <returns>The same service collection, for chaining.</returns>
|
|
public static IServiceCollection AddOtOpcUaHealth(this IServiceCollection services)
|
|
{
|
|
services.AddHealthChecks()
|
|
.AddTypeActivatedCheck<DatabaseHealthCheck<OtOpcUaConfigDbContext>>(
|
|
"configdb",
|
|
failureStatus: null,
|
|
tags: new[] { ZbHealthTags.Ready, ZbHealthTags.Active },
|
|
args: new DatabaseHealthCheckOptions<OtOpcUaConfigDbContext>
|
|
{
|
|
ProbeQuery = static (db, ct) => db.Deployments.AsNoTracking().Take(1).ToListAsync(ct),
|
|
})
|
|
.AddTypeActivatedCheck<AkkaClusterHealthCheck>(
|
|
"akka",
|
|
failureStatus: null,
|
|
tags: new[] { ZbHealthTags.Ready, ZbHealthTags.Active },
|
|
args: AkkaClusterStatusPolicy.OtOpcUaCompat)
|
|
.AddTypeActivatedCheck<ActiveNodeHealthCheck>(
|
|
"admin-leader",
|
|
failureStatus: null,
|
|
tags: new[] { ZbHealthTags.Active },
|
|
args: "admin")
|
|
// Registered unconditionally, not driver-gated. AddOtOpcUaHealth takes no role argument
|
|
// and runs on every node; the check itself resolves ISyncStatus optionally and reports
|
|
// Healthy when LocalDb is absent (admin-only graphs) or replication is default-OFF, so a
|
|
// plain node is never degraded by it. A factory registration keeps this no-arg signature
|
|
// while still reading ISyncStatus + options + the sync port from the container.
|
|
.Add(new HealthCheckRegistration(
|
|
"localdb-replication",
|
|
sp => new LocalDbReplicationHealthCheck(
|
|
sp.GetService<ISyncStatus>(),
|
|
sp.GetRequiredService<IOptions<ReplicationOptions>>(),
|
|
LocalDbRegistration.SyncListenPort(sp.GetRequiredService<IConfiguration>())),
|
|
failureStatus: null,
|
|
tags: new[] { ZbHealthTags.Active }));
|
|
return services;
|
|
}
|
|
|
|
/// <summary>Maps the OtOpcUa health check endpoints to the route builder.</summary>
|
|
/// <param name="app">The endpoint route builder.</param>
|
|
/// <returns>The same endpoint route builder, for chaining.</returns>
|
|
public static IEndpointRouteBuilder MapOtOpcUaHealth(this IEndpointRouteBuilder app)
|
|
{
|
|
app.MapZbHealth();
|
|
return app;
|
|
}
|
|
}
|