123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- package trace
- import (
- "context"
- "testing"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "go.opentelemetry.io/otel"
- "go.opentelemetry.io/otel/propagation"
- "go.opentelemetry.io/otel/trace"
- "google.golang.org/grpc/metadata"
- )
- const (
- traceIDStr = "4bf92f3577b34da6a3ce929d0e0e4736"
- spanIDStr = "00f067aa0ba902b7"
- )
- var (
- traceID = mustTraceIDFromHex(traceIDStr)
- spanID = mustSpanIDFromHex(spanIDStr)
- )
- func mustTraceIDFromHex(s string) (t trace.TraceID) {
- var err error
- t, err = trace.TraceIDFromHex(s)
- if err != nil {
- panic(err)
- }
- return
- }
- func mustSpanIDFromHex(s string) (t trace.SpanID) {
- var err error
- t, err = trace.SpanIDFromHex(s)
- if err != nil {
- panic(err)
- }
- return
- }
- func TestExtractValidTraceContext(t *testing.T) {
- stateStr := "key1=value1,key2=value2"
- state, err := trace.ParseTraceState(stateStr)
- require.NoError(t, err)
- tests := []struct {
- name string
- traceparent string
- tracestate string
- sc trace.SpanContext
- }{
- {
- name: "not sampled",
- traceparent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00",
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- Remote: true,
- }),
- },
- {
- name: "sampled",
- traceparent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- TraceFlags: trace.FlagsSampled,
- Remote: true,
- }),
- },
- {
- name: "valid tracestate",
- traceparent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00",
- tracestate: stateStr,
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- TraceState: state,
- Remote: true,
- }),
- },
- {
- name: "invalid tracestate perserves traceparent",
- traceparent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00",
- tracestate: "invalid$@#=invalid",
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- Remote: true,
- }),
- },
- {
- name: "future version not sampled",
- traceparent: "02-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00",
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- Remote: true,
- }),
- },
- {
- name: "future version sampled",
- traceparent: "02-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- TraceFlags: trace.FlagsSampled,
- Remote: true,
- }),
- },
- {
- name: "future version sample bit set",
- traceparent: "02-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-09",
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- TraceFlags: trace.FlagsSampled,
- Remote: true,
- }),
- },
- {
- name: "future version sample bit not set",
- traceparent: "02-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-08",
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- Remote: true,
- }),
- },
- {
- name: "future version additional data",
- traceparent: "02-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00-XYZxsf09",
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- Remote: true,
- }),
- },
- {
- name: "B3 format ending in dash",
- traceparent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00-",
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- Remote: true,
- }),
- },
- {
- name: "future version B3 format ending in dash",
- traceparent: "03-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00-",
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- Remote: true,
- }),
- },
- }
- otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
- propagation.TraceContext{}, propagation.Baggage{}))
- propagator := otel.GetTextMapPropagator()
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- ctx := context.Background()
- md := metadata.MD{}
- md.Set("traceparent", tt.traceparent)
- md.Set("tracestate", tt.tracestate)
- _, spanCtx := Extract(ctx, propagator, &md)
- assert.Equal(t, tt.sc, spanCtx)
- })
- }
- }
- func TestExtractInvalidTraceContext(t *testing.T) {
- tests := []struct {
- name string
- header string
- }{
- {
- name: "wrong version length",
- header: "0000-00000000000000000000000000000000-0000000000000000-01",
- },
- {
- name: "wrong trace ID length",
- header: "00-ab00000000000000000000000000000000-cd00000000000000-01",
- },
- {
- name: "wrong span ID length",
- header: "00-ab000000000000000000000000000000-cd0000000000000000-01",
- },
- {
- name: "wrong trace flag length",
- header: "00-ab000000000000000000000000000000-cd00000000000000-0100",
- },
- {
- name: "bogus version",
- header: "qw-00000000000000000000000000000000-0000000000000000-01",
- },
- {
- name: "bogus trace ID",
- header: "00-qw000000000000000000000000000000-cd00000000000000-01",
- },
- {
- name: "bogus span ID",
- header: "00-ab000000000000000000000000000000-qw00000000000000-01",
- },
- {
- name: "bogus trace flag",
- header: "00-ab000000000000000000000000000000-cd00000000000000-qw",
- },
- {
- name: "upper case version",
- header: "A0-00000000000000000000000000000000-0000000000000000-01",
- },
- {
- name: "upper case trace ID",
- header: "00-AB000000000000000000000000000000-cd00000000000000-01",
- },
- {
- name: "upper case span ID",
- header: "00-ab000000000000000000000000000000-CD00000000000000-01",
- },
- {
- name: "upper case trace flag",
- header: "00-ab000000000000000000000000000000-cd00000000000000-A1",
- },
- {
- name: "zero trace ID and span ID",
- header: "00-00000000000000000000000000000000-0000000000000000-01",
- },
- {
- name: "trace-flag unused bits set",
- header: "00-ab000000000000000000000000000000-cd00000000000000-09",
- },
- {
- name: "missing options",
- header: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7",
- },
- {
- name: "empty options",
- header: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-",
- },
- }
- otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
- propagation.TraceContext{}, propagation.Baggage{}))
- propagator := otel.GetTextMapPropagator()
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- ctx := context.Background()
- md := metadata.MD{}
- md.Set("traceparent", tt.header)
- _, spanCtx := Extract(ctx, propagator, &md)
- assert.Equal(t, trace.SpanContext{}, spanCtx)
- })
- }
- }
- func TestInjectValidTraceContext(t *testing.T) {
- stateStr := "key1=value1,key2=value2"
- state, err := trace.ParseTraceState(stateStr)
- require.NoError(t, err)
- tests := []struct {
- name string
- traceparent string
- tracestate string
- sc trace.SpanContext
- }{
- {
- name: "not sampled",
- traceparent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00",
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- Remote: true,
- }),
- },
- {
- name: "sampled",
- traceparent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- TraceFlags: trace.FlagsSampled,
- Remote: true,
- }),
- },
- {
- name: "unsupported trace flag bits dropped",
- traceparent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- TraceFlags: 0xff,
- Remote: true,
- }),
- },
- {
- name: "with tracestate",
- traceparent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00",
- tracestate: stateStr,
- sc: trace.NewSpanContext(trace.SpanContextConfig{
- TraceID: traceID,
- SpanID: spanID,
- TraceState: state,
- Remote: true,
- }),
- },
- }
- otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
- propagation.TraceContext{}, propagation.Baggage{}))
- propagator := otel.GetTextMapPropagator()
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- ctx := context.Background()
- ctx = trace.ContextWithRemoteSpanContext(ctx, tt.sc)
- want := metadata.MD{}
- want.Set("traceparent", tt.traceparent)
- if len(tt.tracestate) > 0 {
- want.Set("tracestate", tt.tracestate)
- }
- md := metadata.MD{}
- Inject(ctx, propagator, &md)
- assert.Equal(t, want, md)
- mm := &metadataSupplier{
- metadata: &md,
- }
- assert.NotEmpty(t, mm.Keys())
- })
- }
- }
- func TestInvalidSpanContextDropped(t *testing.T) {
- invalidSC := trace.SpanContext{}
- require.False(t, invalidSC.IsValid())
- ctx := trace.ContextWithRemoteSpanContext(context.Background(), invalidSC)
- otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
- propagation.TraceContext{}, propagation.Baggage{}))
- propagator := otel.GetTextMapPropagator()
- md := metadata.MD{}
- Inject(ctx, propagator, &md)
- mm := &metadataSupplier{
- metadata: &md,
- }
- assert.Empty(t, mm.Keys())
- assert.Equal(t, "", mm.Get("traceparent"), "injected invalid SpanContext")
- }
|