From baf687218c71bd45b766f4dedbbaedf7efec2213 Mon Sep 17 00:00:00 2001 From: Baptiste Mayelle Date: Mon, 26 Feb 2024 11:50:04 +0100 Subject: [PATCH] Support OTEL_PROPAGATORS to configure tracing propagation Co-authored-by: Romain --- .../observability/tracing/opentelemetry.md | 17 ++ go.mod | 15 +- go.sum | 30 +- pkg/tracing/opentelemetry/opentelemetry.go | 2 - .../opentelemetry/opentelemetry_test.go | 261 ++++++++++++++++-- pkg/tracing/tracing.go | 8 +- 6 files changed, 288 insertions(+), 45 deletions(-) diff --git a/docs/content/observability/tracing/opentelemetry.md b/docs/content/observability/tracing/opentelemetry.md index 0ea6bd19f..107cbe2d2 100644 --- a/docs/content/observability/tracing/opentelemetry.md +++ b/docs/content/observability/tracing/opentelemetry.md @@ -30,6 +30,23 @@ tracing: By default, the OpenTelemetry trace exporter will sample 100% of traces. See [OpenTelemetry's SDK configuration](https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/#general-sdk-configuration) to customize the sampling strategy. +!!! info "Propagation" + + Traefik supports the `OTEL_PROPAGATORS` env variable to set up the propragators. The supported propagators are: + + - tracecontext (default) + - baggage (default) + - b3 + - b3multi + - jaeger + - xray + - ottrace + + Example of configuration: + + OTEL_PROPAGATORS=b3,jaeger + + ### HTTP configuration _Optional_ diff --git a/go.mod b/go.mod index 702fbd501..c14f09de5 100644 --- a/go.mod +++ b/go.mod @@ -67,16 +67,17 @@ require ( github.com/vulcand/oxy/v2 v2.0.0-20230427132221-be5cf38f3c1c github.com/vulcand/predicate v1.2.0 go.opentelemetry.io/collector/pdata v0.66.0 - go.opentelemetry.io/otel v1.21.0 + go.opentelemetry.io/contrib/propagators/autoprop v0.48.0 + go.opentelemetry.io/otel v1.23.0 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 - go.opentelemetry.io/otel/metric v1.21.0 - go.opentelemetry.io/otel/sdk v1.21.0 + go.opentelemetry.io/otel/metric v1.23.0 + go.opentelemetry.io/otel/sdk v1.23.0 go.opentelemetry.io/otel/sdk/metric v1.21.0 - go.opentelemetry.io/otel/trace v1.21.0 + go.opentelemetry.io/otel/trace v1.23.0 golang.org/x/exp v0.0.0-20231006140011-7918f672742d golang.org/x/mod v0.14.0 golang.org/x/net v0.20.0 @@ -173,7 +174,7 @@ require ( github.com/go-errors/errors v1.0.1 // indirect github.com/go-jose/go-jose/v3 v3.0.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/jsonpointer v0.20.0 // indirect @@ -308,6 +309,10 @@ require ( go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect go.etcd.io/etcd/client/v3 v3.5.9 // indirect go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/propagators/aws v1.23.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.23.0 // indirect + go.opentelemetry.io/contrib/propagators/jaeger v1.23.0 // indirect + go.opentelemetry.io/contrib/propagators/ot v1.23.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/mock v0.3.0 // indirect diff --git a/go.sum b/go.sum index c9bd69ebd..afabf6df9 100644 --- a/go.sum +++ b/go.sum @@ -355,8 +355,8 @@ github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNV github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= @@ -1178,8 +1178,18 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/collector/pdata v0.66.0 h1:UdE5U6MsDNzuiWaXdjGx2lC3ElVqWmN/hiUE8vyvSuM= go.opentelemetry.io/collector/pdata v0.66.0/go.mod h1:pqyaznLzk21m+1KL6fwOsRryRELL+zNM0qiVSn0MbVc= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/contrib/propagators/autoprop v0.48.0 h1:sBPzh/5mNVo4yknFgh0iTezFeljhV8FO9mcj79LsdOg= +go.opentelemetry.io/contrib/propagators/autoprop v0.48.0/go.mod h1:Ij+STHaLubeiNHJVgYaRU8XPI1Y7DmlMq0HwJboIc1k= +go.opentelemetry.io/contrib/propagators/aws v1.23.0 h1:pY2NxI5WwbvuUXSnqahpjqdZrA1JI/elKCGwElimPWA= +go.opentelemetry.io/contrib/propagators/aws v1.23.0/go.mod h1:4sNW/xRJ8qpkj7AnStkrjJu0lBQjgiuW4rpEpRfY+dw= +go.opentelemetry.io/contrib/propagators/b3 v1.23.0 h1:aaIGWc5JdfRGpCafLRxMJbD65MfTa206AwSKkvGS0Hg= +go.opentelemetry.io/contrib/propagators/b3 v1.23.0/go.mod h1:Gyz7V7XghvwTq+mIhLFlTgcc03UDroOg8vezs4NLhwU= +go.opentelemetry.io/contrib/propagators/jaeger v1.23.0 h1:KFxfTCTkH1usVFzDaWzbmNdFX7ybUTCtkLsUTww0nG4= +go.opentelemetry.io/contrib/propagators/jaeger v1.23.0/go.mod h1:xU+81opGquQICJGzwscLXAQLnIPWI+q7Zu4AQSrgXf8= +go.opentelemetry.io/contrib/propagators/ot v1.23.0 h1:JCvB5Mg4bPR57nuKbENxzCsUAlTwVggCsLdew3mqyoU= +go.opentelemetry.io/contrib/propagators/ot v1.23.0/go.mod h1:cO0XToAIUsLnIJrrN0jVFH4fJvZPlHvZfsPrcfPwQdg= +go.opentelemetry.io/otel v1.23.0 h1:Df0pqjqExIywbMCMTxkAwzjLZtRf+bBKLbUcpxO2C9E= +go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 h1:jd0+5t/YynESZqsSyPz+7PAFdEop0dlN0+PkyHYo8oI= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0/go.mod h1:U707O40ee1FpQGyhvqnzmCJm1Wh6OX6GGBVn0E6Uyyk= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 h1:bflGWrfYyuulcdxf14V6n9+CoQcu5SAAdHmDPAJnlps= @@ -1190,14 +1200,14 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqhe go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/metric v1.23.0 h1:pazkx7ss4LFVVYSxYew7L5I6qvLXHA0Ap2pwV+9Cnpo= +go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= +go.opentelemetry.io/otel/sdk v1.23.0 h1:0KM9Zl2esnl+WSukEmlaAEjVY5HDZANOHferLq36BPc= +go.opentelemetry.io/otel/sdk v1.23.0/go.mod h1:wUscup7byToqyKJSilEtMf34FgdCAsFpFOjXnAwFfO0= go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/otel/trace v1.23.0 h1:37Ik5Ib7xfYVb4V1UtnT97T1jI+AoIYkJyPkuL4iJgI= +go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= diff --git a/pkg/tracing/opentelemetry/opentelemetry.go b/pkg/tracing/opentelemetry/opentelemetry.go index 24a737206..3806ffcd4 100644 --- a/pkg/tracing/opentelemetry/opentelemetry.go +++ b/pkg/tracing/opentelemetry/opentelemetry.go @@ -16,7 +16,6 @@ import ( "go.opentelemetry.io/otel/exporters/otlp/otlptrace" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" - "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.21.0" @@ -82,7 +81,6 @@ func (c *Config) Setup(serviceName string, sampleRate float64, globalAttributes ) otel.SetTracerProvider(tracerProvider) - otel.SetTextMapPropagator(propagation.TraceContext{}) log.Debug().Msg("OpenTelemetry tracer configured") diff --git a/pkg/tracing/opentelemetry/opentelemetry_test.go b/pkg/tracing/opentelemetry/opentelemetry_test.go index 3df441c02..86f3a7b99 100644 --- a/pkg/tracing/opentelemetry/opentelemetry_test.go +++ b/pkg/tracing/opentelemetry/opentelemetry_test.go @@ -23,9 +23,11 @@ import ( func TestTracing(t *testing.T) { tests := []struct { - desc string - headers map[string]string - assertFn func(*testing.T, string) + desc string + propagators string + headers map[string]string + wantServiceHeadersFn func(t *testing.T, headers http.Header) + assertFn func(*testing.T, string) }{ { desc: "service name and version", @@ -37,11 +39,18 @@ func TestTracing(t *testing.T) { }, }, { - desc: "context propagation", + desc: "TraceContext propagation", + propagators: "tracecontext", headers: map[string]string{ "traceparent": "00-00000000000000000000000000000001-0000000000000001-01", "tracestate": "foo=bar", }, + wantServiceHeadersFn: func(t *testing.T, headers http.Header) { + t.Helper() + + assert.Regexp(t, `(00-00000000000000000000000000000001-\w{16}-01)`, headers["Traceparent"][0]) + assert.Equal(t, []string{"foo=bar"}, headers["Tracestate"]) + }, assertFn: func(t *testing.T, trace string) { t.Helper() @@ -50,6 +59,188 @@ func TestTracing(t *testing.T) { assert.Regexp(t, `("traceState":"foo=bar")`, trace) }, }, + { + desc: "root span TraceContext propagation", + propagators: "tracecontext", + wantServiceHeadersFn: func(t *testing.T, headers http.Header) { + t.Helper() + + assert.Regexp(t, `(00-\w{32}-\w{16}-01)`, headers["Traceparent"][0]) + }, + assertFn: func(t *testing.T, trace string) { + t.Helper() + + assert.Regexp(t, `("traceId":"\w{32}")`, trace) + assert.Regexp(t, `("parentSpanId":"\w{16}")`, trace) + }, + }, + { + desc: "B3 propagation", + propagators: "b3", + headers: map[string]string{ + "b3": "00000000000000000000000000000001-0000000000000002-1-0000000000000001", + }, + wantServiceHeadersFn: func(t *testing.T, headers http.Header) { + t.Helper() + + assert.Regexp(t, `(00000000000000000000000000000001-\w{16}-1)`, headers["B3"][0]) + }, + assertFn: func(t *testing.T, trace string) { + t.Helper() + + assert.Regexp(t, `("traceId":"00000000000000000000000000000001")`, trace) + assert.Regexp(t, `("parentSpanId":"0000000000000002")`, trace) + }, + }, + { + desc: "root span B3 propagation", + propagators: "b3", + wantServiceHeadersFn: func(t *testing.T, headers http.Header) { + t.Helper() + + assert.Regexp(t, `(\w{32}-\w{16}-1)`, headers["B3"][0]) + }, + assertFn: func(t *testing.T, trace string) { + t.Helper() + + assert.Regexp(t, `("traceId":"\w{32}")`, trace) + assert.Regexp(t, `("parentSpanId":"\w{16}")`, trace) + }, + }, + { + desc: "B3 propagation Multiple Headers", + propagators: "b3multi", + headers: map[string]string{ + "x-b3-traceid": "00000000000000000000000000000001", + "x-b3-parentspanid": "0000000000000001", + "x-b3-spanid": "0000000000000002", + "x-b3-sampled": "1", + }, + wantServiceHeadersFn: func(t *testing.T, headers http.Header) { + t.Helper() + + assert.Equal(t, "00000000000000000000000000000001", headers["X-B3-Traceid"][0]) + assert.Equal(t, "0000000000000001", headers["X-B3-Parentspanid"][0]) + assert.Equal(t, "1", headers["X-B3-Sampled"][0]) + assert.Len(t, headers["X-B3-Spanid"][0], 16) + }, + assertFn: func(t *testing.T, trace string) { + t.Helper() + + assert.Regexp(t, `("traceId":"00000000000000000000000000000001")`, trace) + assert.Regexp(t, `("parentSpanId":"0000000000000002")`, trace) + }, + }, + { + desc: "root span B3 propagation Multiple Headers", + propagators: "b3multi", + wantServiceHeadersFn: func(t *testing.T, headers http.Header) { + t.Helper() + + assert.Regexp(t, `(\w{32})`, headers["X-B3-Traceid"][0]) + assert.Equal(t, "1", headers["X-B3-Sampled"][0]) + assert.Regexp(t, `(\w{16})`, headers["X-B3-Spanid"][0]) + }, + assertFn: func(t *testing.T, trace string) { + t.Helper() + + assert.Regexp(t, `("traceId":"\w{32}")`, trace) + assert.Regexp(t, `("parentSpanId":"")`, trace) + }, + }, + { + desc: "Baggage propagation", + propagators: "baggage", + headers: map[string]string{ + "baggage": "userId=id", + }, + wantServiceHeadersFn: func(t *testing.T, headers http.Header) { + t.Helper() + + assert.Equal(t, []string{"userId=id"}, headers["Baggage"]) + }, + }, + { + desc: "Jaeger propagation", + propagators: "jaeger", + headers: map[string]string{ + "uber-trace-id": "00000000000000000000000000000001:0000000000000002:0000000000000001:1", + }, + wantServiceHeadersFn: func(t *testing.T, headers http.Header) { + t.Helper() + + assert.Regexp(t, `(00000000000000000000000000000001:\w{16}:0:1)`, headers["Uber-Trace-Id"][0]) + }, + assertFn: func(t *testing.T, trace string) { + t.Helper() + + assert.Regexp(t, `("traceId":"00000000000000000000000000000001")`, trace) + assert.Regexp(t, `("parentSpanId":"\w{16}")`, trace) + }, + }, + { + desc: "root span Jaeger propagation", + propagators: "jaeger", + wantServiceHeadersFn: func(t *testing.T, headers http.Header) { + t.Helper() + + assert.Regexp(t, `(\w{32}:\w{16}:0:1)`, headers["Uber-Trace-Id"][0]) + }, + assertFn: func(t *testing.T, trace string) { + t.Helper() + + assert.Regexp(t, `("traceId":"\w{32}")`, trace) + assert.Regexp(t, `("parentSpanId":"\w{16}")`, trace) + }, + }, + { + desc: "XRay propagation", + propagators: "xray", + headers: map[string]string{ + "X-Amzn-Trace-Id": "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1", + }, + wantServiceHeadersFn: func(t *testing.T, headers http.Header) { + t.Helper() + + assert.Regexp(t, `(Root=1-5759e988-bd862e3fe1be46a994272793;Parent=\w{16};Sampled=1)`, headers["X-Amzn-Trace-Id"][0]) + }, + assertFn: func(t *testing.T, trace string) { + t.Helper() + + assert.Regexp(t, `("traceId":"5759e988bd862e3fe1be46a994272793")`, trace) + assert.Regexp(t, `("parentSpanId":"\w{16}")`, trace) + }, + }, + { + desc: "root span XRay propagation", + propagators: "xray", + wantServiceHeadersFn: func(t *testing.T, headers http.Header) { + t.Helper() + + assert.Regexp(t, `(Root=1-\w{8}-\w{24};Parent=\w{16};Sampled=1)`, headers["X-Amzn-Trace-Id"][0]) + }, + assertFn: func(t *testing.T, trace string) { + t.Helper() + + assert.Regexp(t, `("traceId":"\w{32}")`, trace) + assert.Regexp(t, `("parentSpanId":"\w{16}")`, trace) + }, + }, + { + desc: "no propagation", + propagators: "none", + wantServiceHeadersFn: func(t *testing.T, headers http.Header) { + t.Helper() + + assert.Empty(t, headers) + }, + assertFn: func(t *testing.T, trace string) { + t.Helper() + + assert.Regexp(t, `("traceId":"\w{32}")`, trace) + assert.Regexp(t, `("parentSpanId":"\w{16}")`, trace) + }, + }, } traceCh := make(chan string) @@ -71,28 +262,44 @@ func TestTracing(t *testing.T) { })) t.Cleanup(collector.Close) - tracingConfig := &static.Tracing{ - ServiceName: "traefik", - SampleRate: 1.0, - OTLP: &opentelemetry.Config{ - HTTP: &types.OtelHTTP{ - Endpoint: collector.URL, - }, - }, - } - - newTracing, closer, err := tracing.NewTracing(tracingConfig) - require.NoError(t, err) - t.Cleanup(func() { - _ = closer.Close() - }) - - chain := alice.New(tracingMiddle.WrapEntryPointHandler(context.Background(), newTracing, "test")) - epHandler, err := chain.Then(http.NotFoundHandler()) - require.NoError(t, err) - for _, test := range tests { t.Run(test.desc, func(t *testing.T) { + t.Setenv("OTEL_PROPAGATORS", test.propagators) + + service := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + tracer := tracing.TracerFromContext(r.Context()) + ctx, span := tracer.Start(r.Context(), "service") + defer span.End() + + r = r.WithContext(ctx) + + tracing.InjectContextIntoCarrier(r) + + if test.wantServiceHeadersFn != nil { + test.wantServiceHeadersFn(t, r.Header) + } + }) + + tracingConfig := &static.Tracing{ + ServiceName: "traefik", + SampleRate: 1.0, + OTLP: &opentelemetry.Config{ + HTTP: &types.OtelHTTP{ + Endpoint: collector.URL, + }, + }, + } + + newTracing, closer, err := tracing.NewTracing(tracingConfig) + require.NoError(t, err) + t.Cleanup(func() { + _ = closer.Close() + }) + + chain := alice.New(tracingMiddle.WrapEntryPointHandler(context.Background(), newTracing, "test")) + epHandler, err := chain.Then(service) + require.NoError(t, err) + req := httptest.NewRequest(http.MethodGet, "http://www.test.com", nil) for k, v := range test.headers { req.Header.Set(k, v) @@ -107,8 +314,10 @@ func TestTracing(t *testing.T) { t.Error("Trace not exported") case trace := <-traceCh: - assert.Equal(t, http.StatusNotFound, rw.Code) - test.assertFn(t, trace) + assert.Equal(t, http.StatusOK, rw.Code) + if test.assertFn != nil { + test.assertFn(t, trace) + } } }) } diff --git a/pkg/tracing/tracing.go b/pkg/tracing/tracing.go index 4a64ab1b3..a3e1623c7 100644 --- a/pkg/tracing/tracing.go +++ b/pkg/tracing/tracing.go @@ -11,6 +11,8 @@ import ( "github.com/rs/zerolog/log" "github.com/traefik/traefik/v3/pkg/config/static" "github.com/traefik/traefik/v3/pkg/tracing/opentelemetry" + "go.opentelemetry.io/contrib/propagators/autoprop" + "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/propagation" @@ -37,6 +39,8 @@ func NewTracing(conf *static.Tracing) (trace.Tracer, io.Closer, error) { backend = defaultBackend } + otel.SetTextMapPropagator(autoprop.NewTextMapPropagator()) + return backend.Setup(conf.ServiceName, conf.SampleRate, conf.GlobalAttributes) } @@ -57,13 +61,13 @@ func TracerFromContext(ctx context.Context) trace.Tracer { // ExtractCarrierIntoContext reads cross-cutting concerns from the carrier into a Context. func ExtractCarrierIntoContext(ctx context.Context, headers http.Header) context.Context { - propagator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) + propagator := otel.GetTextMapPropagator() return propagator.Extract(ctx, propagation.HeaderCarrier(headers)) } // InjectContextIntoCarrier sets cross-cutting concerns from the request context into the request headers. func InjectContextIntoCarrier(req *http.Request) { - propagator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) + propagator := otel.GetTextMapPropagator() propagator.Inject(req.Context(), propagation.HeaderCarrier(req.Header)) }