HealthCheck Endpoints in .NET Core

⚡Monitoring Application Uptime with HealthCheck Endpoints in .NET Core

After setting up a local instance of Uptime Kuma to keep tabs on my other important services like MQTT, MS-SQL Server and Redis, I realised I needed a way to monitor the uptime of my identity provider and various other APIs as well. Knowing how long they have been running since their last restart can give valuable insights into their health and stability and gives me the ability to leverage Uptime Kuma’s ability to send push notifications when a specific health condition isn’t satisfied, so I know immediately when something’s up (or not!).

🤔What are HealthCheck Endpoints?

HealthCheck endpoints are special URLs within an application that provide information about the health and status of the application and its dependencies, typically output in JSON format. These endpoints can be queried by monitoring systems or other services to determine if the application is running correctly. These health checks can include various parameters such as database connectivity, API availability, memory usage, and custom checks tailored to specific application requirements – which is where I’ll be jumping in.

🛠️Implementing HealthCheck Endpoints in .NET Core

Implementing HealthCheck endpoints in .NET Core is very straightforward. The framework provides a dedicated package, Microsoft.Extensions.Diagnostics.HealthChecks, which includes all necessary components to create and manage health checks.

Here’s a basic example of setting up a HealthCheck endpoint in a .NET Core application:

  • Add the HealthChecks package
dotnet add package Microsoft.Extensions.Diagnostics.HealthChecks
  • Configure HealthChecks in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
    services.AddHealthChecks()
            .AddCheck("Sample Health Check", () => 
                HealthCheckResult.Healthy("The check indicates a healthy result."));
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHealthChecks("/health");
    });
}

In this example, a simple health check is added, and the HealthCheck endpoint is exposed at /health.

🔨Creating a Custom HealthCheck

With the basics done, we’ve configured our app to expose a HealthChecks endpoint at /health – this path is entirely yours to configure.
But lets dig a bit deeper, we don’t want all the logic of our health check contained in the Startup class. Let’s create a dedicated healthcheck class to hold our logic.

using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Diagnostics.HealthChecks;

public class UptimeHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, 
        CancellationToken cancellationToken = default)
    {
        // Here you can add your custom logic to determine the health status.
        // For simplicity, we return a healthy status if the uptime value is equal to or greater than 1 hour.

        var uptime = GetUptime(); // A private method for this example
        var isHealthy = uptime >= 1;

        if (isHealthy)
        {
            return Task.FromResult(HealthCheckResult.Healthy("The application is healthy."));
        }
        else
        {
            return Task.FromResult(HealthCheckResult.Unhealthy("The application is not healthy."));
        }
    }

    private TimeSpan GetUptime()
    {
        // You can replace this with your actual uptime calculation.
        return TimeSpan.FromHours(2); // Example: 2 hours of uptime.
    }
}

What we’ve got here is a class that implements the IHealthCheck interface and gives us a framework to build out the healthcheck so we can use it in the Startup. For brevity I’ve also added some basic logic to give us a Health or Unhealthy status. Feel free to play around with the GetUptime method and test different values.

Configuring the startup to use our new HealthCheck is again, pretty easy. We call the same methods as before, but specify our type that implements the IHealthCheck interface and then give it a name.

public void ConfigureServices(IServiceCollection services)
{
    services.AddHealthChecks()
            .AddCheck<UptimeHealthCheck>("uptime_health_check");
}

⚠️Don’t forget to still call UseEndpoints and map the HealthCheck endpoint as above.

Running the application and calling into our healthcheck endpoint gives us a JSON response, with the overall health of the application (which is derived from the health status of other checks) and the details of the other checks it ran. For example;

{
    "status": "Healthy",
    "totalDuration": "00:00:00.0000202",
    "entries": {
        "uptime_health_check": {
            "description": "The application is healthy.",
            "duration": "00:00:00.0000202",
            "status": "Healthy",
            "tags": []
        }
    }
}

That’s it! Creating a custom health check is easy and gives you simple and effective monitoring for your services and applications.

✨A Few Favorites

There are a plethora of useful health checks already premade and ready to go out there. A few I’ve come to use the most are listed below, including my own version of the uptime health check that I maintain a public GitHub repo for.

Scroll to Top