Skip to content

Commit d0c9aa3

Browse files
WFE: Track in-flight HTTP requests by endpoint using a gauge (#7758)
1 parent d17d71c commit d0c9aa3

File tree

2 files changed

+58
-13
lines changed

2 files changed

+58
-13
lines changed

metrics/measured_http/http.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ type MeasuredHandler struct {
4545
clk clock.Clock
4646
// Normally this is always responseTime, but we override it for testing.
4747
stat *prometheus.HistogramVec
48+
// inFlightRequestsGauge is a gauge that tracks the number of requests
49+
// currently in flight, labeled by endpoint.
50+
inFlightRequestsGauge *prometheus.GaugeVec
4851
}
4952

5053
func New(m serveMux, clk clock.Clock, stats prometheus.Registerer, opts ...otelhttp.Option) http.Handler {
@@ -55,17 +58,34 @@ func New(m serveMux, clk clock.Clock, stats prometheus.Registerer, opts ...otelh
5558
},
5659
[]string{"endpoint", "method", "code"})
5760
stats.MustRegister(responseTime)
61+
62+
inFlightRequestsGauge := prometheus.NewGaugeVec(
63+
prometheus.GaugeOpts{
64+
Name: "in_flight_requests",
65+
Help: "Tracks the number of WFE requests currently in flight, labeled by endpoint.",
66+
},
67+
[]string{"endpoint"},
68+
)
69+
stats.MustRegister(inFlightRequestsGauge)
70+
5871
return otelhttp.NewHandler(&MeasuredHandler{
59-
serveMux: m,
60-
clk: clk,
61-
stat: responseTime,
72+
serveMux: m,
73+
clk: clk,
74+
stat: responseTime,
75+
inFlightRequestsGauge: inFlightRequestsGauge,
6276
}, "server", opts...)
6377
}
6478

6579
func (h *MeasuredHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
6680
begin := h.clk.Now()
6781
rwws := &responseWriterWithStatus{w, 0}
6882

83+
subHandler, pattern := h.Handler(r)
84+
if pattern != "/" {
85+
h.inFlightRequestsGauge.WithLabelValues(pattern).Inc()
86+
defer h.inFlightRequestsGauge.WithLabelValues(pattern).Dec()
87+
}
88+
6989
// Use the method string only if it's a recognized HTTP method. This avoids
7090
// ballooning timeseries with invalid methods from public input.
7191
var method string
@@ -78,7 +98,6 @@ func (h *MeasuredHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
7898
method = "unknown"
7999
}
80100

81-
subHandler, pattern := h.Handler(r)
82101
defer func() {
83102
h.stat.With(prometheus.Labels{
84103
"endpoint": pattern,

metrics/measured_http/http_test.go

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,21 @@ func TestMeasuring(t *testing.T) {
4242
},
4343
[]string{"endpoint", "method", "code"})
4444

45+
inFlightRequestsGauge := prometheus.NewGaugeVec(
46+
prometheus.GaugeOpts{
47+
Name: "in_flight_requests",
48+
Help: "Tracks the number of WFE requests currently in flight, labeled by endpoint.",
49+
},
50+
[]string{"endpoint"},
51+
)
52+
4553
mux := http.NewServeMux()
4654
mux.Handle("/foo", sleepyHandler{clk})
4755
mh := MeasuredHandler{
48-
serveMux: mux,
49-
clk: clk,
50-
stat: stat,
56+
serveMux: mux,
57+
clk: clk,
58+
stat: stat,
59+
inFlightRequestsGauge: inFlightRequestsGauge,
5160
}
5261
mh.ServeHTTP(httptest.NewRecorder(), &http.Request{
5362
URL: &url.URL{Path: "/foo"},
@@ -95,13 +104,21 @@ func TestUnknownMethod(t *testing.T) {
95104
Help: "fake",
96105
},
97106
[]string{"endpoint", "method", "code"})
107+
inFlightRequestsGauge := prometheus.NewGaugeVec(
108+
prometheus.GaugeOpts{
109+
Name: "in_flight_requests",
110+
Help: "Tracks the number of WFE requests currently in flight, labeled by endpoint.",
111+
},
112+
[]string{"endpoint"},
113+
)
98114

99115
mux := http.NewServeMux()
100116
mux.Handle("/foo", sleepyHandler{clk})
101117
mh := MeasuredHandler{
102-
serveMux: mux,
103-
clk: clk,
104-
stat: stat,
118+
serveMux: mux,
119+
clk: clk,
120+
stat: stat,
121+
inFlightRequestsGauge: inFlightRequestsGauge,
105122
}
106123
mh.ServeHTTP(httptest.NewRecorder(), &http.Request{
107124
URL: &url.URL{Path: "/foo"},
@@ -140,14 +157,22 @@ func TestWrite(t *testing.T) {
140157
},
141158
[]string{"endpoint", "method", "code"})
142159

160+
inFlightRequestsGauge := prometheus.NewGaugeVec(
161+
prometheus.GaugeOpts{
162+
Name: "in_flight_requests",
163+
Help: "Tracks the number of WFE requests currently in flight, labeled by endpoint.",
164+
},
165+
[]string{"endpoint"})
166+
143167
mux := http.NewServeMux()
144168
mux.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) {
145169
w.Write([]byte{})
146170
})
147171
mh := MeasuredHandler{
148-
serveMux: mux,
149-
clk: clk,
150-
stat: stat,
172+
serveMux: mux,
173+
clk: clk,
174+
stat: stat,
175+
inFlightRequestsGauge: inFlightRequestsGauge,
151176
}
152177
mh.ServeHTTP(httptest.NewRecorder(), &http.Request{
153178
URL: &url.URL{Path: "/foo"},
@@ -162,6 +187,7 @@ func TestWrite(t *testing.T) {
162187
},
163188
[]string{"endpoint", "method", "code"})
164189
mh.stat = stat
190+
mh.inFlightRequestsGauge = inFlightRequestsGauge
165191
expectedLabels := map[string]string{
166192
"endpoint": "/foo",
167193
"method": "GET",

0 commit comments

Comments
 (0)