Motivation
The examples in this post are for a HTTP health check see Health Checks for detailed motivation and alternatives like TCP.
We can leverage and extend the existing Microsoft.Extensions.Diagnostics.HealthChecks
to check the APIs downstream dependencies are operational. This can be done with a simple New Relic Synthetic Monitor that polls http://myapi/healthcheck
which would then in turn poll http://dependency-1/ping
ect
The healthcheck endpoint should at very least require authorization in the form of a scope check.
Code Example
- Install the following packages
Microsoft.AspNetCore.Diagnostics.HealthChecks
Microsoft.Extensions.Diagnostics.HealthChecks
- Create a contract each dependency must filfull. Here its helpful for the method to return a tuple of
bool isHealthy
andstring? description
as this will be displayed whenhttp://myapi/healthz
is queried.
1 | public interface IHealthCheckClient |
- Now leverage inheritance to extend the clients interface, this is a bit of a hack but the alternative is to add
IsHealthyAsync
to each clients interface -_-
1 | public interface IDependency1Client : IHealthCheckClient |
- Now implement the
IsHealthyAsync
method fromIHealthCheckClient
to query the ping endpoint. Example:http://dependency-1/ping
1 | public class Dependency1Client : IDependency1Client |
- Create a service health check class that takes a generic type where the type is
IHealthCheckClient
and additionally implement IHealthCheck
- \HealthChecks\ServiceHealthCheck.cs
1 | using Microsoft.Extensions.Diagnostics.HealthChecks; |
- Extend the the service collection in Program.cs to add named health checks, its a fluent api so you can chain them.
1 | services.AddHealthChecks() |
- Still in Program.cs expose the
healthz
endpoint. Thez
inhealthz
is often used as a shorthand for “health check”. In the context of software development, a “health check” is a routine that tests whether a particular component of a system is functioning properly. The “z” is added to the end of “health” to create a unique and distinct word that can be used as a URL endpoint for checking the health of a particular system or component. This convention is often used in the context of microservices architecture, where multiple small services are combined to create a larger system.
1 | app.MapHealthChecks("/healthz") |
You can also use a ResponseWriter to format the response nicely.