Просмотр исходного кода

feat(metrics): Gin 中间件 - 活跃请求、延迟、状态码

master
fengsilin 3 недель назад
Родитель
Сommit
67e78f2c44
2 измененных файлов: 113 добавлений и 0 удалений
  1. +85
    -0
      common/metrics/metrics_test.go
  2. +28
    -0
      common/metrics/middleware.go

+ 85
- 0
common/metrics/metrics_test.go Просмотреть файл

@@ -1,8 +1,11 @@
package metrics

import (
"net/http/httptest"
"testing"
"time"

"github.com/gin-gonic/gin"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"
"github.com/stretchr/testify/assert"
@@ -121,3 +124,85 @@ func TestMetricsDisabledIsNoOp(t *testing.T) {
m.ActiveRequests.WithLabelValues("gpt-4").Inc()
m.RequestDuration.WithLabelValues("1", "gpt-4", "true", "chat").Observe(1.0)
}

func TestMetricsMiddleware_ActiveRequests(t *testing.T) {
gin.SetMode(gin.TestMode)
reg := newTestRegistry()
m := NewMetrics(reg)

r := gin.New()
r.Use(MetricsMiddleware(m))

blockCh := make(chan struct{})
r.GET("/test", func(c *gin.Context) {
<-blockCh
c.Status(200)
})

go func() {
req := httptest.NewRequest("GET", "/test", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
}()
go func() {
req := httptest.NewRequest("GET", "/test", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
}()

time.Sleep(100 * time.Millisecond)

assert.Equal(t, float64(2), testutil.ToFloat64(m.ActiveRequests.WithLabelValues("")))

close(blockCh)
time.Sleep(100 * time.Millisecond)

assert.Equal(t, float64(0), testutil.ToFloat64(m.ActiveRequests.WithLabelValues("")))
}

func TestMetricsMiddleware_RequestsTotalByCode(t *testing.T) {
gin.SetMode(gin.TestMode)
reg := newTestRegistry()
m := NewMetrics(reg)

r := gin.New()
r.Use(MetricsMiddleware(m))
r.GET("/200", func(c *gin.Context) { c.Status(200) })
r.GET("/400", func(c *gin.Context) { c.Status(400) })
r.GET("/500", func(c *gin.Context) { c.Status(500) })

for i := 0; i < 3; i++ {
req := httptest.NewRequest("GET", "/200", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
}
req := httptest.NewRequest("GET", "/400", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
req = httptest.NewRequest("GET", "/500", nil)
w = httptest.NewRecorder()
r.ServeHTTP(w, req)

assert.Equal(t, float64(3), testutil.ToFloat64(m.RequestsTotal.WithLabelValues("", "", "200", "", "")))
assert.Equal(t, float64(1), testutil.ToFloat64(m.RequestsTotal.WithLabelValues("", "", "400", "", "")))
assert.Equal(t, float64(1), testutil.ToFloat64(m.RequestsTotal.WithLabelValues("", "", "500", "", "")))
}

func TestMetricsMiddleware_RequestDuration(t *testing.T) {
gin.SetMode(gin.TestMode)
reg := newTestRegistry()
m := NewMetrics(reg)

r := gin.New()
r.Use(MetricsMiddleware(m))
r.GET("/slow", func(c *gin.Context) {
time.Sleep(100 * time.Millisecond)
c.Status(200)
})

req := httptest.NewRequest("GET", "/slow", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)

assert.Equal(t, 1, testutil.CollectAndCount(m.RequestDuration))
}

+ 28
- 0
common/metrics/middleware.go Просмотреть файл

@@ -0,0 +1,28 @@
package metrics

import (
"strconv"
"time"

"github.com/gin-gonic/gin"
)

// MetricsMiddleware 是一个 Gin 中间件,采集活跃请求数、请求延迟和状态码。
func MetricsMiddleware(m *Metrics) gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()

m.ActiveRequests.WithLabelValues("").Inc()
defer func() {
m.ActiveRequests.WithLabelValues("").Dec()

elapsed := time.Since(start).Seconds()
status := strconv.Itoa(c.Writer.Status())

m.RequestsTotal.WithLabelValues("", "", status, "", "").Inc()
m.RequestDuration.WithLabelValues("", "", "", "").Observe(elapsed)
}()

c.Next()
}
}

Загрузка…
Отмена
Сохранить