ASP.NET Core 內建的系統健康檢查 示範

每次系統剛上線時,總是會有某些功能出現錯誤,或與正式環境設定不一致的地方,無法執行。一開始筆者都會自己建立測試頁面,讓管理員可以查看各功能是否正常,但其實 ASP.NET Core 本身就有內建系統健康檢查,能夠快速確認定義好的健康檢查事項是否都正常。

健康檢查範例

這裡建立兩個健康檢查範例,都需要實作 IHealthCheck 介面。

簡單健康檢查範例

這是微軟官網中的範例,透過修改 isHealthy 為 false 方便觀察不健康時的訊息。
    
public class SampleHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default
    )
    {
        var isHealthy = true;


        if (isHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("健康"));
        }

        return Task.FromResult(
            new HealthCheckResult(
                context.Registration.FailureStatus, "不健康"));
    }
}
    

連線到 Google

這個範例是用來檢查是否能夠連線到 google ,用以當作能否連線到網際網路的依據。
    
public class GoogleHealthCheck : IHealthCheck
{
    public async Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default
    )
    {
        Console.WriteLine("GoogleHealthCheck");
        using var client = new HttpClient();
        try
        {
            var response = await client.GetAsync("http://www.google.com", cancellationToken);

            if (response.IsSuccessStatusCode)
            {
                return HealthCheckResult.Healthy("可以正常連線到 Google");
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("GoogleHealthCheck Exception");
        }

        return HealthCheckResult.Unhealthy("無法連線到 Google");
    }
}
    

註冊服務

將系統健康檢查服務註冊連結為 /healthz
    
builder.Services.AddHealthChecks()
    .AddCheck<GoogleHealthCheck>("Google 連接檢查")
    .AddCheck<SampleHealthCheck>("範例健康檢查");

var app = builder.Build();

app.MapHealthChecks("/healthz");
    

只要開啟 /healthz 頁面,就會看到顯示當前健康度狀態的訊息
    
Healthy
    

如果將上面的 isHealthy 設定為 false,回應內容就會變成 Unhealthy ,然後會在 log 中出現下方的警告訊息:
    
fail: Microsoft.Extensions.Diagnostics.HealthChecks.DefaultHealthCheckService[103]
      Health check 範例健康檢查 with status Unhealthy completed after 0.9322ms with message '不健康'
    

回傳錯誤訊息

上面提到 /healthz API 只有當前狀態名稱,不會有詳細的訊息,那想要顯示各個的狀態該怎麼做?其實我們可以自訂回傳的訊息:
    
// app.MapHealthChecks("/healthz");
app.MapHealthChecks("/healthz", new HealthCheckOptions
    {
        ResponseWriter = (context, report) =>
        {
            context.Response.ContentType = "application/json";

            var response = new
            {
                Status = report.Status.ToString(),
                TotalDuration = report.TotalDuration,
                Entries = report.Entries.Select(e => new
                {
                    Service = e.Key,
                    Status = e.Value.Status.ToString(),
                    Description = e.Value.Description
                })
            };

            var json = JsonSerializer.Serialize(response, new JsonSerializerOptions
            {
                WriteIndented = true,
                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
            });
            return context.Response.WriteAsync(json);
        }
    }
);
    

範例回應:
    
{
    "Status": "Unhealthy",
    "TotalDuration": "00:00:00.0656890",
    "Entries": [
        {
            "Service": "Google 連接檢查",
            "Status": "Healthy",
            "Description": "可以正常連線到 Google"
        },
        {
            "Service": "範例健康檢查",
            "Status": "Unhealthy",
            "Description": "不健康"
        }
    ]
}
    



參考資料:
Microsoft.Learn - Health checks in ASP.NET Core
Microsoft.Learn - Health monitoring

留言