a9dea19531
Introduce health checking functionality with liveness and readiness endpoints to monitor the application's status. Implement a health checker that verifies database connectivity and provides a simple liveness check. Update service routing to use the new health checker functionality. Add corresponding unit tests for validation.
74 lines
1.7 KiB
Go
74 lines
1.7 KiB
Go
package health
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/json"
|
|
"log/slog"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
type Checker struct {
|
|
db *sql.DB
|
|
logger *slog.Logger
|
|
}
|
|
|
|
func New(db *sql.DB, logger *slog.Logger) *Checker {
|
|
return &Checker{
|
|
db: db,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
type HealthStatus struct {
|
|
Status string `json:"status"`
|
|
Checks map[string]string `json:"checks,omitempty"`
|
|
}
|
|
|
|
// LivenessHandler checks if the application is running
|
|
// This is a simple check that always returns OK if the handler is reached
|
|
func (h *Checker) LivenessHandler(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusOK)
|
|
_ = json.NewEncoder(w).Encode(HealthStatus{
|
|
Status: "UP",
|
|
})
|
|
}
|
|
|
|
// ReadinessHandler checks if the application is ready to accept traffic
|
|
// This checks database connectivity and other critical dependencies
|
|
func (h *Checker) ReadinessHandler(w http.ResponseWriter, r *http.Request) {
|
|
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
|
|
defer cancel()
|
|
|
|
checks := make(map[string]string)
|
|
allHealthy := true
|
|
|
|
// Check database connectivity
|
|
if err := h.db.PingContext(ctx); err != nil {
|
|
h.logger.With("error", err).Warn("database health check failed")
|
|
checks["database"] = "DOWN"
|
|
allHealthy = false
|
|
} else {
|
|
checks["database"] = "UP"
|
|
}
|
|
|
|
status := HealthStatus{
|
|
Status: "UP",
|
|
Checks: checks,
|
|
}
|
|
|
|
if !allHealthy {
|
|
status.Status = "DOWN"
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusServiceUnavailable)
|
|
_ = json.NewEncoder(w).Encode(status)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusOK)
|
|
_ = json.NewEncoder(w).Encode(status)
|
|
}
|