go-health
is a Go library for setting up monitoring of anything within an
application. Anything that can have a health status can be registered, and then
an HTTP server can be started to serve a combined health status.
It follows the proposed standard Health Check Response Format for HTTP APIs
(but you don’t even have to know that, go-health
takes care of that for you).
ℹ️ The code below is minimal. There’s more to go-health
, but this is enough to
get something up and running.
Let’s say your application has a database handle, and you want to monitor that
it can actually communicate with the database. First implement the Checker
interface:
import (
"github.com/dotse/go-health"
)
type MyApplication struct {
conn Connection
// …
}
func (app *MyApplication) CheckHealth(ctx context.Context) []health.Check {
c := health.Check{}
if err := app.conn.Ping(ctx); err != nil{
c.Status = health.StatusFail
c.Output = err.Error()
}
return []health.Check{ c }
}
Then whenever you create your application register it as a health check:
app := NewMyApplication()
health.Register(ctx, "my-application", app)
health.StartServer(ctx)
Either like the above, e.g. in main()
, or the application could even register
itself on creation. You can register any number of checks. The reported health
status will be the ‘worst’ of all the registered checkers.
Then there will be an HTTP server listening on http://127.0.0.1:9999/ and serving a fresh health response on each request.
To then check the health, GET the response and look at its status
field.
go-health
has a function for this too:
resp, err := health.CheckNow(ctx)
if err != nil {
return err
}
fmt.Printf("Status: %s\n", resp.Status)
go-health
provides a command-line tool for health checking. To install it run:
go install github.com/dotse/go-health/cmd/healthcheck@latest
For usage documentation see usage.txt
.
A way to create a health check for a Docker image is to use the same binary as
your application to do the checking. E.g. if the application is invoked with the
first argument healthcheck
:
func main() {
// …
if os.Args[1] == "healthcheck" {
health.Main(ctx)
}
// Your other code, including health.StartServer(ctx)…
}
Main()
will GET the current health from the local HTTP server, parse the
response and os.Exit()
either 0 or 1, depending on the health.
Then in your Dockerfile
add:
HEALTHCHECK --interval=10s --timeout=30s CMD ./app healthcheck
💁 Voilà! A bit of code and your Docker image has a built-in health check for all the things you want monitored.
If your Kubernetes pod runs a health check server, e.g. using
health.StartServer(ctx)
, then probing it can be as little as:
spec:
containers:
- # …
ports:
- containerPort: 9999
name: health
livenessProbe:
httpGet:
port: health
readinessProbe:
httpGet:
port: health
startupProbe:
httpGet:
port: health