-
Notifications
You must be signed in to change notification settings - Fork 0
/
middleware.go
97 lines (80 loc) · 2.42 KB
/
middleware.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package ginprometheus
import (
"context"
"github.com/gin-gonic/gin"
"go.opentelemetry.io/otel/attribute"
semconv "go.opentelemetry.io/otel/semconv/v1.25.0"
"time"
)
func recordSystemMetrics(ctx context.Context, recorder Recorder, interval time.Duration, attributes []attribute.KeyValue) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
recorder.ObserveSystemMetric(ctx, attributes)
case <-ctx.Done():
// 上下文取消信号,退出循环
return
}
}
}
// Middleware 请求中间件
func Middleware(options ...Option) gin.HandlerFunc {
ctx := context.Background()
// 默认配置
cfg := defaultConfig()
for _, option := range options {
option.apply(cfg)
}
// start the prometheus server
initMetrics(cfg.prometheusPort, cfg.serviceName)
// 初始化记录器
recorder := cfg.recorder
if recorder == nil {
recorder = NewHttpMetricsRecorder(cfg.serviceName, cfg.version, cfg.metricPrefix)
}
if cfg.recordSystemMetric {
go recordSystemMetrics(ctx, recorder, time.Minute, cfg.globalAttributes)
}
return func(ginCtx *gin.Context) {
// 获取这次请求的完整路径
route := ginCtx.FullPath()
if len(route) <= 0 {
ginCtx.Next()
return
}
if !cfg.recordFilter(route, ginCtx.Request) {
ginCtx.Next()
return
}
start := time.Now()
reqAttributes := append(cfg.attributes(route, ginCtx.Request), cfg.globalAttributes...)
if cfg.recordInFlight {
// count 类型,需要开始时 + 1, 结束时 -1
recorder.AddInflightRequests(ctx, 1, reqAttributes)
defer recorder.AddInflightRequests(ctx, -1, reqAttributes)
}
defer func() {
// generate a new slice
resAttributes := append(reqAttributes[0:0], reqAttributes...)
if cfg.groupedStatus {
// 200 300 400 500
code := int(ginCtx.Writer.Status()/100) * 100
resAttributes = append(resAttributes, semconv.HTTPStatusCodeKey.Int(code))
} else {
resAttributes = append(resAttributes, semconv.HTTPStatusCodeKey.Int(ginCtx.Writer.Status()))
}
recorder.AddRequests(ctx, 1, resAttributes)
if cfg.recordSize {
requestSize := computeApproximateRequestSize(ginCtx.Request)
recorder.ObserveHTTPRequestSize(ctx, requestSize, resAttributes)
recorder.ObserveHTTPResponseSize(ctx, int64(ginCtx.Writer.Size()), resAttributes)
}
if cfg.recordDuration {
recorder.ObserveHTTPRequestDuration(ctx, time.Since(start), resAttributes)
}
}()
ginCtx.Next()
}
}