feat(gateway): 可观测性 —— Prometheus 指标 + 结构化日志 + 探针
往"生产可运维"推一步(网关前门):
- Prometheus /metrics:sundynix_http_requests_total{method,route,status}、
request_duration_seconds 直方图、requests_in_flight。route 用 c.FullPath()
路由模板(/tasks/:id/...)避免按真实路径高基数。
- 结构化访问日志:slog JSON 到 stderr(request_id/method/route/status/latency_ms/
ip/uid/bytes),替代 gin 默认文本日志;gin.New()+Recovery 自管中间件链。
- RequestID 中间件:生成/透传 X-Request-ID,写上下文+响应头,供日志关联。
- 探针:/healthz(liveness,不查依赖)、/readyz(readiness,DB+Redis 就绪才 200,
否则 503),供 k8s 等导流判断;/api/v1/health 深度聚合保留。
- 三个根端点不挂业务鉴权(/metrics 生产应由网络层限制抓取来源)。
验证:单测(计数 +1 / X-Request-ID 生成与透传);实跑 /healthz 200、/readyz 200
(db,redis ready)、/metrics 输出真实指标、访问日志 JSON 正常、X-Request-ID 回写。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -95,6 +95,22 @@ func (h *Handler) StreamTask(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// Healthz: GET /healthz —— 存活探针(liveness):进程能应答即 200,不查依赖。
|
||||
func (h *Handler) Healthz(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
||||
}
|
||||
|
||||
// Readyz: GET /readyz —— 就绪探针(readiness):核心依赖(DB/Redis)可用才 200,否则 503。
|
||||
// 供 k8s 等编排器在依赖未就绪时暂不导流。NATS 在启动时即连(连不上会 fatal),故不单列。
|
||||
func (h *Handler) Readyz(c *gin.Context) {
|
||||
deps := gin.H{"db": h.db.Enabled(), "redis": h.cache.Enabled()}
|
||||
if h.db.Enabled() && h.cache.Enabled() {
|
||||
c.JSON(http.StatusOK, gin.H{"status": "ready", "deps": deps})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{"status": "not_ready", "deps": deps})
|
||||
}
|
||||
|
||||
// Health: GET /api/v1/health —— 聚合各依赖子系统健康,供桌面端顶栏五盏灯实时点亮。
|
||||
// gateway/db/redis/nats 网关本地可判;milvus/neo4j 经 mcp-go health 工具取(不可用则置否)。
|
||||
func (h *Handler) Health(c *gin.Context) {
|
||||
|
||||
Reference in New Issue
Block a user