feat: Add health check monitoring for ProfileWorker
ProfileWorker changes: - Implement IHealthCheck interface - Replace _workCount with DateTime-based tracking - Track _lastSuccessfulRun, _consecutiveFailures, _lastException - Graceful shutdown handling (OperationCanceledException) - Health states: Healthy, Degraded (1-2 failures), Unhealthy (3x interval) DependencyInjection changes: - Register ProfileWorker as singleton (for health check access) - Use factory pattern for IHostedService registration Program.cs changes: - Add health check service with ProfileWorker - Map /health endpoint (full JSON response with all checks) - Map /health/ready endpoint (filtered by 'ready' tag) - Custom JSON response writer with detailed metrics
This commit is contained in:
@@ -101,6 +101,10 @@ builder.Services.AddHangfireServer();
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
// Add health checks
|
||||
builder.Services.AddHealthChecks()
|
||||
.AddCheck<ProfileWorker>("profile-worker", tags: new[] { "ready", "worker" });
|
||||
|
||||
// Add Serilog.UI with SQLite provider - use same path from configuration
|
||||
var serilogUiLogDirectory = builder.Configuration.GetValue<string>("Application:LogDirectory")
|
||||
?? throw new InvalidOperationException("Application:LogDirectory not found in configuration.");
|
||||
@@ -139,6 +143,36 @@ app.UseSerilogUi();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
// Map health check endpoints
|
||||
app.MapHealthChecks("/health", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = async (context, report) =>
|
||||
{
|
||||
context.Response.ContentType = "application/json";
|
||||
var result = System.Text.Json.JsonSerializer.Serialize(new
|
||||
{
|
||||
status = report.Status.ToString(),
|
||||
timestamp = DateTime.UtcNow,
|
||||
checks = report.Entries.Select(e => new
|
||||
{
|
||||
name = e.Key,
|
||||
status = e.Value.Status.ToString(),
|
||||
description = e.Value.Description,
|
||||
duration = e.Value.Duration.TotalMilliseconds,
|
||||
exception = e.Value.Exception?.Message,
|
||||
data = e.Value.Data
|
||||
})
|
||||
});
|
||||
await context.Response.WriteAsync(result);
|
||||
}
|
||||
});
|
||||
|
||||
app.MapHealthChecks("/health/ready", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions
|
||||
{
|
||||
Predicate = check => check.Tags.Contains("ready")
|
||||
});
|
||||
|
||||
// Redirect root path to Hangfire dashboard
|
||||
app.MapGet("/", () => Results.Redirect("/hangfire"));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user