Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple health-check endpoints in .NET Core 3.x

Is there a way to configure multiple healthcheck endpoints in .NET Core 3.x?

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
};

This is what I have currently and I can't seem to configure another one on top of this.

Redirect in this case won't work as one of these will endpoints will behind a firewall.

like image 516
h-rai Avatar asked Dec 11 '22 01:12

h-rai


2 Answers

Not sure what is your purpose for having multiple healthcheck endpoints.

If it is to support different "liveness" and "readiness" healthchecks, then the correct approach is indicated by Microsoft documentation "Filter Health Checks".

In essence, it relies on adding tags to your health checks and then using those tags to route to the appropriate controller. You don't need to specify a healthcheck with "live" tag as you get the basic Http test out of the box.

In Startup.ConfigureServices()

services.AddHealthChecks()
        .AddCheck("SQLReady", () => HealthCheckResult.Degraded("SQL is degraded!"), tags: new[] { "ready" })
        .AddCheck("CacheReady", () => HealthCheckResult.Healthy("Cache is healthy!"), tags: new[] { "ready" });

In Startup.Configure()

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("ready"),});

    endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
    {
        Predicate = (_) => false});
});
like image 100
maurocam Avatar answered Dec 16 '22 00:12

maurocam


Since HealthChecks is a plain middleware, you can always configure the pipeline in the same way as other normal middlewares.

For example:

//in a sequence way
app.UseHealthChecks("/path1");
app.UseHealthChecks("/path2");

// in a branch way: check a predicate function dynamically
app.MapWhen(
    ctx => ctx.Request.Path.StartsWithSegments("/path3") || ctx.Request.Path.StartsWithSegments("/path4"), 
    appBuilder=>{
        appBuilder.UseMiddleware<HealthCheckMiddleware>();
    }
);

// use endpoint routing
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    endpoints.MapHealthChecks("/health1");
    endpoints.MapHealthChecks("/health2");
});

like image 42
itminus Avatar answered Dec 16 '22 01:12

itminus