HealthCheckPlus 4.0.0
dotnet add package HealthCheckPlus --version 4.0.0
NuGet\Install-Package HealthCheckPlus -Version 4.0.0
<PackageReference Include="HealthCheckPlus" Version="4.0.0" />
<PackageVersion Include="HealthCheckPlus" Version="4.0.0" />
<PackageReference Include="HealthCheckPlus" />
paket add HealthCheckPlus --version 4.0.0
#r "nuget: HealthCheckPlus, 4.0.0"
#:package HealthCheckPlus@4.0.0
#addin nuget:?package=HealthCheckPlus&version=4.0.0
#tool nuget:?package=HealthCheckPlus&version=4.0.0
Welcome to HealthCheckPlus
Per-status polling policies, cached results, and a smarter publisher pipeline for ASP.NET Core health checks.
HealthCheckPlus is written in C#, targeting .NET 10, .NET 9, and .NET 8. It builds on top of ASP.NET Core's native health check system (Microsoft.Extensions.Diagnostics.HealthChecks) rather than replacing it - your existing IHealthCheck implementations and third-party check packages keep working unchanged.
Table of Contents
- Features
- Installing
- Examples
- Usage
- Documentation
- Changelog
- Code of Conduct
- Contributing
- Credits
- License
Features
Per-status scheduling. Each health check can poll at a different rate depending on its own last-known status - for example, check a healthy dependency every 30 seconds but a degraded one every 5. Configure a Healthy policy (the default, always required), and optionally a Degraded and/or Unhealthy policy for each check.
A cache of the last result per check. A request to /health doesn't necessarily re-run every check synchronously - it reads whatever the last poll already produced, subject to that check's own policy. You can also read the cached result for any check, or force one to Unhealthy/Degraded directly from application code (e.g. after catching an exception talking to a dependency) - see SwitchToUnhealthy/SwitchToDegraded below.
Adopting external/third-party checks. Register a check from any existing IHealthChecksBuilder extension (e.g. AddRedis(...)) and give it its own delay, period, and policy rules the same way as a custom check.
An optional background service. Runs checks on its own schedule, independent of HTTP traffic, and drives every registered IHealthCheckPublisher with two extra filters on top of the native publisher pipeline:
- Publish only every N idle cycles, not every cycle (
AfterIdleCount). - Publish only when the aggregate report actually changed since the last publish (
WhenReportChange). - A publisher can add its own custom gating via
IHealthCheckPlusPublisher.PublisherCondition.
Six response templates, all serialized as application/json; charset=utf-8, from a short status-only body up to full details with descriptions and exceptions:
WriteShortDetails/WriteShortDetailsPlusWriteDetailsWithoutException/WriteDetailsWithoutExceptionPlusWriteDetailsWithException/WriteDetailsWithExceptionPlus
The ...Plus variants add dateRef/origin to each entry (how stale a cached result is, and what triggered it), which means they need an extra IStateHealthChecksPlus parameter - so ResponseWriter takes a small lambda instead of a direct method reference: ResponseWriter = (ctx, report) => HealthCheckPlusOptions.WriteDetailsWithExceptionPlus(ctx, report, stateHealthChecksPlus) (see the Samples for a full working example).
Native metrics via System.Diagnostics.Metrics (check executions, status transitions, publisher invocations) - no extra package dependency, consumable by any exporter (OpenTelemetry, Prometheus, App Insights, ...).
A fluent, chainable API that extends the native health check builder rather than replacing it.
Installing
Top layer
Install-Package HealthCheckPlus [-pre]
dotnet add package HealthCheckPlus [--prerelease]
Other layer
Install-Package HealthCheckPlus.Abstractions [-pre]
dotnet add package HealthCheckPlus.Abstractions [--prerelease]
Note: [-pre]/[--prerelease] usage for pre-release versions
Examples
Three runnable projects under Samples — clone the repo and dotnet run any of them:
- HealthCheckPlusDemo — the smallest complete setup: custom checks, an adopted external check (Redis), per-status policies, the HTTP endpoints, and the manual-override/middleware patterns. Start here.
- HealthCheckPlusDemoBackgroudService — the same setup plus background polling and publishing:
AddBackgroundPolicy, a customIHealthCheckPublisher, and five endpoints side by side showing different response templates (short, full, default, and interop with the nativeUseHealthChecksmiddleware). - HealthCheckPlusDemoMetrics — observing the native
System.Diagnostics.Metricsinstrumentation: aMeterListenerprints everyhealthcheckplus.*measurement to the console as it's recorded, no exporter required.
Usage
HealthCheckPlus uses a fluent interface - method chaining, in the same style as the native IHealthChecksBuilder it extends - so a full setup reads top to bottom as one continuous configuration.
//At Startup / Program (without background services policies)
builder.Services
//Add HealthCheckPlus - the set of tracked checks comes from whatever ends up registered
//below (AddCheckPlus/AddCheckLinkTo/native AddCheck), no separate list to keep in sync.
//A check added only via a native extension still needs AddCheckPlus/AddCheckLinkTo for
//its own Healthy policy below, or the host fails fast at startup naming it.
.AddHealthChecksPlus()
//your custom HC
.AddCheckPlus<HcTeste1>("HcTest1")
//your custom HC
.AddCheckPlus<HcTeste2>("HcTest2", failureStatus: HealthStatus.Degraded)
//external HC
.AddRedis("connection string", "MyRedis")
//register external HC
.AddCheckLinkTo("Redis", "MyRedis", TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(30))
//policy for Unhealthy
.AddUnhealthyPolicy("HcTest1", TimeSpan.FromSeconds(2))
//policy for Degraded
.AddDegradedPolicy("HcTest2", TimeSpan.FromSeconds(3))
//policy for Unhealthy
.AddUnhealthyPolicy("Redis", TimeSpan.FromSeconds(1));
//At Startup / Program (with background services policies)
builder.Services
//Add HealthCheckPlus
.AddHealthChecksPlus()
//your custom HC with custom delay and period
.AddCheckPlus<HcTeste1>("HcTest1", TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(10))
//your custom HC without delay and period (using BackgroundPolicy)
.AddCheckPlus<HcTeste2>("HcTest2", failureStatus: HealthStatus.Degraded)
//external HC
.AddRedis("connection string", "MyRedis")
//register external HC without delay and period (using BackgroundPolicy)
.AddCheckLinkTo("Redis", "MyRedis")
//policy for running in Background service
.AddBackgroundPolicy((opt) =>
{
opt.Delay = TimeSpan.FromSeconds(5);
opt.Timeout = TimeSpan.FromSeconds(30);
opt.Idle = TimeSpan.FromSeconds(1);
//opt.AllStatusPeriod(TimeSpan.FromSeconds(30));
opt.HealthyPeriod = TimeSpan.FromSeconds(30);
opt.DegradedPeriod = TimeSpan.FromSeconds(30);
opt.UnhealthyPeriod = TimeSpan.FromSeconds(30);
//Publishing.Enabled defaults to false - assigning a new PublishingOptions() (as below) is
//what turns it on. AfterIdleCount/WhenReportChange below happen to match its own defaults,
//but the assignment itself is not redundant boilerplate: deleting this block silently
//disables all publishing, with no log or metric signal.
opt.Publishing = new PublishingOptions()
{
AfterIdleCount = 1,
WhenReportChange = true
};
});
//At Startup / Program (optional)
var app = builder.Build();
//save interfaces IStateHealthChecksPlus
using (IServiceScope startscope = app.Services.CreateScope())
{
_stateHealthChecksPlus = startscope.ServiceProvider.GetRequiredService<IStateHealthChecksPlus>();
}
//At Startup / Program
//Endpoints HC
app
//Extend HealthCheckOptions with HealthCheckPlusOptions
.UseHealthChecksPlus("/health/live", new HealthCheckPlusOptions
{
//name for HealthCheck kind
HealthCheckName = "live",
//custom function for status value of report
StatusHealthReport = (rep) =>
{
if (rep.StatusResult("HcTest1") == HealthStatus.Unhealthy)
{
//do something
}
if (rep.TryGetNotHealthy(out var results))
{
//do something
}
return HealthStatus.Degraded;
},
//Result Status Codes (same behavior as HealthCheckOptions)
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
}
})
//default HealthCheckPlusOptions (same behavior as default HealthCheckOptions)
.UseHealthChecksPlus("/health/ready", new HealthCheckPlusOptions
{
//name for HealthCheck kind
HealthCheckName = "ready",
//template for Response (same behavior as HealthCheckOptions)
ResponseWriter = HealthCheckPlusOptions.WriteDetailsWithoutException,
//Result Status Codes (same behavior as HealthCheckOptions)
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
}
});
//example of use in the middleware pipeline
_ = app.Use(async (context, next) =>
{
if (_stateHealthChecksPlus.Status("live") == HealthStatus.Unhealthy)
{
var msg = JsonSerializer.Serialize(new { Error = "App Unhealthy" });
context.Response.ContentType = "application/json";
context.Response.ContentLength = msg.Length;
context.Response.StatusCode = 500;
await context.Response.WriteAsync(msg);
await context.Response.CompleteAsync();
return;
}
await next();
});
//example of use in a business class using dependency injection
public class MyBusiness
{
public MyBusiness(IStateHealthChecksPlus healthCheckApp)
{
if (healthCheckApp.Status("live") == HealthStatus.Degraded)
{
//do something
}
if (healthCheckApp.StatusResult("HcTest2").Status == HealthStatus.Unhealthy)
{
//do something. This dependency 'HcTest2' is not available
}
try
{
//redis access
}
catch (ExceptionRedis rex)
{
healthCheckApp.SwitchToUnhealthy("Redis");
}
}
}
//example of Publisher condition to execute
public class SamplePublishHealth : IHealthCheckPlusPublisher
{
public Func<HealthReport, bool>? PublisherCondition { get; set; } = (_) => true;
public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
Documentation
- Points of attention — what to know before you build on HealthCheckPlus, in plain language. Start here.
- Architecture — how HealthCheckPlus is put together internally, for maintainers and contributors.
- Operational runbook — how to read a health check response and diagnose common problems, for operators.
- API reference — generated from the XML doc comments.
- Release methodology — how a release's quality is verified before it ships.
- Architecture decisions — the load-bearing design decisions behind this library, with context and alternatives considered.
Changelog
See CHANGELOG.md for the version history.
Code of Conduct
This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community. For more information see the Code of Conduct.
Contributing
See the Contributing guide for developer documentation.
Credits
API documentation generated by
- XmlDocMarkdown, Copyright (c) 2024 Ed Ball
- See an unrefined customization to contain header and other adjustments in project XmlDocMarkdownGenerator
License
Copyright 2023 @ Fernando Cerqueira
HealthCheckPlus is licensed under the MIT license. See LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- HealthCheckPlus.Abstractions (>= 4.0.0)
-
net8.0
- HealthCheckPlus.Abstractions (>= 4.0.0)
-
net9.0
- HealthCheckPlus.Abstractions (>= 4.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated | |
|---|---|---|---|
| 4.0.0 | 40 | 8/20/2026 | |
| 3.0.1 | 374 | 11/14/2025 | |
| 3.0.0 | 677 | 3/26/2025 | |
| 2.0.1 | 3,932 | 2/26/2024 | |
| 2.0.0 | 283 | 2/24/2024 | |
| 2.0.0-beta2 | 237 | 2/20/2024 | |
| 2.0.0-beta1 | 224 | 2/19/2024 | |
| 2.0.0-beta | 223 | 2/19/2024 | |
| 1.0.5 | 303 | 1/29/2024 | |
| 1.0.4 | 388 | 11/14/2023 | |
| 1.0.3 | 411 | 9/28/2023 | |
| 1.0.2 | 1,799 | 2/8/2023 | |
| 1.0.1 | 461 | 2/6/2023 | |
| 1.0.0 | 514 | 2/6/2023 |