Skip to content

Commit f277fdb

Browse files
authored
feat(sc-52274): add status label to request_* http metrics (#249)
Co-authored-by: dmytrorezn <dmytrorezn>
1 parent 7b40d46 commit f277fdb

2 files changed

Lines changed: 55 additions & 18 deletions

File tree

middleware/metrics.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package middleware
22

33
import (
4+
"strconv"
5+
46
"github.com/gin-gonic/gin"
57
"github.com/prometheus/client_golang/prometheus"
68

@@ -9,9 +11,17 @@ import (
911

1012
const labelPath = "path"
1113
const labelMethod = "method"
14+
const labelStatus = "status"
15+
16+
const (
17+
_ = iota
18+
_
19+
labelStatusIndex
20+
)
1221

1322
func MetricsMiddleware(namespace string, labels prometheus.Labels, reg prometheus.Registerer) gin.HandlerFunc {
14-
perfMetric := metrics.NewHttpServerMetric(namespace, []string{labelPath, labelMethod}, labels, reg)
23+
perfMetric := metrics.NewHttpServerMetric(namespace, []string{labelPath, labelMethod, labelStatus}, labels, reg)
24+
1525
return func(c *gin.Context) {
1626
path := c.FullPath()
1727
method := c.Request.Method
@@ -22,13 +32,21 @@ func MetricsMiddleware(namespace string, labels prometheus.Labels, reg prometheu
2232
return
2333
}
2434

25-
labelValues := []string{path, method}
35+
labelValues := []string{path, method, "none"}
2636

2737
startTime := perfMetric.Start(labelValues...)
38+
2839
c.Next()
40+
41+
var (
42+
statusCode = c.Writer.Status()
43+
statusCodeStr = strconv.FormatInt(int64(statusCode), 10)
44+
)
45+
labelValues[labelStatusIndex] = statusCodeStr
46+
47+
// record duration with status code
2948
perfMetric.Duration(startTime, labelValues...)
3049

31-
statusCode := c.Writer.Status()
3250
switch {
3351
case 200 <= statusCode && statusCode <= 299:
3452
perfMetric.Success(labelValues...)

middleware/metrics_test.go

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,49 +27,68 @@ func TestMetricsMiddleware(t *testing.T) {
2727
router.GET("/error", func(c *gin.Context) {
2828
_ = c.AbortWithError(http.StatusInternalServerError, errors.New("oops error"))
2929
})
30+
router.GET("/404", func(c *gin.Context) {
31+
_ = c.AbortWithError(http.StatusNotFound, errors.New("404"))
32+
})
3033

3134
// 2 successes, 1 errors
3235
_ = performRequest("GET", "/success?haha=1&hoho=2", router)
3336
_ = performRequest("GET", "/error?hehe=1&huhu=3", router)
3437
_ = performRequest("GET", "/success/hihi", router)
38+
_ = performRequest("GET", "/404", router)
3539

3640
metricFamilies, err := r.Gather()
3741
require.NoError(t, err)
38-
39-
const executionFailedTotal = "execution_failed_total"
40-
const executionSucceededTotal = "execution_succeeded_total"
41-
42+
const (
43+
requestSucceededTotalKey = "request_succeeded_total"
44+
requestClientErrTotalKey = "request_client_error_total"
45+
requestServerErrTotalKey = "request_server_error_total"
46+
)
4247
// metricFamily.Name --> label --> counter value
4348
expected := map[string]map[string]int{
44-
executionSucceededTotal: {
49+
requestSucceededTotalKey: {
4550
"/success": 1,
4651
"/success/:test": 1,
4752
"/error": 0,
53+
"/404": 0,
4854
},
49-
executionFailedTotal: {
55+
requestServerErrTotalKey: {
5056
"/success": 0,
5157
"/success/:test": 0,
5258
"/error": 1,
59+
"/404": 0,
60+
},
61+
requestClientErrTotalKey: {
62+
"/success": 0,
63+
"/success/:test": 0,
64+
"/error": 0,
65+
"/404": 1,
5366
},
5467
}
55-
5668
for _, metricFamily := range metricFamilies {
5769
expectedLabelCounterMap, ok := expected[*metricFamily.Name]
5870
if !ok {
5971
continue
6072
}
61-
6273
require.Len(t, metricFamily.Metric, len(expectedLabelCounterMap))
6374
for _, metric := range metricFamily.Metric {
64-
require.Len(t, metric.Label, 2)
65-
var chosenLabelIdx = -1
75+
require.Len(t, metric.Label, 3)
76+
labelIndexes := map[string]int{
77+
labelMethod: -1,
78+
labelPath: -1,
79+
labelStatus: -1,
80+
}
6681
for idx, label := range metric.Label {
67-
if *label.Name == labelPath {
68-
chosenLabelIdx = idx
69-
}
82+
labelIndexes[*label.Name] = idx
83+
}
84+
require.Equal(t, len(labelIndexes), 3)
85+
for _, labelIdx := range labelIndexes {
86+
require.NotEqual(t, -1, labelIdx)
7087
}
71-
require.NotEqual(t, -1, chosenLabelIdx)
72-
require.Equal(t, float64(expectedLabelCounterMap[*metric.Label[chosenLabelIdx].Value]), *metric.Counter.Value)
88+
pathIdx := labelIndexes[labelPath]
89+
path := *metric.Label[pathIdx].Value
90+
expectedPathMetric := float64(expectedLabelCounterMap[path])
91+
require.Equal(t, expectedPathMetric, *metric.Counter.Value)
7392
}
7493
}
7594
}

0 commit comments

Comments
 (0)