Repository: traefik/traefik (language: go)

Issue:
Title: TraceID missing from access logs in Traefik v3.3 with the same configuration as v3.2
### Welcome!

- [x] Yes, I've searched similar issues on [GitHub](https://github.com/traefik/traefik/issues) and didn't find any.
- [x] Yes, I've searched similar issues on the [Traefik community forum](https://community.traefik.io) and didn't find any.

### What did you do?

Title: TraceID missing from access logs in Traefik v3.3 with the same configuration as v3.2
```
3.2 {"ClientAddr":"192.168.113.194:55139","ClientHost":"192.168.113.194","ClientPort":"55139","DownstreamContentSize":701,"DownstreamStatus":200,"Duration":899236,"OriginContentSize":701,"OriginDuration":795168,"OriginStatus":200,"Overhead":104068,"RequestAddr":"test.com","RequestContentSize":0,"RequestCount":1,"RequestHost":"test.com","RequestMethod":"GET","RequestPath":"/","RequestPort":"-","RequestProtocol":"HTTP/1.1","RequestScheme":"http","RetryAttempts":0,"RouterName":"jupyterhub@file","ServiceAddr":"0.0.0.0:8084","ServiceName":"service-jupyterhub@file","ServiceURL":"http://0.0.0.0:8084","SpanId":"8263e0541e1a448a","StartLocal":"2025-01-15T20:57:12.523173048+08:00","StartUTC":"2025-01-15T12:57:12.523173048Z","TraceId":"9fd814b6a08c05099ca01d65886d0dcf","entryPointName":"http","level":"info","msg":"","time":"2025-01-15T20:57:12+08:00"}
```
```
3.3
{"ClientAddr":"192.168.113.194:56710","ClientHost":"192.168.113.194","ClientPort":"56710","DownstreamContentSize":701,"DownstreamStatus":200,"Duration":651922,"OriginContentSize":701,"OriginDuration":575498,"OriginStatus":200,"Overhead":76424,"RequestAddr":"test.com","RequestContentSize":0,"RequestCount":3,"RequestHost":"test.com","RequestMethod":"GET","RequestPath":"/","RequestPort":"-","RequestProtocol":"HTTP/1.1","RequestScheme":"http","RetryAttempts":0,"RouterName":"jupyterhub@file","ServiceAddr":"0.0.0.0:8084","ServiceName":"service-jupyterhub@file","ServiceURL":"http://0.0.0.0:8084","StartLocal":"2025-01-15T21:03:43.627955701+08:00","downstream_Content-Length":"701","downstream_Content-Type":"text/plain; charset=utf-8","downstream_Date":"Wed, 15 Jan 2025 13:03:43 GMT","entryPointName":"web","level":"info","msg":"","origin_Content-Length":"701","origin_Content-Type":"text/plain; charset=utf-8","origin_Date":"Wed, 15 Jan 2025 13:03:43 GMT","request_Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","request_Accept-Encoding":"gzip, deflate","request_Accept-Language":"zh-CN,zh-Hans;q=0.9","request_Priority":"u=0, i","request_Upgrade-Insecure-Requests":"1","request_User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Safari/605.1.15","request_X-Forwarded-Host":"test.com","request_X-Forwarded-Port":"80","request_X-Forwarded-Proto":"http","request_X-Forwarded-Server":"xingchen-debian","request_X-Real-Ip":"192.168.113.194","time":"2025-01-15T21:03:43+08:00"}

```

### What did you see instead?

None

### What version of Traefik are you using?

Version:      3.3.2
Codename:     saintnectaire
Go version:   go1.23.4
Built:        2025-01-14T15:52:24Z
OS/Arch:      linux/amd6

### What is your environment & configuration?

```toml
[accessLog]
  filePath = "/var/log/traefik-access.log"
  bufferingSize = 100
  format = "json"
  [accessLog.fields]
    defaultMode = "keep"
    [accessLog.fields.names]
      "ClientUsername" = "drop"
      "StartUTC" = "drop"
    [accessLog.fields.headers]
      defaultMode = "keep"
```

Add more configuration information here.


### If applicable, please paste the log output in DEBUG level

_No response_


Discussion / hints:

Fix patch:
diff --git a/pkg/middlewares/accesslog/logger.go b/pkg/middlewares/accesslog/logger.go
index dec5b29009..e0c2582bcf 100644
--- a/pkg/middlewares/accesslog/logger.go
+++ b/pkg/middlewares/accesslog/logger.go
@@ -24,6 +24,7 @@ import (
 	traefiktls "github.com/traefik/traefik/v3/pkg/tls"
 	"github.com/traefik/traefik/v3/pkg/types"
 	"go.opentelemetry.io/contrib/bridges/otellogrus"
+	"go.opentelemetry.io/otel/trace"
 )
 
 type key string
@@ -209,6 +210,12 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request, next http
 		},
 	}
 
+	if span := trace.SpanFromContext(req.Context()); span != nil {
+		spanContext := span.SpanContext()
+		logDataTable.Core[TraceID] = spanContext.TraceID().String()
+		logDataTable.Core[SpanID] = spanContext.SpanID().String()
+	}
+
 	reqWithDataTable := req.WithContext(context.WithValue(req.Context(), DataTableKey, logDataTable))
 
 	core[RequestCount] = nextRequestCount()
diff --git a/pkg/middlewares/observability/entrypoint.go b/pkg/middlewares/observability/entrypoint.go
index 8b356b03b8..64b89b9213 100644
--- a/pkg/middlewares/observability/entrypoint.go
+++ b/pkg/middlewares/observability/entrypoint.go
@@ -8,7 +8,6 @@ import (
 	"github.com/containous/alice"
 	"github.com/rs/zerolog/log"
 	"github.com/traefik/traefik/v3/pkg/middlewares"
-	"github.com/traefik/traefik/v3/pkg/middlewares/accesslog"
 	"github.com/traefik/traefik/v3/pkg/tracing"
 	"go.opentelemetry.io/otel/attribute"
 	"go.opentelemetry.io/otel/trace"
@@ -63,12 +62,6 @@ func (e *entryPointTracing) ServeHTTP(rw http.ResponseWriter, req *http.Request)
 
 	e.tracer.CaptureServerRequest(span, req)
 
-	if logData := accesslog.GetLogData(req); logData != nil {
-		spanContext := span.SpanContext()
-		logData.Core[accesslog.TraceID] = spanContext.TraceID().String()
-		logData.Core[accesslog.SpanID] = spanContext.SpanID().String()
-	}
-
 	recorder := newStatusCodeRecorder(rw, http.StatusOK)
 	e.next.ServeHTTP(recorder, req)
 


Test patch:
diff --git a/pkg/middlewares/accesslog/logger_test.go b/pkg/middlewares/accesslog/logger_test.go
index 43cec09014..f7721966fe 100644
--- a/pkg/middlewares/accesslog/logger_test.go
+++ b/pkg/middlewares/accesslog/logger_test.go
@@ -28,6 +28,7 @@ import (
 	"github.com/traefik/traefik/v3/pkg/types"
 	"go.opentelemetry.io/collector/pdata/plog/plogotlp"
 	"go.opentelemetry.io/otel/trace"
+	"go.opentelemetry.io/otel/trace/noop"
 )
 
 const delta float64 = 1e-10
@@ -409,6 +410,8 @@ func TestLoggerJSON(t *testing.T) {
 				"time":                    assertNotEmpty(),
 				"StartLocal":              assertNotEmpty(),
 				"StartUTC":                assertNotEmpty(),
+				TraceID:                   assertNotEmpty(),
+				SpanID:                    assertNotEmpty(),
 			},
 		},
 		{
@@ -452,6 +455,8 @@ func TestLoggerJSON(t *testing.T) {
 				"time":                    assertNotEmpty(),
 				StartLocal:                assertNotEmpty(),
 				StartUTC:                  assertNotEmpty(),
+				TraceID:                   assertNotEmpty(),
+				SpanID:                    assertNotEmpty(),
 			},
 		},
 		{
@@ -627,6 +632,8 @@ func TestLogger_AbortedRequest(t *testing.T) {
 		"downstream_Content-Type":      assertString("text/plain"),
 		"downstream_Transfer-Encoding": assertString("chunked"),
 		"downstream_Cache-Control":     assertString("no-cache"),
+		TraceID:                        assertNotEmpty(),
+		SpanID:                         assertNotEmpty(),
 	}
 
 	config := &types.AccessLog{
@@ -945,6 +952,10 @@ func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS bool) {
 		}
 	}
 
+	tracer := noop.Tracer{}
+	spanCtx, _ := tracer.Start(req.Context(), "test")
+	req = req.WithContext(spanCtx)
+
 	chain := alice.New()
 	chain = chain.Append(capture.Wrap)
 	chain = chain.Append(WrapHandler(logger))
diff --git a/pkg/middlewares/observability/entrypoint_test.go b/pkg/middlewares/observability/entrypoint_test.go
index 0b94f5fd52..d39d3b8429 100644
--- a/pkg/middlewares/observability/entrypoint_test.go
+++ b/pkg/middlewares/observability/entrypoint_test.go
@@ -7,7 +7,6 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
-	"github.com/traefik/traefik/v3/pkg/middlewares/accesslog"
 	"github.com/traefik/traefik/v3/pkg/tracing"
 	"go.opentelemetry.io/otel/attribute"
 )
@@ -79,27 +78,3 @@ func TestEntryPointMiddleware_tracing(t *testing.T) {
 		})
 	}
 }
-
-func TestEntryPointMiddleware_tracingInfoIntoLog(t *testing.T) {
-	req := httptest.NewRequest(http.MethodGet, "http://www.test.com/", http.NoBody)
-	req = req.WithContext(
-		context.WithValue(
-			req.Context(),
-			accesslog.DataTableKey,
-			&accesslog.LogData{Core: accesslog.CoreLogData{}},
-		),
-	)
-
-	next := http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {})
-
-	tracer := &mockTracer{}
-
-	handler := newEntryPoint(context.Background(), tracing.NewTracer(tracer, []string{}, []string{}, []string{}), "test", next)
-	handler.ServeHTTP(httptest.NewRecorder(), req)
-
-	expectedSpanCtx := tracer.spans[0].SpanContext()
-
-	logData := accesslog.GetLogData(req)
-	assert.Equal(t, expectedSpanCtx.TraceID().String(), logData.Core[accesslog.TraceID])
-	assert.Equal(t, expectedSpanCtx.SpanID().String(), logData.Core[accesslog.SpanID])
-}