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

health

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Sep 30, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package health provides comprehensive health check functionality for Forge microservices.

The health package implements Kubernetes-compatible health checks with support for both liveness and readiness probes. It provides concurrent health check execution, configurable timeouts, and detailed status reporting.

Health Check Types

The package supports two types of health checks:

  • Liveness: Indicates whether the application is alive and responding
  • Readiness: Indicates whether the application is ready to serve traffic

Basic Usage

Implement the Check interface for your dependencies:

type DatabaseCheck struct {
	db *sql.DB
}

func (c *DatabaseCheck) Name() string {
	return "database"
}

func (c *DatabaseCheck) Liveness(ctx context.Context) error {
	return c.db.PingContext(ctx)
}

func (c *DatabaseCheck) Readiness(ctx context.Context) error {
	// More comprehensive readiness check
	if err := c.db.PingContext(ctx); err != nil {
		return err
	}
	// Check if migrations are up to date, etc.
	return nil
}

Register checks with the health registry:

registry := health.NewRegistry(logger)
config := health.DefaultCheckConfig("database")
registry.Register(&DatabaseCheck{db: db}, config)

HTTP Endpoints

The framework automatically exposes health endpoints:

  • /health: Combined liveness and readiness status
  • /health/live: Liveness probe endpoint
  • /health/ready: Readiness probe endpoint

Concurrent Execution

All health checks are executed concurrently with proper timeout handling. Failed non-required checks don't affect overall service health.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AlwaysHealthyCheck

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

AlwaysHealthyCheck is a check that always reports healthy status. Useful for testing or as a placeholder.

func NewAlwaysHealthyCheck

func NewAlwaysHealthyCheck(name string) *AlwaysHealthyCheck

NewAlwaysHealthyCheck creates a check that always reports healthy.

func (*AlwaysHealthyCheck) Liveness

func (c *AlwaysHealthyCheck) Liveness(ctx context.Context) error

Liveness always returns nil (healthy).

func (*AlwaysHealthyCheck) Name

func (c *AlwaysHealthyCheck) Name() string

Name returns the name of the check.

func (*AlwaysHealthyCheck) Readiness

func (c *AlwaysHealthyCheck) Readiness(ctx context.Context) error

Readiness always returns nil (healthy).

type AlwaysUnhealthyCheck

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

AlwaysUnhealthyCheck is a check that always reports unhealthy status. Useful for testing failure scenarios.

func NewAlwaysUnhealthyCheck

func NewAlwaysUnhealthyCheck(name string, err error) *AlwaysUnhealthyCheck

NewAlwaysUnhealthyCheck creates a check that always reports unhealthy.

func (*AlwaysUnhealthyCheck) Liveness

func (c *AlwaysUnhealthyCheck) Liveness(ctx context.Context) error

Liveness always returns an error (unhealthy).

func (*AlwaysUnhealthyCheck) Name

func (c *AlwaysUnhealthyCheck) Name() string

Name returns the name of the check.

func (*AlwaysUnhealthyCheck) Readiness

func (c *AlwaysUnhealthyCheck) Readiness(ctx context.Context) error

Readiness always returns an error (unhealthy).

type BasicCheck

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

BasicCheck provides a simple implementation of Check interface.

func NewBasicCheck

func NewBasicCheck(config CheckConfig, liveness, readiness func(ctx context.Context) error) *BasicCheck

NewBasicCheck creates a new BasicCheck.

func (*BasicCheck) Config

func (c *BasicCheck) Config() CheckConfig

Config returns the check configuration.

func (*BasicCheck) Liveness

func (c *BasicCheck) Liveness(ctx context.Context) error

Liveness performs the liveness check.

func (*BasicCheck) Name

func (c *BasicCheck) Name() string

Name returns the name of the health check.

func (*BasicCheck) Readiness

func (c *BasicCheck) Readiness(ctx context.Context) error

Readiness performs the readiness check.

type Check

type Check interface {
	// Name returns a unique name for this health check.
	Name() string

	// Liveness performs a liveness check. This should be a fast, lightweight
	// check that indicates whether the dependency is alive and responding.
	// A failed liveness check typically indicates a need for service restart.
	Liveness(ctx context.Context) error

	// Readiness performs a readiness check. This can be more comprehensive
	// than liveness and indicates whether the dependency is ready to serve
	// requests. A failed readiness check should result in the service being
	// marked as not ready (but still alive).
	Readiness(ctx context.Context) error
}

Check represents a health check that can be performed on a service dependency. Each check supports both liveness (is the dependency alive) and readiness (is the dependency ready to serve requests) semantics.

Implementations should be lightweight and fast, especially for liveness checks. Readiness checks can be more comprehensive but should still complete within the configured timeout.

Health checks are executed concurrently by the health registry, so implementations must be thread-safe.

type CheckConfig

type CheckConfig struct {
	// Name is the unique name of the health check
	Name string

	// Required indicates whether this check is required for readiness.
	// If true, the service will not be marked as ready until this check passes.
	Required bool

	// Timeout is the maximum time to wait for the health check to complete.
	Timeout time.Duration

	// Interval is how often to perform the check (for periodic checks).
	Interval time.Duration

	// InitialDelay is how long to wait before performing the first check.
	InitialDelay time.Duration
}

CheckConfig contains common configuration for health checks. Use DefaultCheckConfig() as a starting point and customize as needed.

The Required field determines whether a failed check affects overall service health:

  • Required=true: Service is unhealthy if this check fails
  • Required=false: Check failure is logged but doesn't affect service health

Timeout applies to both liveness and readiness checks for this specific check. The health registry also enforces an overall timeout for all checks combined.

func DefaultCheckConfig

func DefaultCheckConfig(name string) CheckConfig

DefaultCheckConfig returns a CheckConfig with sensible defaults. All checks are marked as required by default with a 5-second timeout and 30-second check interval for periodic monitoring.

Customize the returned config as needed:

config := health.DefaultCheckConfig("database")
config.Required = false  // Make non-critical
config.Timeout = 10 * time.Second  // Longer timeout

type CheckResult

type CheckResult struct {
	Name      string    `json:"name"`
	Status    Status    `json:"status"`
	Message   string    `json:"message,omitempty"`
	Error     string    `json:"error,omitempty"`
	Duration  string    `json:"duration"`
	Timestamp time.Time `json:"timestamp"`
	Required  bool      `json:"required"`
}

CheckResult represents the result of executing a health check.

func NewCheckResult

func NewCheckResult(name string, required bool, duration time.Duration, err error) CheckResult

NewCheckResult creates a new CheckResult.

func (CheckResult) IsHealthy

func (r CheckResult) IsHealthy() bool

IsHealthy returns true if the check result indicates a healthy status.

func (CheckResult) Redacted added in v0.3.0

func (r CheckResult) Redacted() CheckResult

Redacted returns a copy of the CheckResult with the raw Error detail removed. Error strings from dependency checks (e.g. database or cache connectivity failures) can embed internal topology such as hostnames, IPs, and ports, so they must not be exposed over unauthenticated interfaces like the public HTTP health endpoints. The check name and Status remain, which is all an external caller needs; the full detail is still available internally (e.g. to the background runner's logs).

type HealthySummary

type HealthySummary struct {
	Total     int `json:"total"`
	Healthy   int `json:"healthy"`
	Unhealthy int `json:"unhealthy"`
	Required  int `json:"required"`
}

HealthySummary provides a summary of healthy vs unhealthy checks.

type Logger

type Logger interface {
	Debug(msg string, fields ...any)
	Info(msg string, fields ...any)
	Warn(msg string, fields ...any)
	Error(msg string, fields ...any)
}

Logger interface for health check logging.

type NoopLogger

type NoopLogger struct{}

NoopLogger is a logger that does nothing.

func (NoopLogger) Debug

func (NoopLogger) Debug(msg string, fields ...any)

Debug discards a debug-level message.

func (NoopLogger) Error

func (NoopLogger) Error(msg string, fields ...any)

Error discards an error-level message.

func (NoopLogger) Info

func (NoopLogger) Info(msg string, fields ...any)

Info discards an info-level message.

func (NoopLogger) Warn

func (NoopLogger) Warn(msg string, fields ...any)

Warn discards a warning-level message.

type Registry

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

Registry manages a collection of health checks and provides methods to check the overall health status of a service.

By default, Registry computes results live on every call (the original behavior, and what unit tests and direct library use still get). Calling Start runs checks in the background on their configured Interval and serves cached results instead, so a probe read never blocks on a slow or hanging dependency check.

func NewRegistry

func NewRegistry(logger Logger) *Registry

NewRegistry creates a new health check registry.

func (*Registry) CheckConfig added in v0.3.0

func (r *Registry) CheckConfig(name string) (CheckConfig, bool)

CheckConfig returns the configuration for a specific check.

func (*Registry) CheckHealth

func (r *Registry) CheckHealth(ctx context.Context) Report

CheckHealth performs both liveness and readiness checks and returns combined results.

When the background runner is active, both sides are built from a single cached snapshot (one lock acquisition) rather than two serialized live rounds of every check.

func (*Registry) CheckLiveness

func (r *Registry) CheckLiveness(ctx context.Context) Report

CheckLiveness performs liveness checks on all registered health checks.

If the background runner is active, this serves the latest cached results instead of computing them live.

func (*Registry) CheckReadiness

func (r *Registry) CheckReadiness(ctx context.Context) Report

CheckReadiness performs readiness checks on all registered health checks.

If the background runner is active, this serves the latest cached results instead of computing them live.

func (*Registry) IsReady

func (r *Registry) IsReady() bool

IsReady returns true if the service has been explicitly marked as ready.

func (*Registry) MustRegister

func (r *Registry) MustRegister(check Check, config CheckConfig)

MustRegister registers a health check and panics if registration fails.

func (*Registry) Register

func (r *Registry) Register(check Check, config CheckConfig) error

Register registers a health check with the registry.

If the background runner is already started (see Start), the new check is picked up immediately and scheduled on its own goroutine so that checks registered after startup still get background execution.

func (*Registry) RegisteredChecks added in v0.3.0

func (r *Registry) RegisteredChecks() []string

RegisteredChecks returns the names of all registered checks.

func (*Registry) SetReady

func (r *Registry) SetReady(ready bool)

SetReady marks the service as ready. This affects the overall readiness status.

func (*Registry) Start added in v0.3.0

func (r *Registry) Start(ctx context.Context) error

Start launches the background check runner: one goroutine per registered check that waits its CheckConfig.InitialDelay, runs an immediate round, and then re-runs on CheckConfig.Interval until Stop is called or ctx is done. Once started, CheckLiveness/CheckReadiness/CheckHealth serve the cached results from these rounds instead of computing live, so a probe read is never blocked by a slow or hanging dependency.

Start is not safe to call twice without an intervening Stop.

func (*Registry) Stop added in v0.3.0

func (r *Registry) Stop(ctx context.Context) error

Stop cancels all background runner goroutines and waits for them to exit, or for ctx to be done, whichever comes first. It is safe to call even if Start was never called. After Stop returns (with a nil error), no runner goroutines remain.

func (*Registry) Unregister

func (r *Registry) Unregister(name string)

Unregister removes a health check from the registry.

If the background runner is active, the check's goroutine notices the removal on its next tick (or initial round) and exits on its own; there is nothing further to clean up here.

type Report added in v0.3.0

type Report struct {
	Status    Status                 `json:"status"`
	Message   string                 `json:"message,omitempty"`
	Timestamp time.Time              `json:"timestamp"`
	Details   map[string]CheckResult `json:"details,omitempty"`
	Service   string                 `json:"service,omitempty"`
	Version   string                 `json:"version,omitempty"`
	Uptime    string                 `json:"uptime,omitempty"`
}

Report represents the overall health status of a service, including aggregated results from individual health checks.

func NewHealthyReport added in v0.3.0

func NewHealthyReport(message string) Report

NewHealthyReport creates a new healthy status with the given message.

func NewUnhealthyReport added in v0.3.0

func NewUnhealthyReport(message string) Report

NewUnhealthyReport creates a new unhealthy status with the given message.

func NewUnknownReport added in v0.3.0

func NewUnknownReport(message string) Report

NewUnknownReport creates a new unknown status with the given message.

func (Report) FailedChecks added in v0.3.0

func (h Report) FailedChecks() []CheckResult

FailedChecks returns a slice of check results that failed.

func (Report) HTTPStatus added in v0.3.0

func (h Report) HTTPStatus() int

HTTPStatus returns the appropriate HTTP status code for this health status.

func (Report) HealthySummary added in v0.3.0

func (h Report) HealthySummary() HealthySummary

HealthySummary returns a summary of the health check results.

func (Report) IsHealthy added in v0.3.0

func (h Report) IsHealthy() bool

IsHealthy returns true if the overall status is healthy.

func (Report) IsLive added in v0.3.0

func (h Report) IsLive() bool

IsLive returns true if the status indicates the service is alive. For liveness checks, we consider the service live if it's not explicitly unhealthy.

func (Report) IsReady added in v0.3.0

func (h Report) IsReady() bool

IsReady returns true if the status indicates the service is ready to serve requests. This is an alias for IsHealthy for readiness checks.

func (Report) JSON added in v0.3.0

func (h Report) JSON() ([]byte, error)

JSON returns the JSON representation of the health status.

func (Report) Redacted added in v0.3.0

func (h Report) Redacted() Report

Redacted returns a copy of the Report safe for exposure over unauthenticated interfaces such as the public HTTP health endpoints. Every entry in Details has its raw error detail stripped via CheckResult.Redacted, while the overall Status, Message, and per-check name/status/duration/required metadata are preserved.

func (Report) RequiredFailedChecks added in v0.3.0

func (h Report) RequiredFailedChecks() []CheckResult

RequiredFailedChecks returns a slice of required check results that failed.

func (Report) String added in v0.3.0

func (h Report) String() string

String returns a string representation of the health status.

func (Report) WithService added in v0.3.0

func (h Report) WithService(service string) Report

WithService sets the service name on the health status.

func (Report) WithUptime added in v0.3.0

func (h Report) WithUptime(uptime time.Duration) Report

WithUptime sets the uptime on the health status.

func (Report) WithVersion added in v0.3.0

func (h Report) WithVersion(version string) Report

WithVersion sets the version on the health status.

type Status

type Status string

Status represents the status of a health check.

const (
	StatusHealthy   Status = "healthy"
	StatusUnhealthy Status = "unhealthy"
	StatusUnknown   Status = "unknown"
)

type StatusResponse

type StatusResponse struct {
	Status  Status `json:"status"`
	Message string `json:"message,omitempty"`
}

StatusResponse is a simplified response for basic health checks.

func NewStatusResponse

func NewStatusResponse(status Report) StatusResponse

NewStatusResponse creates a new status response from a health status.

func (StatusResponse) HTTPStatus

func (s StatusResponse) HTTPStatus() int

HTTPStatus returns the appropriate HTTP status code.

func (StatusResponse) JSON

func (s StatusResponse) JSON() ([]byte, error)

JSON returns the JSON representation of the status response.

Jump to

Keyboard shortcuts

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