using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.HealthChecks; namespace ZB.MOM.WW.OtOpcUa.Host.Health; public static class HealthEndpoints { /// /// Registers the standard ASP.NET Core health-check infrastructure plus the OtOpcUa-specific /// probes. Mirrors ScadaLink's three-tier pattern: ready = boot ok; active = /// fully serving traffic; healthz = bare process liveness. /// public static IServiceCollection AddOtOpcUaHealth(this IServiceCollection services) { services.AddHealthChecks() .AddCheck("configdb", tags: new[] { "ready", "active" }) .AddCheck("akka", tags: new[] { "ready", "active" }) .AddCheck("admin-leader", tags: new[] { "active" }); return services; } public static IEndpointRouteBuilder MapOtOpcUaHealth(this IEndpointRouteBuilder app) { // AllowAnonymous on all three — Traefik / k8s liveness probes / load-balancers // hit these without credentials. Without it the AddOtOpcUaAuth fallback policy // 401s every probe and Traefik marks every backend unhealthy. app.MapHealthChecks("/health/ready", new HealthCheckOptions { Predicate = c => c.Tags.Contains("ready"), }).AllowAnonymous(); app.MapHealthChecks("/health/active", new HealthCheckOptions { Predicate = c => c.Tags.Contains("active"), }).AllowAnonymous(); app.MapHealthChecks("/healthz", new HealthCheckOptions { Predicate = _ => false, // process-liveness only — no probes run. }).AllowAnonymous(); return app; } }