Reputation: 127
I am trying to add multiple health checks to a background service. I don't want the core application that adds the background service to have know the details of or have to add all the health checks at the core application level. I could add a IHealthChecksBuilder at the service constructor and add a IHealthCheck class for each check to the background service class. But how do I reference to the objects or configuration of the background service. I have only written a couple of CLEAN Architecture projects so I am still trying to get the hang pushing the logic deeper and keeping the components totally separated.
Things that I am trying to avoid in my Program.cs:
services.AddHostedService<ETL>();
services.AddHealthChecks()
.ForwardToPrometheus()
.AddCheck<StartupHealthCheck>("ETL");
Which I want to be handled by a simple.
services.AddHostedService<ETL>();
services.AddHealthChecks()
.ForwardToPrometheus();
Thank for the help
Upvotes: 0
Views: 2400
Reputation: 38860
You could add an extension method to automatically find and register checks in the assembly:
public static class HealthChecksExtensions
{
public static IHealthChecksBuilder AddAssemblyChecks(this IHealthChecksBuilder checksBuilder, params Assembly[] assemblies)
{
var checks = assemblies
.SelectMany(a => a.GetTypes())
.Where(a => !a.IsAbstract && !a.IsInterface && !a.IsGenericTypeDefinition && a.IsAssignableTo(typeof(IHealthCheck)));
foreach (var check in checks)
{
var registration = new HealthCheckRegistration(
check.GetType().Name,
sp => (IHealthCheck)ActivatorUtilities.GetServiceOrCreateInstance(sp, check),
null,
null
);
checksBuilder.Add(registration);
}
return checksBuilder;
}
}
Usage:
services.AddHealthChecks()
.ForwardToPrometheus()
.AddAssemblyChecks(Assembly.GetEntryAssembly());
Or if the health checks are in another assembly (library) that you add to a project, you could possibly add an extension method there that doesn't take params Assembly[] assemblies
and instead use Assembly.GetExecutingAssembly()
in the method, which would find any in the assembly that the extension method belongs to:
public static class HealthChecksExtensions
{
public static IHealthChecksBuilder AddAssemblyChecks(this IHealthChecksBuilder checksBuilder)
{
var checks = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(a => !a.IsAbstract && !a.IsInterface && !a.IsGenericTypeDefinition && a.IsAssignableTo(typeof(IHealthCheck)));
foreach (var check in checks)
{
var registration = new HealthCheckRegistration(
check.GetType().Name,
sp => (IHealthCheck)ActivatorUtilities.GetServiceOrCreateInstance(sp, check),
null,
null
);
checksBuilder.Add(registration);
}
return checksBuilder;
}
}
Or if you're OK registering the checks manually, but elsewhere:
public static class HealthCheckExtensions
{
public static IHealthChecksBuilder AddMyChecks(this IHealthChecksBuilder checksBuilder)
{
checksBuilder.AddCheck<StartupHealthCheck>("ETL");
return checksBuilder;
}
}
Usage:
services.AddHealthChecks()
.ForwardToPrometheus()
.AddMyChecks();
Upvotes: 1