6
"net/http"
7
"net/http/httptest"
8
"strings"
9
+ "sync"
10
"testing"
11
11
- "github.com/prometheus/client_golang/prometheus"
12
+ "github.com/caddyserver/caddy/v2"
13
"github.com/prometheus/client_golang/prometheus/testutil"
14
)
15
28
}
29
30
func TestMetricsInstrumentedHandler(t *testing.T) {
31
+ ctx, _ := caddy.NewContext(caddy.Context{Context: context.Background()})
32
+ metrics := &Metrics{
33
+ init: sync.Once{},
34
+ httpMetrics: &httpMetrics{},
35
+ }
36
handlerErr := errors.New("oh noes")
37
response := []byte("hello world!")
38
h := HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
33
- if actual := testutil.ToFloat64(httpMetrics.requestInFlight); actual != 1.0 {
39
+ if actual := testutil.ToFloat64(metrics.httpMetrics.requestInFlight); actual != 1.0 {
40
t.Errorf("Not same: expected %#v, but got %#v", 1.0, actual)
41
}
42
if handlerErr == nil {
49
return h.ServeHTTP(w, r)
50
})
51
46
- ih := newMetricsInstrumentedHandler("bar", mh)
52
+ ih := newMetricsInstrumentedHandler(ctx, "bar", mh, metrics)
53
54
r := httptest.NewRequest("GET", "/", nil)
55
w := httptest.NewRecorder()
57
if actual := ih.ServeHTTP(w, r, h); actual != handlerErr {
58
t.Errorf("Not same: expected %#v, but got %#v", handlerErr, actual)
59
}
54
- if actual := testutil.ToFloat64(httpMetrics.requestInFlight); actual != 0.0 {
60
+ if actual := testutil.ToFloat64(metrics.httpMetrics.requestInFlight); actual != 0.0 {
61
t.Errorf("Not same: expected %#v, but got %#v", 0.0, actual)
62
}
63
70
mh = middlewareHandlerFunc(func(w http.ResponseWriter, r *http.Request, h Handler) error {
71
return nil
72
})
67
- ih = newMetricsInstrumentedHandler("empty", mh)
73
+ ih = newMetricsInstrumentedHandler(ctx, "empty", mh, metrics)
74
r = httptest.NewRequest("GET", "/", nil)
75
w = httptest.NewRecorder()
76
89
return Error(http.StatusTooManyRequests, nil)
90
})
91
86
- ih = newMetricsInstrumentedHandler("foo", mh)
92
+ ih = newMetricsInstrumentedHandler(ctx, "foo", mh, metrics)
93
94
r = httptest.NewRequest("GET", "/", nil)
95
w = httptest.NewRecorder()
189
caddy_http_request_errors_total{handler="bar",server="UNKNOWN"} 1
190
caddy_http_request_errors_total{handler="foo",server="UNKNOWN"} 1
191
`
186
- if err := testutil.GatherAndCompare(prometheus.DefaultGatherer, strings.NewReader(expected),
192
+ if err := testutil.GatherAndCompare(ctx.GetMetricsRegistry(), strings.NewReader(expected),
193
+ "caddy_http_request_size_bytes",
194
+ "caddy_http_response_size_bytes",
195
+ // caddy_http_request_duration_seconds_sum will vary based on how long the test took to run,
196
+ // so we check just the _bucket and _count metrics
197
+ "caddy_http_request_duration_seconds_bucket",
198
+ "caddy_http_request_duration_seconds_count",
199
+ "caddy_http_request_errors_total",
200
+ ); err != nil {
201
+ t.Errorf("received unexpected error: %s", err)
202
+ }
203
+}
204
+
205
+func TestMetricsInstrumentedHandlerPerHost(t *testing.T) {
206
+ ctx, _ := caddy.NewContext(caddy.Context{Context: context.Background()})
207
+ metrics := &Metrics{
208
+ PerHost: true,
209
+ init: sync.Once{},
210
+ httpMetrics: &httpMetrics{},
211
+ }
212
+ handlerErr := errors.New("oh noes")
213
+ response := []byte("hello world!")
214
+ h := HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
215
+ if actual := testutil.ToFloat64(metrics.httpMetrics.requestInFlight); actual != 1.0 {
216
+ t.Errorf("Not same: expected %#v, but got %#v", 1.0, actual)
217
+ }
218
+ if handlerErr == nil {
219
+ w.Write(response)
220
+ }
221
+ return handlerErr
222
+ })
223
+
224
+ mh := middlewareHandlerFunc(func(w http.ResponseWriter, r *http.Request, h Handler) error {
225
+ return h.ServeHTTP(w, r)
226
+ })
227
+
228
+ ih := newMetricsInstrumentedHandler(ctx, "bar", mh, metrics)
229
+
230
+ r := httptest.NewRequest("GET", "/", nil)
231
+ w := httptest.NewRecorder()
232
+
233
+ if actual := ih.ServeHTTP(w, r, h); actual != handlerErr {
234
+ t.Errorf("Not same: expected %#v, but got %#v", handlerErr, actual)
235
+ }
236
+ if actual := testutil.ToFloat64(metrics.httpMetrics.requestInFlight); actual != 0.0 {
237
+ t.Errorf("Not same: expected %#v, but got %#v", 0.0, actual)
238
+ }
239
+
240
+ handlerErr = nil
241
+ if err := ih.ServeHTTP(w, r, h); err != nil {
242
+ t.Errorf("Received unexpected error: %v", err)
243
+ }
244
+
245
+ // an empty handler - no errors, no header written
246
+ mh = middlewareHandlerFunc(func(w http.ResponseWriter, r *http.Request, h Handler) error {
247
+ return nil
248
+ })
249
+ ih = newMetricsInstrumentedHandler(ctx, "empty", mh, metrics)
250
+ r = httptest.NewRequest("GET", "/", nil)
251
+ w = httptest.NewRecorder()
252
+
253
+ if err := ih.ServeHTTP(w, r, h); err != nil {
254
+ t.Errorf("Received unexpected error: %v", err)
255
+ }
256
+ if actual := w.Result().StatusCode; actual != 200 {
257
+ t.Errorf("Not same: expected status code %#v, but got %#v", 200, actual)
258
+ }
259
+ if actual := w.Result().Header; len(actual) != 0 {
260
+ t.Errorf("Not empty: expected headers to be empty, but got %#v", actual)
261
+ }
262
+
263
+ // handler returning an error with an HTTP status
264
+ mh = middlewareHandlerFunc(func(w http.ResponseWriter, r *http.Request, h Handler) error {
265
+ return Error(http.StatusTooManyRequests, nil)
266
+ })
267
+
268
+ ih = newMetricsInstrumentedHandler(ctx, "foo", mh, metrics)
269
+
270
+ r = httptest.NewRequest("GET", "/", nil)
271
+ w = httptest.NewRecorder()
272
+
273
+ if err := ih.ServeHTTP(w, r, nil); err == nil {
274
+ t.Errorf("expected error to be propagated")
275
+ }
276
+
277
+ expected := `
278
+ # HELP caddy_http_request_duration_seconds Histogram of round-trip request durations.
279
+ # TYPE caddy_http_request_duration_seconds histogram
280
+ caddy_http_request_duration_seconds_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="0.005"} 1
281
+ caddy_http_request_duration_seconds_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="0.01"} 1
282
+ caddy_http_request_duration_seconds_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="0.025"} 1
283
+ caddy_http_request_duration_seconds_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="0.05"} 1
284
+ caddy_http_request_duration_seconds_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="0.1"} 1
285
+ caddy_http_request_duration_seconds_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="0.25"} 1
286
+ caddy_http_request_duration_seconds_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="0.5"} 1
287
+ caddy_http_request_duration_seconds_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="1"} 1
288
+ caddy_http_request_duration_seconds_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="2.5"} 1
289
+ caddy_http_request_duration_seconds_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="5"} 1
290
+ caddy_http_request_duration_seconds_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="10"} 1
291
+ caddy_http_request_duration_seconds_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="+Inf"} 1
292
+ caddy_http_request_duration_seconds_count{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN"} 1
293
+ # HELP caddy_http_request_size_bytes Total size of the request. Includes body
294
+ # TYPE caddy_http_request_size_bytes histogram
295
+ caddy_http_request_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="256"} 1
296
+ caddy_http_request_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="1024"} 1
297
+ caddy_http_request_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="4096"} 1
298
+ caddy_http_request_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="16384"} 1
299
+ caddy_http_request_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="65536"} 1
300
+ caddy_http_request_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="262144"} 1
301
+ caddy_http_request_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="1.048576e+06"} 1
302
+ caddy_http_request_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="4.194304e+06"} 1
303
+ caddy_http_request_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="+Inf"} 1
304
+ caddy_http_request_size_bytes_sum{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN"} 23
305
+ caddy_http_request_size_bytes_count{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN"} 1
306
+ caddy_http_request_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="256"} 1
307
+ caddy_http_request_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="1024"} 1
308
+ caddy_http_request_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="4096"} 1
309
+ caddy_http_request_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="16384"} 1
310
+ caddy_http_request_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="65536"} 1
311
+ caddy_http_request_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="262144"} 1
312
+ caddy_http_request_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="1.048576e+06"} 1
313
+ caddy_http_request_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="4.194304e+06"} 1
314
+ caddy_http_request_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="+Inf"} 1
315
+ caddy_http_request_size_bytes_sum{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN"} 23
316
+ caddy_http_request_size_bytes_count{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN"} 1
317
+ caddy_http_request_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="256"} 1
318
+ caddy_http_request_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="1024"} 1
319
+ caddy_http_request_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="4096"} 1
320
+ caddy_http_request_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="16384"} 1
321
+ caddy_http_request_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="65536"} 1
322
+ caddy_http_request_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="262144"} 1
323
+ caddy_http_request_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="1.048576e+06"} 1
324
+ caddy_http_request_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="4.194304e+06"} 1
325
+ caddy_http_request_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="+Inf"} 1
326
+ caddy_http_request_size_bytes_sum{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN"} 23
327
+ caddy_http_request_size_bytes_count{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN"} 1
328
+ # HELP caddy_http_response_size_bytes Size of the returned response.
329
+ # TYPE caddy_http_response_size_bytes histogram
330
+ caddy_http_response_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="256"} 1
331
+ caddy_http_response_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="1024"} 1
332
+ caddy_http_response_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="4096"} 1
333
+ caddy_http_response_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="16384"} 1
334
+ caddy_http_response_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="65536"} 1
335
+ caddy_http_response_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="262144"} 1
336
+ caddy_http_response_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="1.048576e+06"} 1
337
+ caddy_http_response_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="4.194304e+06"} 1
338
+ caddy_http_response_size_bytes_bucket{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN",le="+Inf"} 1
339
+ caddy_http_response_size_bytes_sum{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN"} 12
340
+ caddy_http_response_size_bytes_count{code="200",handler="bar",host="example.com",method="GET",server="UNKNOWN"} 1
341
+ caddy_http_response_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="256"} 1
342
+ caddy_http_response_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="1024"} 1
343
+ caddy_http_response_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="4096"} 1
344
+ caddy_http_response_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="16384"} 1
345
+ caddy_http_response_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="65536"} 1
346
+ caddy_http_response_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="262144"} 1
347
+ caddy_http_response_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="1.048576e+06"} 1
348
+ caddy_http_response_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="4.194304e+06"} 1
349
+ caddy_http_response_size_bytes_bucket{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN",le="+Inf"} 1
350
+ caddy_http_response_size_bytes_sum{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN"} 0
351
+ caddy_http_response_size_bytes_count{code="200",handler="empty",host="example.com",method="GET",server="UNKNOWN"} 1
352
+ caddy_http_response_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="256"} 1
353
+ caddy_http_response_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="1024"} 1
354
+ caddy_http_response_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="4096"} 1
355
+ caddy_http_response_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="16384"} 1
356
+ caddy_http_response_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="65536"} 1
357
+ caddy_http_response_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="262144"} 1
358
+ caddy_http_response_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="1.048576e+06"} 1
359
+ caddy_http_response_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="4.194304e+06"} 1
360
+ caddy_http_response_size_bytes_bucket{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN",le="+Inf"} 1
361
+ caddy_http_response_size_bytes_sum{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN"} 0
362
+ caddy_http_response_size_bytes_count{code="429",handler="foo",host="example.com",method="GET",server="UNKNOWN"} 1
363
+ # HELP caddy_http_request_errors_total Number of requests resulting in middleware errors.
364
+ # TYPE caddy_http_request_errors_total counter
365
+ caddy_http_request_errors_total{handler="bar",host="example.com",server="UNKNOWN"} 1
366
+ caddy_http_request_errors_total{handler="foo",host="example.com",server="UNKNOWN"} 1
367
+ `
368
+ if err := testutil.GatherAndCompare(ctx.GetMetricsRegistry(), strings.NewReader(expected),
369
"caddy_http_request_size_bytes",
370
"caddy_http_response_size_bytes",
371
// caddy_http_request_duration_seconds_sum will vary based on how long the test took to run,