Reputation: 308
I was learing about HealthChecks following the information posted on the MSDN site: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-5.0#register-health-check-services
The following code snippet tells that if an unhealthy checks returns I can overwrite the value by saying it's degraded instead.
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>(
"example_health_check",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" });
So I tried this with this implementation, assuming that I would get a degraded result instead of an unhealthy one:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks().AddCheck<ExampleHealthCheck>("ExampleHealthCheck", failureStatus: HealthStatus.Degraded);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
}
}
internal class ExampleHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default(CancellationToken))
{
return Task.FromResult(HealthCheckResult.Unhealthy("An unhealthy result."));
}
}
Can someone shed some light on why this isn't working or where I got it wrong?
Upvotes: 1
Views: 2044
Reputation: 581
It is quite confusing, because you expect that the HealthCheck gives you back automatically the result you defined on the failureStatus
property, but your HealthCheck explicitly returns Unhealthy
.
If you take a look at the AddHealthCheck<T>
method on GitHub, you will see in only creates an instance of HealthCheckRegistration
.
public static IHealthChecksBuilder AddCheck(
this IHealthChecksBuilder builder,
string name,
IHealthCheck instance,
HealthStatus? failureStatus = null,
IEnumerable<string>? tags = null,
TimeSpan? timeout = null)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
if (instance == null)
{
throw new ArgumentNullException(nameof(instance));
}
return builder.Add(new HealthCheckRegistration(name, instance, failureStatus, tags, timeout));
}
This object is afterwards passed inside the context of your health check. You can then read the failureStatus which is expected in case of failure and then return an HealthCheckResult
from it. In your case, this would return Degraded
:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks().AddCheck<ExampleHealthCheck>("ExampleHealthCheck", failureStatus: HealthStatus.Degraded);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
}
}
internal class ExampleHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default(CancellationToken))
{
return Task.FromResult(new HealthCheckResult(context.Registration.FailureStatus));
}
}
Upvotes: 2