@marcel91200 / caddy Mirror · read-only / commits / b1d456d8
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

metrics: Fix panic when headers aren't written (#3737)

Signed-off-by: Dave Henderson <dhenderson@gmail.com>

Dave Henderson committed Sep 21, 2020 at 15:42 UTC b1d456d8abf15616afb6c6893af90473b4941365
2 files changed +27 -1
modules/caddyhttp/metrics.go
+9 -1
@@ -108,7 +108,7 @@ func newMetricsInstrumentedHandler(handler string, mh MiddlewareHandler) *metric
108 func (h *metricsInstrumentedHandler) ServeHTTP(w http.ResponseWriter, r *http.Request, next Handler) error {
109 server := serverNameFromContext(r.Context())
110 labels := prometheus.Labels{"server": server, "handler": h.handler}
111 - statusLabels := prometheus.Labels{"server": server, "handler": h.handler, "method": r.Method}
111 + statusLabels := prometheus.Labels{"server": server, "handler": h.handler, "method": r.Method, "code": ""}
112
113 inFlight := httpMetrics.requestInFlight.With(labels)
114 inFlight.Inc()
@@ -134,6 +134,14 @@ func (h *metricsInstrumentedHandler) ServeHTTP(w http.ResponseWriter, r *http.Re
134 return err
135 }
136
137 + // If the code hasn't been set yet, and we didn't encounter an error, we're
138 + // probably falling through with an empty handler.
139 + if statusLabels["code"] == "" {
140 + // we still sanitize it, even though it's likely to be 0. A 200 is
141 + // returned on fallthrough so we want to reflect that.
142 + statusLabels["code"] = sanitizeCode(wrec.Status())
143 + }
144 +
145 httpMetrics.requestDuration.With(statusLabels).Observe(dur)
146 httpMetrics.requestSize.With(statusLabels).Observe(float64(computeApproximateRequestSize(r)))
147 httpMetrics.responseSize.With(statusLabels).Observe(float64(wrec.Size()))
modules/caddyhttp/metrics_test.go
+18
@@ -57,6 +57,24 @@ func TestMetricsInstrumentedHandler(t *testing.T) {
57 if err := ih.ServeHTTP(w, r, h); err != nil {
58 t.Errorf("Received unexpected error: %w", err)
59 }
60 +
61 + // an empty handler - no errors, no header written
62 + mh = middlewareHandlerFunc(func(w http.ResponseWriter, r *http.Request, h Handler) error {
63 + return nil
64 + })
65 + ih = newMetricsInstrumentedHandler("empty", mh)
66 + r = httptest.NewRequest("GET", "/", nil)
67 + w = httptest.NewRecorder()
68 +
69 + if err := ih.ServeHTTP(w, r, h); err != nil {
70 + t.Errorf("Received unexpected error: %w", err)
71 + }
72 + if actual := w.Result().StatusCode; actual != 200 {
73 + t.Errorf("Not same: expected status code %#v, but got %#v", 200, actual)
74 + }
75 + if actual := w.Result().Header; len(actual) != 0 {
76 + t.Errorf("Not empty: expected headers to be empty, but got %#v", actual)
77 + }
78 }
79
80 type middlewareHandlerFunc func(http.ResponseWriter, *http.Request, Handler) error