web-dev-qa-db-ja.com

ASP.NET Core Health Check内に依存関係を挿入する方法

新しい ASP.NET Code 2.2 Healthchecks 機能を使用しようとしています。

.netブログのこの link では、例を示しています。

public void ConfigureServices(IServiceCollection services)
{
    //...
    services
        .AddHealthChecks()
        .AddCheck(new SqlConnectionHealthCheck("MyDatabase", Configuration["ConnectionStrings:DefaultConnection"]));
    //...
}

public void Configure(IApplicationBuilder app)
{
    app.UseHealthChecks("/healthz");
}

Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheckインターフェースを実装するカスタムチェックを追加できます。しかし、型ではなくインスタンスをAddCheckメソッドに提供する必要があり、ConfigureServicesメソッド内で実行する必要があるため、カスタムチェッカーに依存関係を挿入できません。

これを回避する方法はありますか?

12
lmcarreiro

.NET Core 3.0以降、登録はより簡単になり、これに要約されます

public void ConfigureServices(IServiceCollection services)
{
    services.AddHealthChecks();
    services.AddSingleton<SomeDependency>();
    services.AddCheck<SomeHealthCheck>("mycheck");
}

singletontransientの競合が発生するので、競合が発生しないことに注意してください。エンジンが使用する必要があるもの。

チェックの名前は必須であるため、1つ選択する必要があります。

accepted asnwer は動作しなくなったようです。

1
Yennefer

短い答え

ASP.NET Core Health Check内に依存関係を挿入する方法。

サービスを正しい順序で登録すると、SomeDependencySomeHealthCheckコンストラクターへの注入に使用できるようになり、SomeHealthCheckがヘルスチェック機能の一部として実行されます。

public void ConfigureServices(IServiceCollection services)
{
    services.AddHealthChecks();
    services.AddSingleton<SomeDependency>();

    // register the custom health check 
    // after AddHealthChecks and after SomeDependency 
    services.AddSingleton<IHealthCheck, SomeHealthCheck>();
}

もっと詳しく

A Health Checkサンプルのコメント は次のように述べています。

IHealthCheckサービスはすべて、ヘルスチェックサービスとミドルウェアで利用できます。すべてのヘルスチェックをシングルトンサービスとして登録することをお勧めします。

完全なサンプル

using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;

public class SomeDependency
{
    public string GetMessage() => "Hello from SomeDependency";
}

public class SomeHealthCheck : IHealthCheck
{
    public string Name => nameof(SomeHealthCheck);

    private readonly SomeDependency someDependency;

    public SomeHealthCheck(SomeDependency someDependency)
    {
        this.someDependency = someDependency;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var message = this.someDependency.GetMessage();
        var result = new HealthCheckResult(HealthCheckStatus.Failed, null, null, null);
        return Task.FromResult(result);
    }
}

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHealthChecks();
        services.AddSingleton<SomeDependency>();
        services.AddSingleton<IHealthCheck, SomeHealthCheck>();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseHealthChecks("/healthz");
        app.Run(async (context) => await context.Response.WriteAsync("Hello World!"));
    }
}

このサンプルも GitHubで入手可能 です。

6
Shaun Luttin

Shaunの答えに加えて、 open pull-request があります。これにより、任意のライフタイム(一時的でスコープ付き)のサービスをヘルスチェックに挿入できます。これはおそらく2.2リリースに含まれるでしょう。

ヘルスチェックで一時的なスコープサービスを使用できる場合は、 一時的なライフスタイルを使用してサービスを登録する を行う必要があります。

2
Henk Mollema

私はASP.NET Core 3.1 Web APIでこれに苦労していました。

services.AddHealthChecks();
services.AddSingleton<IHealthCheck, MyHealthCheck1>();    
services.AddSingleton<IHealthCheck, MyHealthCheck2>();

残念ながら、ASP.NET Core 3.1では、IHealthCheck実装が呼び出されなかったため、実際には機能しないようです。

代わりに、Startup.ConfigureServices()で以下を実行する必要がありました。

services.AddHealthChecks()
    .AddCheck<MyHealthCheck1>("My1-check",
        HealthStatus.Unhealthy,
        new string[] { "tag1" })
    .AddCheck<MyHealthCheck2>("My2-check",
        HealthStatus.Unhealthy,
        new string[] { "tag2" });

次に、Startup.Configure()で、次のようにMapHealthChecks()も呼び出しました。

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapHealthChecks("/hc");
});
0
js80