Files
sundynix-agentix/sundynix-gateway/internal/middleware/observability_test.go
T
Blizzard b6a6875795 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>
2026-06-19 10:38:31 +08:00

49 lines
1.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package middleware
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/prometheus/client_golang/prometheus/testutil"
)
func newEngine() *gin.Engine {
gin.SetMode(gin.TestMode)
r := gin.New()
r.Use(RequestID(), Observe())
r.GET("/ping", func(c *gin.Context) { c.String(http.StatusOK, "pong") })
return r
}
func TestObserve_CountsAndRequestID(t *testing.T) {
r := newEngine()
before := testutil.ToFloat64(httpRequests.WithLabelValues("GET", "/ping", "200"))
w := httptest.NewRecorder()
r.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/ping", nil))
if w.Code != 200 {
t.Fatalf("状态码=%d", w.Code)
}
if w.Header().Get("X-Request-ID") == "" {
t.Error("应自动生成并回写 X-Request-ID")
}
after := testutil.ToFloat64(httpRequests.WithLabelValues("GET", "/ping", "200"))
if after != before+1 {
t.Errorf("请求计数应 +1before=%v after=%v", before, after)
}
}
func TestRequestID_PropagatesIncoming(t *testing.T) {
r := newEngine()
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/ping", nil)
req.Header.Set("X-Request-ID", "trace-abc-123")
r.ServeHTTP(w, req)
if got := w.Header().Get("X-Request-ID"); got != "trace-abc-123" {
t.Errorf("应透传入站 X-Request-IDgot %q", got)
}
}