MiniAPI(十三)：HealthCheck

開発者がプログラムを開発することは「生」の過程であり、運用担当者が日常的な運用を担当することは「育」の過程である。その「育」の過程で、運用担当者は第一時間にプログラムの状況を理解したいと望む。ヘルスチェックは、その最も基本的な手段である。

```csharp
var builder = WebApplication.CreateBuilder(args);//ヘルスチェックサービスを注入
builder.Services.AddHealthChecks();
var app = builder.Build();
app.MapGet("/test", () =>{   
    return DateTime.Now;
});//ミドルウェアを追加し、ヘルスチェックのアクセスパスを/healthに設定
app.MapHealthChecks("/health");
app.Run();
```

![alt 画像](https://mmbiz.qpic.cn/mmbiz_png/4CAA63nvHRDmSOLu7luzsAkryUvl432WHSoXTrDF2wRFtdLrwr0sJcU0bRCRyHVngm2t1TbPfB28Esykqm7o5g/640?wx_fmt=png)

また、オーバーライドによって返される文字列を変更することもできます：

```csharp
app.MapHealthChecks("/health", new HealthCheckOptions{  
    ResponseWriter = (context, result) => {  
        var backContent = "this is health";  
        return context.Response.WriteAsync(backContent);  
    }
});
```

もちろん、このようなヘルスチェックはホストが起動しているかどうかを確認するだけです。さらに深いレベルのチェックが必要であれば、`IHealthCheck`を実装することによって実現できます。

```csharp
using Microsoft.Extensions.Diagnostics.HealthChecks;

var builder = WebApplication.CreateBuilder(args);//カスタムのヘルスチェッククラスを注入
builder.Services.AddHealthChecks().AddCheck<TestHealthCheck>("test_health_check");
var app = builder.Build();
app.MapGet("/test", () =>{  
    return DateTime.Now;
});//ミドルウェアを追加し、ヘルスチェックのアクセスパスを/healthに設定
app.MapHealthChecks("/health");
app.Run();

public class TestHealthCheck : IHealthCheck{    
    public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)    {  
       //これはサードパーティーの空きメモリ取得ライブラリです
        var client = new MemoryMetricsClient();  
        var metrics = client.GetMetrics();  
        
        Console.WriteLine("Free : " + metrics.Free);  
        //ビジネス要件として、メモリが1000M以上であればヘルスとする
        var healthCheckResultHealthy = metrics.Free > 1000;  
        if (healthCheckResultHealthy)        {  
            return Task.FromResult(HealthCheckResult.Healthy("healthy"));  
        }  
        return Task.FromResult(new HealthCheckResult(context.Registration.FailureStatus,"unhealthy"));    
    }
}
```
この実装があれば、ビジネス上のさまざまな判断サービスが健康かどうかを容易に実現できます。

上記のすべてのヘルスチェックはプルモードであり、つまり外部監視サービスが本サービスの `/health` にリクエストを送り、情報を取得して健康かどうかを判断します。ASP.NET Coreではプッシュモードも提供しています。以下のように：

```csharp
using Microsoft.Extensions.Diagnostics.HealthChecks;
using MiniDemo05;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHealthChecks().AddCheck<TestHealthCheck>("test_health_check");//プッシュパラメータの設定
builder.Services.Configure<HealthCheckPublisherOptions>(options =>{
    options.Delay = TimeSpan.FromSeconds(1);  
    options.Period = TimeSpan.FromSeconds(5);
});//プッシュサービスを注入
builder.Services.AddSingleton<IHealthCheckPublisher, HealthPublisher>();

var app = builder.Build();

app.MapGet("/test", () =>{
    return DateTime.Now;
});
app.Run();

public class TestHealthCheck : IHealthCheck{    
    public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)    {  
        var client = new MemoryMetricsClient();  
        var metrics = client.GetMetrics();  
        Console.WriteLine("Total: " + metrics.Total);  
        Console.WriteLine("Used : " + metrics.Used);  
        Console.WriteLine("Free : " + metrics.Free);
        
        var healthCheckResultHealthy = metrics.Free > 6000;  
        if (healthCheckResultHealthy)        {  
            return Task.FromResult(HealthCheckResult.Healthy("healthy"));  
        }  
        return Task.FromResult(new HealthCheckResult(context.Registration.FailureStatus,"unhealthy"));    
    }
}

public class HealthPublisher : IHealthCheckPublisher{    
    private readonly ILogger<HealthPublisher> _logger;    
    public HealthPublisher(ILogger<HealthPublisher> logger)    {  
        _logger = logger;
    }    
    public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)    {  
        _logger.LogInformation($"{DateTime.Now.ToString()},{ report.Status}");  
        return Task.CompletedTask;    
    }
}
```
監視パラメータがURLの場合、`HealthPublisher`で健康な結果をプッシュすることができます。

(Translated by GPT)

元のリンク：https://mp.weixin.qq.com/s?__biz=MzA3NDM1MzIyMQ==&mid=2247484896&idx=1&sn=c5b92d82f645bcdb8fabd0f6f103775e&chksm=9f005acaa877d3dce8cc00ec1047ae31ca1c2c76cac1d5a244bf4db37b95b03a0741d3c4dd98&token=541757603&lang=zh_CN#rd