.NET Core HealthCheck - 使用依赖注入和参数添加 HealthCheck

.NET Core HealthCheck - Add HealthCheck with dependency injection and parameters

我有不同的 class 继承基础 class。基础 class 实现接口 IHealthCheck。每个 class 都有一个构造函数,根据 class 需要一个记录器和参数。 例如:

public ConnectionHealthCheck(ILogger logger, string address)
        : base(logger)
    {
         Address = address;
    }

我有一个 appSettings.json,它允许我配置多个诊断以在我的健康检查服务中执行。

我在 App.xaml.cs 中获得了诊断列表,我正在尝试将它们添加到 HealthCheck 列表中。

问题是我不能使用旁边的参数进行依赖注入,我不知道什么是最好的解决方案...

这是我的部分代码。

OnStartup 方法:

protected override void OnStartup(StartupEventArgs e)
    {
        var a = Assembly.GetExecutingAssembly();
        using var stream = a.GetManifestResourceStream("appsettings.json");

        Configuration = new ConfigurationBuilder()
            .AddJsonStream(stream)
            .Build();

        var host = new HostBuilder()
            .ConfigureHostConfiguration(c => c.AddConfiguration(Configuration))
                .ConfigureServices(ConfigureServices)
                .ConfigureLogging(ConfigureLogging)
                .Build();
       [...] }

configureService 方法:

private void ConfigureServices(IServiceCollection serviceCollection)
    {
        // create and add the healthCheck for each diag in the appSettings file
        List<DiagnosticConfigItem> diagnostics = Configuration.GetSection("AppSettings:Diagnostics").Get<List<DiagnosticConfigItem>>();
        diagnostics.ForEach(x => CreateHealthCheck(serviceCollection, x)); 
        [...] }

CreateHealthCheck 方法的问题出在哪里:

private void CreateHealthCheck(IServiceCollection serviceCollection, DiagnosticConfigItem configItem)
    {
        EnumDiagType type;

        try
        {
            type = (EnumDiagType)Enum.Parse(typeof(EnumDiagType), configItem.Type, true);
        }
        catch (Exception)
        {
            throw new Exception("Diagnostic type not supported");
        }

        switch (type)
        {
            case EnumDiagType.Connection:
                serviceCollection.AddHealthChecks().AddCheck(nameof(ConnectionHealthCheck), new ConnectionHealthCheck(???, configItem.Value));
                break;
            case EnumDiagType.Other:
                [...] }

如您所见,我无法创建 ConnectionHealthCheck 的实例 class 因为我无法访问 ILogger 对象...

那我该怎么做呢?我想过不同的解决方案,但我没有答案或方法

.NET Core 内置的 DI 可以在 Constructor 级别注入组件。 所以使用下面的方式,我在我的 ASP.NET 核心项目中使用。

public class Startup
{
    public Startup(IWebHostEnvironment environment, IConfiguration configuration, ILoggerFactory loggerFactory)
    {
        Environment = environment;
        Configuration = configuration;
        LoggerFactory = loggerFactory;
    }

    public IConfiguration Configuration { get; }
    public ILoggerFactory LoggerFactory { get; }
    public IWebHostEnvironment Environment { get; }
    
    private void ConfigureServices(IServiceCollection serviceCollection)
    {
        List<DiagnosticConfigItem> diagnostics = Configuration.GetSection("AppSettings:Diagnostics").Get<List<DiagnosticConfigItem>>();
        diagnostics.ForEach(x => CreateHealthCheck(serviceCollection, x, LoggerFactory)); 
    }
    private void CreateHealthCheck(IServiceCollection serviceCollection, DiagnosticConfigItem configItem)
    {
        // Create a ILogger<T> based on your Type by
        loggerFactory.CreateLogger<MessagingServices>())
    }
}
    

这可能有些粗糙,但希望对您有所帮助。

您可以使用 HealthCheckRegistration 注册您的 class(它应该实现 IHealthCheck),它具有接受委托 Func<IServiceProvider,IHealthCheck> 的构造函数,这允许您使用 IServiceProvider 来解析创建健康检查实例所需的参数 class。像这样:

public static class ConnectionHealthCheckBuilderExtensions
{
    const string DefaultName = "example_health_check";

    public static IHealthChecksBuilder AddConnectionHealthCheck(
        this IHealthChecksBuilder builder,
        string name = default,
        DiagnosticConfigItem configItem,
        HealthStatus? failureStatus = default,
        IEnumerable<string> tags = default)
    {
        return builder.Add(new HealthCheckRegistration(
            name ?? DefaultName,
            sp => new ConnectionHealthCheck(sp.GetRequiredService<ISomeService>(), configItem.Value),
            failureStatus,
            tags));
    }
}

有关详细信息,请参阅文档的 this 部分。