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
This commit is contained in:
douxu 2026-05-07 16:43:34 +08:00
parent 9661278935
commit 1ee722dd58
5 changed files with 42 additions and 14 deletions

View File

@ -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.

1
go.mod
View File

@ -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

2
go.sum
View File

@ -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=

View File

@ -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),

View File

@ -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()