Production monitoring requires visibility into application health, database connectivity, and downstream service availability. .NET Core provides a built-in Health Checks framework that exposes HTTP endpoints to report status to container orchestrators (like Kubernetes) or load balancers (like Azure App Gateway or NGINX).
Step 1: Install Required NuGet Packages
Add the health checks UI and database diagnostics packages to your project:
Bash
dotnet add package Microsoft.Extensions.Diagnostics.HealthChecks
dotnet add package AspNetCore.Diagnostics.HealthChecks.EntityFrameworkCore
Step 2: Implement a Custom Health Check
Beyond checking database connections, you might want to verify custom dependencies, such as external API reachability, disk space availability, or custom memory thresholds. Implement IHealthCheck:
C#
using Microsoft.Extensions.Diagnostics.HealthChecks;
public class ExternalApiHealthCheck : IHealthCheck
{
private readonly HttpClient _httpClient;
public ExternalApiHealthCheck(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<HealthCheckResult> CheckHealthAsync(
HealthContext context,
CancellationToken cancellationToken = default)
{
try
{
// Ping an external dependency or internal microservice endpoint
var response = await _httpClient.GetAsync("https://api.github.com/status", cancellationToken);
if (response.IsSuccessStatusCode)
{
return HealthCheckResult.Healthy("External API is fully operational.");
}
return HealthCheckResult.Degraded("External API returned a non-success status code.");
}
fatch (Exception ex)
{
return HealthCheckResult.Unhealthy("External API is unreachable.", ex);
}
}
}
Step 3: Register Health Checks in Program.cs
Configure your built-in and custom health checks in the dependency injection container, segmenting them by operational tiers (e.g., Liveness vs. Readiness probes).
C#
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
var builder = WebApplication.CreateBuilder(args);
// Register Health Checks services
builder.Services.AddHealthChecks()
// 1. Built-in EF Core database check
.AddDbContextCheck<AppDbContext>("database", failureStatus: HealthStatus.Unhealthy)
// 2. Custom registered HTTP dependency check
.AddCheck<ExternalApiHealthCheck>("external-github-api", failureStatus: HealthStatus.Degraded);
builder.Services.AddHttpClient<ExternalApiHealthCheck>();
builder.Services.AddControllers();
var app = builder.Build();
// Map comprehensive endpoint reporting JSON details
app.MapHealthChecks("/health/detailed", new HealthCheckOptions
{
ResponseWriter = async (context, report) =>
{
context.Response.ContentType = "application/json";
var response = new
{
Status = report.Status.ToString(),
Checks = report.Entries.Select(e => new
{
Component = e.Key,
Status = e.Value.Status.ToString(),
Description = e.Value.Description,
Duration = e.Value.Duration
}),
TotalDuration = report.TotalDuration
};
await context.Response.WriteAsJsonAsync(response);
}
});
// Map lightweight liveness endpoint for Kubernetes probes
app.MapHealthChecks("/health/liveness", new HealthCheckOptions
{
Predicate = r => r.Tags.Contains("liveness")
});
app.Run();