From 1ee722dd589c6e385c188520b17386c540f23ae1 Mon Sep 17 00:00:00 2001 From: douxu Date: Thu, 7 May 2026 16:43:34 +0800 Subject: [PATCH] refactor: migrate trace propagation from B3 to W3C TraceContext - switch OTel propagator from b3.New() to propagation.TraceContext{} - rename B3 header constants to generic internal context keys - remove go.opentelemetry.io/contrib/propagators/b3 dependency - add amqpHeaderCarrier to inject W3C traceparent into AMQP message headers --- constants/trace.go | 10 ++++++---- go.mod | 1 - go.sum | 2 -- middleware/trace.go | 10 +++------- mq/publish_up_down_limit_event.go | 33 +++++++++++++++++++++++++++++++ 5 files changed, 42 insertions(+), 14 deletions(-) diff --git a/constants/trace.go b/constants/trace.go index ab5c5df..e5e595a 100644 --- a/constants/trace.go +++ b/constants/trace.go @@ -1,11 +1,13 @@ // Package constants define constant variable package constants -// Assuming the B3 specification +// Internal context keys for trace values set by StartTrace middleware. +// These are gin/stdlib context keys only — actual W3C header propagation +// (traceparent / tracestate) is handled automatically by the OTel propagator. const ( - HeaderTraceID = "X-B3-TraceId" - HeaderSpanID = "X-B3-SpanId" - HeaderParentSpanID = "X-B3-ParentSpanId" + HeaderTraceID = "trace-id" + HeaderSpanID = "span-id" + HeaderParentSpanID = "parent-span-id" ) // traceCtxKey is an unexported type for context keys to avoid collisions with other packages. diff --git a/go.mod b/go.mod index a815516..9f24f78 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,6 @@ require ( github.com/swaggo/gin-swagger v1.6.0 github.com/swaggo/swag v1.16.4 github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 - go.opentelemetry.io/contrib/propagators/b3 v1.43.0 go.opentelemetry.io/otel v1.43.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 go.opentelemetry.io/otel/sdk v1.43.0 diff --git a/go.sum b/go.sum index 97e2fcf..19c0d18 100644 --- a/go.sum +++ b/go.sum @@ -183,8 +183,6 @@ github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfS github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/propagators/b3 v1.43.0 h1:CETqV3QLLPTy5yNrqyMr41VnAOOD4lsRved7n4QG00A= -go.opentelemetry.io/contrib/propagators/b3 v1.43.0/go.mod h1:Q4mCiCdziYzpNR0g+6UqVotAlCDZdzz6L8jwY4knOrw= go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= diff --git a/middleware/trace.go b/middleware/trace.go index 9712de8..65c1ee2 100644 --- a/middleware/trace.go +++ b/middleware/trace.go @@ -14,7 +14,6 @@ import ( "modelRT/logger" "github.com/gin-gonic/gin" - "go.opentelemetry.io/contrib/propagators/b3" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" @@ -25,7 +24,7 @@ import ( ) // InitTracerProvider creates an OTLP TracerProvider and registers it as the global provider. -// It also registers the B3 propagator to stay compatible with existing B3 infrastructure. +// It registers the W3C TraceContext propagator (traceparent header). // The caller is responsible for calling Shutdown on the returned provider during graceful shutdown. func InitTracerProvider(ctx context.Context, cfg config.ModelRTConfig) (*sdktrace.TracerProvider, error) { opts := []otlptracehttp.Option{ @@ -52,18 +51,15 @@ func InitTracerProvider(ctx context.Context, cfg config.ModelRTConfig) (*sdktrac ) otel.SetTracerProvider(tp) - otel.SetTextMapPropagator(b3.New()) + otel.SetTextMapPropagator(propagation.TraceContext{}) return tp, nil } -// StartTrace extracts upstream B3 trace context from request headers and starts a server span. -// Typed context keys are also injected for backward compatibility with the existing logger -// until the logger is migrated to read from the OTel span context (Step 6). +// StartTrace extracts upstream W3C trace context from request headers and starts a server span. func StartTrace() gin.HandlerFunc { tracer := otel.Tracer("modelRT/http") return func(c *gin.Context) { - // Extract upstream trace context from B3 headers (X-B3-TraceId etc.) ctx := otel.GetTextMapPropagator().Extract( c.Request.Context(), propagation.HeaderCarrier(c.Request.Header), diff --git a/mq/publish_up_down_limit_event.go b/mq/publish_up_down_limit_event.go index 9d4bbbf..65879d7 100644 --- a/mq/publish_up_down_limit_event.go +++ b/mq/publish_up_down_limit_event.go @@ -11,8 +11,36 @@ import ( "modelRT/mq/event" amqp "github.com/rabbitmq/amqp091-go" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/propagation" ) +// amqpHeaderCarrier adapts amqp.Table to propagation.TextMapCarrier for trace context injection. +type amqpHeaderCarrier amqp.Table + +func (c amqpHeaderCarrier) Get(key string) string { + val, ok := amqp.Table(c)[key] + if !ok { + return "" + } + str, _ := val.(string) + return str +} + +func (c amqpHeaderCarrier) Set(key, value string) { + amqp.Table(c)[key] = value +} + +func (c amqpHeaderCarrier) Keys() []string { + keys := make([]string, 0, len(c)) + for k := range c { + keys = append(keys, k) + } + return keys +} + +var _ propagation.TextMapCarrier = amqpHeaderCarrier{} + // MsgChan define variable of channel to store messages that need to be sent to rabbitMQ var MsgChan chan *event.EventRecord @@ -124,6 +152,10 @@ func PushUpDownLimitEventToRabbitMQ(ctx context.Context, msgChan chan *event.Eve continue } + // inject current trace context into AMQP headers so eventRT can restore the span chain + headers := amqp.Table{} + otel.GetTextMapPropagator().Inject(ctx, amqpHeaderCarrier(headers)) + // send event alarm message to rabbitMQ queue routingKey := eventRecord.Category pubCtx, cancel := context.WithTimeout(ctx, 5*time.Second) @@ -135,6 +167,7 @@ func PushUpDownLimitEventToRabbitMQ(ctx context.Context, msgChan chan *event.Eve amqp.Publishing{ ContentType: "text/plain", Body: recordBytes, + Headers: headers, }) cancel()