Web API – Health Checks

By | 15/12/2021

In this post, we will see how to configure and use Health Checks in a Web API .NET Core project.
But first of all, what are the Health Checks?
From Microsoft web site:
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 a variety of 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.”

In a nutshell, Health Checks help us to reporting the health of app infrastructure components like database, Service Bus, Blob Storage and so on.
Here https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks, we can find all packages that we can use with many different components.

We start creating a new Web API project called CheckHealth and then, we will install the package HealthChecks using the command:
Install-Package Microsoft.AspNetCore.Diagnostics.HealthChecks

Then, in order to use this library, we have to modify the methods ConfigureServices and Configure in the file Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    // we add the Health Checks Middleware 
    services.AddHealthChecks();
    services.AddControllers();
    services.AddSwaggerGen(c =>
    {
         c.SwaggerDoc("v1", new OpenApiInfo { Title = "CheckHealth", Version = "v1" });
    });
}


public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
  ...
  ...
  ...

  app.UseEndpoints(endpoints =>
  {
      endpoints.MapControllers();
      // We add the endpoint for the Health Check
      endpoints.MapHealthChecks("/checkService");
  });
}



Now, if we run the application and we go to https://localhost:44357/checkService, this will be the result:

Using this endpoint we can check if our service is running.
In the same way, using the other packages, we can check if other components in our service are running, as for example database, queue, blob storage and so on.
Let’s see some example:

SQL SERVER
Using the package AspNetCore.HealthChecks.SqlServer, we can check if a SQL Server database is running.
For example, if I want to use in a project the instance of SQL Server (DESKTOP-376N87T) installed in my machine where I have created a db called testDB, with this library I can check if it is running:

First of all, we have to install the package for Sql Server, using the command:
Install-Package AspNetCore.HealthChecks.SqlServer

Then, we have to modify the file Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
   // we add the Health Checks Middleware 
   services.AddHealthChecks()
           // we add the connection string for Sql Server with a tag
           .AddSqlServer("data source=DESKTOP-376N87T;database=testdb;Integrated Security=SSPI;persist security info=True;", tags: new[] { "sql" });
   services.AddControllers();
   services.AddSwaggerGen(c =>
   {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "CheckHealth", Version = "v1" });
   });
}


public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
  ...
  ...
  ...

  app.UseEndpoints(endpoints =>
  {
      endpoints.MapControllers();
      // Endpoint for the General Health Check
      endpoints.MapHealthChecks("/checkService/Service", new HealthCheckOptions()
      {
          Predicate = (_) => false
      });
      // Endpoint for the Sql Server Health Check
      endpoints.MapHealthChecks("/checkService/SqlServer", new HealthCheckOptions()
      {
          Predicate = (check) => check.Tags.Contains("sql")
      });
  });
}



If we run the application and we test the SqlServer endpoint, this will be the result:

But, if we stop the Sql Server instance, we will have another result:

We can see that Sql Server doesn’t work but, if we check the service, this will be the result:

AZURE STORAGE
Using the package AspNetCore.HealthChecks.AzureStorage, we can check if an AzureStorage like for example Blob or Table is running.
First of all, we go to Azure Portal and we create a Blob Service/Container called testblob:


Then, we have to install the package for AzureStorage, using the command:
Install-Package AspNetCore.HealthChecks.AzureStorage

Now, we have to modify the file Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
   // we add the Health Checks Middleware 
   services.AddHealthChecks()
           // we add the connection string for Sql Server with a tag
           .AddSqlServer("data source=DESKTOP-376N87T;database=testdb;Integrated Security=SSPI;persist security info=True;", tags: new[] { "sql" })
          // we add the connection string for the storage account with a tag                
           .AddAzureBlobStorage("DefaultEndpointsProtocol=https;AccountName=testhealth;AccountKey=/rHRgGjrdY6lZ0w9HgcuOqfbL5l/Hshif6ZMnvoggY6G8J0Op2NhyTzUkEKS3cB404fZpas2FDFOnONaCVWScg==;EndpointSuffix=core.windows.net", tags: new[] { "blob" });
   services.AddControllers();
   services.AddSwaggerGen(c =>
   {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "CheckHealth", Version = "v1" });
   });
}


public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
  ...
  ...
  ...

  app.UseEndpoints(endpoints =>
  {
      endpoints.MapControllers();
      // Endpoint for the General Health Check
      endpoints.MapHealthChecks("/checkService/Service", new HealthCheckOptions()
      {
          Predicate = (_) => false
      });
      // Endpoint for the Sql Server Health Check
      endpoints.MapHealthChecks("/checkService/SqlServer", new HealthCheckOptions()
      {
          Predicate = (check) => check.Tags.Contains("sql")
      });
      // Endpoint for the Blob Storage Server Health Check
      endpoints.MapHealthChecks("/checkService/BlobStorage", new HealthCheckOptions()
      {
          Predicate = (check) => check.Tags.Contains("blob")
      });
  });
}



If we run the application and we test the Blob Storage endpoint, this will be the result:

But, if we delete the Storage Account and we try again to check it, this will be the result:

AZURE SERVICE BUS
Using the package AspNetCore.HealthChecks.AzureServiceBus, we can check if an Azure Service Bus like for example a Queue is running.
First of all, we go to Azure Portal and we create a Service Bus called testhealth where we will create a Queue called queueforhealth:

Then, we have to install the package for AzureServiceBus, using the command:
Install-Package AspNetCore.HealthChecks.AzureServiceBus

Now, we have to modify the file Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
   // we add the Health Checks Middleware 
   services.AddHealthChecks()
           // we add the connection string for Sql Server with a tag
           .AddSqlServer("data source=DESKTOP-376N87T;database=testdb;Integrated Security=SSPI;persist security info=True;", tags: new[] { "sql" })
          // we add the connection string for the storage account with a tag                
           .AddAzureBlobStorage("DefaultEndpointsProtocol=https;AccountName=testhealth;AccountKey=/rHRgGjrdY6lZ0w9HgcuOqfbL5l/Hshif6ZMnvoggY6G8J0Op2NhyTzUkEKS3cB404fZpas2FDFOnONaCVWScg==;EndpointSuffix=core.windows.net", tags: new[] { "blob" })
          // we add the endpoint for Service Bus and the Queue name with a tag
           .AddAzureServiceBusQueue("Endpoint=sb://testhealth.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=257LN/nWaZsR8ZqBXD82jR0ZzzHUNKPAyDi2/+EKW0o=", "queueforhealth", tags: new[] { "queue" });
   services.AddControllers();
   services.AddSwaggerGen(c =>
   {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "CheckHealth", Version = "v1" });
   });
}


public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
  ...
  ...
  ...

  app.UseEndpoints(endpoints =>
  {
      endpoints.MapControllers();
      // Endpoint for the General Health Check
      endpoints.MapHealthChecks("/checkService/Service", new HealthCheckOptions()
      {
          Predicate = (_) => false
      });
      // Endpoint for the Sql Server Health Check
      endpoints.MapHealthChecks("/checkService/SqlServer", new HealthCheckOptions()
      {
          Predicate = (check) => check.Tags.Contains("sql")
      });
      // Endpoint for the Blob Storage Server Health Check
      endpoints.MapHealthChecks("/checkService/BlobStorage", new HealthCheckOptions()
      {
          Predicate = (check) => check.Tags.Contains("blob")
      });
      // Endpoint for the Queue Health Check
      endpoints.MapHealthChecks("/checkService/Queue", new HealthCheckOptions()
      {
          Predicate = (check) => check.Tags.Contains("queue")
      });
  });
}



If we run the application and we test the Queue endpoint, this will be the result:

But, if we delete the Queue and we try again to check it, this will be the result:






Leave a Reply

Your email address will not be published. Required fields are marked *