December 28,2020
By John Hinz @jhinz
In today's distributed development environments, a fundamental necessity to the operation of those environments is knowing whether individual components are operating correctly. The means for confirming health, or not, is often called a health check. Health checks provide a periodic inquiry into the state of our components. In .NET we have a predefined contract for health checks in IHealthCheck.
IHealthCheck describes a single method (all the best interfaces do) called CheckHealthAsync. There are two parameters in CheckHealthAsync, a context and a cancellation token. The context is a window into registration options. Allowing the health check code to tune its health check.
The entry point for setting up health checks is through the service collection. It is an extension method to IServiceCollection called AddHealthChecks. This method returns an IHealthChecksBuilder in turn has another extension method called AddCheck. AddCheck is a generic method constrained to reference types and of course, types that implement IHealthCheck. That generic parameter is also your custom health check implementation of IHealthCheck.
If you need a health check that requires parameters there is another extension to IServiceCollection called AddTypeActivatedCheck. You can specify the parameters using an object array as outlined in the code sample below:
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices((hostContext, services) => { services.AddHealthChecks().AddTypeActivatedCheck<FileSystemCheck>( "FileSystemQuery", new object[] { hostContext.Configuration.GetSection("WatchFolder").Value }); });
Once we've setup the plumbing for our health check we need to expose an API that monitors can query for our component's status. We can expose the endpoint in our Configure method as shown in the example below:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapHealthChecks("/health", new HealthCheckOptions() { AllowCachingResponses = false, ResponseWriter = FileSystemCheck.WriteResponse }); }); }
By exposing the health of our services to monitoring systems we can ensure the proper execution and functioning of our applications.