From 53ef54a312cb1b85819ffc7ae7d878e21fe79cf8 Mon Sep 17 00:00:00 2001 From: Kevin Lyda Date: Fri, 3 May 2024 11:51:30 +0100 Subject: [PATCH 1/2] Remove invalid UTF-8 data. --- echoprometheus/prometheus.go | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/echoprometheus/prometheus.go b/echoprometheus/prometheus.go index cc864c8..f337788 100644 --- a/echoprometheus/prometheus.go +++ b/echoprometheus/prometheus.go @@ -11,17 +11,19 @@ import ( "context" "errors" "fmt" + "io" + "net/http" + "sort" + "strconv" + "strings" + "time" + "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "github.com/labstack/gommon/log" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/common/expfmt" - "io" - "net/http" - "sort" - "strconv" - "time" ) const ( @@ -268,12 +270,12 @@ func (conf MiddlewareConfig) ToMiddleware() (echo.MiddlewareFunc, error) { } values := make([]string, len(labelNames)) - values[0] = strconv.Itoa(status) - values[1] = c.Request().Method - values[2] = c.Request().Host - values[3] = url + values[0] = strings.ToValidUTF8(strconv.Itoa(status), "�") + values[1] = strings.ToValidUTF8(c.Request().Method, "�") + values[2] = strings.ToValidUTF8(c.Request().Host, "�") + values[3] = strings.ToValidUTF8(url, "�") for _, cv := range customValuers { - values[cv.index] = cv.valueFunc(c, err) + values[cv.index] = strings.ToValidUTF8(cv.valueFunc(c, err), "�") } requestDuration.WithLabelValues(values...).Observe(elapsed) From d623559ac42c31f312e2ca1b53a88f9fef77ce26 Mon Sep 17 00:00:00 2001 From: Kevin Lyda Date: Wed, 8 May 2024 09:11:25 +0100 Subject: [PATCH 2/2] Catch invalid UTF-8 and log it This will catch and log UTF-8 without causing the middleware to panic. --- echoprometheus/prometheus.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/echoprometheus/prometheus.go b/echoprometheus/prometheus.go index f337788..1f9ed82 100644 --- a/echoprometheus/prometheus.go +++ b/echoprometheus/prometheus.go @@ -270,15 +270,22 @@ func (conf MiddlewareConfig) ToMiddleware() (echo.MiddlewareFunc, error) { } values := make([]string, len(labelNames)) - values[0] = strings.ToValidUTF8(strconv.Itoa(status), "�") - values[1] = strings.ToValidUTF8(c.Request().Method, "�") - values[2] = strings.ToValidUTF8(c.Request().Host, "�") - values[3] = strings.ToValidUTF8(url, "�") + values[0] = strconv.Itoa(status) + values[1] = c.Request().Method + values[2] = c.Request().Host + values[3] = url for _, cv := range customValuers { values[cv.index] = strings.ToValidUTF8(cv.valueFunc(c, err), "�") } - requestDuration.WithLabelValues(values...).Observe(elapsed) + // The first metric set is done this way to ensure + // that the values all contain valid UTF8. If not, it + // returns, if they are then .WithLabelValues is fine. + if obs, tmpErr := requestDuration.GetMetricWithLabelValues(values...); tmpErr == nil { + obs.Observe(elapsed) + } else { + return fmt.Errorf("requestDuration observation failed, err: %w", tmpErr) + } requestCount.WithLabelValues(values...).Inc() requestSize.WithLabelValues(values...).Observe(float64(reqSz)) responseSize.WithLabelValues(values...).Observe(float64(c.Response().Size))