Skip to content

Commit bf13891

Browse files
committed
feat(metrics): add http metrics
1 parent 571c2db commit bf13891

File tree

2 files changed

+51
-13
lines changed

2 files changed

+51
-13
lines changed

modules/metrics/collector.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@ import (
1111
"code.gitea.io/gitea/modules/setting"
1212

1313
"github.com/prometheus/client_golang/prometheus"
14+
"github.com/prometheus/common/model"
1415
)
1516

1617
const namespace = "gitea_"
1718

19+
func init() {
20+
model.NameValidationScheme = model.UTF8Validation
21+
}
22+
1823
// Collector implements the prometheus.Collector interface and
1924
// exposes gitea metrics for prometheus
2025
type Collector struct {

routers/common/middleware.go

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ package common
66
import (
77
"fmt"
88
"net/http"
9+
"strconv"
910
"strings"
10-
"time"
1111

1212
"code.gitea.io/gitea/modules/cache"
1313
"code.gitea.io/gitea/modules/httplib"
@@ -18,17 +18,42 @@ import (
1818

1919
"gitea.com/go-chi/session"
2020
"github.com/chi-middleware/proxy"
21+
"github.com/felixge/httpsnoop"
2122
"github.com/go-chi/chi/v5"
2223
"github.com/prometheus/client_golang/prometheus"
2324
"github.com/prometheus/client_golang/prometheus/promauto"
2425
)
2526

26-
var responseLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{
27-
Namespace: "http",
28-
Subsystem: "request",
29-
Name: "duration_seconds",
30-
Help: "Gitea response time",
31-
}, []string{"route"})
27+
var (
28+
// reqInflightGauge tracks the amount of currently handled requests
29+
reqInflightGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{
30+
Namespace: "http",
31+
Subsystem: "server",
32+
Name: "active_requests",
33+
Help: "Number of active HTTP server requests.",
34+
}, []string{"http.request.method"})
35+
// reqDurationHistogram tracks the time taken by http request
36+
reqDurationHistogram = promauto.NewHistogramVec(prometheus.HistogramOpts{
37+
Namespace: "http",
38+
Subsystem: "server",
39+
Name: "request_duration",
40+
Help: "Measures the latency of HTTP requests processed by the server",
41+
}, []string{"http.request.method", "http.response.status_code", "http.route"})
42+
// reqSizeHistogram tracks the size of request
43+
reqSizeHistogram = promauto.NewHistogramVec(prometheus.HistogramOpts{
44+
Namespace: "http",
45+
Subsystem: "server_request",
46+
Name: "body_size",
47+
Help: "Size of HTTP server request bodies.",
48+
}, []string{"http.request.method", "http.response.status_code", "http.route"})
49+
// respSizeHistogram tracks the size of the response
50+
respSizeHistogram = promauto.NewHistogramVec(prometheus.HistogramOpts{
51+
Namespace: "http",
52+
Subsystem: "server_response",
53+
Name: "body_size",
54+
Help: "Size of HTTP server response bodies.",
55+
}, []string{"http.request.method", "http.response.status_code", "http.route"})
56+
)
3257

3358
// ProtocolMiddlewares returns HTTP protocol related middlewares, and it provides a global panic recovery
3459
func ProtocolMiddlewares() (handlers []any) {
@@ -107,17 +132,25 @@ func ForwardedHeadersHandler(limit int, trustedProxies []string) func(h http.Han
107132
return proxy.ForwardedHeaders(opt)
108133
}
109134

135+
// RouteMetrics instruments http requests and responses
110136
func RouteMetrics() func(h http.Handler) http.Handler {
111137
return func(next http.Handler) http.Handler {
112138
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
113-
start := time.Now()
139+
inflight := reqInflightGauge.WithLabelValues(req.Method)
140+
inflight.Inc()
141+
defer inflight.Dec()
142+
143+
m := httpsnoop.CaptureMetrics(next, resp, req)
114144
next.ServeHTTP(resp, req)
115-
elapsed := time.Since(start).Seconds()
116-
route := "ui"
117-
if strings.HasPrefix(req.URL.Path, "/api") {
118-
route = "api"
145+
route := chi.RouteContext(req.Context()).RoutePattern()
146+
code := strconv.Itoa(m.Code)
147+
reqDurationHistogram.WithLabelValues(req.Method, code, route).Observe(m.Duration.Seconds())
148+
respSizeHistogram.WithLabelValues(req.Method, code, route).Observe(float64(m.Written))
149+
size := req.ContentLength
150+
if size < 0 {
151+
size = 0
119152
}
120-
responseLatency.WithLabelValues(route).Observe(elapsed)
153+
reqSizeHistogram.WithLabelValues(req.Method, code, route).Observe(float64(size))
121154
})
122155
}
123156
}

0 commit comments

Comments
 (0)