112 lines
2.3 KiB
Go
112 lines
2.3 KiB
Go
package health
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// Response represents a health check response
|
|
type Response struct {
|
|
Status string `json:"status"`
|
|
Timestamp time.Time `json:"timestamp"`
|
|
Version string `json:"version,omitempty"`
|
|
Checks []Check `json:"checks,omitempty"`
|
|
}
|
|
|
|
// Check represents an individual health check
|
|
type Check struct {
|
|
Name string `json:"name"`
|
|
Status string `json:"status"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
// Handler handles health check requests
|
|
type Handler struct {
|
|
version string
|
|
checks []HealthChecker
|
|
}
|
|
|
|
// HealthChecker interface for health checks
|
|
type HealthChecker interface {
|
|
Name() string
|
|
Check() error
|
|
}
|
|
|
|
// NewHandler creates a new health check handler
|
|
func NewHandler(version string) *Handler {
|
|
return &Handler{
|
|
version: version,
|
|
checks: make([]HealthChecker, 0),
|
|
}
|
|
}
|
|
|
|
// AddCheck adds a health checker
|
|
func (h *Handler) AddCheck(checker HealthChecker) {
|
|
h.checks = append(h.checks, checker)
|
|
}
|
|
|
|
// ServeHTTP implements http.Handler
|
|
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
response := Response{
|
|
Status: "ok",
|
|
Timestamp: time.Now().UTC(),
|
|
Version: h.version,
|
|
Checks: make([]Check, 0, len(h.checks)),
|
|
}
|
|
|
|
allHealthy := true
|
|
for _, checker := range h.checks {
|
|
check := Check{
|
|
Name: checker.Name(),
|
|
Status: "ok",
|
|
}
|
|
|
|
if err := checker.Check(); err != nil {
|
|
check.Status = "error"
|
|
check.Error = err.Error()
|
|
allHealthy = false
|
|
}
|
|
|
|
response.Checks = append(response.Checks, check)
|
|
}
|
|
|
|
if !allHealthy {
|
|
response.Status = "error"
|
|
w.WriteHeader(http.StatusServiceUnavailable)
|
|
} else {
|
|
w.WriteHeader(http.StatusOK)
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(response)
|
|
}
|
|
|
|
// SimpleChecker is a basic health checker
|
|
type SimpleChecker struct {
|
|
name string
|
|
fn func() error
|
|
}
|
|
|
|
// NewSimpleChecker creates a new simple health checker
|
|
func NewSimpleChecker(name string, fn func() error) *SimpleChecker {
|
|
return &SimpleChecker{
|
|
name: name,
|
|
fn: fn,
|
|
}
|
|
}
|
|
|
|
// Name returns the checker name
|
|
func (c *SimpleChecker) Name() string {
|
|
return c.name
|
|
}
|
|
|
|
// Check performs the health check
|
|
func (c *SimpleChecker) Check() error {
|
|
return c.fn()
|
|
} |