ASP .NET Core Health Checks

 


ASP .Net HealthChecks


When we implement and deploy a service, we need to monitor it to check its status. If for some reason, the service is down, we could run a back-up server. In brief, Health Checks monitors our services.

Health Checks are usually used by external monitoring services. If the service's health is not good, we may auto-scale the server or take any other necessary steps to prevent the service's downtime.

Health Checks has the following uses:

Health Checks monitor the resources used by the service, such as memory and disk.

Health checks also check for other resources such as Databases. It makes a dummy DB operation to make sure the Database is working fine.

Microsoft.AspNetCore.Diagnostics.HealthChecks is the package implicitly developed for ASP .NET Core apps. For the Entity Framework Health Checks, we have Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.


Demo:

a.Create an ASP .NET Core Web Application.



b. Open Startup.cs, in ConfigureServices method, add services.AddHealthChecks();


   public void ConfigureServices(IServiceCollection services)

        {

            services.AddControllers();

            services.AddHealthChecks();

        }

c. Next in the Configure method, add the app.UseHealthChecks("/health check"); /health check is the endpoint name. You can name it anything.

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseHealthChecks("/healthCheck");

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

That's it. When you run the application with /healthCheck, you could see the below result:



This makes a basic service's health check: if any request is made to the service, it would respond to the request. However, we may need extra checks in our service.


Custom Health Check

The custom health check is used when we need to manually check our service's health; for example, we will be downloading a file to process logic. If the download always fails during health checks, we can return the service status as unhealthy. This is because our service is not in the right state when the business logic fails (because downloading a file fails). This is just an example. However, you can have your own health checks as per your requirement.

To add a custom health check, create a class, and derive the class from IHealthCheck.


To continue on our demo,

d. Add a .cs file to our project and add the following logically the .cs file.

namespace HealthChecksDemo

{

    public class CustomHealthCheckExample : IHealthCheck

    {

        public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)

        {

//todo: add your logic here. If something not right return HealthCheckResult.UnHealthy()

           return Task.FromResult(HealthCheckResult.Healthy());

        }

    }

}

e. Next, register it with the .Net Core's Health Check middleware.

  services.AddHealthChecks()

                .AddCheck<CustomHealthCheckExample>("DemoCustom");


Custom Health Check Response 

The default .Net Core response says whether the service is healthy or not. However, when we add multiple health checks (DBContext health check, custom health checks), we would like to know which health check failed. For this, we can add a custom health check response.

Let us continue on our demo:

f. Add a class HealthCheckResponse.cs file and add the below code. 

namespace HealthChecksDemo

{

    public class HealthCheckResponse

    {

        public string status { get; set; }


        public IEnumerable<MyHealthCheck> checks { get; set; }


        public TimeSpan duration { get; set; }

    }

}

g. Add one more class MyHealthCheck.cs.

    public class MyHealthCheck
    {
        public string component_status { get; set; }

        public string component { get; set; }

        public string description { get; set; }
    }


Steps f and g are just for grouping the code.

Do you remember registering our service for health checks by adding services?AddHealthChecks();? this takes additional parameter - HealthCheckOptions.

Using HealthCheckOptions we can customise our health check response as below:


var healthCheckOptions = new HealthCheckOptions();


            healthCheckOptions.ResponseWriter = async (context, report) =>

            {

                context.Response.ContentType = "application/json";


                var response = new HealthCheckResponse

                {

                    status = report.Status.ToString(),

                    checks = report.Entries.Select(x => new MyHealthCheck

                    {

                      component = x.Key,

                        component_status = x.Value.Status.ToString(),

                        description = x.Value.Description

                    }),

                    duration = report.TotalDuration

                };

                await context.Response.WriteAsync(JsonConvert.SerializeObject(response));

            };

               

            app.UseHealthChecks("/healthCheck", healthCheckOptions);


Now running the health check on the service will respond as below:



Entity Framework Health Checks

For checking EF health, we need to install the following package from the NuGet package manager.




Next, add the below line. This checks the database.

 services.AddHealthChecks()

                 .AddDbContextCheck<myDbContext>();


Happy Coding!