65dc805eb5
- 前端: ESLint+Prettier配置、Tailwind v4配置、ErrorBoundary、全局AuthLoader优化、ReactQuery分层 - 后端: MinIO凭证移除、Docker统一为govai品牌、zerolog日志封装、错误码枚举、文件上传校验、单元测试(13项全通过) - 运维: 健康检查增强(PG/Redis ping)、Prometheus指标(/metrics端点)、多租户tenant包、RateLimit nil防御 - 移动: citation_prompt.txt → internal/assets/
85 lines
1.9 KiB
Go
85 lines
1.9 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
"runtime"
|
|
"time"
|
|
|
|
"github.com/enterprise-ai-platform/server/internal/response"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
"github.com/redis/go-redis/v9"
|
|
)
|
|
|
|
type HealthHandler struct {
|
|
pool *pgxpool.Pool
|
|
rdb *redis.Client
|
|
}
|
|
|
|
func NewHealthHandler(pool *pgxpool.Pool, rdb *redis.Client) *HealthHandler {
|
|
return &HealthHandler{pool: pool, rdb: rdb}
|
|
}
|
|
|
|
func (h *HealthHandler) HealthCheck(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
|
|
type dep struct {
|
|
Name string `json:"name"`
|
|
Status string `json:"status"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
deps := []dep{}
|
|
|
|
// PostgreSQL
|
|
if h.pool != nil {
|
|
if err := h.pool.Ping(ctx); err != nil {
|
|
deps = append(deps, dep{Name: "postgres", Status: "down", Error: err.Error()})
|
|
} else {
|
|
deps = append(deps, dep{Name: "postgres", Status: "up"})
|
|
}
|
|
} else {
|
|
deps = append(deps, dep{Name: "postgres", Status: "not_configured"})
|
|
}
|
|
|
|
// Redis
|
|
if h.rdb != nil {
|
|
if err := h.rdb.Ping(ctx).Err(); err != nil {
|
|
deps = append(deps, dep{Name: "redis", Status: "down", Error: err.Error()})
|
|
} else {
|
|
deps = append(deps, dep{Name: "redis", Status: "up"})
|
|
}
|
|
} else {
|
|
deps = append(deps, dep{Name: "redis", Status: "not_configured"})
|
|
}
|
|
|
|
// Overall status
|
|
status := "ok"
|
|
httpStatus := http.StatusOK
|
|
for _, d := range deps {
|
|
if d.Status == "down" {
|
|
status = "degraded"
|
|
httpStatus = http.StatusServiceUnavailable
|
|
break
|
|
}
|
|
}
|
|
|
|
// Runtime stats
|
|
var m runtime.MemStats
|
|
runtime.ReadMemStats(&m)
|
|
|
|
response.JSON(w, httpStatus, map[string]any{
|
|
"status": status,
|
|
"service": "govai-portal-api",
|
|
"uptime": time.Since(startTime).String(),
|
|
"go": runtime.Version(),
|
|
"memory": map[string]any{
|
|
" Alloc": m.Alloc / 1024 / 1024,
|
|
"Sys": m.Sys / 1024 / 1024,
|
|
"NumGC": m.NumGC,
|
|
"Goroutine": runtime.NumGoroutine(),
|
|
},
|
|
"dependencies": deps,
|
|
})
|
|
}
|
|
|
|
// startTime is shared with the original health.go init block.
|
|
var startTime = time.Now() |