From f197cec7f3a599ca18807e7b7719ef7666cfdb70 Mon Sep 17 00:00:00 2001 From: Dave Henderson Date: Tue, 22 Sep 2020 22:10:34 -0400 Subject: metrics: Always track method label in uppercase (#3742) * metrics: Always track method label in uppercase Signed-off-by: Dave Henderson * Just use strings.ToUpper for clarity Signed-off-by: Dave Henderson --- metrics.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'metrics.go') diff --git a/metrics.go b/metrics.go index a7ff3b7..55fb0a3 100644 --- a/metrics.go +++ b/metrics.go @@ -1,6 +1,10 @@ package caddy import ( + "net/http" + "strconv" + "strings" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) @@ -30,3 +34,44 @@ var adminMetrics = struct { requestCount *prometheus.CounterVec requestErrors *prometheus.CounterVec }{} + +// Similar to promhttp.InstrumentHandlerCounter, but upper-cases method names +// instead of lower-casing them. +// +// Unlike promhttp.InstrumentHandlerCounter, this assumes a "code" and "method" +// label is present, and will panic otherwise. +func instrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + d := newDelegator(w) + next.ServeHTTP(d, r) + counter.With(prometheus.Labels{ + "code": sanitizeCode(d.status), + "method": strings.ToUpper(r.Method), + }).Inc() + }) +} + +func newDelegator(w http.ResponseWriter) *delegator { + return &delegator{ + ResponseWriter: w, + } +} + +type delegator struct { + http.ResponseWriter + status int +} + +func (d *delegator) WriteHeader(code int) { + d.status = code + d.ResponseWriter.WriteHeader(code) +} + +func sanitizeCode(s int) string { + switch s { + case 0, 200: + return "200" + default: + return strconv.Itoa(s) + } +} -- cgit v1.2.3