AspNetCore.Diagnostics.HealthChecks icon indicating copy to clipboard operation
AspNetCore.Diagnostics.HealthChecks copied to clipboard

Report endpoints that return 200 as healthy

Open maxkoshevoi opened this issue 3 years ago • 4 comments

Please, fill the following sections to help us fix the issue

What happened:

I have an endpoint that just returns 200 status code (without the body), and HealthChecks UI reports it as Unhealthy with following error:

Response is null or message can't be deserialized as HealthChecks.UI.Core.UIHealthReport.

image

What you expected to happen:

Endpoint status should be healthy

How to reproduce it (as minimally and precisely as possible):

Source code sample:

Anything else we need to know?:

Environment:

  • .NET Core version: 6
  • Healthchecks version: 6.0.4
  • Operative system: Windows
  • Others:

maxkoshevoi avatar May 18 '22 13:05 maxkoshevoi

  1. I think this is by design to require response body.
  2. What is the stacktrace of error?

sungam3r avatar May 24 '22 20:05 sungam3r

  1. I think this is by design to require response body.

Hm, in this case this might be a feature request to

  • Report endpoints that return 200 and no body as healthy
  • Report endpoints that return non-200 codes and invalid body as unhealthy, and threat whole body as a error message

I don't need this feature anymore (updated original endpoint to return json), but it still might be useful

maxkoshevoi avatar May 26 '22 09:05 maxkoshevoi

Hi @maxkoshevoi

Probably is some confusion here! The UI request for a specified endpoint with specified json body ( the result of healthcheck(s) on some app/service ), check a sample of healthcheck with the UI response writer

https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/blob/7b69de9ee3a4a2e8619b72015858bb16d6982f14/samples/HealthChecks.Sample/Startup.cs#L52

Internally, this endpoint response the information of healthchecks checked, ie, the endpoint added to the ui are not the final healtchecks, are endpoints with a specified response writer that show the results of regular healthchecks

See a sample on https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/blob/master/samples/HealthChecks.Sample/Startup.cs

unaizorrilla avatar May 26 '22 09:05 unaizorrilla

The UI request for a specified endpoint with specified json body

Yes, I get that. My issue is that I had a .Net Framework app that had custom health check implementation (that just returned 200 without the body). And I wanted to also display it on the UI.

Currently, I've updated my code to produce expected Json response using internal logic of AspNetCore.HealthChecks.UI.Core package, so I'm fine. But supporting different health check outputs would be nice (or if UI could be manually configured to interpret non-standard health results)

namespace MyFrameworkApp.HealthChecks
{
    public class HealthCheckService : IHealthCheckService
    {
        private readonly Dictionary<string, IHealthCheck> _healthChecks = new();

        public IHealthCheckService AddHealthCheck(string name, IHealthCheck healthCheck)
        {
            _healthChecks.Add(name, healthCheck);
            return this;
        }

        public async Task<IHttpActionResult> CheckOverallHealthAsync(ApiController controller)
        {
            var result = await CheckOverallHealthAsyncCore();
            return GetWebResponse(result, controller);
        }

        public async Task<HealthReport> CheckOverallHealthAsyncCore()
        {
            var totalTime = Stopwatch.StartNew();

            var entries = new Dictionary<string, HealthReportEntry>();
            foreach (var healthCheck in _healthChecks)
            {
                var entry = await RunCheckAsync(healthCheck.Value);
                entries.Add(healthCheck.Key, entry);
            }

            return new HealthReport(entries, totalTime.Elapsed);
        }

        private IHttpActionResult GetWebResponse(HealthReport report, ApiController controller)
        {
            var options = new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Ignore,
                Converters = { new StringEnumConverter() }
            };

            var uiReport = UIHealthReport.CreateFrom(report);
            return new JsonResult<UIHealthReport>(uiReport, options, Encoding.UTF8, controller);
        }

        private async Task<HealthReportEntry> RunCheckAsync(IHealthCheck healthCheck)
        {
            HealthReportEntry entry;

            var stopwatch = Stopwatch.StartNew();
            var context = new HealthCheckContext
            {
                Registration = new HealthCheckRegistration(string.Empty, healthCheck, HealthStatus.Unhealthy, Array.Empty<string>())
            };
            try
            {
                var checkResult = await healthCheck.CheckHealthAsync(context);
                entry = new HealthReportEntry(
                    status: checkResult.Status,
                    description: checkResult.Description,
                    duration: stopwatch.Elapsed,
                    exception: checkResult.Exception,
                    data: checkResult.Data);
            }
            catch (Exception ex)
            {
                entry = new HealthReportEntry(
                    status: HealthStatus.Unhealthy,
                    description: ex.Message,
                    duration: stopwatch.Elapsed,
                    exception: ex,
                    data: null);
            }

            return entry;
        }
    }
}

maxkoshevoi avatar May 26 '22 10:05 maxkoshevoi

Closed due to inactivity.

I do not think adding support for responses 200 OK without body serves much value now but if someone like - PR is welcome.

sungam3r avatar Jul 30 '23 05:07 sungam3r