@@ -6,8 +6,8 @@ package common
6
6
import (
7
7
"fmt"
8
8
"net/http"
9
+ "strconv"
9
10
"strings"
10
- "time"
11
11
12
12
"code.gitea.io/gitea/modules/cache"
13
13
"code.gitea.io/gitea/modules/httplib"
@@ -18,17 +18,42 @@ import (
18
18
19
19
"gitea.com/go-chi/session"
20
20
"github.com/chi-middleware/proxy"
21
+ "github.com/felixge/httpsnoop"
21
22
"github.com/go-chi/chi/v5"
22
23
"github.com/prometheus/client_golang/prometheus"
23
24
"github.com/prometheus/client_golang/prometheus/promauto"
24
25
)
25
26
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
+ )
32
57
33
58
// ProtocolMiddlewares returns HTTP protocol related middlewares, and it provides a global panic recovery
34
59
func ProtocolMiddlewares () (handlers []any ) {
@@ -107,17 +132,25 @@ func ForwardedHeadersHandler(limit int, trustedProxies []string) func(h http.Han
107
132
return proxy .ForwardedHeaders (opt )
108
133
}
109
134
135
+ // RouteMetrics instruments http requests and responses
110
136
func RouteMetrics () func (h http.Handler ) http.Handler {
111
137
return func (next http.Handler ) http.Handler {
112
138
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 )
114
144
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
119
152
}
120
- responseLatency .WithLabelValues (route ).Observe (elapsed )
153
+ reqSizeHistogram .WithLabelValues (req . Method , code , route ).Observe (float64 ( size ) )
121
154
})
122
155
}
123
156
}
0 commit comments