Adding HealthChecks to your application can drastically reduce troubleshooting time
Why would you want to monitor your applications health?
- Health checks can test an applications dependencies, such as databases and external service endpoints, to confirm availability and normal functioning.
Out of the box Health Checks UI
Here is how to monitor SQL Server tables & Custom Services via HealthChecks in Asp.net Core .NET 7
Add the following Health Check nuget packages to your project solution:
AspNetCore.HealthChecks.UI
AspNetCore.HealthChecks.UI.Client
AspNetCore.HealthChecks.UI.Core
AspNetCore.HealthChecks.SqlServer
AspNetCore.HealthChecks.UI.InMemory.Storage
Create a new class named SampleHealthCheck.cs in a new Folder called 'HealthChecks' in your solution
SampleHealthCheck.cs
public class SampleHealthCheck : IHealthCheck
{
IService _service;
public SampleHealthCheck(IService service)
{
_service = service;
}
public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
var timer = new Stopwatch();
timer.Start();
await _service.GetSampleDataAsync();
timer.Stop();
var timeTaken = timer.Elapsed.TotalMilliseconds;
if (timeTaken < 2000)
return HealthCheckResult.Healthy($"Response Time: {timeTaken}");
else if (timeTaken < 3000)
return HealthCheckResult.Degraded($"Response Time: {timeTaken}");
else
return HealthCheckResult.Unhealthy($"Response Time: {timeTaken}");
}
}
This new class injects a repository for sample purposes. You can imagine this service responsible for fetching data from an external API or a database. From there we execute a method and measure the time is takes to return a result. You can refine the timeTaken double to the appropriate value depending on the expected execution speed of your method. The HealthCheckResult struct determines the health of the application. Note, if any of your health checks return ‘Degraded’, all your health checks will be considered ‘Degraded’, the same goes for ‘Unhealthy’.
Create a new class named CustomHealthChecks.cs in the application root with the following:
This is our own custom service collection we will later call in Program.cs.
.AddSqlServer executes a simple SELECT query on a table
.AddCheck<SampleHealthCheck> wires up our class we created in the previous step.
This makes these two health checks available and queryable.
CustomHealthChecks.cs
public static class CustomHealthChecks
{
public static IServiceCollection AddCustomHealthChecks(this IServiceCollection services, WebApplicationBuilder builder)
{
builder.Services
.AddHealthChecks()
//Query MSSQL table for health check
.AddSqlServer(
connectionString: builder.Configuration.GetConnectionString("ConnString_Live"),
healthQuery: "Select top 1000 * from user_table order by createdt desc",
name: "User Table Check"
)
//Test a repository method for health check
.AddCheck("Sample Service Check");
if (builder.Environment.IsDevelopment())
{
builder.Services
.AddHealthChecksUI(setup => {
setup.AddHealthCheckEndpoint("Health Checks Local", "https://localhost:7083/health");
})
.AddInMemoryStorage();
}
else
{
builder.Services
.AddHealthChecksUI(setup =>
{
setup.AddHealthCheckEndpoint("Health Checks", "https://webservice.[publishedapplicationuri].com:4438/health");
})
.AddInMemoryStorage();
}
return services;
}
}
Program.cs
Here is where everything comes together.
We add our IService repository so it’s available for Dependency Injection and wire up our service collection: AddCustomHealthChecks.
using HealthChecks.UI.Client;
IConfiguration Configuration;
var builder = WebApplication.CreateBuilder(args);
Configuration = builder.Configuration;
builder.Services.AddSingleton();
builder.Services.AddCustomHealthChecks(builder);
var app = builder.Build();
app.MapHealthChecks("/health", new HealthCheckOptions
{
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
//Style you HealthChecks UI with this file
app.MapHealthChecksUI(setup =>
{
setup.AddCustomStylesheet("wwwroot/css/HealthChecks.css");
});
app.Run();
From there you should be able to query two endpoints for health checks
https://localhost:4438/health
This end point will return the health checks in JSON format. You can query this endpoint to create custom components on your application to display your application health.
https://localhost:4438/healthchecks-ui#/healthchecks
This will load the built in Health Checks UI
Want to learn more?
Service Collections with Blazor Server
What is a service collection? Service collections are a way of registering and resolving dependencies in C# applications using the built-in dependency injection (DI) system. Blazor Server is a web framework that allows you to run C# code on the server and interact with the user interface through a SignalR connection. To use service collections…
Read moreIn Memory State Management with Blazor Server
Creating your first In Memory State Container with Blazor Server Web technology has come along way in the relatively recent past. With the surge in popularity of SPAs and Javascript Frameworks a lot of developers have come to expect certain functionality out of the box. Blazor Server being a stateful application framework offers us a…
Read moreIHttpClientFactory vs. HttpClient
Why should you use IHttpClientFactory The main reason to use IHttpClientFactoryinstead of HttpClient directly is to manage the life cycle of HttpClient instances. HttpClient was designed to be instantiated once and reused throughout the application life cycle. If you continually instantiate new HttpClients you may unnecessarily be squandering resources. Another use case is for simplicities…
Read more