health

package
v0.8.0 Latest Latest
Warning

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

Go to latest
Published: Aug 27, 2024 License: Apache-2.0 Imports: 10 Imported by: 2

Documentation

Overview

Package health contains a gRPC and an HTTP server providing application health related information.

Applications may use this package to provide liveness and readiness endpoints for Kubernetes probes.

Application version information is also made available which should be set at build time with the `-X` linker flag. This helps identify exactly which version of the application is healthy or not.

Example
package main

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"

	"github.com/anz-bank/pkg/health"
)

func main() {
	// normally set with go build linker option
	health.RepoURL = "https://github.com/anz-bank/pkg"
	health.CommitHash = "0123456789abcdef0123456789abcdef01234567"
	health.Semver = "v1.2.3"

	mux := http.NewServeMux()
	// register other handlers with mux

	err := health.RegisterWithHTTP(mux)
	if err != nil {
		log.Fatal(err)
	}

	// [run expensive initialisation]

	health.SetReady(true)

	// In this example, we call the handler directly using httptest.
	// Normally you would start a http server.
	// http.ListenAndServe(":9090", mux)
	w := httptest.NewRecorder()
	mux.ServeHTTP(w, httptest.NewRequest("GET", "/readyz", nil))
	mux.ServeHTTP(w, httptest.NewRequest("GET", "/version", nil))

	fmt.Print(w.Body.String())
}
Output:

200 ok
{
  "repo_url": "https://github.com/anz-bank/pkg",
  "commit_hash": "0123456789abcdef0123456789abcdef01234567",
  "build_log_url": "undefined",
  "container_tag": "undefined",
  "semver": "v1.2.3"
}

Index

Examples

Constants

View Source
const Undefined = "undefined"

Undefined is the default value for the version strings. It exists to make it clear that the values have not been supplied at build time, as opposed to the empty string that is a common build-time miscalculated value.

Variables

View Source
var (
	// RepoURL is the canonical repository source code URL.
	// e.g. https://github.com/anz-bank/pkg
	RepoURL = Undefined

	// CommitHash is the full git commit hash.
	// e.g. 1ee4e1f233caea38d6e331299f57dd86efb47361
	CommitHash = Undefined

	// BuildLogURL is the CI run URL.
	// e.g. https://github.com/anz-bank/pkg/actions/runs/84341844
	BuildLogURL = Undefined

	// ContainerTag is the canonical container image tag.
	// e.g. gcr.io/google-containers/hugo
	ContainerTag = Undefined

	// Semver is the semantic version compliant version.
	// e.g. v1.0.4
	Semver = Undefined

	// ScannerURLs is a JSON object containing URLs for additional code
	// scanner links.
	ScannerURLs string
)

Variables served by the Version endpoint/method. These should be set at build time using the `-X` ldflag. e.g.

go build -ldflags='-X github.com/anz-bank/pkg/health.RepoURL="..."`
View Source
var (
	// ErrInvalidSemver is a sentinel error returned when the Semver string
	// is not a valid semantic version string.
	ErrInvalidSemver = fmt.Errorf("invalid semver")
)

Errors defined and returned in this package.

Functions

func IsHealthEndpoint added in v0.0.12

func IsHealthEndpoint(r *http.Request) bool

IsHealthEndpoint returns true if the request is for one of our health check endpoints (/healthz or /readyz). It is intended to be used with the OpenCensus ochttp plugin to not trace health checks.

Use it in the ochttp.Handler:

ochttp.Handler{IsHealthEndpoint: health.IsHealthEndpoint, ...}

func RegisterWithGRPC added in v0.0.13

func RegisterWithGRPC(s *grpc.Server) error

RegisterWithGRPC registers the default server health.DefaultServer.GRPC with the given grpc Server to make the health service available at "anz.health.v1.Health". This RegisterWithGRPC function returns an error when the Version information is invalid.

func RegisterWithHTTP added in v0.0.13

func RegisterWithHTTP(r Router) error

RegisterWithHTTP registers the default server health.DefaultServer.HTTP with the given Router, e.g. a http.ServeMux, to make the health service endpoints available at /healthz, /readyz and /version. This RegisterWithHTTP function returns an error when the Version information is invalid.

func SetReady added in v0.0.13

func SetReady(ready bool)

SetReady sets the ready status served by the DefaultServer. The value can be changed as many times as is necessary over the lifetime of the application. It is valid to call SetReady before the DefaultServer has been registered, however a invalid version information will only be detected when RegisterWithHTTP or RegisterWithGRPC is called.

func SetReadyProvider added in v0.0.20

func SetReadyProvider(r ReadyProvider)

SetReadyProvider sets the ReadyProvider for the DefaultServer.

Types

type GRPCServer

type GRPCServer struct {
	*State
	pb.UnimplementedHealthServer // embedded for forward compatible implementations
}

GRPCServer implements a gRPC interface for the Health service serving the anz.health.v1.Health service.

func NewGRPCServer

func NewGRPCServer() (*GRPCServer, error)

NewGRPCServer returns a GRPCServer. If any of the package-level version variables are invalid, an error is returned.

Example
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/anz-bank/pkg/health"
	"github.com/anz-bank/pkg/health/pb"
)

func main() {
	server, err := health.NewGRPCServer()
	if err != nil {
		log.Fatal(err)
	}
	// go grpcListenAndServe(":8082", server)

	ctx := context.Background()
	resp, err := server.Ready(ctx, &pb.ReadyRequest{})
	fmt.Println("err:", err, "ready:", resp.Ready)

	// [run expensive initialisation]

	server.SetReady(true)

	resp, err = server.Ready(ctx, &pb.ReadyRequest{})
	fmt.Println("err:", err, "ready:", resp.Ready)
}
Output:

err: <nil> ready: false
err: <nil> ready: true

func (*GRPCServer) Alive

Alive implements the anz.health.v1.Health.Alive method returning an empty response. If the caller receives the response without error, it means that the application is alive.

func (*GRPCServer) Ready

Ready implements the anz.health.v1.Health.Ready method, returning a bool value indicating whether the application is ready to receive traffic. An application may become ready or not ready any number of times.

func (*GRPCServer) RegisterWith

func (g *GRPCServer) RegisterWith(s *grpc.Server)

RegisterWith registers the Health GRPCServer with the given grpc.Server.

func (*GRPCServer) Version

Version implements the anz.health.v1.Health.Version method, returning information to identify the running version of the application.

type HTTPServer

type HTTPServer struct {
	*State
	// contains filtered or unexported fields
}

HTTPServer implements an HTTP interface for the Health service at /healthz, /readyz and /version

func NewHTTPServer

func NewHTTPServer() (*HTTPServer, error)

NewHTTPServer returns an HTTPServer.

HTTPServer implements http.Handler and serves HTTP responses on the following paths:

/healthz
/readyz
/version

Use a custom http.Handler or http.ServerMux with HandleAlive, HandleReady and HandleVersion to serve on different URL paths.

If any of the package-level version variables are invalid, an error is returned.

Example
package main

import (
	"fmt"
	"log"
	"net/http/httptest"

	"github.com/anz-bank/pkg/health"
)

func main() {
	server, err := health.NewHTTPServer()
	if err != nil {
		log.Fatal(err)
	}
	// go http.ListenAndServe(":8082", server)

	r := httptest.NewRequest("GET", "/readyz", nil)
	w := httptest.NewRecorder()
	server.ServeHTTP(w, r)
	fmt.Print(w.Body.String())

	// [run expensive initialisation]

	server.SetReady(true)

	w = httptest.NewRecorder()
	server.ServeHTTP(w, r)
	fmt.Print(w.Body.String())
}
Output:

503 service unavailable
200 ok

func (*HTTPServer) HandleAlive

func (h *HTTPServer) HandleAlive(w http.ResponseWriter, r *http.Request)

HandleAlive returns a 200 OK response. If the caller receives this, it means that the application is alive. Any other response should be treated as the application not being alive.

func (*HTTPServer) HandleReady

func (h *HTTPServer) HandleReady(w http.ResponseWriter, r *http.Request)

HandleReady returns a 200 OK response if the application is ready to receive traffic. It returns a 503 Service Unavailable response if it is not ready to receive traffic. An application may become ready or not ready any number of times.

func (*HTTPServer) HandleVersion

func (h *HTTPServer) HandleVersion(w http.ResponseWriter, r *http.Request)

HandleVersion returns a 200 OK response with a JSON body containing the application version information. It is the JSON-serialised form of the health.pb.VersionResponse struct.

func (*HTTPServer) RegisterWith added in v0.0.9

func (h *HTTPServer) RegisterWith(r Router)

RegisterWith registers our handlers for /healthz, /readyz and /version with the given Router. This allows for sharing the root namespace with other paths and not requiring that the caller register each handler individually.

func (*HTTPServer) ServeHTTP

func (h *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler, handling GET requests for /healthz, /readyz and /version. Other methods on these paths will return 405 Method Not Allowed, and other paths will return 404 Not Found.

type ReadyProvider added in v0.0.18

type ReadyProvider interface {
	IsReady() bool
}

The ReadyProvider interface allows for the ready state to be provided from the outside in a pull fashion. Typically there is not need to make use of this interface and just update the Ready state with

State.SetReady(true|false)

However, if required, ReadyProvider can be specified as

State.ReadyProvider = localReadyProvider

this turns State.SetReady into a no-op unless localReadyProvider is also a ReadySetter.

type ReadySetter added in v0.0.18

type ReadySetter interface {
	SetReady(bool)
}

The ReadySetter interface is used in State.SetReady: If the State.ReadyProvider can be type asserted to be a ReadySetter it will be set. The default case wraps a boolean variable for setting and accessing.

type Router added in v0.0.9

type Router interface {
	Handle(path string, h http.Handler)
}

The Router interface allows HTTPServer.RegisterWith to work with any type of mux that implements the Handle method as defined on http.ServeMux.

type Server

type Server struct {
	*State
	GRPC *GRPCServer
	HTTP *HTTPServer
}

Server is a server that can serve health data via gRPC and HTTP.

var (
	// DefaultServer is the Server instance on which the package-level functions
	// operate. Most servers need only a single health server so this provides
	// a convenient definition of it that is available everywhere.
	DefaultServer *Server
)

func NewServer

func NewServer() (*Server, error)

NewServer returns a health.Server implementing a gRPC and an HTTP server, to serve a common set of underlying health data. If any of the package-level version variables are invalid, an error is returned.

Example
package main

import (
	"net"
	"net/http"

	"github.com/anz-bank/pkg/health"
	"google.golang.org/grpc"
)

func main() {
	server, _ := health.NewServer()
	go http.ListenAndServe(":8082", server.HTTP)

	gs := grpc.NewServer()
	server.GRPC.RegisterWith(gs)
	lis, _ := net.Listen("tcp", ":8080")
	go gs.Serve(lis)

	// [run expensive initialisation]

	server.SetReady(true)
}
Output:

type State added in v0.0.12

type State struct {
	ReadyProvider
	Version *pb.VersionResponse
}

State holds the state published by the health servers. Typically a single instance is shared amongst all servers.

func NewState added in v0.0.12

func NewState() (*State, error)

NewState returns a State with the global version variables set in the Version field, and Ready as false. If any of the global version variables cannot be parsed, an error is returned.

func (*State) SetReady added in v0.0.12

func (s *State) SetReady(ready bool)

SetReady sets the ready status served. The value can be changed as many times as is necessary over the lifetime of the application.

func (*State) SetReadyProvider added in v0.0.20

func (s *State) SetReadyProvider(r ReadyProvider)

SetReadyProvider sets the embedded ReadyProvider for state such that the ready value returned by state.IsReady() is ready from it.

Directories

Path Synopsis
Package ochealth exports health.State data via OpenCensus.
Package ochealth exports health.State data via OpenCensus.
Package otelhealth exports health.State data via OpenTelemetry.
Package otelhealth exports health.State data via OpenTelemetry.
Package pb provides protoc generated types and methods for Health service with Alive, Ready and Version methods.
Package pb provides protoc generated types and methods for Health service with Alive, Ready and Version methods.

Jump to

Keyboard shortcuts

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