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 + } + } +}