From 7582da96506689b9516adae046902f78926c2e61 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 26 Oct 2022 18:22:05 +0200 Subject: [PATCH 1/5] Update Yaegi to v0.14.3 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 94e122e67..15344fbe1 100644 --- a/go.mod +++ b/go.mod @@ -60,7 +60,7 @@ require ( github.com/stretchr/testify v1.8.0 github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154 github.com/traefik/paerser v0.1.9 - github.com/traefik/yaegi v0.14.2 + github.com/traefik/yaegi v0.14.3 github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/uber/jaeger-lib v2.2.0+incompatible github.com/unrolled/render v1.0.2 diff --git a/go.sum b/go.sum index 568b63f0b..edfe2cc70 100644 --- a/go.sum +++ b/go.sum @@ -1956,8 +1956,8 @@ github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305 h1:y/1cL5AL2oRcfz github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305/go.mod h1:gXOLibKqQTRAVuVZ9gX7G9Ykky8ll8yb4slxsEMoY0c= github.com/traefik/paerser v0.1.9 h1:x5hZafOt/yogLvr6upoSOYIAn2nh2GsnLb236MOzd4I= github.com/traefik/paerser v0.1.9/go.mod h1:Dk3Bfz6Zyj13/S8pJyRdx/FNvXlsVRVbtp0UK4ZSiA0= -github.com/traefik/yaegi v0.14.2 h1:9t9xepIfar6BrYdwJHGc+XRKo6qFoJCl6Z46N3hUtUw= -github.com/traefik/yaegi v0.14.2/go.mod h1:AVRxhaI2G+nUsaM1zyktzwXn69G3t/AuTDrCiTds9p0= +github.com/traefik/yaegi v0.14.3 h1:LqA0k8DKwvRMc+msfQjNusphHJc+r6WC5tZU5TmUFOM= +github.com/traefik/yaegi v0.14.3/go.mod h1:AVRxhaI2G+nUsaM1zyktzwXn69G3t/AuTDrCiTds9p0= github.com/transip/gotransip/v6 v6.17.0 h1:2RCyqYqz5+Ej8z96EyE4sf6tQrrfEBaFDO0LliSl6+8= github.com/transip/gotransip/v6 v6.17.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= From a041a6b198daa63750cf02b33114e7a902d19589 Mon Sep 17 00:00:00 2001 From: Romain Date: Thu, 27 Oct 2022 16:08:06 +0200 Subject: [PATCH 2/5] Handle capture on redefined http.responseWriters Co-authored-by: Mathieu Lonjaret --- cmd/traefik/traefik.go | 11 +-- ...simple_metrics_with_buffer_middleware.toml | 66 +++++++++++++++ integration/simple_test.go | 80 ++++++++++++++++++- pkg/middlewares/accesslog/logger.go | 16 ++-- pkg/middlewares/accesslog/logger_test.go | 6 +- pkg/middlewares/capture/capture.go | 79 +++++++++--------- pkg/middlewares/capture/capture_test.go | 6 +- pkg/middlewares/metrics/metrics.go | 21 +++-- pkg/server/middleware/chainbuilder.go | 8 +- pkg/server/router/router_test.go | 12 +-- pkg/server/routerfactory_test.go | 6 +- 11 files changed, 228 insertions(+), 83 deletions(-) create mode 100644 integration/fixtures/simple_metrics_with_buffer_middleware.toml diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index f54477375..125025251 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -31,7 +31,6 @@ import ( "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/metrics" "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" - "github.com/traefik/traefik/v2/pkg/middlewares/capture" "github.com/traefik/traefik/v2/pkg/provider/acme" "github.com/traefik/traefik/v2/pkg/provider/aggregator" "github.com/traefik/traefik/v2/pkg/provider/hub" @@ -260,9 +259,8 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err accessLog := setupAccessLog(staticConfiguration.AccessLog) tracer := setupTracing(staticConfiguration.Tracing) - captureMiddleware := setupCapture(staticConfiguration) - chainBuilder := middleware.NewChainBuilder(metricsRegistry, accessLog, tracer, captureMiddleware) + chainBuilder := middleware.NewChainBuilder(metricsRegistry, accessLog, tracer) routerFactory := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, chainBuilder, pluginBuilder, metricsRegistry) // Watcher @@ -565,13 +563,6 @@ func setupTracing(conf *static.Tracing) *tracing.Tracing { return tracer } -func setupCapture(staticConfiguration *static.Configuration) *capture.Handler { - if staticConfiguration.AccessLog == nil && staticConfiguration.Metrics == nil { - return nil - } - return &capture.Handler{} -} - func configureLogging(staticConfiguration *static.Configuration) { // configure default log flags stdlog.SetFlags(stdlog.Lshortfile | stdlog.LstdFlags) diff --git a/integration/fixtures/simple_metrics_with_buffer_middleware.toml b/integration/fixtures/simple_metrics_with_buffer_middleware.toml new file mode 100644 index 000000000..2781c1981 --- /dev/null +++ b/integration/fixtures/simple_metrics_with_buffer_middleware.toml @@ -0,0 +1,66 @@ +[global] + checkNewVersion = false + sendAnonymousUsage = false + +[log] + level = "DEBUG" + +[entryPoints] + [entryPoints.webA] + address = ":8001" + [entryPoints.webB] + address = ":8002" + [entryPoints.webC] + address = ":8003" + +[api] + insecure = true + +[metrics] + [metrics.prometheus] + buckets = "0.1,0.3,1.2,5.0" + +[providers] + [providers.file] + filename = "{{ .SelfFilename }}" + +## dynamic configuration ## + +[http.routers] + + [http.routers.router-without] + entrypoints = ["webA"] + service = "service-without" + rule = "PathPrefix(`/without`)" + + [http.routers.router-req] + entrypoints = ["webB"] + service = "service-req" + rule = "PathPrefix(`/with-req`)" + middlewares = ["buffer-req"] + + [http.routers.router-resp] + entrypoints = ["webC"] + service = "service-resp" + rule = "PathPrefix(`/with-resp`)" + middlewares = ["buffer-resp"] + +[http.middlewares] + [http.middlewares.buffer-req.buffering] + maxRequestBodyBytes = 10 + + [http.middlewares.buffer-resp.buffering] + maxResponseBodyBytes = 10 + +[http.services] + [http.services.service-without.loadBalancer] + [[http.services.service-without.loadBalancer.servers]] + url = "http://{{ .IP }}" + + [http.services.service-req.loadBalancer] + [[http.services.service-req.loadBalancer.servers]] + url = "http://{{ .IP }}" + + [http.services.service-resp.loadBalancer] + [[http.services.service-resp.loadBalancer.servers]] + url = "http://{{ .IP }}" diff --git a/integration/simple_test.go b/integration/simple_test.go index c939d8f0a..28e5291fd 100644 --- a/integration/simple_test.go +++ b/integration/simple_test.go @@ -308,7 +308,7 @@ func (s *SimpleSuite) TestMetricsPrometheusDefaultEntryPoint(c *check.C) { c.Assert(err, checker.IsNil) defer s.killCmd(cmd) - err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("PathPrefix")) + err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("PathPrefix(`/whoami`)")) c.Assert(err, checker.IsNil) err = try.GetRequest("http://127.0.0.1:8000/whoami", 1*time.Second, try.StatusCodeIs(http.StatusOK)) @@ -369,6 +369,84 @@ func (s *SimpleSuite) TestMetricsPrometheusTwoRoutersOneService(c *check.C) { } } +// TestMetricsWithBufferingMiddleware checks that the buffering middleware +// (which introduces its own response writer in the chain), does not interfere with +// the capture middleware on which the metrics mechanism relies. +func (s *SimpleSuite) TestMetricsWithBufferingMiddleware(c *check.C) { + s.createComposeProject(c, "base") + + s.composeUp(c) + defer s.composeDown(c) + + server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte("MORE THAN TEN BYTES IN RESPONSE")) + })) + + server.Start() + defer server.Close() + + file := s.adaptFile(c, "fixtures/simple_metrics_with_buffer_middleware.toml", struct{ IP string }{IP: strings.TrimPrefix(server.URL, "http://")}) + defer os.Remove(file) + + cmd, output := s.traefikCmd(withConfigFile(file)) + defer output(c) + + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer s.killCmd(cmd) + + err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("PathPrefix(`/without`)")) + c.Assert(err, checker.IsNil) + + err = try.GetRequest("http://127.0.0.1:8001/without", 1*time.Second, try.StatusCodeIs(http.StatusOK)) + c.Assert(err, checker.IsNil) + + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8002/with-req", strings.NewReader("MORE THAN TEN BYTES IN REQUEST")) + c.Assert(err, checker.IsNil) + + // The request should fail because the body is too large. + err = try.Request(req, 1*time.Second, try.StatusCodeIs(http.StatusRequestEntityTooLarge)) + c.Assert(err, checker.IsNil) + + // The request should fail because the response exceeds the configured limit. + err = try.GetRequest("http://127.0.0.1:8003/with-resp", 1*time.Second, try.StatusCodeIs(http.StatusInternalServerError)) + c.Assert(err, checker.IsNil) + + request, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/metrics", nil) + c.Assert(err, checker.IsNil) + + response, err := http.DefaultClient.Do(request) + c.Assert(err, checker.IsNil) + c.Assert(response.StatusCode, checker.Equals, http.StatusOK) + + body, err := io.ReadAll(response.Body) + c.Assert(err, checker.IsNil) + + // For allowed requests and responses, the entrypoint and service metrics have the same status code. + c.Assert(string(body), checker.Contains, "traefik_entrypoint_requests_total{code=\"200\",entrypoint=\"webA\",method=\"GET\",protocol=\"http\"} 1") + c.Assert(string(body), checker.Contains, "traefik_entrypoint_requests_bytes_total{code=\"200\",entrypoint=\"webA\",method=\"GET\",protocol=\"http\"} 0") + c.Assert(string(body), checker.Contains, "traefik_entrypoint_responses_bytes_total{code=\"200\",entrypoint=\"webA\",method=\"GET\",protocol=\"http\"} 31") + + c.Assert(string(body), checker.Contains, "traefik_service_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"service-without@file\"} 1") + c.Assert(string(body), checker.Contains, "traefik_service_requests_bytes_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"service-without@file\"} 0") + c.Assert(string(body), checker.Contains, "traefik_service_responses_bytes_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"service-without@file\"} 31") + + // For forbidden requests, the entrypoints have metrics, the services don't. + c.Assert(string(body), checker.Contains, "traefik_entrypoint_requests_total{code=\"413\",entrypoint=\"webB\",method=\"GET\",protocol=\"http\"} 1") + c.Assert(string(body), checker.Contains, "traefik_entrypoint_requests_bytes_total{code=\"413\",entrypoint=\"webB\",method=\"GET\",protocol=\"http\"} 0") + c.Assert(string(body), checker.Contains, "traefik_entrypoint_responses_bytes_total{code=\"413\",entrypoint=\"webB\",method=\"GET\",protocol=\"http\"} 24") + + // For disallowed responses, the entrypoint and service metrics don't have the same status code. + c.Assert(string(body), checker.Contains, "traefik_entrypoint_requests_bytes_total{code=\"500\",entrypoint=\"webC\",method=\"GET\",protocol=\"http\"} 0") + c.Assert(string(body), checker.Contains, "traefik_entrypoint_requests_total{code=\"500\",entrypoint=\"webC\",method=\"GET\",protocol=\"http\"} 1") + c.Assert(string(body), checker.Contains, "traefik_entrypoint_responses_bytes_total{code=\"500\",entrypoint=\"webC\",method=\"GET\",protocol=\"http\"} 21") + + c.Assert(string(body), checker.Contains, "traefik_service_requests_bytes_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"service-resp@file\"} 0") + c.Assert(string(body), checker.Contains, "traefik_service_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"service-resp@file\"} 1") + c.Assert(string(body), checker.Contains, "traefik_service_responses_bytes_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"service-resp@file\"} 31") +} + func (s *SimpleSuite) TestMultipleProviderSameBackendName(c *check.C) { s.createComposeProject(c, "base") diff --git a/pkg/middlewares/accesslog/logger.go b/pkg/middlewares/accesslog/logger.go index 841728582..cf729c6de 100644 --- a/pkg/middlewares/accesslog/logger.go +++ b/pkg/middlewares/accesslog/logger.go @@ -227,6 +227,15 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request, next http core[ClientHost] = forwardedFor } + ctx := req.Context() + capt, err := capture.FromContext(ctx) + if err != nil { + log.FromContext(log.With(ctx, log.Str(log.MiddlewareType, "AccessLogs"))). + WithError(err). + Errorf("Could not get Capture") + return + } + next.ServeHTTP(rw, reqWithDataTable) if _, ok := core[ClientUsername]; !ok { @@ -237,13 +246,6 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request, next http headers: rw.Header().Clone(), } - ctx := req.Context() - capt, err := capture.FromContext(ctx) - if err != nil { - log.FromContext(log.With(ctx, log.Str(log.MiddlewareType, "AccessLogs"))).Errorf("Could not get Capture: %v", err) - return - } - logDataTable.DownstreamResponse.status = capt.StatusCode() logDataTable.DownstreamResponse.size = capt.ResponseSize() logDataTable.Request.size = capt.RequestSize() diff --git a/pkg/middlewares/accesslog/logger_test.go b/pkg/middlewares/accesslog/logger_test.go index b7b3b565e..80bda1530 100644 --- a/pkg/middlewares/accesslog/logger_test.go +++ b/pkg/middlewares/accesslog/logger_test.go @@ -57,7 +57,7 @@ func TestLogRotation(t *testing.T) { }) chain := alice.New() - chain = chain.Append(capture.WrapHandler(&capture.Handler{})) + chain = chain.Append(capture.Wrap) chain = chain.Append(WrapHandler(logHandler)) handler, err := chain.Then(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { rw.WriteHeader(http.StatusOK) @@ -210,7 +210,7 @@ func TestLoggerHeaderFields(t *testing.T) { } chain := alice.New() - chain = chain.Append(capture.WrapHandler(&capture.Handler{})) + chain = chain.Append(capture.Wrap) chain = chain.Append(WrapHandler(logger)) handler, err := chain.Then(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { rw.WriteHeader(http.StatusOK) @@ -784,7 +784,7 @@ func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS bool) { } chain := alice.New() - chain = chain.Append(capture.WrapHandler(&capture.Handler{})) + chain = chain.Append(capture.Wrap) chain = chain.Append(WrapHandler(logger)) handler, err := chain.Then(http.HandlerFunc(logWriterTestHandlerFunc)) require.NoError(t, err) diff --git a/pkg/middlewares/capture/capture.go b/pkg/middlewares/capture/capture.go index 6ee0ed399..845c2e983 100644 --- a/pkg/middlewares/capture/capture.go +++ b/pkg/middlewares/capture/capture.go @@ -3,9 +3,8 @@ // For another middleware to get those attributes of a request/response, this middleware // should be added before in the middleware chain. // -// handler, _ := NewHandler() // chain := alice.New(). -// Append(WrapHandler(handler)). +// Append(capture.Wrap). // Append(myOtherMiddleware). // then(...) // @@ -33,7 +32,6 @@ import ( "net" "net/http" - "github.com/containous/alice" "github.com/traefik/traefik/v2/pkg/middlewares" ) @@ -41,62 +39,67 @@ type key string const capturedData key = "capturedData" -// Handler will store each request data to its context. -type Handler struct{} - -// WrapHandler wraps capture handler into an Alice Constructor. -func WrapHandler(handler *Handler) alice.Constructor { - return func(next http.Handler) (http.Handler, error) { - return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - handler.ServeHTTP(rw, req, next) - }), nil - } +// Wrap returns a new handler that inserts a Capture into the given handler. +// It satisfies the alice.Constructor type. +func Wrap(handler http.Handler) (http.Handler, error) { + c := Capture{} + return c.Reset(handler), nil } -func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request, next http.Handler) { - c := Capture{} - if req.Body != nil { - readCounter := &readCounter{source: req.Body} - c.rr = readCounter - req.Body = readCounter +// FromContext returns the Capture value found in ctx, or an empty Capture otherwise. +func FromContext(ctx context.Context) (Capture, error) { + c := ctx.Value(capturedData) + if c == nil { + return Capture{}, errors.New("value not found in context") } - responseWriter := newResponseWriter(rw) - c.rw = responseWriter - ctx := context.WithValue(req.Context(), capturedData, &c) - next.ServeHTTP(responseWriter, req.WithContext(ctx)) + capt, ok := c.(*Capture) + if !ok { + return Capture{}, errors.New("value stored in context is not a *Capture") + } + return *capt, nil } // Capture is the object populated by the capture middleware, -// allowing to gather information about the request and response. +// holding probes that allow to gather information about the request and response. type Capture struct { rr *readCounter rw responseWriter } -// FromContext returns the Capture value found in ctx, or an empty Capture otherwise. -func FromContext(ctx context.Context) (*Capture, error) { - c := ctx.Value(capturedData) - if c == nil { - return nil, errors.New("value not found") - } - capt, ok := c.(*Capture) - if !ok { - return nil, errors.New("value stored in Context is not a *Capture") - } - return capt, nil +// NeedsReset returns whether the given http.ResponseWriter is the capture's probe. +func (c *Capture) NeedsReset(rw http.ResponseWriter) bool { + return c.rw != rw } -func (c Capture) ResponseSize() int64 { +// Reset returns a new handler that renews the Capture's probes, and inserts +// them when deferring to next. +func (c *Capture) Reset(next http.Handler) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + ctx := context.WithValue(req.Context(), capturedData, c) + newReq := req.WithContext(ctx) + + if newReq.Body != nil { + readCounter := &readCounter{source: newReq.Body} + c.rr = readCounter + newReq.Body = readCounter + } + c.rw = newResponseWriter(rw) + + next.ServeHTTP(c.rw, newReq) + }) +} + +func (c *Capture) ResponseSize() int64 { return c.rw.Size() } -func (c Capture) StatusCode() int { +func (c *Capture) StatusCode() int { return c.rw.Status() } // RequestSize returns the size of the request's body if it applies, // zero otherwise. -func (c Capture) RequestSize() int64 { +func (c *Capture) RequestSize() int64 { if c.rr == nil { return 0 } diff --git a/pkg/middlewares/capture/capture_test.go b/pkg/middlewares/capture/capture_test.go index f6718ad6e..9d8f91fcf 100644 --- a/pkg/middlewares/capture/capture_test.go +++ b/pkg/middlewares/capture/capture_test.go @@ -38,9 +38,8 @@ func TestCapture(t *testing.T) { assert.Equal(t, "bar", string(all)) }) - wrapped := WrapHandler(&Handler{}) chain := alice.New() - chain = chain.Append(wrapped) + chain = chain.Append(Wrap) chain = chain.Append(wrapMiddleware) handlers, err := chain.Then(handler) require.NoError(t, err) @@ -142,8 +141,7 @@ func BenchmarkCapture(b *testing.B) { chain := alice.New() if test.capture || test.body { - captureWrapped := WrapHandler(&Handler{}) - chain = chain.Append(captureWrapped) + chain = chain.Append(Wrap) } handlers, err := chain.Then(next) require.NoError(b, err) diff --git a/pkg/middlewares/metrics/metrics.go b/pkg/middlewares/metrics/metrics.go index 08d0185cc..48ff699c7 100644 --- a/pkg/middlewares/metrics/metrics.go +++ b/pkg/middlewares/metrics/metrics.go @@ -24,6 +24,7 @@ const ( protoWebsocket = "websocket" typeName = "Metrics" nameEntrypoint = "metrics-entrypoint" + nameRouter = "metrics-router" nameService = "metrics-service" ) @@ -56,7 +57,7 @@ func NewEntryPointMiddleware(ctx context.Context, next http.Handler, registry me // NewRouterMiddleware creates a new metrics middleware for a Router. func NewRouterMiddleware(ctx context.Context, next http.Handler, registry metrics.Registry, routerName string, serviceName string) http.Handler { - log.FromContext(middlewares.GetLoggerCtx(ctx, nameEntrypoint, typeName)).Debug("Creating middleware") + log.FromContext(middlewares.GetLoggerCtx(ctx, nameRouter, typeName)).Debug("Creating middleware") return &metricsMiddleware{ next: next, @@ -125,17 +126,25 @@ func (m *metricsMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request) m.reqsTLSCounter.With(tlsLabels...).Add(1) } - start := time.Now() - - m.next.ServeHTTP(rw, req) - ctx := req.Context() + capt, err := capture.FromContext(ctx) if err != nil { - log.FromContext(middlewares.GetLoggerCtx(ctx, nameEntrypoint, typeName)).Errorf("Could not get Capture: %w", err) + for i := 0; i < len(m.baseLabels); i += 2 { + ctx = log.With(ctx, log.Str(m.baseLabels[i], m.baseLabels[i+1])) + } + log.FromContext(ctx).WithError(err).Errorf("Could not get Capture") return } + next := m.next + if capt.NeedsReset(rw) { + next = capt.Reset(m.next) + } + + start := time.Now() + next.ServeHTTP(rw, req) + labels = append(labels, "code", strconv.Itoa(capt.StatusCode())) m.reqDurationHistogram.With(labels...).ObserveFromStart(start) m.reqsCounter.With(labels...).Add(1) diff --git a/pkg/server/middleware/chainbuilder.go b/pkg/server/middleware/chainbuilder.go index b4e1223a8..c5c833606 100644 --- a/pkg/server/middleware/chainbuilder.go +++ b/pkg/server/middleware/chainbuilder.go @@ -18,16 +18,14 @@ type ChainBuilder struct { metricsRegistry metrics.Registry accessLoggerMiddleware *accesslog.Handler tracer *tracing.Tracing - captureMiddleware *capture.Handler } // NewChainBuilder Creates a new ChainBuilder. -func NewChainBuilder(metricsRegistry metrics.Registry, accessLoggerMiddleware *accesslog.Handler, tracer *tracing.Tracing, captureMiddleware *capture.Handler) *ChainBuilder { +func NewChainBuilder(metricsRegistry metrics.Registry, accessLoggerMiddleware *accesslog.Handler, tracer *tracing.Tracing) *ChainBuilder { return &ChainBuilder{ metricsRegistry: metricsRegistry, accessLoggerMiddleware: accessLoggerMiddleware, tracer: tracer, - captureMiddleware: captureMiddleware, } } @@ -35,8 +33,8 @@ func NewChainBuilder(metricsRegistry metrics.Registry, accessLoggerMiddleware *a func (c *ChainBuilder) Build(ctx context.Context, entryPointName string) alice.Chain { chain := alice.New() - if c.captureMiddleware != nil { - chain = chain.Append(capture.WrapHandler(c.captureMiddleware)) + if c.accessLoggerMiddleware != nil || c.metricsRegistry != nil && (c.metricsRegistry.IsEpEnabled() || c.metricsRegistry.IsRouterEnabled() || c.metricsRegistry.IsSvcEnabled()) { + chain = chain.Append(capture.Wrap) } if c.accessLoggerMiddleware != nil { diff --git a/pkg/server/router/router_test.go b/pkg/server/router/router_test.go index 867da0a9b..26e8a68a3 100644 --- a/pkg/server/router/router_test.go +++ b/pkg/server/router/router_test.go @@ -316,7 +316,7 @@ func TestRouterManager_Get(t *testing.T) { roundTripperManager.Update(map[string]*dynamic.ServersTransport{"default@internal": {}}) serviceManager := service.NewManager(rtConf.Services, nil, nil, roundTripperManager) middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil) - chainBuilder := middleware.NewChainBuilder(nil, nil, nil, nil) + chainBuilder := middleware.NewChainBuilder(nil, nil, nil) routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry()) @@ -422,7 +422,7 @@ func TestAccessLog(t *testing.T) { roundTripperManager.Update(map[string]*dynamic.ServersTransport{"default@internal": {}}) serviceManager := service.NewManager(rtConf.Services, nil, nil, roundTripperManager) middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil) - chainBuilder := middleware.NewChainBuilder(nil, nil, nil, nil) + chainBuilder := middleware.NewChainBuilder(nil, nil, nil) routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry()) @@ -439,7 +439,7 @@ func TestAccessLog(t *testing.T) { reqHost := requestdecorator.New(nil) chain := alice.New() - chain = chain.Append(capture.WrapHandler(&capture.Handler{})) + chain = chain.Append(capture.Wrap) chain = chain.Append(accesslog.WrapHandler(accesslogger)) handler, err := chain.Then(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { reqHost.ServeHTTP(w, req, handlers["web"].ServeHTTP) @@ -717,7 +717,7 @@ func TestRuntimeConfiguration(t *testing.T) { roundTripperManager.Update(map[string]*dynamic.ServersTransport{"default@internal": {}}) serviceManager := service.NewManager(rtConf.Services, nil, nil, roundTripperManager) middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil) - chainBuilder := middleware.NewChainBuilder(nil, nil, nil, nil) + chainBuilder := middleware.NewChainBuilder(nil, nil, nil) routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry()) @@ -792,7 +792,7 @@ func TestProviderOnMiddlewares(t *testing.T) { roundTripperManager.Update(map[string]*dynamic.ServersTransport{"default@internal": {}}) serviceManager := service.NewManager(rtConf.Services, nil, nil, roundTripperManager) middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil) - chainBuilder := middleware.NewChainBuilder(nil, nil, nil, nil) + chainBuilder := middleware.NewChainBuilder(nil, nil, nil) routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry()) @@ -860,7 +860,7 @@ func BenchmarkRouterServe(b *testing.B) { serviceManager := service.NewManager(rtConf.Services, nil, nil, staticRoundTripperGetter{res}) middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil) - chainBuilder := middleware.NewChainBuilder(nil, nil, nil, nil) + chainBuilder := middleware.NewChainBuilder(nil, nil, nil) routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry()) diff --git a/pkg/server/routerfactory_test.go b/pkg/server/routerfactory_test.go index 0c6697e38..fdf4efc69 100644 --- a/pkg/server/routerfactory_test.go +++ b/pkg/server/routerfactory_test.go @@ -53,7 +53,7 @@ func TestReuseService(t *testing.T) { managerFactory := service.NewManagerFactory(staticConfig, nil, metrics.NewVoidRegistry(), roundTripperManager, nil) tlsManager := tls.NewManager() - factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(nil, nil, nil, nil), nil, metrics.NewVoidRegistry()) + factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(nil, nil, nil), nil, metrics.NewVoidRegistry()) entryPointsHandlers, _ := factory.CreateRouters(runtime.NewConfig(dynamic.Configuration{HTTP: dynamicConfigs})) @@ -189,7 +189,7 @@ func TestServerResponseEmptyBackend(t *testing.T) { managerFactory := service.NewManagerFactory(staticConfig, nil, metrics.NewVoidRegistry(), roundTripperManager, nil) tlsManager := tls.NewManager() - factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(nil, nil, nil, nil), nil, metrics.NewVoidRegistry()) + factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(nil, nil, nil), nil, metrics.NewVoidRegistry()) entryPointsHandlers, _ := factory.CreateRouters(runtime.NewConfig(dynamic.Configuration{HTTP: test.config(testServer.URL)})) @@ -232,7 +232,7 @@ func TestInternalServices(t *testing.T) { voidRegistry := metrics.NewVoidRegistry() - factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(voidRegistry, nil, nil, nil), nil, voidRegistry) + factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(voidRegistry, nil, nil), nil, voidRegistry) entryPointsHandlers, _ := factory.CreateRouters(runtime.NewConfig(dynamic.Configuration{HTTP: dynamicConfigs})) From 15f747209130b9db440aea90f815a2aa85e68b6d Mon Sep 17 00:00:00 2001 From: Kevin Pollet Date: Thu, 27 Oct 2022 16:53:16 +0200 Subject: [PATCH 3/5] Prepare release v2.9.2 --- CHANGELOG.md | 16 ++++++++++++++++ script/gcg/traefik-bugfix.toml | 6 +++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c14767d8..f4baf1d31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## [v2.9.2](https://github.com/traefik/traefik/tree/v2.9.2) (2022-10-27) +[All Commits](https://github.com/traefik/traefik/compare/v2.9.1...v2.9.2) + +**Bug fixes:** +- **[acme]** Update go-acme/lego to v4.9.0 ([#9413](https://github.com/traefik/traefik/pull/9413) by [tony-defa](https://github.com/tony-defa)) +- **[kv,redis]** Fix Redis configuration type ([#9435](https://github.com/traefik/traefik/pull/9435) by [ldez](https://github.com/ldez)) +- **[logs,middleware,metrics]** Handle capture on redefined http.responseWriters ([#9440](https://github.com/traefik/traefik/pull/9440) by [rtribotte](https://github.com/rtribotte)) +- **[middleware,k8s]** Remove raw cert escape in PassTLSClientCert middleware ([#9412](https://github.com/traefik/traefik/pull/9412) by [rtribotte](https://github.com/rtribotte)) +- **[plugins]** Update Yaegi to v0.14.3 ([#9468](https://github.com/traefik/traefik/pull/9468) by [ldez](https://github.com/ldez)) +- Remove side effect on default transport tests ([#9460](https://github.com/traefik/traefik/pull/9460) by [sdelicata](https://github.com/sdelicata)) + +**Documentation:** +- **[k8s]** Fix links to gateway API guides ([#9445](https://github.com/traefik/traefik/pull/9445) by [kevinpollet](https://github.com/kevinpollet)) +- Simplify dashboard rule example ([#9454](https://github.com/traefik/traefik/pull/9454) by [sosoba](https://github.com/sosoba)) +- Add v2.9 to release page ([#9438](https://github.com/traefik/traefik/pull/9438) by [kevinpollet](https://github.com/kevinpollet)) + ## [v2.9.1](https://github.com/traefik/traefik/tree/v2.9.1) (2022-10-03) [All Commits](https://github.com/traefik/traefik/compare/v2.9.0-rc1...v2.9.1) diff --git a/script/gcg/traefik-bugfix.toml b/script/gcg/traefik-bugfix.toml index 46502fc32..228224a30 100644 --- a/script/gcg/traefik-bugfix.toml +++ b/script/gcg/traefik-bugfix.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example new bugfix v2.9.1 +# example new bugfix v2.9.2 CurrentRef = "v2.9" -PreviousRef = "v2.9.0" +PreviousRef = "v2.9.1" BaseBranch = "v2.9" -FutureCurrentRefName = "v2.9.0" +FutureCurrentRefName = "v2.9.2" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 From 725804840371c77cd2648d2f3661c4039200bb7b Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Thu, 27 Oct 2022 17:50:48 +0200 Subject: [PATCH 4/5] Prepare release v2.9.3 --- .goreleaser.yml | 11 ++++++----- CHANGELOG.md | 9 +++++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 27bc16cd2..9194b4a1e 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -22,22 +22,23 @@ builds: - openbsd goarch: - amd64 - - 386 + - '386' - arm - arm64 - ppc64le - s390x goarm: - - 7 - - 6 - - 5 + - '7' + - '6' ignore: - goos: darwin - goarch: 386 + goarch: '386' - goos: openbsd goarch: arm - goos: openbsd goarch: arm64 + - goos: freebsd + goarch: arm - goos: freebsd goarch: arm64 - goos: windows diff --git a/CHANGELOG.md b/CHANGELOG.md index f4baf1d31..2b0fa7934 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ -## [v2.9.2](https://github.com/traefik/traefik/tree/v2.9.2) (2022-10-27) -[All Commits](https://github.com/traefik/traefik/compare/v2.9.1...v2.9.2) +## [v2.9.3](https://github.com/traefik/traefik/tree/v2.9.3) (2022-10-27) +[All Commits](https://github.com/traefik/traefik/compare/v2.9.1...v2.9.3) **Bug fixes:** - **[acme]** Update go-acme/lego to v4.9.0 ([#9413](https://github.com/traefik/traefik/pull/9413) by [tony-defa](https://github.com/tony-defa)) @@ -14,6 +14,11 @@ - Simplify dashboard rule example ([#9454](https://github.com/traefik/traefik/pull/9454) by [sosoba](https://github.com/sosoba)) - Add v2.9 to release page ([#9438](https://github.com/traefik/traefik/pull/9438) by [kevinpollet](https://github.com/kevinpollet)) +## [v2.9.2](https://github.com/traefik/traefik/tree/v2.9.2) (2022-10-27) +[All Commits](https://github.com/traefik/traefik/compare/v2.9.1...v2.9.2) + +Release canceled. + ## [v2.9.1](https://github.com/traefik/traefik/tree/v2.9.1) (2022-10-03) [All Commits](https://github.com/traefik/traefik/compare/v2.9.0-rc1...v2.9.1) From 454f552691015d5f01041f61ae0cca0cff5d5d5d Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Thu, 27 Oct 2022 20:40:05 +0200 Subject: [PATCH 5/5] Prepare release v2.9.4 --- CHANGELOG.md | 9 +++++++-- Makefile | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b0fa7934..03cf18a10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ -## [v2.9.3](https://github.com/traefik/traefik/tree/v2.9.3) (2022-10-27) -[All Commits](https://github.com/traefik/traefik/compare/v2.9.1...v2.9.3) +## [v2.9.4](https://github.com/traefik/traefik/tree/v2.9.4) (2022-10-27) +[All Commits](https://github.com/traefik/traefik/compare/v2.9.1...v2.9.4) **Bug fixes:** - **[acme]** Update go-acme/lego to v4.9.0 ([#9413](https://github.com/traefik/traefik/pull/9413) by [tony-defa](https://github.com/tony-defa)) @@ -14,6 +14,11 @@ - Simplify dashboard rule example ([#9454](https://github.com/traefik/traefik/pull/9454) by [sosoba](https://github.com/sosoba)) - Add v2.9 to release page ([#9438](https://github.com/traefik/traefik/pull/9438) by [kevinpollet](https://github.com/kevinpollet)) +## [v2.9.3](https://github.com/traefik/traefik/tree/v2.9.3) (2022-10-27) +[All Commits](https://github.com/traefik/traefik/compare/v2.9.1...v2.9.3) + +Release canceled. + ## [v2.9.2](https://github.com/traefik/traefik/tree/v2.9.2) (2022-10-27) [All Commits](https://github.com/traefik/traefik/compare/v2.9.1...v2.9.2) diff --git a/Makefile b/Makefile index c04dc40e7..0c957b003 100644 --- a/Makefile +++ b/Makefile @@ -189,7 +189,7 @@ generate-genconf: .PHONY: release-packages release-packages: generate-webui build-dev-image rm -rf dist - $(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) goreleaser release --skip-publish --timeout="90m" + $(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) goreleaser release --skip-publish -p 4 --timeout="90m" $(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) tar cfz dist/traefik-${VERSION}.src.tar.gz \ --exclude-vcs \ --exclude .idea \