Files

108 lines
2.2 KiB
Go

package monitoring
import (
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// HealthStatus 健康状态
type HealthStatus string
const (
HealthStatusUP HealthStatus = "UP"
HealthStatusDOWN HealthStatus = "DOWN"
HealthStatusUNKNOWN HealthStatus = "UNKNOWN"
)
// HealthCheck 健康检查器
type HealthCheck struct {
db *gorm.DB
}
// NewHealthCheck 创建健康检查器
func NewHealthCheck(db *gorm.DB) *HealthCheck {
return &HealthCheck{db: db}
}
// Status 健康状态
type Status struct {
Status HealthStatus `json:"status"`
Checks map[string]CheckResult `json:"checks"`
}
// CheckResult 检查结果
type CheckResult struct {
Status HealthStatus `json:"status"`
Error string `json:"error,omitempty"`
}
// Check 执行健康检查
func (h *HealthCheck) Check() *Status {
status := &Status{
Status: HealthStatusUP,
Checks: make(map[string]CheckResult),
}
// 检查数据库
dbResult := h.checkDatabase()
status.Checks["database"] = dbResult
if dbResult.Status != HealthStatusUP {
status.Status = HealthStatusDOWN
}
return status
}
// checkDatabase 检查数据库
func (h *HealthCheck) checkDatabase() CheckResult {
if h == nil || h.db == nil {
return CheckResult{
Status: HealthStatusDOWN,
Error: "database not configured",
}
}
sqlDB, err := h.db.DB()
if err != nil {
return CheckResult{
Status: HealthStatusDOWN,
Error: err.Error(),
}
}
// Ping数据库
if err := sqlDB.Ping(); err != nil {
return CheckResult{
Status: HealthStatusDOWN,
Error: err.Error(),
}
}
return CheckResult{Status: HealthStatusUP}
}
// ReadinessHandler reports dependency readiness.
func (h *HealthCheck) ReadinessHandler(c *gin.Context) {
status := h.Check()
httpStatus := http.StatusOK
if status.Status != HealthStatusUP {
httpStatus = http.StatusServiceUnavailable
}
c.JSON(httpStatus, status)
}
// LivenessHandler reports process liveness without dependency checks.
func (h *HealthCheck) LivenessHandler(c *gin.Context) {
c.Status(http.StatusNoContent)
c.Writer.WriteHeaderNow()
}
// Handler keeps backward compatibility with the historical /health endpoint.
func (h *HealthCheck) Handler(c *gin.Context) {
h.ReadinessHandler(c)
}