From 2f5be324fde5a36bcc5ac76cde67a93ae279b7b8 Mon Sep 17 00:00:00 2001 From: Thomas Poignant Date: Mon, 9 Dec 2024 15:56:26 +0100 Subject: [PATCH] fix: Use timeout middleware as the 1st middleware (#2759) * fix: Use timeout middleware as the 1st middleware Signed-off-by: Thomas Poignant * move otel before timeout Signed-off-by: Thomas Poignant * fix linter Signed-off-by: Thomas Poignant --------- Signed-off-by: Thomas Poignant --- cmd/relayproxy/api/server.go | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/cmd/relayproxy/api/server.go b/cmd/relayproxy/api/server.go index c9bda394a2e..bd289c96d32 100644 --- a/cmd/relayproxy/api/server.go +++ b/cmd/relayproxy/api/server.go @@ -19,7 +19,7 @@ import ( "github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/metric" "github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/ofrep" "github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/service" - "go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho" // nolint + "go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho" "go.uber.org/zap" ) @@ -54,8 +54,23 @@ func (s *Server) initRoutes() { s.apiEcho.HideBanner = true s.apiEcho.HidePort = true s.apiEcho.Debug = s.config.IsDebugEnabled() + s.apiEcho.Use(otelecho.Middleware("go-feature-flag")) + // Timeout middleware has to be the first middleware in the list + // (see: https://github.com/labstack/echo/blob/3b017855b4d331002e2b8b28e903679b875ae3e9/middleware/timeout.go#L17) + s.apiEcho.Use(middleware.TimeoutWithConfig( + middleware.TimeoutConfig{ + Skipper: func(c echo.Context) bool { + // ignore websocket in the timeout + return strings.HasPrefix(c.Request().URL.String(), "/ws") + }, + Timeout: time.Duration(s.config.RestAPITimeout) * time.Millisecond, + OnTimeoutRouteErrorHandler: func(err error, c echo.Context) { + s.zapLog.Error("Timeout on route", zap.String("route", c.Path()), zap.Error(err)) + }, + ErrorMessage: `Timeout on the server, please retry later`, + }), + ) s.apiEcho.Use(custommiddleware.ZapLogger(s.zapLog, s.config)) - s.apiEcho.Use(middleware.BodyDumpWithConfig(middleware.BodyDumpConfig{ Skipper: func(_ echo.Context) bool { return !s.zapLog.Core().Enabled(zap.DebugLevel) @@ -64,27 +79,15 @@ func (s *Server) initRoutes() { s.zapLog.Debug("Request info", zap.ByteString("request_body", reqBody)) }, })) - if s.services.Metrics != (metric.Metrics{}) { s.apiEcho.Use(echoprometheus.NewMiddlewareWithConfig(echoprometheus.MiddlewareConfig{ Subsystem: metric.GOFFSubSystem, Registerer: s.services.Metrics.Registry, })) } - - s.apiEcho.Use(otelecho.Middleware("go-feature-flag")) s.apiEcho.Use(middleware.CORSWithConfig(middleware.DefaultCORSConfig)) s.apiEcho.Use(custommiddleware.VersionHeader(s.config)) s.apiEcho.Use(middleware.Recover()) - s.apiEcho.Use(middleware.TimeoutWithConfig( - middleware.TimeoutConfig{ - Skipper: func(c echo.Context) bool { - // ignore websocket in the timeout - return strings.HasPrefix(c.Request().URL.String(), "/ws") - }, - Timeout: time.Duration(s.config.RestAPITimeout) * time.Millisecond, - }), - ) // Init controllers cAllFlags := controller.NewAllFlags(s.services.GOFeatureFlagService, s.services.Metrics)