--- title: Health checks in ASP.NET Core author: guardrex description: Learn how to set up health checks for ASP.NET Core infrastructure, such as apps and databases. monikerRange: '>= aspnetcore-2.2' ms.author: riande ms.custom: mvc ms.date: 12/03/2018 uid: host-and-deploy/health-checks --- # Health checks in ASP.NET Core By [Luke Latham](https://github.com/guardrex) and [Glenn Condron](https://github.com/glennc) ASP.NET Core offers Health Check Middleware and libraries for reporting the health of app infrastructure components. Health checks are exposed by an app as HTTP endpoints. Health check endpoints can be configured for a variety of real-time monitoring scenarios: * Health probes can be used by container orchestrators and load balancers to check an app's status. For example, a container orchestrator may respond to a failing health check by halting a rolling deployment or restarting a container. A load balancer might react to an unhealthy app by routing traffic away from the failing instance to a healthy instance. * Use of memory, disk, and other physical server resources can be monitored for healthy status. * Health checks can test an app's dependencies, such as databases and external service endpoints, to confirm availability and normal functioning. [View or download sample code](https://github.com/aspnet/Docs/tree/master/aspnetcore/host-and-deploy/health-checks/samples) ([how to download](xref:index#how-to-download-a-sample)) The sample app includes examples of the scenarios described in this topic. To run the sample app for a given scenario, use the [dotnet run](/dotnet/core/tools/dotnet-run) command from the project's folder in a command shell. See the sample app's *README.md* file and the scenario descriptions in this topic for details on how to use the sample app. ## Prerequisites Health checks are usually used with an external monitoring service or container orchestrator to check the status of an app. Before adding health checks to an app, decide on which monitoring system to use. The monitoring system dictates what types of health checks to create and how to configure their endpoints. Reference the [Microsoft.AspNetCore.App metapackage](xref:fundamentals/metapackage-app) or add a package reference to the [Microsoft.AspNetCore.Diagnostics.HealthChecks](https://www.nuget.org/packages/Microsoft.AspNetCore.Diagnostics.HealthChecks) package. The sample app provides start-up code to demonstrate health checks for several scenarios. The [database probe](#database-probe) scenario probes the health of a database connection using [BeatPulse](https://github.com/Xabaril/BeatPulse). The [DbContext probe](#entity-framework-core-dbcontext-probe) scenario probes a database using an EF Core `DbContext`. To explore the database scenarios using the sample app: * Create a database and provide its connection string in the *appsettings.json* file of the app. * Add a package reference to [AspNetCore.HealthChecks.SqlServer](https://www.nuget.org/packages/AspNetCore.HealthChecks.SqlServer/). > [!NOTE] > [BeatPulse](https://github.com/Xabaril/BeatPulse) isn't maintained or supported by Microsoft. Another health check scenario demonstrates how to filter health checks to a management port. The sample app requires you to create a *Properties/launchSettings.json* file that includes the management URL and management port. For more information, see the [Filter by port](#filter-by-port) section. ## Basic health probe For many apps, a basic health probe configuration that reports the app's availability to process requests (*liveness*) is sufficient to discover the status of the app. The basic configuration registers health check services and calls the Health Check Middleware to respond at a URL endpoint with a health response. By default, no specific health checks are registered to test any particular dependency or subsystem. The app is considered healthy if it's capable of responding at the health endpoint URL. The default response writer writes the status (`HealthStatus`) as a plaintext response back to the client, indicating either a `HealthStatus.Healthy`, `HealthStatus.Degraded` or `HealthStatus.Unhealthy` status. Register health check services with `AddHealthChecks` in `Startup.ConfigureServices`. Add Health Check Middleware with `UseHealthChecks` in the request processing pipeline of `Startup.Configure`. In the sample app, the health check endpoint is created at `/health` (*BasicStartup.cs*): [!code-csharp[](health-checks/samples/2.x/HealthChecksSample/BasicStartup.cs?name=snippet1&highlight=5,10)] To run the basic configuration scenario using the sample app, execute the following command from the project's folder in a command shell: ```console dotnet run --scenario basic ``` ### Docker example [Docker](xref:host-and-deploy/docker/index) offers a built-in `HEALTHCHECK` directive that can be used to check the status of an app that uses the basic health check configuration: ``` HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit ``` ## Create health checks Health checks are created by implementing the `IHealthCheck` interface. The `IHealthCheck.CheckHealthAsync` method returns a `Task` that indicates the health as `Healthy`, `Degraded`, or `Unhealthy`. The result is written as a plaintext response with a configurable status code (configuration is described in the [Health check options](#health-check-options) section). `HealthCheckResult` can also return optional key-value pairs. ### Example health check The following `ExampleHealthCheck` class demonstrates the layout of a health check: ```csharp public class ExampleHealthCheck : IHealthCheck { public ExampleHealthCheck() { // Use dependency injection (DI) to supply any required services to the // health check. } public Task CheckHealthAsync( HealthCheckContext context, CancellationToken cancellationToken = default(CancellationToken)) { // Execute health check logic here. This example sets a dummy // variable to true. var healthCheckResultHealthy = true; if (healthCheckResultHealthy) { return Task.FromResult( HealthCheckResult.Healthy("The check indicates a healthy result.")); } return Task.FromResult( HealthCheckResult.Unhealthy("The check indicates an unhealthy result.")); } } ``` ### Register health check services The `ExampleHealthCheck` type is added to health check services with `AddCheck`: ```csharp public void ConfigureServices(IServiceCollection services) { services.AddHealthChecks() .AddCheck("example_health_check"); } ``` The `AddCheck` overload shown in the following example sets the failure status (`HealthStatus`) to report when the health check reports a failure. If the failure status is set to `null` (default), `HealthStatus.Unhealthy` is reported. This overload is a useful scenario for library authors, where the failure status indicated by the library is enforced by the app when a health check failure occurs if the health check implementation honors the setting. *Tags* can be used to filter health checks (described further in the [Filter health checks](#filter-health-checks) section). ```csharp services.AddHealthChecks() .AddCheck( "example_health_check", failureStatus: HealthStatus.Degraded, tags: new[] { "example" }); ``` `AddCheck` can also execute a lambda function. In the following example, the health check name is specified as `Example` and the check always returns a healthy state: ```csharp public void ConfigureServices(IServiceCollection services) { services.AddHealthChecks() .AddCheck("Example", () => HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" }) } ``` ### Use Health Checks Middleware In `Startup.Configure`, call `UseHealthChecks` in the processing pipeline with the endpoint URL or relative path: ```csharp public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseHealthChecks("/health"); } ``` If the health checks should listen on a specific port, use an overload of `UseHealthChecks` to set the port (described further in the [Filter by port](#filter-by-port) section): ```csharp app.UseHealthChecks("/health", port: 8000); ``` Health Checks Middleware is a *terminal middleware* in the app's request processing pipeline. The first health check endpoint encountered that's an exact match to the request URL executes and short-circuits the rest of the middleware pipeline. When short-circuiting occurs, no middleware following the matched health check executes. ## Health check options `HealthCheckOptions` provide an opportunity to customize health check behavior: * [Filter health checks](#filter-health-checks) * [Customize the HTTP status code](#customize-the-http-status-code) * [Suppress cache headers](#suppress-cache-headers) * [Customize output](#customize-output) ### Filter health checks By default, Health Check Middleware runs all registered health checks. To run a subset of health checks, provide a function that returns a boolean to the `Predicate` option. In the following example, the `Bar` health check is filtered out by its tag (`bar_tag`) in the function's conditional statement, where `true` is only returned if the health check's `Tag` property matches `foo_tag` or `baz_tag`: ```csharp using System.Threading.Tasks; using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.Extensions.Diagnostics.HealthChecks; public void ConfigureServices(IServiceCollection services) { services.AddHealthChecks() .AddCheck("Foo", () => HealthCheckResult.Healthy("Foo is OK!"), tags: new[] { "foo_tag" }) .AddCheck("Bar", () => HealthCheckResult.Unhealthy("Bar is unhealthy!"), tags: new[] { "bar_tag" }) .AddCheck("Baz", () => HealthCheckResult.Healthy("Baz is OK!"), tags: new[] { "baz_tag" }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseHealthChecks("/health", new HealthCheckOptions() { // Filter out the 'Bar' health check. Only Foo and Baz execute. Predicate = (check) => check.Tags.Contains("foo_tag") || check.Tags.Contains("baz_tag") }); } ``` ### Customize the HTTP status code Use `ResultStatusCodes` to customize the mapping of health status to HTTP status codes. The following `StatusCode` assignments are the default values used by the middleware. Change the status code values to meet your requirements. ```csharp using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.Extensions.Diagnostics.HealthChecks; public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseHealthChecks("/health", new HealthCheckOptions() { // The following StatusCodes are the default assignments for // the HealthStatus properties. ResultStatusCodes = { [HealthStatus.Healthy] = StatusCodes.Status200OK, [HealthStatus.Degraded] = StatusCodes.Status200OK, [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable } }); } ``` ### Suppress cache headers `AllowCachingResponses` controls whether the Health Check Middleware adds HTTP headers to a probe response to prevent response caching. If the value is `false` (default), the middleware sets or overrides the `Cache-Control`, `Expires`, and `Pragma` headers to prevent response caching. If the value is `true`, the middleware doesn't modify the cache headers of the response. ```csharp using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.Extensions.Diagnostics.HealthChecks; public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseHealthChecks("/health", new HealthCheckOptions() { // The default value is false. AllowCachingResponses = false }); } ``` ### Customize output The `ResponseWriter` option gets or sets a delegate used to write the response. The default delegate writes a minimal plaintext response with the string value of `HealthReport.Status`. ```csharp using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.Extensions.Diagnostics.HealthChecks; public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseHealthChecks("/health", new HealthCheckOptions() { // WriteResponse is a delegate used to write the response. ResponseWriter = WriteResponse }); } private static Task WriteResponse(HttpContext httpContext, HealthReport result) { httpContext.Response.ContentType = "application/json"; var json = new JObject( new JProperty("status", result.Status.ToString()), new JProperty("results", new JObject(result.Entries.Select(pair => new JProperty(pair.Key, new JObject( new JProperty("status", pair.Value.Status.ToString()), new JProperty("description", pair.Value.Description), new JProperty("data", new JObject(pair.Value.Data.Select( p => new JProperty(p.Key, p.Value)))))))))); return httpContext.Response.WriteAsync( json.ToString(Formatting.Indented)); } ``` ## Database probe A health check can specify a database query to run as a boolean test to indicate if the database is responding normally. The sample app uses [BeatPulse](https://github.com/Xabaril/BeatPulse), a health check library for ASP.NET Core apps, to perform a health check on a SQL Server database. BeatPulse executes a `SELECT 1` query against the database to confirm the connection to the database is healthy. > [!WARNING] > When checking a database connection with a query, choose a query that returns quickly. The query approach runs the risk of overloading the database and degrading its performance. In most cases, running a test query isn't necessary. Merely making a successful connection to the database is sufficient. If you find it necessary to run a query, choose a simple SELECT query, such as `SELECT 1`. In order to use the BeatPulse library, include a package reference to [AspNetCore.HealthChecks.SqlServer](https://www.nuget.org/packages/AspNetCore.HealthChecks.SqlServer/). Supply a valid database connection string in the *appsettings.json* file of the sample app. The app uses a SQL Server database named `HealthCheckSample`: [!code-json[](health-checks/samples/2.x/HealthChecksSample/appsettings.json?highlight=3)] Register health check services with `AddHealthChecks` in `Startup.ConfigureServices`. The sample app calls BeatPulse's `AddSqlServer` method with the database's connection string (*DbHealthStartup.cs*): [!code-csharp[](health-checks/samples/2.x/HealthChecksSample/DbHealthStartup.cs?name=snippet_ConfigureServices)] Call Health Check Middleware in the app processing pipeline in `Startup.Configure`: [!code-csharp[](health-checks/samples/2.x/HealthChecksSample/DbHealthStartup.cs?name=snippet_Configure)] To run the database probe scenario using the sample app, execute the following command from the project's folder in a command shell: ```console dotnet run --scenario db ``` > [!NOTE] > [BeatPulse](https://github.com/Xabaril/BeatPulse) isn't maintained or supported by Microsoft. ## Entity Framework Core DbContext probe The `DbContext` check is supported in apps that use [Entity Framework (EF) Core](/ef/core/). This check confirms that the app can communicate with the database configured for an EF Core `DbContext`. By default, the `DbContextHealthCheck` calls EF Core's `CanConnectAsync` method. You can customize what operation is run when checking health using overloads of the `AddDbContextCheck` method. `AddDbContextCheck` registers a health check for a `DbContext` (`TContext`). By default, the name of the health check is the name of the `TContext` type. An overload is available to configure the failure status, tags, and a custom test query. In the sample app, `AppDbContext` is provided to `AddDbContextCheck` and registered as a service in `Startup.ConfigureServices`. *DbContextHealthStartup.cs*: [!code-csharp[](health-checks/samples/2.x/HealthChecksSample/DbContextHealthStartup.cs?name=snippet_ConfigureServices)] In the sample app, `UseHealthChecks` adds the Health Check Middleware in `Startup.Configure`. *DbContextHealthStartup.cs*: [!code-csharp[](health-checks/samples/2.x/HealthChecksSample/DbContextHealthStartup.cs?name=snippet_Configure)] To run the `DbContext` probe scenario using the sample app, confirm that the database specified by the the connection string doesn't exist in the SQL Server instance. If the database exists, delete it. Execute the following command from the project's folder in a command shell: ```console dotnet run --scenario dbcontext ``` After the app is running, check the health status by making a request to the `/health` endpoint in a browser. The database and `AppDbContext` don't exist, so app provides the following response: ``` Unhealthy ``` Trigger the sample app to create the database. Make a request to `/createdatabase`. The app responds: ``` Creating the database... Done! Navigate to /health to see the health status. ``` Make a request to the `/health` endpoint. The database and context exist, so app responds: ``` Healthy ``` Trigger the sample app to delete the database. Make a request to `/deletedatabase`. The app responds: ``` Deleting the database... Done! Navigate to /health to see the health status. ``` Make a request to the `/health` endpoint. The app provides an unhealthy response: ``` Unhealthy ``` ## Separate readiness and liveness probes In some hosting scenarios, a pair of health checks are used that distinguish two app states: * The app is functioning but not yet ready to receive requests. This state is the app's *readiness*. * The app is functioning and responding to requests. This state is the app's *liveness*. The readiness check usually performs a more extensive and time-consuming set of checks to determine if all of the app's subsystems and resources are available. A liveness check merely performs a quick check to determine if the app is available to process requests. After the app passes its readiness check, there's no need to burden the app further with the expensive set of readiness checks—further checks only require checking for liveness. The sample app contains a health check to report the completion of long-running startup task in a [Hosted Service](xref:fundamentals/host/hosted-services). The `StartupHostedServiceHealthCheck` exposes a property, `StartupTaskCompleted`, that the hosted service can set to `true` when its long-running task is finished (*StartupHostedServiceHealthCheck.cs*): [!code-csharp[](health-checks/samples/2.x/HealthChecksSample/StartupHostedServiceHealthCheck.cs?name=snippet1&highlight=5)] The long-running background task is started by a [Hosted Service](xref:fundamentals/host/hosted-services) (*Services/StartupHostedService*). At the conclusion of the task, `StartupHostedServiceHealthCheck.StartupTaskCompleted` is set to `true`: [!code-csharp[](health-checks/samples/2.x/HealthChecksSample/Services/StartupHostedService.cs?name=snippet1&highlight=18-20)] The health check is registered with `AddCheck` in `Startup.ConfigureServices` along with the hosted service. Because the hosted service must set the property on the health check, the health check is also registered in the service container (*LivenessProbeStartup.cs*): [!code-csharp[](health-checks/samples/2.x/HealthChecksSample/LivenessProbeStartup.cs?name=snippet_ConfigureServices)] Call Health Check Middleware in the app processing pipeline in `Startup.Configure`. In the sample app, the health check endpoints are created at `/health/ready` for the readiness check and `/health/live` for the liveness check. The readiness check filters health checks to the health check with the `ready` tag. The liveness check filters out the `StartupHostedServiceHealthCheck` by returning `false` in the `HealthCheckOptions.Predicate` (for more information, see [Filter health checks](#filter-health-checks)): [!code-csharp[](health-checks/samples/2.x/HealthChecksSample/LivenessProbeStartup.cs?name=snippet_Configure)] To run the readiness/liveness configuration scenario using the sample app, execute the following command from the project's folder in a command shell: ```console dotnet run --scenario liveness ``` In a browser, visit `/health/ready` several times until 15 seconds have passed. The health check reports `Unhealthy` for the first 15 seconds. After 15 seconds, the endpoint reports `Healthy`, which reflects the completion of the long-running task by the hosted service. ### Kubernetes example Using separate readiness and liveness checks is useful in an environment such as [Kubernetes](https://kubernetes.io/). In Kubernetes, an app might be required to perform time-consuming startup work before accepting requests, such as a test of the underlying database availability. Using separate checks allows the orchestrator to distinguish whether the app is functioning but not yet ready or if the app has failed to start. For more information on readiness and liveness probes in Kubernetes, see [Configure Liveness and Readiness Probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/) in the Kubernetes documentation. The following example demonstrates a Kubernetes readiness probe configuration: ``` spec: template: spec: readinessProbe: # an http probe httpGet: path: /health/ready port: 80 # length of time to wait for a pod to initialize # after pod startup, before applying health checking initialDelaySeconds: 30 timeoutSeconds: 1 ports: - containerPort: 80 ``` ## Metric-based probe with a custom response writer The sample app demonstrates a memory health check with a custom response writer. `MemoryHealthCheck` reports a degraded status if the app uses more than a given threshold of memory (1 GB in the sample app). The `HealthCheckResult` includes Garbage Collector (GC) information for the app (*MemoryHealthCheck.cs*): [!code-csharp[](health-checks/samples/2.x/HealthChecksSample/MemoryHealthCheck.cs?name=snippet1)] Register health check services with `AddHealthChecks` in `Startup.ConfigureServices`. Instead of enabling the health check by passing it to `AddCheck`, the `MemoryHealthCheck` is registered as a service. All `IHealthCheck` registered services are available to the health check services and middleware. We recommend registering health check services as Singleton services. *CustomWriterStartup.cs*: [!code-csharp[](health-checks/samples/2.x/HealthChecksSample/CustomWriterStartup.cs?name=snippet_ConfigureServices&highlight=4)] Call Health Check Middleware in the app processing pipeline in `Startup.Configure`. A `WriteResponse` delegate is provided to the `ResponseWriter` property to output a custom JSON response when the health check executes: [!code-csharp[](health-checks/samples/2.x/HealthChecksSample/CustomWriterStartup.cs?name=snippet_Configure&highlight=6)] The `WriteResponse` method formats the `CompositeHealthCheckResult` into a JSON object and yields JSON output for the health check response: [!code-csharp[](health-checks/samples/2.x/HealthChecksSample/CustomWriterStartup.cs?name=snippet_WriteResponse)] To run the metric-based probe with custom response writer output using the sample app, execute the following command from the project's folder in a command shell: ```console dotnet run --scenario writer ``` > [!NOTE] > [BeatPulse](https://github.com/Xabaril/BeatPulse) includes metric-based health check scenarios, including disk storage and maximum value liveness checks. > > [BeatPulse](https://github.com/Xabaril/BeatPulse) isn't maintained or supported by Microsoft. ## Filter by port Calling `UseHealthChecks` with a port restricts health check requests to the port specified. This is typically used in a container environment to expose a port for monitoring services. The sample app configures the port using the [Environment Variable Configuration Provider](xref:fundamentals/configuration/index#environment-variables-configuration-provider). The port is set in the *launchSettings.json* file and passed to the configuration provider via an environment variable. You must also configure the server to listen to requests on the management port. To use the sample app to demonstrate management port configuration, create the *launchSettings.json* file in a *Properties* folder. The following *launchSettings.json* file isn't included in the sample app's project files and must be created manually. *Properties/launchSettings.json*: ```json { "profiles": { "SampleApp": { "commandName": "Project", "commandLineArgs": "", "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", "ASPNETCORE_URLS": "http://localhost:5000/;http://localhost:5001/", "ASPNETCORE_MANAGEMENTPORT": "5001" }, "applicationUrl": "http://localhost:5000/" } } } ``` Register health check services with `AddHealthChecks` in `Startup.ConfigureServices`. The call to `UseHealthChecks` specifies the management port (*ManagementPortStartup.cs*): [!code-csharp[](health-checks/samples/2.x/HealthChecksSample/ManagementPortStartup.cs?name=snippet1&highlight=12,18)] > [!NOTE] > You can avoid creating the *launchSettings.json* file in the sample app by setting the URLs and management port explicitly in code. In *Program.cs* where the `WebHostBuilder` is created, add a call to `UseUrls` and provide the app's normal response endpoint and the management port endpoint. In *ManagementPortStartup.cs* where `UseHealthChecks` is called, specify the management port explicitly. > > *Program.cs*: > > ```csharp > return new WebHostBuilder() > .UseConfiguration(config) > .UseUrls("http://localhost:5000/;http://localhost:5001/") > .ConfigureLogging(builder => > { > builder.SetMinimumLevel(LogLevel.Trace); > builder.AddConfiguration(config); > builder.AddConsole(); > }) > .UseKestrel() > .UseStartup(startupType) > .Build(); > ``` > > *ManagementPortStartup.cs*: > > ```csharp > app.UseHealthChecks("/health", port: 5001); > ``` To run the management port configuration scenario using the sample app, execute the following command from the project's folder in a command shell: ```console dotnet run --scenario port ``` ## Distribute a health check library To distribute a health check as a library: 1. Write a health check that implements the `IHealthCheck` interface as a standalone class. The class can rely on [dependency injection (DI)](xref:fundamentals/dependency-injection), type activation, and [named options](xref:fundamentals/configuration/options) to access configuration data. ```csharp using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Diagnostics.HealthChecks; namespace SampleApp { public class ExampleHealthCheck : IHealthCheck { private readonly string _data1; private readonly int? _data2; public ExampleHealthCheck(string data1, int? data2) { _data1 = data1 ?? throw new ArgumentNullException(nameof(data1)); _data2 = data2 ?? throw new ArgumentNullException(nameof(data2)); } public async Task CheckHealthAsync( HealthCheckContext context, CancellationToken cancellationToken) { try { // Health check logic // // data1 and data2 are used in the method to // run the probe's health check logic. // Assume that it's possible for this health check // to throw an AccessViolationException. return HealthCheckResult.Healthy(); } catch (AccessViolationException ex) { return new HealthCheckResult( context.Registration.FailureStatus, description: "An access violation occurred during the check.", exception: ex, data: null); } } } } ``` 1. Write an extension method with parameters that the consuming app calls in its `Startup.Configure` method. In the following example, assume the following health check method signature: ```csharp ExampleHealthCheck(string, string, int ) ``` The preceding signature indicates that the `ExampleHealthCheck` requires additional data to process the health check probe logic. The data is provided to the delegate used to create the health check instance when the health check is registered with an extension method. In the following example, the caller specifies optional: * health check name (`name`). If `null`, `example_health_check` is used. * string data point for the health check (`data1`). * integer data point for the health check (`data2`). If `null`, `1` is used. * failure status (`HealthStatus`). The default is `null`. If `null`, `HealthStatus.Unhealthy` is reported for a failure status. * tags (`IEnumerable`). ```csharp using System.Collections.Generic; using Microsoft.Extensions.Diagnostics.HealthChecks; public static class ExampleHealthCheckBuilderExtensions { const string NAME = "example_health_check"; public static IHealthChecksBuilder AddExampleHealthCheck( this IHealthChecksBuilder builder, string name = default, string data1, int data2 = 1, HealthStatus? failureStatus = default, IEnumerable tags = default) { return builder.Add(new HealthCheckRegistration( name ?? NAME, sp => new ExampleHealthCheck(data1, data2), failureStatus, tags)); } } ``` ## Health Check Publisher When an `IHealthCheckPublisher` is added to the service container, the health check system periodically executes your health checks and calls `PublishAsync` with the result. This is useful in a push-based health monitoring system scenario that expects each process to call the monitoring system periodically in order to determine health. The `IHealthCheckPublisher` interface has a single method: ```csharp Task PublishAsync(HealthReport report, CancellationToken cancellationToken); ``` > [!NOTE] > [BeatPulse](https://github.com/Xabaril/BeatPulse) includes publishers for several systems, including [Application Insights](/azure/application-insights/app-insights-overview). > > [BeatPulse](https://github.com/Xabaril/BeatPulse) isn't maintained or supported by Microsoft.