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)
|
||
|
|
}
|