Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NetCore 2.2 - Health Check Support #1058

Open
say25 opened this issue Mar 6, 2019 · 3 comments

Comments

@say25
Copy link
Contributor

@say25 say25 commented Mar 6, 2019

Feature Request

Support for NetCore 2.2 Health Checks

Description

I have health checks set up using the new NetCore 2.2 health checks yet they do not show in Swagger UI. Can we add support for this to Swashbuckle.AspNetCore?

@domaindrivendev

This comment has been minimized.

Copy link
Owner

@domaindrivendev domaindrivendev commented Apr 8, 2019

Swashbuckle is built on top of ApiExplorer, the API metadata component, that ships with ASP.NET Core.

If health-checks endpoints aren't surfaced by that, then they won't be surfaced by Swashbuckle. This is a fundamental aspect to the SB design and is unlikely to change anytime soon.

IMO, this sounds like a perfect candidate for a community add-on package (see https://github.com/domaindrivendev/Swashbuckle.AspNetCore#community-packages).

If there was a willing contributor, they could start a new project called Swashbuckle.AspNetCore.HealthChecks, that exposes an extension method on SwaggerGenOptions for enabling the functionality - e.g. EnableHealthCheckDescriptions. Then behind the scenes, this could be implemented as a Document Filter (see readme) that adds the relevant Operation descriptions to the Swagger/OAI document generated by Swashbuckle.

@tomkerkhove

This comment has been minimized.

Copy link
Contributor

@tomkerkhove tomkerkhove commented Jul 3, 2019

For those interested in this, you can expose a pass-through API endpoint based on HealthCheckService which is used behind the scenes via AddHealthChecks:

 [Route("api/v1/health")]
public class HealthController : Controller
{
    private readonly HealthCheckService _healthCheckService;
    public HealthController(HealthCheckService healthCheckService)
    {
        _healthCheckService = healthCheckService;
    }

    /// <summary>
    ///     Get Health
    /// </summary>
    /// <remarks>Provides an indication about the health of the API</remarks>
    [HttpGet]
    [ProducesResponseType(typeof(HealthReport), (int)HttpStatusCode.OK)]
    [SwaggerOperation(OperationId = "Health_Get")]
    [SwaggerResponse((int)HttpStatusCode.OK, Description = "API is healthy")]
    [SwaggerResponse((int)HttpStatusCode.ServiceUnavailable, Description = "API is not healthy")]
    public async Task<IActionResult> Get()
    {
        var report = await _healthCheckService.CheckHealthAsync();
        return report.Status == HealthStatus.Healthy ? Ok(report) : StatusCode((int)HttpStatusCode.ServiceUnavailable, report);
    }
}
@markshoe

This comment has been minimized.

Copy link

@markshoe markshoe commented Oct 22, 2019

I took a similar approach to @tomkerkhove, but since I wanted to retain the ability to customize the response using the HealthCheckOptions.ResponseWriter and use the ActionResult pattern, I created a HealthCheckActionResult

    public class HealthCheckActionResult : ActionResult
    {
        private readonly HealthCheckOptions _healthCheckOptions;
        private readonly HealthCheckService _healthCheckService;

        public HealthCheckActionResult(HealthCheckService healthCheckService, HealthCheckOptions healthCheckOptions)
        {
            _healthCheckOptions = healthCheckOptions;
            _healthCheckService = healthCheckService;
        }

        public HealthReport HealthReport { get; private set; }

        public override async Task ExecuteResultAsync(ActionContext context)
        {
            HealthReport = await _healthCheckService.CheckHealthAsync(_healthCheckOptions.Predicate, context.HttpContext.RequestAborted);
            context.HttpContext.Response.StatusCode = _healthCheckOptions.ResultStatusCodes[HealthReport.Status];
            await _healthCheckOptions.ResponseWriter(context.HttpContext, HealthReport);
        }
    }

And then in my controller,

        private readonly HealthCheckService _healthCheckService;
        private readonly HealthCheckOptions _healthCheckOptions;

        public DiagnosticsController(HealthCheckService healthCheckService, HealthCheckOptions healthCheckOptions = null)
        {
            _healthCheckService = healthCheckService ?? throw new ArgumentNullException(nameof(healthCheckService));
            _healthCheckOptions = healthCheckOptions ?? new HealthCheckOptions();
        }

        [HttpGet("healthcheck")]
        public HealthCheckActionResult GetHealthReport()
        {
            return new HealthCheckActionResult(_healthCheckService, _healthCheckOptions);
        }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.