QuickStart Health Check Setup in ASP.NET Core 5 Web API
Tags: dotnet, csharp, webdev
Published: 2021-03-28 01:15:45

In this post we will integrate ASP.NET Core Health-Checks in .NET 5 Core API Project. This is a straightforward, quick start guide to get things started with health checks with a graphical user interface and no database dependency.

In this example a memory check based on the Garbage collector will be setup. We will use the [AspNetCore.Diagnostics.HealthChecks](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks) library to display the results in a more friendly User interface.

#Setup
The first step is to create a new ASP.NET Core WebApi project in your environment. In this example I will use openApi set as true and .NET 5.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7wn1i1cjk3n1ru80957.png)

## Packages
Install the following nuget packages:

* AspNetCore.HealthChecks.UI
* AspNetCore.HealthChecks.UI.InMemory.Storage
* AspNetCore.HealthChecks.UI.Client


##ConfigureServices
```csharp
  public void ConfigureServices(IServiceCollection services)
        {
            services.AddHealthChecks().AddCheck<MemoryHealthCheck>("Memory");
            services.AddHealthChecksUI(opt =>
            {
                opt.SetEvaluationTimeInSeconds(15); //time in seconds between check
            }).AddInMemoryStorage();

            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApi.HealthCheck", Version = "v1" });
            });
        }
```

##Configure

```csharp
  public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApi.HealthCheck v1"));
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

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

            app.UseRouting()
             .UseEndpoints(config =>
             {
                 config.MapHealthChecks("/hc", new HealthCheckOptions
                 {
                     Predicate = _ => true,
                     ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
                 });

                 config.MapHealthChecksUI(setup =>
                 {
                     setup.UIPath = "/hc-ui";
                     setup.ApiPath = "/hc-json";  
                 });

                 config.MapDefaultControllerRoute();
             });
        }
```

## MemoryCheck.cs

```csharp
 public class MemoryHealthCheck : IHealthCheck
    {
        private readonly IOptionsMonitor<MemoryCheckOptions> _options;

        public MemoryHealthCheck(IOptionsMonitor<MemoryCheckOptions> options)
        {
            _options = options;
        }

        public string Name => "memory_check";

        public Task<HealthCheckResult> CheckHealthAsync(
            HealthCheckContext context,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var options = _options.Get(context.Registration.Name);

            // Include GC information in the reported diagnostics.
            var allocated = GC.GetTotalMemory(forceFullCollection: false);
            var data = new Dictionary<string, object>()
        {
            { "AllocatedBytes", allocated },
            { "Gen0Collections", GC.CollectionCount(0) },
            { "Gen1Collections", GC.CollectionCount(1) },
            { "Gen2Collections", GC.CollectionCount(2) },
        };
            var status = (allocated < options.Threshold) ?
                HealthStatus.Healthy : context.Registration.FailureStatus;

            return Task.FromResult(new HealthCheckResult(
                status,
                description: "Reports degraded status if allocated bytes " +
                    $">= {options.Threshold} bytes.",
                exception: null,
                data: data));
        }
    }

    public class MemoryCheckOptions
    {
        // Failure threshold (in bytes)
        public long Threshold { get; set; } = 1024L * 1024L * 1024L;
    }
```

##appsettings.json
```json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "HealthChecksUI": {
    "HealthChecks": [
      {
        "Name": "Web App",
        "Uri": "/hc"
      }
    ]
  }
}
```

#Result
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/49kc4rwyj1p7r49tfv7s.png)


# References
* [Health checks in ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-5.0g)
* [GitHub Example](https://github.com/Caio-Sousa/WebApi.HealthCheck)