Skip to content

Health Checks #462

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

Open
DigitalFlow opened this issue Jan 28, 2021 · 2 comments
Open

Health Checks #462

DigitalFlow opened this issue Jan 28, 2021 · 2 comments

Comments

@DigitalFlow
Copy link

Hi there,

I recently switched to Giraffe for my F# API needs and I am amazed so far.
We started on a simple .NET Core F# setup and Giraffe is very much an approvement.

What I am wondering however and what the docs don't seem to point out:
How to wrap the Health checks that you might have constructed with plain .NET Core?

Before it looked like this:

let configureServices (services : IServiceCollection) =
        services.AddCors()    |> ignore
        services.AddGiraffe() |> ignore

        services
            .AddHealthChecks()
            .AddCheck<BasicHealthCheck>("Basic_Health")
            .AddCheck<CdsHealthCheck>("Cds_Health_Check")
        |> ignore

and a health check looked like this:

namespace FunctionalWebAPI.Domain

open System.Threading.Tasks
open Microsoft.Extensions.Diagnostics.HealthChecks

type BasicHealthCheck() =
    interface IHealthCheck with
        member __.CheckHealthAsync(context, cancellationToken) =
            async { return new HealthCheckResult(HealthStatus.Healthy) }
            |> Async.StartAsTask

Now with Giraffe I changed it to this:

module FunctionalWebAPI.Domain.BasicHealthCheck

open Giraffe
open Microsoft.AspNetCore.Http
open FSharp.Control.Tasks.V2.ContextInsensitive
open Microsoft.Extensions.Diagnostics.HealthChecks

let getBasicHealth =
    fun (next : HttpFunc) (ctx : HttpContext) ->
        task {
            return! json (HealthCheckResult(HealthStatus.Healthy)) next ctx
        }

and route:

route "/health" >=> getBasicHealth

That works for one simple health check.
But now I have multiple ones. I tried to "fish my way through" like this

route "/health" >=> getBasicHealth >=> getExtendedHealth

but it is never executing "getExtendedHealth" , probably because getBasicHealth already returns a full json response.
In addition to that if composing would work, I would still need to compose the root health status, so an aggregated health of all checks.

There must be an easier way than combining them all myself, right?
Thanks for this framework and thanks for your help.

Kind Regards,
Florian

@dustinmoris
Copy link
Member

What do the different health checks do?

If you want different health checks then you can have multiple endpoints:

/health >=> healthCheck
/live >=> liveCheck
/ready >=> readyCheck

etc.

If multiple health checks share some code then move your code into a reusable function or dependency which can be called by all the different checks. I don't understand why there is a complete different abstraction for health checks when they are just some simple endpoints no different than all other code.

My honest recommendation would be to implement health endpoints like a normal endpoint and apply normal software patterns for code sharing and reusability if that is needed. It's going to be more readable and similar to the rest of the web app code which will make it easier to understand and maintain.

@DigitalFlow
Copy link
Author

Hi @dustinmoris,

thanks for your response.

They do not share code, but the thought was that I would apply this railway programming pattern, so that I return "Healthy" when getBasicHealth and getExtendedHealth both return healthy, but if getBasicHealth fails, I directly return "Unhealthy".

Kind Regards,
Florian

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants