From 4ff460d321dd9f94c83b09e83121e9d17a88d912 Mon Sep 17 00:00:00 2001 From: Bart Koelman <104792814+bart-vmware@users.noreply.github.com> Date: Tue, 27 Jan 2026 08:39:11 +0100 Subject: [PATCH 1/2] Enable skipping AspNet health checks at actuator endpoint --- .../Common/HealthChecks/HealthAggregator.cs | 8 ++-- .../Actuators/Health/HealthAggregationTest.cs | 47 +++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/Common/src/Common/HealthChecks/HealthAggregator.cs b/src/Common/src/Common/HealthChecks/HealthAggregator.cs index 972837e11d..8db7d89bfa 100644 --- a/src/Common/src/Common/HealthChecks/HealthAggregator.cs +++ b/src/Common/src/Common/HealthChecks/HealthAggregator.cs @@ -68,7 +68,10 @@ await Parallel.ForEachAsync(contributors, cancellationToken, async (contributor, private static async Task> AggregateMicrosoftHealthChecksAsync(ICollection contributors, ICollection healthCheckRegistrations, IServiceProvider serviceProvider, CancellationToken cancellationToken) { - if (healthCheckRegistrations.Count == 0) + HealthCheckRegistration[] activeHealthCheckRegistrations = + healthCheckRegistrations.Where(registration => !registration.Tags.Contains("SkipFromHealthActuator")).ToArray(); + + if (activeHealthCheckRegistrations.Length == 0) { return new Dictionary(); } @@ -76,8 +79,7 @@ private static async Task> Aggreg var healthChecks = new ConcurrentDictionary(); var keys = new ConcurrentBag(contributors.Select(contributor => contributor.Id)); - // run all HealthCheckRegistration checks in parallel - await Parallel.ForEachAsync(healthCheckRegistrations, cancellationToken, async (registration, _) => + await Parallel.ForEachAsync(activeHealthCheckRegistrations, cancellationToken, async (registration, _) => { string contributorName = GetKey(keys, registration.Name); SteeltoeHealthCheckResult healthCheckResult; diff --git a/src/Management/test/Endpoint.Test/Actuators/Health/HealthAggregationTest.cs b/src/Management/test/Endpoint.Test/Actuators/Health/HealthAggregationTest.cs index 216764db61..e80600e6ef 100644 --- a/src/Management/test/Endpoint.Test/Actuators/Health/HealthAggregationTest.cs +++ b/src/Management/test/Endpoint.Test/Actuators/Health/HealthAggregationTest.cs @@ -517,6 +517,53 @@ public async Task Converts_AspNet_health_check_results() """); } + [Fact] + public async Task Can_skip_AspNet_health_check() + { + WebApplicationBuilder builder = TestWebApplicationBuilderFactory.Create(); + builder.Configuration.AddInMemoryCollection(AppSettings); + builder.Services.AddHealthActuator(); + + IHealthChecksBuilder checksBuilder = builder.Services.AddHealthChecks(); + checksBuilder.AddCheck("aspnet-unhealthy-check", tags: ["SkipFromHealthActuator"]); + checksBuilder.AddCheck("aspnet-healthy-check"); + + await using WebApplication host = builder.Build(); + + host.MapHealthChecks("/health"); + await host.StartAsync(TestContext.Current.CancellationToken); + using HttpClient httpClient = host.GetTestClient(); + + HttpResponseMessage actuatorResponse = await httpClient.GetAsync(new Uri("http://localhost/actuator/health"), TestContext.Current.CancellationToken); + + actuatorResponse.StatusCode.Should().Be(HttpStatusCode.OK); + + string actuatorResponseBody = await actuatorResponse.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); + + actuatorResponseBody.Should().BeJson(""" + { + "status": "UP", + "components": { + "aspnet-healthy-check": { + "status": "UP", + "description": "healthy-description", + "details": { + "healthy-data-key": "healthy-data-value" + } + } + } + } + """); + + HttpResponseMessage aspNetResponse = await httpClient.GetAsync(new Uri("http://localhost/health"), TestContext.Current.CancellationToken); + + aspNetResponse.StatusCode.Should().Be(HttpStatusCode.ServiceUnavailable); + + string aspNetResponseBody = await aspNetResponse.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); + + aspNetResponseBody.Should().Be("Unhealthy"); + } + [Fact] public async Task Can_use_scoped_AspNet_health_check() { From 9d02258f43841500cee37b9894868fd7feea35dc Mon Sep 17 00:00:00 2001 From: Bart Koelman <104792814+bart-vmware@users.noreply.github.com> Date: Tue, 27 Jan 2026 15:32:47 +0100 Subject: [PATCH 2/2] Rename tag to ExcludeFromHealthActuator --- src/Common/src/Common/HealthChecks/HealthAggregator.cs | 2 +- .../Endpoint.Test/Actuators/Health/HealthAggregationTest.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Common/src/Common/HealthChecks/HealthAggregator.cs b/src/Common/src/Common/HealthChecks/HealthAggregator.cs index 8db7d89bfa..076928ed0b 100644 --- a/src/Common/src/Common/HealthChecks/HealthAggregator.cs +++ b/src/Common/src/Common/HealthChecks/HealthAggregator.cs @@ -69,7 +69,7 @@ private static async Task> Aggreg ICollection healthCheckRegistrations, IServiceProvider serviceProvider, CancellationToken cancellationToken) { HealthCheckRegistration[] activeHealthCheckRegistrations = - healthCheckRegistrations.Where(registration => !registration.Tags.Contains("SkipFromHealthActuator")).ToArray(); + healthCheckRegistrations.Where(registration => !registration.Tags.Contains("ExcludeFromHealthActuator")).ToArray(); if (activeHealthCheckRegistrations.Length == 0) { diff --git a/src/Management/test/Endpoint.Test/Actuators/Health/HealthAggregationTest.cs b/src/Management/test/Endpoint.Test/Actuators/Health/HealthAggregationTest.cs index e80600e6ef..ad76b9eaad 100644 --- a/src/Management/test/Endpoint.Test/Actuators/Health/HealthAggregationTest.cs +++ b/src/Management/test/Endpoint.Test/Actuators/Health/HealthAggregationTest.cs @@ -525,7 +525,7 @@ public async Task Can_skip_AspNet_health_check() builder.Services.AddHealthActuator(); IHealthChecksBuilder checksBuilder = builder.Services.AddHealthChecks(); - checksBuilder.AddCheck("aspnet-unhealthy-check", tags: ["SkipFromHealthActuator"]); + checksBuilder.AddCheck("aspnet-unhealthy-check", tags: ["ExcludeFromHealthActuator"]); checksBuilder.AddCheck("aspnet-healthy-check"); await using WebApplication host = builder.Build();