Help us shape the future of Go! Take the 2026 Go Developer Survey

health

package module
v1.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 13, 2026 License: MIT Imports: 21 Imported by: 6

README

⚕ go-health

License GoDoc Releases Issues

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).

Example

ℹ️ The code below is minimal. There’s more to go-health, but this is enough to get something up and running.

Setting up Health Checks

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.

Checking the Health

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)
Command-Line Tool

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.

Using as a Docker Health Check

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.

Using as a Kubernetes Probe

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

Documentation

Overview

Package health contains health checking utilities.

The most interesting part of the API is Register (and RegisterFunc), which is a simple way to set up a health check for ‘anything’.

As soon as any health checks are registered a summary of them is served at http://0.0.0.0:9999.

For services there is `HealthCheckCommand()` to put (early) in `main()`, e.g:

if len(os.Args) >= 2 && os.Args[1] == "healthcheck" {
	health.Main()
}

Docker images can then use the following:

HEALTHCHECK --interval=10s --timeout=30s CMD ./app healthcheck

See <https://inadarei.github.io/rfc-healthcheck/>.

Example
package main

import (
	"context"

	"github.com/dotse/go-health"
)

func main() {
	ctx := context.Background()

	// Register an instance of some type that implements HealthChecker:
	m := new(MyTypeWithHealthCheck)
	health.Register(ctx, "mytype", m)

	// Register a function:
	r := health.RegisterFunc(ctx, "func", func(context.Context) (checks []health.Check) {
		// Checkers can return any number of checks.
		for range 3 {
			var check health.Check
			// Make the relevant changes to `check` here, most importantly
			// `check.Status`.
			checks = append(checks, check)
		}

		return checks
	})
	defer r.Deregister()
}

type MyTypeWithHealthCheck struct{}

func (*MyTypeWithHealthCheck) CheckHealth(context.Context) []health.Check {
	return []health.Check{{}}
}

Index

Examples

Constants

View Source
const (
	// ExitErr is the exit code on failure.
	ExitErr = 1
	// ExitUser is the exit code when the user did something wrong.
	ExitUser = 2
)
View Source
const (
	// ComponentTypeComponent is ‘component’.
	ComponentTypeComponent = "component"
	// ComponentTypeDatastore is ‘datastore’.
	ComponentTypeDatastore = "datastore"
	// ComponentTypeSystem is ‘system’.
	ComponentTypeSystem = "system"
)
View Source
const (
	// ContentType is the media (MIME) type returned by the server.
	ContentType = "application/health+json"
	// EnvHealthPort is ‘HEALTH_PORT’; the environment variable to configure the
	// health check HTTP port.
	EnvHealthPort = "HEALTH_PORT"
)

Variables

This section is empty.

Functions

func DeregisterAll added in v0.4.0

func DeregisterAll()

DeregisterAll removes all previously registered health checkers.

func HandleHTTP added in v0.3.0

func HandleHTTP(w http.ResponseWriter, req *http.Request)

HandleHTTP serves a health response over HTTP. It supports the GET, HEAD and OPTIONS methods as well as content negotiation.

func Main added in v0.3.0

func Main(ctx context.Context)

Main is a utility for services that exits the current process with 0 or 1 for a healthy or unhealthy state, respectively.

func StartServer added in v0.3.0

func StartServer(ctx context.Context) error

StartServer starts an HTTP server at 0.0.0.0:${HEALTH_PORT:-9999} serving health checks. Can be called multiple times but will only start one server.

Will block until the server is listening.

The server will be stopped when the passed context.Context is cancelled.

Types

type Check

type Check struct {
	ComponentID       string     `json:"componentId,omitempty"`
	ComponentType     string     `json:"componentType,omitempty"`
	ObservedValue     any        `json:"observedValue,omitempty"`
	ObservedUnit      string     `json:"observedUnit,omitempty"`
	Status            Status     `json:"status"`
	AffectedEndpoints []string   `json:"affectedEndpoints,omitempty"`
	Time              *time.Time `json:"time,omitempty"`
	Output            string     `json:"output,omitempty"`
	Links             []string   `json:"links,omitempty"`
}

Check represent a single health check point.

func (*Check) Good

func (check *Check) Good() bool

Good returns true if the Check is good, i.e. its status is ‘pass’ or ‘warn’.

func (*Check) SetObservedTime

func (check *Check) SetObservedTime(duration time.Duration)

SetObservedTime sets the observedValue field to a time duration (and the observedUnit field to the correct unit).

type Checker

type Checker interface {
	CheckHealth(ctx context.Context) (checks []Check)
}

Checker can be implemented by anything whose health can be checked.

type CheckerFunc added in v0.3.0

type CheckerFunc func(context.Context) []Check

CheckerFunc is a wrapper for a function that implements Checker.

func (CheckerFunc) CheckHealth added in v0.3.0

func (f CheckerFunc) CheckHealth(ctx context.Context) []Check

CheckHealth implements Checker by calling the CheckerFunc.

func (CheckerFunc) LogValue added in v0.3.0

func (f CheckerFunc) LogValue() slog.Value

type Option added in v0.3.0

type Option interface {
	// contains filtered or unexported methods
}

Option is an optional configuration for CheckHealth.

func WithHost added in v0.3.0

func WithHost(host string) Option

WithHost is an Option for CheckHealth to specify the host.

func WithPort added in v0.3.0

func WithPort(port uint16) Option

WithPort is an Option for CheckHealth to specify the port number.

func WithTimeout added in v0.3.0

func WithTimeout(timeout time.Duration) Option

WithTimeout is an Option for CheckHealth to specify a timeout. See net/http.Client.Timeout.

type Registered

type Registered struct {
	// contains filtered or unexported fields
}

Registered is returned when registering a health check. It can be used to deregister that particular check at a later time, e.g. when closing whatever is being checked.

func Register

func Register(ctx context.Context, name string, checker Checker) Registered

Register registers a health checker.

func RegisterFunc

func RegisterFunc(
	ctx context.Context,
	name string,
	f func(context.Context) []Check,
) Registered

RegisterFunc registers a health check function.

func RegisterSQLConn added in v0.3.0

func RegisterSQLConn(
	ctx context.Context,
	conn *sql.Conn,
	name string,
	base Check,
) Registered

func RegisterSQLDB added in v0.3.0

func RegisterSQLDB(
	ctx context.Context,
	db *sql.DB,
	name string,
	base Check,
) Registered

func (Registered) Deregister

func (r Registered) Deregister()

Deregister removes a previously registered health checker.

type Response

type Response struct {
	Status      Status             `json:"status"`
	Version     string             `json:"version,omitempty"`
	ReleaseID   string             `json:"releaseId,omitempty"`
	Notes       []string           `json:"notes,omitempty"`
	Output      string             `json:"output,omitempty"`
	Checks      map[string][]Check `json:"checks,omitempty"`
	Links       []string           `json:"links,omitempty"`
	ServiceID   string             `json:"serviceID,omitempty"`
	Description string             `json:"description,omitempty"`
}

Response represents a health check response, containing any number of Checks.

func CheckHealth

func CheckHealth(ctx context.Context, options ...Option) (*Response, error)

CheckHealth gets a Response from an HTTP server.

Example
package main

import (
	"context"
	"fmt"
	"time"

	"github.com/dotse/go-health"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// The server can be started before registering…
	if err := health.StartServer(ctx); err != nil {
		panic(err)
	}

	// Set up a checker so that there’s something to report.
	r := health.RegisterFunc(ctx, "example", func(context.Context) []health.Check {
		return []health.Check{{
			Status: health.StatusPass,
			Output: "all good",
		}}
	})
	defer r.Deregister()

	// …or after. (Subsequent StartServer()s do nothing.)
	if err := health.StartServer(ctx); err != nil {
		panic(err)
	}

	// Get the current health status of a server running at localhost. More
	// configuration is possible.
	resp, err := health.CheckHealth(ctx, health.WithTimeout(time.Minute))
	if resp == nil || err != nil {
		panic(err)
	}

	fmt.Printf(
		`
resp.Status: %q
resp.Checks["example"][0].Status: %q
resp.Checks["example"][0].Output: %q
err: %v
`,
		resp.Status,
		resp.Checks["example"][0].Status,
		resp.Checks["example"][0].Output,
		err,
	)

}
Output:
resp.Status: "pass"
resp.Checks["example"][0].Status: "pass"
resp.Checks["example"][0].Output: "all good"
err: <nil>

func CheckNow added in v0.3.0

func CheckNow(ctx context.Context) (resp Response, err error)

CheckNow returns the current (local) health status accumulated from all registered health checkers.

func ReadResponse

func ReadResponse(r io.Reader) (*Response, error)

ReadResponse reads a JSON Response from an io.Reader.

func (*Response) AddChecks

func (resp *Response) AddChecks(name string, checks ...Check)

AddChecks adds Checks to a Response and sets the status of the Response to the ‘worst’ status.

func (*Response) Good

func (resp *Response) Good() bool

Good returns true if the Response is good, i.e. its status is ‘pass’ or ‘warn’.

func (*Response) Write

func (resp *Response) Write(w io.Writer) (int64, error)

Write writes a JSON Response to an io.Writer.

type Status

type Status uint8

Status is the status part of a Response or Check.

const (
	// StatusPass is ‘pass’.
	StatusPass Status = iota
	// StatusWarn is ‘warn’.
	StatusWarn Status = iota
	// StatusFail is ‘fail’.
	StatusFail Status = iota
)

func WorstStatus

func WorstStatus(status Status, statuses ...Status) (worst Status)

WorstStatus returns the worst of a number of statuses, where ‘warn’ is worse than ‘pass’ but ‘fail’ is worse than ‘warn’.

func (Status) MarshalJSON

func (status Status) MarshalJSON() ([]byte, error)

MarshalJSON encodes a status as a JSON string.

func (Status) MarshalText

func (status Status) MarshalText() ([]byte, error)

MarshalText encodes a status as a string.

func (Status) String

func (status Status) String() string

String turns a status into a string.

func (*Status) UnmarshalJSON

func (status *Status) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes a status from a JSON string.

Directories

Path Synopsis
cmd
healthcheck command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL