Write and send .Net application health checks to Elasticsearch using Microsoft AspNetCore HealthChecks

Ingrid Jardillier
Zenika
Published in
4 min readApr 20, 2023

--

Good practices to properly write and send health checks to Elasticsearch, using Microsoft AspNetCore HealthChecks.

What are health checks?

ASP.NET Core offers Health Checks Middleware and libraries for reporting the health of app infrastructure components.

Health checks are exposed by an app as HTTP endpoints. Health check endpoints can be configured for various real-time monitoring scenarios:

  • Health probes can be used by container orchestrators and load balancers to check an app’s status. For example, a container orchestrator may respond to a failing health check by halting a rolling deployment or restarting a container. A load balancer might react to an unhealthy app by routing traffic away from the failing instance to a healthy instance.
  • Use of memory, disk, and other physical server resources can be monitored for healthy status.
  • Health checks can test an app’s dependencies, such as databases and external service endpoints, to confirm availability and normal functioning.

Health checks are typically used with an external monitoring service or container orchestrator to check the status of an app. Before adding health checks to an app, decide on which monitoring system to use. The monitoring system dictates what types of health checks to create and how to configure their endpoints.

Source : Health checks in ASP.NET Core

NuGet packages

Following Xabaril NuGet package is used:

There are a lot of NuGet packages provided by Xabaril which can help you to add health checks for your application dependencies: Azure services, databases, events bus, network, …

Health checks implementation

First, you have to add the following packages in your csproj file (you can update the version to the latest available for your .Net version):

<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="6.0.5" />

Then, you have to register the HealthCheck service. This is done here in a custom extension which is used in the ConfigureServices of the Startup file:

public virtual void ConfigureServices(IServiceCollection services)
{
// …
services.AddCustomHealthCheck(Configuration)
// …
}

public static IServiceCollection AddCustomHealthCheck(
this IServiceCollection services, IConfiguration configuration)
{
IHealthChecksBuilder hcBuilder = services.AddHealthChecks();
hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy());
return services;
}

This “self” check is just here to say that if the endpoint responds (the application is alive). You can also manage Unhealthy and Degraded mode if needed.

The third step is to map endpoints for health checks:

public void Configure(IApplicationBuilder app)
{
app.UseRouting();
// ...

app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/liveness", new HealthCheckOptions
{
Predicate = r => r.Name.Contains("self")
});

endpoints.MapHealthChecks("/hc", new HealthCheckOptions()
{
Predicate = _ => true,
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
});
}

The first map exposes the /liveness endpoint with the self check described in the previous section.

The result of a call to http://localhost:8080/liveness will just be:

Status code : 200 (Ok)
Content : Healthy

The second map exposes the /hc endpoint with an aggregation of all health checks defined in a JSON format.

The result of a call to http://localhost:8080/hc will be:

Status code : 200 (Ok)
Content : {"status":"Healthy","totalDuration":"00:00:00.0027779","entries":{"self":{"data":{},"duration":"00:00:00.0008869","status":"Healthy","tags":[]}}}

Sending health checks to Elasticsearch

All the health checks are available on the /hc endpoint.

To send the health checks to Elasticseach, you will have to configure a metricbeat agent with http module:

metricbeat.modules:
- module: http
metricsets:
- json
period: 10s
hosts: ["host.docker.internal:8080"]
namespace: "healthchecks"
path: "/hc"

For more information about this metricbeat configuration, you can have a look to: https://github.com/ijardillier/docker-elk/blob/master/metricbeat/config/modules.d/http.yml

You can also use heartbeat agent and the /liveness endpoint in order to use the Uptime app in Kibana:

heartbeat.monitors:
- type: http
id: http-monitor
name: HTTP Monitor
schedule: '@every 5s' # every 5 seconds from start of beat
urls:
- "http://host.docker.internal:8080/liveness"

For more information about this heartbeat configuration, you can have a look to: https://github.com/ijardillier/docker-elk/blob/master/extensions/beats/heartbeat/config/heartbeat.yml

When using Prometheus, it is possible to forward health checks metrics to Prometheus endpoint, and retrieve it with the same configuration of metricbeat, in a prometheus module. We will implement this in the next article.

Analyse health checks in Kibana

You can check how health checks are ingested in the Discover module:

With Metricbeat:

Health checks with Metricbeat on Discover
Health checks with Metricbeat on Discover

With Heartbeat:

Health checks with Heartbeat on Discover
Health checks with Heartbeat on Discover

You can see how health checks are displayed in the Uptime App:

Health checks on Uptime App
Health checks on Uptime App

Conclusion

In this article, we have seen how to use Microsoft AspNetCore Healchecks to write and send health checks to Elasticsearch.

A complete sample, with 2 projects (.Net API and .Net client with Blazor UI) is available on Github.

In the next article, we will focus on metrics with Prometheus.

--

--