diff --git a/api/trace/b3_propagator.go b/api/trace/b3_propagator.go index fe78f8727..6f5b15986 100644 --- a/api/trace/b3_propagator.go +++ b/api/trace/b3_propagator.go @@ -29,9 +29,10 @@ const ( B3SpanIDHeader = "X-B3-SpanId" B3SampledHeader = "X-B3-Sampled" B3ParentSpanIDHeader = "X-B3-ParentSpanId" + b3TraceIDPadding = "0000000000000000" ) -// B3 propagator serializes core.SpanContext to/from B3 Headers. +// B3 propagator serializes SpanContext to/from B3 Headers. // This propagator supports both version of B3 headers, // 1. Single Header : // X-B3: {TraceId}-{SpanId}-{SamplingState}-{ParentSpanId} @@ -87,8 +88,15 @@ func (b3 B3) Extract(ctx context.Context, supplier propagation.HTTPSupplier) con return ContextWithRemoteSpanContext(ctx, sc) } +func fixB3TID(in string) string { + if len(in) == 16 { + in = b3TraceIDPadding + in + } + return in +} + func (b3 B3) extract(supplier propagation.HTTPSupplier) SpanContext { - tid, err := IDFromHex(supplier.Get(B3TraceIDHeader)) + tid, err := IDFromHex(fixB3TID(supplier.Get(B3TraceIDHeader))) if err != nil { return EmptySpanContext() } @@ -139,7 +147,7 @@ func (b3 B3) extractSingleHeader(supplier propagation.HTTPSupplier) SpanContext } var err error - sc.TraceID, err = IDFromHex(parts[0]) + sc.TraceID, err = IDFromHex(fixB3TID(parts[0])) if err != nil { return EmptySpanContext() } diff --git a/api/trace/testtrace/b3_propagator_data_test.go b/api/trace/testtrace/b3_propagator_data_test.go index 6cb4a092c..432ce4995 100644 --- a/api/trace/testtrace/b3_propagator_data_test.go +++ b/api/trace/testtrace/b3_propagator_data_test.go @@ -24,6 +24,10 @@ type extractTest struct { wantSc trace.SpanContext } +var ( + traceID64bitPadded = mustTraceIDFromHex("0000000000000000a3ce929d0e0e4736") +) + var extractMultipleHeaders = []extractTest{ { name: "sampling state defer", @@ -125,6 +129,17 @@ var extractMultipleHeaders = []extractTest{ }, wantSc: trace.EmptySpanContext(), }, + { + name: "left-padding 64-bit traceID", + headers: map[string]string{ + trace.B3TraceIDHeader: "a3ce929d0e0e4736", + trace.B3SpanIDHeader: "00f067aa0ba902b7", + }, + wantSc: trace.SpanContext{ + TraceID: traceID64bitPadded, + SpanID: spanID, + }, + }, } var extractSingleHeader = []extractTest{ @@ -188,6 +203,16 @@ var extractSingleHeader = []extractTest{ }, wantSc: trace.EmptySpanContext(), }, + { + name: "left-padding 64-bit traceID", + headers: map[string]string{ + trace.B3SingleHeader: "a3ce929d0e0e4736-00f067aa0ba902b7", + }, + wantSc: trace.SpanContext{ + TraceID: traceID64bitPadded, + SpanID: spanID, + }, + }, } var extractInvalidB3MultipleHeaders = []extractTest{ diff --git a/exporters/trace/zipkin/exporter_test.go b/exporters/trace/zipkin/exporter_test.go index 76b78a7cc..7665b020a 100644 --- a/exporters/trace/zipkin/exporter_test.go +++ b/exporters/trace/zipkin/exporter_test.go @@ -50,7 +50,7 @@ func startMockZipkinCollector(t *testing.T) *mockZipkinCollector { t: t, closing: false, } - listener, err := net.Listen("tcp", ":0") + listener, err := net.Listen("tcp", "127.0.0.1:0") require.NoError(t, err) collector.url = fmt.Sprintf("http://%s", listener.Addr().String()) server := &http.Server{