/
metrics.go
117 lines (103 loc) · 2.95 KB
/
metrics.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package gin
import (
"bytes"
"encoding/json"
"github.com/vnroyalclub/kratos/pkg/net/metadata"
"github.com/vnroyalclub/kratos/pkg/stat/metric"
"github.com/gin-gonic/gin"
"strconv"
"time"
)
const (
//clientNamespace = "http_client"
serverNamespace = "http_server"
)
var (
_metricServerReqDur = metric.NewHistogramVec(&metric.HistogramVecOpts{
Namespace: serverNamespace,
Subsystem: "requests",
Name: "duration_ms",
Help: "http server requests duration(ms).",
Labels: []string{"path", "caller", "method"},
Buckets: []float64{5, 10, 25, 50, 100, 250, 500, 1000},
})
_metricServerReqCodeTotal = metric.NewCounterVec(&metric.CounterVecOpts{
Namespace: serverNamespace,
Subsystem: "requests",
Name: "code_total",
Help: "http server requests error count.",
Labels: []string{"path", "caller", "method", "code"},
})
_metricServerBBR = metric.NewCounterVec(&metric.CounterVecOpts{
Namespace: serverNamespace,
Subsystem: "",
Name: "bbr_total",
Help: "http server bbr total.",
Labels: []string{"url", "method"},
})
//_metricClientReqDur = metric.NewHistogramVec(&metric.HistogramVecOpts{
// Namespace: clientNamespace,
// Subsystem: "requests",
// Name: "duration_ms",
// Help: "http client requests duration(ms).",
// Labels: []string{"path", "method"},
// Buckets: []float64{5, 10, 25, 50, 100, 250, 500, 1000},
//})
//_metricClientReqCodeTotal = metric.NewCounterVec(&metric.CounterVecOpts{
// Namespace: clientNamespace,
// Subsystem: "requests",
// Name: "code_total",
// Help: "http client requests code count.",
// Labels: []string{"path", "method", "code"},
//})
)
type responseBodyWriter struct {
gin.ResponseWriter
body *bytes.Buffer
}
func (r responseBodyWriter) Write(b []byte) (int, error) {
r.body.Write(b)
return r.ResponseWriter.Write(b)
}
var skipPath = []string{"/metrics", "/debug", "/healthcheck"}
func ServerReqMetric() gin.HandlerFunc {
const noUser = "no_user"
var skip map[string]struct{}
if length := len(skipPath); length > 0 {
skip = make(map[string]struct{}, length)
for _, path := range skipPath {
skip[path] = struct{}{}
}
}
return func(c *gin.Context) {
path := c.FullPath()
if _, ok := skip[path]; ok {
c.Next()
return
}
now := time.Now()
req := c.Request
w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer}
c.Writer = w
c.Next()
var code int
resp := &JSON{}
err := json.Unmarshal(w.body.Bytes(), resp)
if err != nil {
code = c.Writer.Status()
//log.Error("Metric get response error, can't catch response code")
//return
} else {
code = resp.Code
}
dt := time.Since(now)
caller := metadata.String(c, metadata.Caller)
if caller == "" {
caller = noUser
}
if len(path) > 0 {
_metricServerReqCodeTotal.Inc(path[1:], caller, req.Method, strconv.Itoa(code))
_metricServerReqDur.Observe(int64(dt/time.Millisecond), path[1:], caller, req.Method)
}
}
}