Last post, I showed how to add simple health check for your own system in ASP.Net Core. However, if your system integrates with a third party system, you might want to also check if their system is healthy.
ASP.Net Core makes it simple to add more complex health check such as checking external system by providing an interface which you can implement called IHealthCheck.
There are 3 statuses currently supported we can describe the status of the system:
1. Healthy: connection succeeded
2. Degraded: connection succeeded but took too long
3. Unhealthy: connection failed
public class ExternalWebHealthCheck : IHealthCheck
{
private string _host;
public ExternalWebHealthCheck(string host)
{
_host = host;
}
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
try
{
using var ping = new Ping();
var reply = await ping.SendPingAsync(_host);
if (reply.Status != IPStatus.Success)
{
return HealthCheckResult.Unhealthy();
}
if (reply.RoundtripTime > 100)
{
return HealthCheckResult.Degraded();
}
return HealthCheckResult.Healthy();
}
catch
{
return HealthCheckResult.Unhealthy();
}
}
}
The health check will need to be registered in the Startup class as followed
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks()
.AddCheck("Microsoft", new ExternalWebHealthCheck ("www.microsoft.com"))
.AddCheck("Facebook", new ExternalWebHealthCheck("www.facebook.com"));
services.AddControllers();
}
This is what you’ll see when you hit the /healthcheck endpoint
This is all good, but if one of the external services is unhealthy, you’ll just see Unhealthy status without knowing which service it is. To fix that, you can add your custom response.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Other configurations...
var options = new HealthCheckOptions
{
ResponseWriter = async (context, healthCheckReport) =>
{
context.Response.ContentType = "application/json";
var result = JsonConvert.SerializeObject(new
{
Status = healthCheckReport.Status.ToString(),
ExternalServices = healthCheckReport.Entries
.Select(e => new
{
Key = e.Key,
Value = e.Value.Status.ToString()
})
});
await context.Response.WriteAsync(result);
}
};
app.UseHealthChecks("/healthcheck", options);
// Other configurations...
}
The result now looks like this
It is not limited to http pings, you can actually do all kinds of checks. You can try connecting to a database, pinging a SOAP service, check the messaging queues, etc.