Skip to content

Commit

Permalink
Record request metrics on HTTP errors
Browse files Browse the repository at this point in the history
If the error returned by the wrapped handler is a `Caddy.HandlerError`,
that indicates a problem that still yielded a successful HTTP
transaction, so it makes sense to observe request duration and size
metrics for it.

See mholt/caddy-ratelimit#35 for some context.
  • Loading branch information
tgeoghegan authored and francislavoie committed Dec 15, 2023
1 parent b49ec05 commit 655ad1b
Showing 1 changed file with 21 additions and 11 deletions.
32 changes: 21 additions & 11 deletions modules/caddyhttp/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,22 +137,32 @@ func (h *metricsInstrumentedHandler) ServeHTTP(w http.ResponseWriter, r *http.Re
err := h.mh.ServeHTTP(wrec, r, next)
dur := time.Since(start).Seconds()
httpMetrics.requestCount.With(labels).Inc()

observeRequest := func(status int) {
// If the code hasn't been set yet, and we didn't encounter an error, we're
// probably falling through with an empty handler.
if statusLabels["code"] == "" {
// we still sanitize it, even though it's likely to be 0. A 200 is
// returned on fallthrough so we want to reflect that.
statusLabels["code"] = metrics.SanitizeCode(status)
}

httpMetrics.requestDuration.With(statusLabels).Observe(dur)
httpMetrics.requestSize.With(statusLabels).Observe(float64(computeApproximateRequestSize(r)))
httpMetrics.responseSize.With(statusLabels).Observe(float64(wrec.Size()))
}

if err != nil {
if handlerError, ok := err.(HandlerError); ok {
observeRequest(handlerError.StatusCode)
}

httpMetrics.requestErrors.With(labels).Inc()
return err
}

// If the code hasn't been set yet, and we didn't encounter an error, we're
// probably falling through with an empty handler.
if statusLabels["code"] == "" {
// we still sanitize it, even though it's likely to be 0. A 200 is
// returned on fallthrough so we want to reflect that.
statusLabels["code"] = metrics.SanitizeCode(wrec.Status())
return err
}

httpMetrics.requestDuration.With(statusLabels).Observe(dur)
httpMetrics.requestSize.With(statusLabels).Observe(float64(computeApproximateRequestSize(r)))
httpMetrics.responseSize.With(statusLabels).Observe(float64(wrec.Size()))
observeRequest(wrec.Status())

return nil
}
Expand Down

0 comments on commit 655ad1b

Please sign in to comment.