A go implementation of the Health Checks API used for microservice exploration, documentation and monitoring.
OTHER License
A go implementation of the Health Checks API used for microservice exploration, documentation and monitoring.
Using the healthchecks
framework in your service is easy.
StatusEndpoint
for each dependency in your service.healthchecks
framework to respond to all /status/...
requests passing a slice of all your StatusEndpoint
s.StatusEndpoint
s correctly, the framework will take care of the rest.Example:
// Define a StatusEndpoint at '/status/db' for a database dependency
db := healthchecks.StatusEndpoint{
Name: "The DB",
Slug: "db",
Type: "internal",
IsTraversable: false,
StatusCheck: sqlsc.SQLDBStatusChecker{
DB: myDB
},
TraverseCheck: nil,
}
// Define a StatusEndpoint at '/status/service-organization' for the Organization service
org := healthchecks.StatusEndpoint{
Name: "Organization Service",
Slug: "service-organization",
Type: "http",
IsTraversable: true,
StatusCheck: httpsc.HttpStatusChecker{
BaseUrl: "[Read value from config]",
},
TraverseCheck: httpsc.HttpStatusChecker{
BaseUrl: "[Read value from config]",
},
}
// Define the list of StatusEndpoints for your service
statusEndpoints := []healthchecks.StatusEndpoint{ db, org }
// Set the path for the about and version files
aboutFilePath := "conf/about.json"
versionFilePath := "conf/version.txt"
// Set up any service injected customData for /status/about response.
// Values can be any valid JSON conversion and will override values set in about.json.
customData := make(map[string]interface{})
// Examples:
//
// String value
// customData["a-string"] = "some-value"
//
// Number value
// customData["a-number"] = 123
//
// Boolean value
// customData["a-bool"] = true
//
// Array
// customData["an-array"] = []string{"val1", "val2"}
//
// Custom object
// customObject := make(map[string]interface{})
// customObject["key1"] = 1
// customObject["key2"] = "some-value"
// customData["an-object"] = customObject
// Register all the "/status/..." requests to use our health checking framework
http.Handle("/status/", healthchecks.Handler(statusEndpoints, aboutFilePath, versionFilePath, customData))
A StatusCheck
is a struct which implements the function func CheckStatus(name string) StatusList
. A StatusCheck
is defined or used in
a service but executed by the healthchecks
framework. The key to a successful StatusCheck
is to handle all errors on the
dependency you are checking. Below is an example of a StatusCheck
that checks the connection of Redis
using the
gopkg.in/redis.v4
driver.
type RedisStatusChecker struct {
client RedisClient
}
func (r RedisStatusChecker) CheckStatus(name string) healthchecks.StatusList {
pong, err := r.client.Ping()
// Set a default response
s := healthchecks.Status{
Description: name,
Result: healthchecks.OK,
Details: "",
}
// Handle any errors that Ping() function returned
if err != nil {
s = healthchecks.Status{
Description: name,
Result: healthchecks.CRITICAL,
Details: err.Error(),
}
}
// Make sure the pong response is what we expected
if pong != "PONG" {
s = healthchecks.Status{
Description: name,
Result: healthchecks.CRITICAL,
Details: fmt.Sprintf("Expecting `PONG` response, got `%s`", pong),
}
}
// Return our response
return healthchecks.StatusList{ StatusList: []healthchecks.Status{ s }}
}
A TraverseCheck
is a struct which implements the function func Traverse(traversalPath []string, action string) (string, error)
.
A TraverseCheck
is defined or used in a service but executed by the healthchecks
framework. The key to a successful
TraverseCheck
is to build and execute the /status/traverse?action=[action]&dependencies=[dependencies]
request to
the service you are trying to traverse to and returning the response or error you got. Below is an example of a
TraverseCheck
for an HTTP service.
type HttpStatusChecker struct {
BaseUrl string
Name string
}
func (h HttpStatusChecker) Traverse(traversalPath []string, action string) (string, error) {
dependencies := ""
if len(traversalPath) > 0 {
dependencies = fmt.Sprintf("&dependencies=%s", strings.Join(traversalPath, ","))
}
// Build our HTTP request
url := fmt.Sprintf("%s/status/traverse?action=%s%s", h.BaseUrl, action, dependencies)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Printf("Error creating request: %s \n", err.Error())
return "", err
}
// Execute HTTP request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Printf("Error executing request: %s \n", err.Error())
return "", err
}
// Defer the closing of the body
defer resp.Body.Close()
// Read our response
responseBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("Error reading response body: %s", err.Error())
return "", err
}
// Return our response
return string(responseBody), nil
}
Contribute by submitting a PR and a bug report in GitHub.
healthchecks is released under the Apache License, Version 2.0. See LICENSE for details.