health

package module
v0.2.4 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2023 License: MIT Imports: 7 Imported by: 9

README

go-health

License GoDoc Releases Issues

go-health is a Go library for easily 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. Simply implement the Checker interface:

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

type MyApplication struct {
    db sql.DB

    // ...
}

func (app *MyApplication) CheckHealth() []health.Check {
    c := health.Check{}
    if err := app.db.Ping(); 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(true, "my-application", app)
server.Start()

Either like the above, e.g. in main(), or the application could even register itself on creation. You can register as many times as you want. 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 := client.CheckHealth(c.config)
if err == nil {
    fmt.Printf("Status: %s\n", resp.Status)
} else {
    fmt.Printf("ERROR: %v\n", err)
}
Using as a Docker Health Check

An easy 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" {
        client.CheckHealthCommand()
    }

    // Your other code...
}

CheckHealthCommand() 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 few lines of code and your Docker image has a built-in health check for all the things you want monitored.

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" {
    client.CheckHealthCommand()
}

Docker images can then use the following:

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

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

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

// Register a function:
RegisterFunc("func", func() (checks []Check) {
	// Checkers can return any number of checks.
	for i := 0; i < 3; i++ {
		var check Check
		// Make the relevant changes to `check` here, most importantly
		// `check.Status`.
		checks = append(checks, check)
	}
	return
})
Output:

Index

Examples

Constants

View Source
const (
	// ComponentTypeComponent is "component".
	ComponentTypeComponent = "component"
	// ComponentTypeDatastore is "datastore".
	ComponentTypeDatastore = "datastore"
	// ComponentTypeSystem is "system".
	ComponentTypeSystem = "system"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Check

type Check struct {
	ComponentID       string      `json:"componentId,omitempty"`
	ComponentType     string      `json:"componentType,omitempty"`
	ObservedValue     interface{} `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() []Check
}

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

type Registered

type Registered string

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(name string, checker Checker) Registered

Register registers a health checker.

func RegisterFunc

func RegisterFunc(name string, f func() []Check) Registered

RegisterFunc registers a health check function.

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() (resp Response)

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

func CheckHealthContext added in v0.2.0

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

CheckHealthContext 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

Jump to

Keyboard shortcuts

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