From 8756ea717d6aeca0e071e7f566bebe81eeffe376 Mon Sep 17 00:00:00 2001 From: Gianluca Zuccarelli Date: Mon, 21 Nov 2022 17:04:39 +0000 Subject: [PATCH] prometheus: middleware to record 5xx errors Create a custom middleware function to measure 5xx requests for all composer & worker routes and not just the `/composer` endpoint. The result is a prometheus metric that contains info on the request status code, path & method. A helper function has been added to clean the dynamic parameters in the path routes to reduce metric cardinality --- internal/prometheus/helpers.go | 15 ++++++++++++++ internal/prometheus/middleware.go | 34 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 internal/prometheus/helpers.go diff --git a/internal/prometheus/helpers.go b/internal/prometheus/helpers.go new file mode 100644 index 000000000..26b25f510 --- /dev/null +++ b/internal/prometheus/helpers.go @@ -0,0 +1,15 @@ +package prometheus + +import ( + "regexp" + "strings" +) + +func pathLabel(path string) string { + r := regexp.MustCompile(":(.*)") + segments := strings.Split(path, "/") + for i, segment := range segments { + segments[i] = r.ReplaceAllString(segment, "-") + } + return strings.Join(segments, "/") +} diff --git a/internal/prometheus/middleware.go b/internal/prometheus/middleware.go index 26c88edc8..3be932400 100644 --- a/internal/prometheus/middleware.go +++ b/internal/prometheus/middleware.go @@ -1,6 +1,8 @@ package prometheus import ( + "errors" + "strconv" "strings" "github.com/labstack/echo/v4" @@ -18,3 +20,35 @@ func MetricsMiddleware(next echo.HandlerFunc) echo.HandlerFunc { return next(ctx) } } + +func StatusMiddleware(subsystem string) func(next echo.HandlerFunc) echo.HandlerFunc { + counter := StatusRequestsCounter(subsystem) + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(ctx echo.Context) error { + + // call the next handler to see if + // an error occurred, see: + // - https://github.com/labstack/echo/issues/1837#issuecomment-816399630 + // - https://github.com/labstack/echo/discussions/1820#discussioncomment-529428 + err := next(ctx) + + path := pathLabel(ctx.Path()) + method := ctx.Request().Method + status := ctx.Response().Status + + httpErr := new(echo.HTTPError) + if errors.As(err, &httpErr) { + status = httpErr.Code + } + + counter.WithLabelValues( + method, + path, + strconv.Itoa(status), + subsystem, + ).Inc() + + return err + } + } +}