Compare commits

...

4 Commits

Author SHA1 Message Date
Kevin Pollet
ce42e8501e
Prepare release v3.4.0 2025-05-05 15:34:04 +02:00
kevinpollet
bf399f3075
Merge branch v3.3 into v3.4 2025-05-05 11:08:36 +02:00
Romain
74bc93308b
Prepare release v3.3.7 2025-05-05 10:38:04 +02:00
Romain
87b57406ff
Add SpanID and TraceID accessLogs fields only when tracing is enabled 2025-04-28 14:26:05 +02:00
7 changed files with 147 additions and 37 deletions

View File

@ -3,11 +3,11 @@ PLEASE READ THIS MESSAGE.
Documentation fixes or enhancements: Documentation fixes or enhancements:
- for Traefik v2: use branch v2.11 - for Traefik v2: use branch v2.11
- for Traefik v3: use branch v3.3 - for Traefik v3: use branch v3.4
Bug fixes: Bug fixes:
- for Traefik v2: use branch v2.11 - for Traefik v2: use branch v2.11
- for Traefik v3: use branch v3.3 - for Traefik v3: use branch v3.4
Enhancements: Enhancements:
- for Traefik v2: we only accept bug fixes - for Traefik v2: we only accept bug fixes

View File

@ -1,3 +1,47 @@
## [v3.4.0](https://github.com/traefik/traefik/tree/v3.4.0) (2025-05-05)
[All Commits](https://github.com/traefik/traefik/compare/v3.3.0-rc1...v3.4.0)
**Enhancements:**
- **[acme]** Add acme.profile and acme.emailAddresses options ([#11597](https://github.com/traefik/traefik/pull/11597) by [ldez](https://github.com/ldez))
- **[docker,ecs,docker/swarm,consulcatalog,nomad]** Allow configuring server URLs with label providers ([#11374](https://github.com/traefik/traefik/pull/11374) by [yelvert](https://github.com/yelvert))
- **[k8s/crd]** Improve CEL validation on Ingress CRD resources ([#11311](https://github.com/traefik/traefik/pull/11311) by [mloiseleur](https://github.com/mloiseleur))
- **[k8s/crd]** Remove default load-balancing strategy from CRD ([#11701](https://github.com/traefik/traefik/pull/11701) by [kevinpollet](https://github.com/kevinpollet))
- **[k8s/crd]** Restrict regex validation of HTTP status codes for Ingress CRD resources ([#11670](https://github.com/traefik/traefik/pull/11670) by [jnoordsij](https://github.com/jnoordsij))
- **[k8s/gatewayapi]** Set rule priority in Gateway API TLSRoute ([#11443](https://github.com/traefik/traefik/pull/11443) by [augustozanellato](https://github.com/augustozanellato))
- **[k8s/ingress]** Add ingress status for ClusterIP and NodePort Service Type ([#11100](https://github.com/traefik/traefik/pull/11100) by [mlec1](https://github.com/mlec1))
- **[middleware,authentication]** Add option to preserve request method in forwardAuth ([#11473](https://github.com/traefik/traefik/pull/11473) by [an09mous](https://github.com/an09mous))
- **[middleware]** Support rewriting status codes in error page middleware ([#11520](https://github.com/traefik/traefik/pull/11520) by [sevensolutions](https://github.com/sevensolutions))
- **[middleware]** Add Redis rate limiter ([#10211](https://github.com/traefik/traefik/pull/10211) by [longquan0104](https://github.com/longquan0104))
- **[service]** Add p2c load-balancing strategy for servers load-balancer ([#11547](https://github.com/traefik/traefik/pull/11547) by [rtribotte](https://github.com/rtribotte))
- **[sticky-session]** Support domain configuration for sticky cookies ([#11556](https://github.com/traefik/traefik/pull/11556) by [jleal52](https://github.com/jleal52))
- **[tls,k8s/crd,service]** Allow root CA to be added through config maps ([#11475](https://github.com/traefik/traefik/pull/11475) by [Nelwhix](https://github.com/Nelwhix))
- **[tls]** Add support to disable session ticket ([#11609](https://github.com/traefik/traefik/pull/11609) by [avdhoot](https://github.com/avdhoot))
- **[udp]** Add support for UDP routing in systemd socket activation ([#11022](https://github.com/traefik/traefik/pull/11022) by [tsiid](https://github.com/tsiid))
- **[webui]** Add auto webui theme option and default to it ([#11455](https://github.com/traefik/traefik/pull/11455) by [zizzfizzix](https://github.com/zizzfizzix))
- Replace experimental maps and slices with stdlib ([#11350](https://github.com/traefik/traefik/pull/11350) by [Juneezee](https://github.com/Juneezee))
- Bump github.com/redis/go-redis/v9 to v9.7.3 ([#11687](https://github.com/traefik/traefik/pull/11687) by [kevinpollet](https://github.com/kevinpollet))
**Documentation:**
- Prepare release v3.4.0-rc1 ([#11654](https://github.com/traefik/traefik/pull/11654) by [kevinpollet](https://github.com/kevinpollet))
- Prepare release v3.4.0-rc2 ([#11707](https://github.com/traefik/traefik/pull/11707) by [rtribotte](https://github.com/rtribotte))
- Deprecate defaultRuleSyntax and ruleSyntax options ([#11619](https://github.com/traefik/traefik/pull/11619) by [rtribotte](https://github.com/rtribotte))
**Misc:**
- Merge branch v3.3 into master ([#11653](https://github.com/traefik/traefik/pull/11653) by [kevinpollet](https://github.com/kevinpollet))
- Merge branch v3.3 into master ([#11595](https://github.com/traefik/traefik/pull/11595) by [kevinpollet](https://github.com/kevinpollet))
- Merge branch v3.3 into master ([#11541](https://github.com/traefik/traefik/pull/11541) by [kevinpollet](https://github.com/kevinpollet))
- Merge branch v3.3 into master ([#11504](https://github.com/traefik/traefik/pull/11504) by [kevinpollet](https://github.com/kevinpollet))
- Merge branch v3.3 into master ([#11420](https://github.com/traefik/traefik/pull/11420) by [kevinpollet](https://github.com/kevinpollet))
- Merge branch v3.3 into master ([#11394](https://github.com/traefik/traefik/pull/11394) by [mmatur](https://github.com/mmatur))
- Merge branch v3.3 into v3.4 ([#11736](https://github.com/traefik/traefik/pull/11736) by [kevinpollet](https://github.com/kevinpollet))
- Merge branch v3.3 into v3.4 ([#11705](https://github.com/traefik/traefik/pull/11705) by [kevinpollet](https://github.com/kevinpollet))
## [v3.3.7](https://github.com/traefik/traefik/tree/v3.3.7) (2025-05-05)
[All Commits](https://github.com/traefik/traefik/compare/v3.3.6...v3.3.7)
**Bug fixes:**
- **[logs,middleware,accesslogs]** Add SpanID and TraceID accessLogs fields only when tracing is enabled ([#11715](https://github.com/traefik/traefik/pull/11715) by [rtribotte](https://github.com/rtribotte))
## [v3.4.0-rc2](https://github.com/traefik/traefik/tree/v3.4.0-rc2) (2025-04-18) ## [v3.4.0-rc2](https://github.com/traefik/traefik/tree/v3.4.0-rc2) (2025-04-18)
[All Commits](https://github.com/traefik/traefik/compare/v3.4.0-rc1...v3.4.0-rc2) [All Commits](https://github.com/traefik/traefik/compare/v3.4.0-rc1...v3.4.0-rc2)

View File

@ -212,9 +212,11 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request, next http
if span := trace.SpanFromContext(req.Context()); span != nil { if span := trace.SpanFromContext(req.Context()); span != nil {
spanContext := span.SpanContext() spanContext := span.SpanContext()
if spanContext.HasTraceID() && spanContext.HasSpanID() {
logDataTable.Core[TraceID] = spanContext.TraceID().String() logDataTable.Core[TraceID] = spanContext.TraceID().String()
logDataTable.Core[SpanID] = spanContext.SpanID().String() logDataTable.Core[SpanID] = spanContext.SpanID().String()
} }
}
reqWithDataTable := req.WithContext(context.WithValue(req.Context(), DataTableKey, logDataTable)) reqWithDataTable := req.WithContext(context.WithValue(req.Context(), DataTableKey, logDataTable))

View File

@ -27,8 +27,10 @@ import (
"github.com/traefik/traefik/v3/pkg/middlewares/capture" "github.com/traefik/traefik/v3/pkg/middlewares/capture"
"github.com/traefik/traefik/v3/pkg/types" "github.com/traefik/traefik/v3/pkg/types"
"go.opentelemetry.io/collector/pdata/plog/plogotlp" "go.opentelemetry.io/collector/pdata/plog/plogotlp"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/noop" "go.opentelemetry.io/otel/trace/embedded"
) )
const delta float64 = 1e-10 const delta float64 = 1e-10
@ -310,7 +312,7 @@ func TestLoggerHeaderFields(t *testing.T) {
func TestLoggerCLF(t *testing.T) { func TestLoggerCLF(t *testing.T) {
logFilePath := filepath.Join(t.TempDir(), logFileNameSuffix) logFilePath := filepath.Join(t.TempDir(), logFileNameSuffix)
config := &types.AccessLog{FilePath: logFilePath, Format: CommonFormat} config := &types.AccessLog{FilePath: logFilePath, Format: CommonFormat}
doLogging(t, config) doLogging(t, config, false)
logData, err := os.ReadFile(logFilePath) logData, err := os.ReadFile(logFilePath)
require.NoError(t, err) require.NoError(t, err)
@ -322,7 +324,7 @@ func TestLoggerCLF(t *testing.T) {
func TestLoggerCLFWithBufferingSize(t *testing.T) { func TestLoggerCLFWithBufferingSize(t *testing.T) {
logFilePath := filepath.Join(t.TempDir(), logFileNameSuffix) logFilePath := filepath.Join(t.TempDir(), logFileNameSuffix)
config := &types.AccessLog{FilePath: logFilePath, Format: CommonFormat, BufferingSize: 1024} config := &types.AccessLog{FilePath: logFilePath, Format: CommonFormat, BufferingSize: 1024}
doLogging(t, config) doLogging(t, config, false)
// wait a bit for the buffer to be written in the file. // wait a bit for the buffer to be written in the file.
time.Sleep(50 * time.Millisecond) time.Sleep(50 * time.Millisecond)
@ -371,10 +373,11 @@ func TestLoggerJSON(t *testing.T) {
desc string desc string
config *types.AccessLog config *types.AccessLog
tls bool tls bool
tracing bool
expected map[string]func(t *testing.T, value interface{}) expected map[string]func(t *testing.T, value interface{})
}{ }{
{ {
desc: "default config", desc: "default config without tracing",
config: &types.AccessLog{ config: &types.AccessLog{
FilePath: "", FilePath: "",
Format: JSONFormat, Format: JSONFormat,
@ -410,8 +413,48 @@ func TestLoggerJSON(t *testing.T) {
"time": assertNotEmpty(), "time": assertNotEmpty(),
"StartLocal": assertNotEmpty(), "StartLocal": assertNotEmpty(),
"StartUTC": assertNotEmpty(), "StartUTC": assertNotEmpty(),
TraceID: assertNotEmpty(), },
SpanID: assertNotEmpty(), },
{
desc: "default config with tracing",
config: &types.AccessLog{
FilePath: "",
Format: JSONFormat,
},
tracing: true,
expected: map[string]func(t *testing.T, value interface{}){
RequestContentSize: assertFloat64(0),
RequestHost: assertString(testHostname),
RequestAddr: assertString(testHostname),
RequestMethod: assertString(testMethod),
RequestPath: assertString(testPath),
RequestProtocol: assertString(testProto),
RequestScheme: assertString(testScheme),
RequestPort: assertString("-"),
DownstreamStatus: assertFloat64(float64(testStatus)),
DownstreamContentSize: assertFloat64(float64(len(testContent))),
OriginContentSize: assertFloat64(float64(len(testContent))),
OriginStatus: assertFloat64(float64(testStatus)),
RequestRefererHeader: assertString(testReferer),
RequestUserAgentHeader: assertString(testUserAgent),
RouterName: assertString(testRouterName),
ServiceURL: assertString(testServiceName),
ClientUsername: assertString(testUsername),
ClientHost: assertString(testHostname),
ClientPort: assertString(strconv.Itoa(testPort)),
ClientAddr: assertString(fmt.Sprintf("%s:%d", testHostname, testPort)),
"level": assertString("info"),
"msg": assertString(""),
"downstream_Content-Type": assertString("text/plain; charset=utf-8"),
RequestCount: assertFloat64NotZero(),
Duration: assertFloat64NotZero(),
Overhead: assertFloat64NotZero(),
RetryAttempts: assertFloat64(float64(testRetryAttempts)),
"time": assertNotEmpty(),
"StartLocal": assertNotEmpty(),
"StartUTC": assertNotEmpty(),
TraceID: assertString("01000000000000000000000000000000"),
SpanID: assertString("0100000000000000"),
}, },
}, },
{ {
@ -455,8 +498,6 @@ func TestLoggerJSON(t *testing.T) {
"time": assertNotEmpty(), "time": assertNotEmpty(),
StartLocal: assertNotEmpty(), StartLocal: assertNotEmpty(),
StartUTC: assertNotEmpty(), StartUTC: assertNotEmpty(),
TraceID: assertNotEmpty(),
SpanID: assertNotEmpty(),
}, },
}, },
{ {
@ -578,9 +619,9 @@ func TestLoggerJSON(t *testing.T) {
test.config.FilePath = logFilePath test.config.FilePath = logFilePath
if test.tls { if test.tls {
doLoggingTLS(t, test.config) doLoggingTLS(t, test.config, test.tracing)
} else { } else {
doLogging(t, test.config) doLogging(t, test.config, test.tracing)
} }
logData, err := os.ReadFile(logFilePath) logData, err := os.ReadFile(logFilePath)
@ -632,8 +673,6 @@ func TestLogger_AbortedRequest(t *testing.T) {
"downstream_Content-Type": assertString("text/plain"), "downstream_Content-Type": assertString("text/plain"),
"downstream_Transfer-Encoding": assertString("chunked"), "downstream_Transfer-Encoding": assertString("chunked"),
"downstream_Cache-Control": assertString("no-cache"), "downstream_Cache-Control": assertString("no-cache"),
TraceID: assertNotEmpty(),
SpanID: assertNotEmpty(),
} }
config := &types.AccessLog{ config := &types.AccessLog{
@ -854,7 +893,7 @@ func TestNewLogHandlerOutputStdout(t *testing.T) {
file, restoreStdout := captureStdout(t) file, restoreStdout := captureStdout(t)
defer restoreStdout() defer restoreStdout()
doLogging(t, test.config) doLogging(t, test.config, false)
written, err := os.ReadFile(file.Name()) written, err := os.ReadFile(file.Name())
require.NoError(t, err, "unable to read captured stdout from file") require.NoError(t, err, "unable to read captured stdout from file")
@ -913,7 +952,7 @@ func captureStdout(t *testing.T) (out *os.File, restoreStdout func()) {
return file, restoreStdout return file, restoreStdout
} }
func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS bool) { func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS, tracing bool) {
t.Helper() t.Helper()
logger, err := NewHandler(config) logger, err := NewHandler(config)
require.NoError(t, err) require.NoError(t, err)
@ -952,9 +991,10 @@ func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS bool) {
} }
} }
tracer := noop.Tracer{} if tracing {
spanCtx, _ := tracer.Start(req.Context(), "test") contextWithSpan := trace.ContextWithSpan(req.Context(), &mockSpan{})
req = req.WithContext(spanCtx) req = req.WithContext(contextWithSpan)
}
chain := alice.New() chain := alice.New()
chain = chain.Append(capture.Wrap) chain = chain.Append(capture.Wrap)
@ -965,16 +1005,16 @@ func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS bool) {
handler.ServeHTTP(httptest.NewRecorder(), req) handler.ServeHTTP(httptest.NewRecorder(), req)
} }
func doLoggingTLS(t *testing.T, config *types.AccessLog) { func doLoggingTLS(t *testing.T, config *types.AccessLog, tracing bool) {
t.Helper() t.Helper()
doLoggingTLSOpt(t, config, true) doLoggingTLSOpt(t, config, true, tracing)
} }
func doLogging(t *testing.T, config *types.AccessLog) { func doLogging(t *testing.T, config *types.AccessLog, tracing bool) {
t.Helper() t.Helper()
doLoggingTLSOpt(t, config, false) doLoggingTLSOpt(t, config, false, tracing)
} }
func logWriterTestHandlerFunc(rw http.ResponseWriter, r *http.Request) { func logWriterTestHandlerFunc(rw http.ResponseWriter, r *http.Request) {
@ -1091,3 +1131,27 @@ func streamBackend(rw http.ResponseWriter, r *http.Request) {
} }
} }
} }
// mockSpan is an implementation of Span that preforms no operations.
type mockSpan struct {
embedded.Span
}
var _ trace.Span = &mockSpan{}
func (*mockSpan) SpanContext() trace.SpanContext {
return trace.NewSpanContext(trace.SpanContextConfig{TraceID: trace.TraceID{1}, SpanID: trace.SpanID{1}})
}
func (*mockSpan) IsRecording() bool { return true }
func (s *mockSpan) SetStatus(_ codes.Code, _ string) {}
func (s *mockSpan) SetAttributes(...attribute.KeyValue) {}
func (s *mockSpan) End(...trace.SpanEndOption) {}
func (s *mockSpan) RecordError(_ error, _ ...trace.EventOption) {}
func (s *mockSpan) AddEvent(_ string, _ ...trace.EventOption) {}
func (s *mockSpan) AddLink(_ trace.Link) {}
func (s *mockSpan) SetName(_ string) {}
func (s *mockSpan) TracerProvider() trace.TracerProvider {
return nil
}

View File

@ -4,11 +4,11 @@ RepositoryName = "traefik"
OutputType = "file" OutputType = "file"
FileName = "traefik_changelog.md" FileName = "traefik_changelog.md"
# example new bugfix v3.3.6 # example new bugfix v3.3.7
CurrentRef = "v3.3" CurrentRef = "v3.3"
PreviousRef = "v3.3.5" PreviousRef = "v3.3.6"
BaseBranch = "v3.3" BaseBranch = "v3.3"
FutureCurrentRefName = "v3.3.6" FutureCurrentRefName = "v3.3.7"
ThresholdPreviousRef = 10 ThresholdPreviousRef = 10
ThresholdCurrentRef = 10 ThresholdCurrentRef = 10

View File

@ -4,11 +4,11 @@ RepositoryName = "traefik"
OutputType = "file" OutputType = "file"
FileName = "traefik_changelog.md" FileName = "traefik_changelog.md"
# example final release of v3.3.0 # example final release of v3.4.0
CurrentRef = "v3.3" CurrentRef = "v3.4"
PreviousRef = "v3.3.0-rc1" PreviousRef = "v3.4.0-rc1"
BaseBranch = "v3.3" BaseBranch = "v3.4"
FutureCurrentRefName = "v3.3.0" FutureCurrentRefName = "v3.4.0"
ThresholdPreviousRef = 10 ThresholdPreviousRef = 10
ThresholdCurrentRef = 10 ThresholdCurrentRef = 10

View File

@ -4,11 +4,11 @@ RepositoryName = "traefik"
OutputType = "file" OutputType = "file"
FileName = "traefik_changelog.md" FileName = "traefik_changelog.md"
# example final release of v3.3.0 # example final release of v3.4.0
CurrentRef = "v3.3.0-rc1" CurrentRef = "v3.4.0-rc1"
PreviousRef = "v3.2.0-rc1" PreviousRef = "v3.3.0-rc1"
BaseBranch = "master" BaseBranch = "master"
FutureCurrentRefName = "v3.3.0" FutureCurrentRefName = "v3.4.0"
ThresholdPreviousRef = 10 ThresholdPreviousRef = 10
ThresholdCurrentRef = 10 ThresholdCurrentRef = 10