feat: add metrics (#3624)

This commit is contained in:
MarkJoyMa
2023-10-26 23:51:28 +08:00
committed by GitHub
parent 199e86050e
commit c05e03bb5a
14 changed files with 759 additions and 29 deletions

View File

@@ -0,0 +1,71 @@
package internal
import (
"net/http"
"net/url"
"strconv"
"time"
"github.com/zeromicro/go-zero/core/metric"
"github.com/zeromicro/go-zero/core/timex"
)
const clientNamespace = "httpc_client"
var (
MetricClientReqDur = metric.NewHistogramVec(&metric.HistogramVecOpts{
Namespace: clientNamespace,
Subsystem: "requests",
Name: "duration_ms",
Help: "http client requests duration(ms).",
Labels: []string{"name", "method", "url"},
Buckets: []float64{0.25, 0.5, 1, 2, 5, 10, 25, 50, 100, 250, 500, 1000, 2000, 5000, 10000, 15000},
})
MetricClientReqCodeTotal = metric.NewCounterVec(&metric.CounterVecOpts{
Namespace: clientNamespace,
Subsystem: "requests",
Name: "code_total",
Help: "http client requests code count.",
Labels: []string{"name", "method", "url", "code"},
})
)
type (
MetricsURLRewriter func(u url.URL) string
)
func MetricsInterceptor(name string, pr MetricsURLRewriter) Interceptor {
return func(r *http.Request) (*http.Request, ResponseHandler) {
startTime := timex.Now()
return r, func(resp *http.Response, err error) {
u := cleanURL(*r.URL)
method := r.Method
var (
code int
path string
)
// error or resp is nil, set code=500
if err != nil || resp == nil {
code = http.StatusInternalServerError
} else {
code = resp.StatusCode
}
if pr != nil {
path = pr(u)
} else {
path = u.String()
}
MetricClientReqDur.ObserveFloat(float64(timex.Since(startTime))/float64(time.Millisecond), name, method, path)
MetricClientReqCodeTotal.Inc(name, method, path, strconv.Itoa(code))
}
}
}
func cleanURL(r url.URL) url.URL {
r.RawQuery = ""
r.RawFragment = ""
r.User = nil
return r
}

View File

@@ -0,0 +1,35 @@
package internal
import (
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/zeromicro/go-zero/core/logx"
)
func TestMetricsInterceptor(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
logx.Disable()
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(100 * time.Millisecond)
w.WriteHeader(http.StatusInternalServerError)
}))
defer svr.Close()
req, err := http.NewRequest(http.MethodGet, svr.URL, nil)
assert.NotNil(t, req)
assert.Nil(t, err)
interceptor := MetricsInterceptor("test", nil)
req, handler := interceptor(req)
resp, err := http.DefaultClient.Do(req)
assert.NotNil(t, resp)
assert.Nil(t, err)
handler(resp, err)
}