80 lines
2.3 KiB
Go
80 lines
2.3 KiB
Go
// Package monitor 运行监控(方案系统管理模块补足)。
|
||
//
|
||
// 提供 Prometheus 指标采集中间件,覆盖 4 金指标:
|
||
// - Latency:请求延迟直方图
|
||
// - Traffic:请求总量计数器
|
||
// - Errors:错误响应计数器
|
||
// - Saturation:并发在途请求 gauge
|
||
//
|
||
// 使用方式:
|
||
// r := gin.Default()
|
||
// r.Use(monitor.Middleware())
|
||
// r.GET("/metrics", monitor.Handler())
|
||
package monitor
|
||
|
||
import (
|
||
"strconv"
|
||
"time"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"github.com/prometheus/client_golang/prometheus"
|
||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||
)
|
||
|
||
var (
|
||
// httpDuration 请求延迟直方图(Latency)。
|
||
httpDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||
Name: "tcs_http_request_duration_seconds",
|
||
Help: "HTTP 请求延迟(秒)",
|
||
Buckets: []float64{0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10},
|
||
}, []string{"method", "path", "status"})
|
||
|
||
// httpRequests 请求总量计数器(Traffic)。
|
||
httpRequests = promauto.NewCounterVec(prometheus.CounterOpts{
|
||
Name: "tcs_http_requests_total",
|
||
Help: "HTTP 请求总量",
|
||
}, []string{"method", "path", "status"})
|
||
|
||
// httpErrors 错误响应计数器(Errors)。
|
||
httpErrors = promauto.NewCounterVec(prometheus.CounterOpts{
|
||
Name: "tcs_http_errors_total",
|
||
Help: "HTTP 错误响应总量(状态码 >= 400)",
|
||
}, []string{"method", "path", "status"})
|
||
|
||
// httpInFlight 并发在途请求(Saturation)。
|
||
httpInFlight = promauto.NewGauge(prometheus.GaugeOpts{
|
||
Name: "tcs_http_in_flight_requests",
|
||
Help: "当前在途 HTTP 请求数",
|
||
})
|
||
)
|
||
|
||
// Middleware 返回 Gin 中间件,采集 Prometheus 指标。
|
||
func Middleware() gin.HandlerFunc {
|
||
return func(c *gin.Context) {
|
||
start := time.Now()
|
||
httpInFlight.Inc()
|
||
|
||
c.Next()
|
||
|
||
httpInFlight.Dec()
|
||
status := strconv.Itoa(c.Writer.Status())
|
||
elapsed := time.Since(start).Seconds()
|
||
path := c.FullPath()
|
||
if path == "" {
|
||
path = "unknown"
|
||
}
|
||
|
||
httpDuration.WithLabelValues(c.Request.Method, path, status).Observe(elapsed)
|
||
httpRequests.WithLabelValues(c.Request.Method, path, status).Inc()
|
||
if c.Writer.Status() >= 400 {
|
||
httpErrors.WithLabelValues(c.Request.Method, path, status).Inc()
|
||
}
|
||
}
|
||
}
|
||
|
||
// Handler 返回 Prometheus metrics 暴露端点。
|
||
func Handler() gin.HandlerFunc {
|
||
return gin.WrapH(promhttp.Handler())
|
||
}
|