diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e3cc0ed7..4deef4055 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Move the `go.opentelemetry.io/otel/api/unit` package to `go.opentelemetry.io/otel/unit`. (#1185) - Renamed `SamplingDecision` values to comply with OpenTelemetry specification change. (#1192) +### Removed + +- Remove the B3 propagator from `go.opentelemetry.io/otel/propagators`. It is now located in the + `go.opentelemetry.io/contrib/propagators/` module. (#1191) + ### Fixed - Zipkin example no longer mentions `ParentSampler`, corrected to `ParentBased`. (#1171) diff --git a/propagators/b3.go b/propagators/b3.go deleted file mode 100644 index 6c231a52e..000000000 --- a/propagators/b3.go +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package propagators - -import ( - "context" - "errors" - "strings" - - "go.opentelemetry.io/otel/api/propagation" - "go.opentelemetry.io/otel/api/trace" -) - -const ( - // Default B3 Header names. - b3ContextHeader = "b3" - b3DebugFlagHeader = "x-b3-flags" - b3TraceIDHeader = "x-b3-traceid" - b3SpanIDHeader = "x-b3-spanid" - b3SampledHeader = "x-b3-sampled" - b3ParentSpanIDHeader = "x-b3-parentspanid" - - b3TraceIDPadding = "0000000000000000" - - // B3 Single Header encoding widths. - separatorWidth = 1 // Single "-" character. - samplingWidth = 1 // Single hex character. - traceID64BitsWidth = 64 / 4 // 16 hex character Trace ID. - traceID128BitsWidth = 128 / 4 // 32 hex character Trace ID. - spanIDWidth = 16 // 16 hex character ID. - parentSpanIDWidth = 16 // 16 hex character ID. -) - -var ( - empty = trace.EmptySpanContext() - - errInvalidSampledByte = errors.New("invalid B3 Sampled found") - errInvalidSampledHeader = errors.New("invalid B3 Sampled header found") - errInvalidTraceIDHeader = errors.New("invalid B3 TraceID header found") - errInvalidSpanIDHeader = errors.New("invalid B3 SpanID header found") - errInvalidParentSpanIDHeader = errors.New("invalid B3 ParentSpanID header found") - errInvalidScope = errors.New("require either both TraceID and SpanID or none") - errInvalidScopeParent = errors.New("ParentSpanID requires both TraceID and SpanID to be available") - errInvalidScopeParentSingle = errors.New("ParentSpanID requires TraceID, SpanID and Sampled to be available") - errEmptyContext = errors.New("empty request context") - errInvalidTraceIDValue = errors.New("invalid B3 TraceID value found") - errInvalidSpanIDValue = errors.New("invalid B3 SpanID value found") - errInvalidParentSpanIDValue = errors.New("invalid B3 ParentSpanID value found") -) - -// B3Encoding is a bitmask representation of the B3 encoding type. -type B3Encoding uint8 - -// supports returns if e has o bit(s) set. -func (e B3Encoding) supports(o B3Encoding) bool { - return e&o == o -} - -const ( - // B3MultipleHeader is a B3 encoding that uses multiple headers to - // transmit tracing information all prefixed with `x-b3-`. - B3MultipleHeader B3Encoding = 1 << iota - // B3SingleHeader is a B3 encoding that uses a single header named `b3` - // to transmit tracing information. - B3SingleHeader - // B3Unspecified is an unspecified B3 encoding. - B3Unspecified B3Encoding = 0 -) - -// B3 is a propagator that supports the B3 HTTP encoding. -// -// Both single (https://github.com/openzipkin/b3-propagation#single-header) -// and multiple (https://github.com/openzipkin/b3-propagation#single-header) -// header encoding are supported. -type B3 struct { - // InjectEncoding are the B3 encodings used when injecting trace - // information. If no encoding is specified (i.e. `B3Unspecified`) - // `B3MultipleHeader` will be used as the default as it is the most - // backwards compatible. - InjectEncoding B3Encoding -} - -var _ propagation.HTTPPropagator = B3{} - -// Inject injects a context into the supplier as B3 HTTP headers. -// The parent span ID is omitted because it is not tracked in the -// SpanContext. -func (b3 B3) Inject(ctx context.Context, supplier propagation.HTTPSupplier) { - sc := trace.SpanFromContext(ctx).SpanContext() - - if b3.InjectEncoding.supports(B3SingleHeader) { - header := []string{} - if sc.TraceID.IsValid() && sc.SpanID.IsValid() { - header = append(header, sc.TraceID.String(), sc.SpanID.String()) - } - - if sc.IsDebug() { - header = append(header, "d") - } else if !sc.IsDeferred() { - if sc.IsSampled() { - header = append(header, "1") - } else { - header = append(header, "0") - } - } - - supplier.Set(b3ContextHeader, strings.Join(header, "-")) - } - - if b3.InjectEncoding.supports(B3MultipleHeader) || b3.InjectEncoding == B3Unspecified { - if sc.TraceID.IsValid() && sc.SpanID.IsValid() { - supplier.Set(b3TraceIDHeader, sc.TraceID.String()) - supplier.Set(b3SpanIDHeader, sc.SpanID.String()) - } - - if sc.IsDebug() { - // Since Debug implies deferred, don't also send "X-B3-Sampled". - supplier.Set(b3DebugFlagHeader, "1") - } else if !sc.IsDeferred() { - if sc.IsSampled() { - supplier.Set(b3SampledHeader, "1") - } else { - supplier.Set(b3SampledHeader, "0") - } - } - } -} - -// Extract extracts a context from the supplier if it contains B3 HTTP -// headers. -func (b3 B3) Extract(ctx context.Context, supplier propagation.HTTPSupplier) context.Context { - var ( - sc trace.SpanContext - err error - ) - - // Default to Single Header if a valid value exists. - if h := supplier.Get(b3ContextHeader); h != "" { - sc, err = extractSingle(h) - if err == nil && sc.IsValid() { - return trace.ContextWithRemoteSpanContext(ctx, sc) - } - // The Single Header value was invalid, fallback to Multiple Header. - } - - var ( - traceID = supplier.Get(b3TraceIDHeader) - spanID = supplier.Get(b3SpanIDHeader) - parentSpanID = supplier.Get(b3ParentSpanIDHeader) - sampled = supplier.Get(b3SampledHeader) - debugFlag = supplier.Get(b3DebugFlagHeader) - ) - sc, err = extractMultiple(traceID, spanID, parentSpanID, sampled, debugFlag) - if err != nil || !sc.IsValid() { - return ctx - } - return trace.ContextWithRemoteSpanContext(ctx, sc) -} - -// GetAllKeys returns the HTTP header names this propagator will use when -// injecting. -func (b3 B3) GetAllKeys() []string { - header := []string{} - if b3.InjectEncoding.supports(B3SingleHeader) { - header = append(header, b3ContextHeader) - } - if b3.InjectEncoding.supports(B3MultipleHeader) || b3.InjectEncoding == B3Unspecified { - header = append(header, b3TraceIDHeader, b3SpanIDHeader, b3SampledHeader, b3DebugFlagHeader) - } - return header -} - -// extractMultiple reconstructs a SpanContext from header values based on B3 -// Multiple header. It is based on the implementation found here: -// https://github.com/openzipkin/zipkin-go/blob/v0.2.2/propagation/b3/spancontext.go -// and adapted to support a SpanContext. -func extractMultiple(traceID, spanID, parentSpanID, sampled, flags string) (trace.SpanContext, error) { - var ( - err error - requiredCount int - sc = trace.SpanContext{} - ) - - // correct values for an existing sampled header are "0" and "1". - // For legacy support and being lenient to other tracing implementations we - // allow "true" and "false" as inputs for interop purposes. - switch strings.ToLower(sampled) { - case "0", "false": - // Zero value for TraceFlags sample bit is unset. - case "1", "true": - sc.TraceFlags = trace.FlagsSampled - case "": - sc.TraceFlags = trace.FlagsDeferred - default: - return empty, errInvalidSampledHeader - } - - // The only accepted value for Flags is "1". This will set Debug to - // true. All other values and omission of header will be ignored. - if flags == "1" { - sc.TraceFlags |= trace.FlagsDebug - } - - if traceID != "" { - requiredCount++ - id := traceID - if len(traceID) == 16 { - // Pad 64-bit trace IDs. - id = b3TraceIDPadding + traceID - } - if sc.TraceID, err = trace.IDFromHex(id); err != nil { - return empty, errInvalidTraceIDHeader - } - } - - if spanID != "" { - requiredCount++ - if sc.SpanID, err = trace.SpanIDFromHex(spanID); err != nil { - return empty, errInvalidSpanIDHeader - } - } - - if requiredCount != 0 && requiredCount != 2 { - return empty, errInvalidScope - } - - if parentSpanID != "" { - if requiredCount == 0 { - return empty, errInvalidScopeParent - } - // Validate parent span ID but we do not use it so do not save it. - if _, err = trace.SpanIDFromHex(parentSpanID); err != nil { - return empty, errInvalidParentSpanIDHeader - } - } - - return sc, nil -} - -// extractSingle reconstructs a SpanContext from contextHeader based on a B3 -// Single header. It is based on the implementation found here: -// https://github.com/openzipkin/zipkin-go/blob/v0.2.2/propagation/b3/spancontext.go -// and adapted to support a SpanContext. -func extractSingle(contextHeader string) (trace.SpanContext, error) { - if contextHeader == "" { - return empty, errEmptyContext - } - - var ( - sc = trace.SpanContext{} - sampling string - ) - - headerLen := len(contextHeader) - - if headerLen == samplingWidth { - sampling = contextHeader - } else if headerLen == traceID64BitsWidth || headerLen == traceID128BitsWidth { - // Trace ID by itself is invalid. - return empty, errInvalidScope - } else if headerLen >= traceID64BitsWidth+spanIDWidth+separatorWidth { - pos := 0 - var traceID string - if string(contextHeader[traceID64BitsWidth]) == "-" { - // traceID must be 64 bits - pos += traceID64BitsWidth // {traceID} - traceID = b3TraceIDPadding + string(contextHeader[0:pos]) - } else if string(contextHeader[32]) == "-" { - // traceID must be 128 bits - pos += traceID128BitsWidth // {traceID} - traceID = string(contextHeader[0:pos]) - } else { - return empty, errInvalidTraceIDValue - } - var err error - sc.TraceID, err = trace.IDFromHex(traceID) - if err != nil { - return empty, errInvalidTraceIDValue - } - pos += separatorWidth // {traceID}- - - sc.SpanID, err = trace.SpanIDFromHex(contextHeader[pos : pos+spanIDWidth]) - if err != nil { - return empty, errInvalidSpanIDValue - } - pos += spanIDWidth // {traceID}-{spanID} - - if headerLen > pos { - if headerLen == pos+separatorWidth { - // {traceID}-{spanID}- is invalid. - return empty, errInvalidSampledByte - } - pos += separatorWidth // {traceID}-{spanID}- - - if headerLen == pos+samplingWidth { - sampling = string(contextHeader[pos]) - } else if headerLen == pos+parentSpanIDWidth { - // {traceID}-{spanID}-{parentSpanID} is invalid. - return empty, errInvalidScopeParentSingle - } else if headerLen == pos+samplingWidth+separatorWidth+parentSpanIDWidth { - sampling = string(contextHeader[pos]) - pos += samplingWidth + separatorWidth // {traceID}-{spanID}-{sampling}- - - // Validate parent span ID but we do not use it so do not - // save it. - _, err = trace.SpanIDFromHex(contextHeader[pos:]) - if err != nil { - return empty, errInvalidParentSpanIDValue - } - } else { - return empty, errInvalidParentSpanIDValue - } - } - } else { - return empty, errInvalidTraceIDValue - } - switch sampling { - case "": - sc.TraceFlags = trace.FlagsDeferred - case "d": - sc.TraceFlags = trace.FlagsDebug - case "1": - sc.TraceFlags = trace.FlagsSampled - case "0": - // Zero value for TraceFlags sample bit is unset. - default: - return empty, errInvalidSampledByte - } - - return sc, nil -} diff --git a/propagators/b3_benchmark_test.go b/propagators/b3_benchmark_test.go deleted file mode 100644 index e35fbd7af..000000000 --- a/propagators/b3_benchmark_test.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package propagators_test - -import ( - "context" - "net/http" - "testing" - - "go.opentelemetry.io/otel/api/trace" - "go.opentelemetry.io/otel/propagators" -) - -func BenchmarkExtractB3(b *testing.B) { - testGroup := []struct { - name string - tests []extractTest - }{ - { - name: "valid headers", - tests: extractHeaders, - }, - { - name: "invalid headers", - tests: extractInvalidHeaders, - }, - } - - for _, tg := range testGroup { - propagator := propagators.B3{} - for _, tt := range tg.tests { - traceBenchmark(tg.name+"/"+tt.name, b, func(b *testing.B) { - ctx := context.Background() - req, _ := http.NewRequest("GET", "http://example.com", nil) - for h, v := range tt.headers { - req.Header.Set(h, v) - } - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = propagator.Extract(ctx, req.Header) - } - }) - } - } -} - -func BenchmarkInjectB3(b *testing.B) { - testGroup := []struct { - name string - tests []injectTest - }{ - { - name: "valid headers", - tests: injectHeader, - }, - { - name: "invalid headers", - tests: injectInvalidHeader, - }, - } - - for _, tg := range testGroup { - for _, tt := range tg.tests { - propagator := propagators.B3{InjectEncoding: tt.encoding} - traceBenchmark(tg.name+"/"+tt.name, b, func(b *testing.B) { - req, _ := http.NewRequest("GET", "http://example.com", nil) - ctx := trace.ContextWithSpan( - context.Background(), - testSpan{sc: tt.sc}, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - propagator.Inject(ctx, req.Header) - } - }) - } - } -} - -func traceBenchmark(name string, b *testing.B, fn func(*testing.B)) { - b.Run(name, func(b *testing.B) { - b.ReportAllocs() - fn(b) - }) - b.Run(name, func(b *testing.B) { - b.ReportAllocs() - fn(b) - }) -} diff --git a/propagators/b3_data_test.go b/propagators/b3_data_test.go deleted file mode 100644 index a995ff8f0..000000000 --- a/propagators/b3_data_test.go +++ /dev/null @@ -1,1021 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package propagators_test - -import ( - "fmt" - - "go.opentelemetry.io/otel/api/trace" - "go.opentelemetry.io/otel/propagators" -) - -const ( - b3Context = "b3" - b3Flags = "x-b3-flags" - b3TraceID = "x-b3-traceid" - b3SpanID = "x-b3-spanid" - b3Sampled = "x-b3-sampled" - b3ParentSpanID = "x-b3-parentspanid" -) - -type extractTest struct { - name string - headers map[string]string - wantSc trace.SpanContext -} - -var ( - traceID64bitPadded = mustTraceIDFromHex("0000000000000000a3ce929d0e0e4736") -) - -var extractHeaders = []extractTest{ - { - name: "empty", - headers: map[string]string{}, - wantSc: trace.EmptySpanContext(), - }, - { - name: "multiple: sampling state defer", - headers: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsDeferred, - }, - }, - { - name: "multiple: sampling state deny", - headers: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "0", - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - }, - }, - { - name: "multiple: sampling state accept", - headers: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "1", - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }, - }, - { - name: "multiple: sampling state as a boolean: true", - headers: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "true", - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }, - }, - { - name: "multiple: sampling state as a boolean: false", - headers: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "false", - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - }, - }, - { - name: "multiple: debug flag set", - headers: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Flags: "1", - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsDeferred | trace.FlagsDebug, - }, - }, - { - name: "multiple: debug flag set to not 1 (ignored)", - headers: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "1", - b3Flags: "2", - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }, - }, - { - // spec explicitly states "Debug implies an accept decision, so don't - // also send the X-B3-Sampled header", make sure sampling is - // deferred. - name: "multiple: debug flag set and sampling state is deny", - headers: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "0", - b3Flags: "1", - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsDebug, - }, - }, - { - name: "multiple: with parent span id", - headers: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "1", - b3ParentSpanID: "00f067aa0ba90200", - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }, - }, - { - name: "multiple: with only sampled state header", - headers: map[string]string{ - b3Sampled: "0", - }, - wantSc: trace.EmptySpanContext(), - }, - { - name: "multiple: left-padding 64-bit traceID", - headers: map[string]string{ - b3TraceID: "a3ce929d0e0e4736", - b3SpanID: spanIDStr, - }, - wantSc: trace.SpanContext{ - TraceID: traceID64bitPadded, - SpanID: spanID, - TraceFlags: trace.FlagsDeferred, - }, - }, - { - name: "single: sampling state defer", - headers: map[string]string{ - b3Context: fmt.Sprintf("%s-%s", traceIDStr, spanIDStr), - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsDeferred, - }, - }, - { - name: "single: sampling state deny", - headers: map[string]string{ - b3Context: fmt.Sprintf("%s-%s-0", traceIDStr, spanIDStr), - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - }, - }, - { - name: "single: sampling state accept", - headers: map[string]string{ - b3Context: fmt.Sprintf("%s-%s-1", traceIDStr, spanIDStr), - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }, - }, - { - name: "single: sampling state debug", - headers: map[string]string{ - b3Context: fmt.Sprintf("%s-%s-d", traceIDStr, spanIDStr), - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsDebug, - }, - }, - { - name: "single: with parent span id", - headers: map[string]string{ - b3Context: fmt.Sprintf("%s-%s-1-00000000000000cd", traceIDStr, spanIDStr), - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }, - }, - { - name: "single: with only sampling state deny", - headers: map[string]string{ - b3Context: "0", - }, - wantSc: trace.EmptySpanContext(), - }, - { - name: "single: left-padding 64-bit traceID", - headers: map[string]string{ - b3Context: fmt.Sprintf("a3ce929d0e0e4736-%s", spanIDStr), - }, - wantSc: trace.SpanContext{ - TraceID: traceID64bitPadded, - SpanID: spanID, - TraceFlags: trace.FlagsDeferred, - }, - }, - { - name: "both single and multiple: single priority", - headers: map[string]string{ - b3Context: fmt.Sprintf("%s-%s-1", traceIDStr, spanIDStr), - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "0", - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }, - }, - // An invalid Single Headers should fallback to multiple. - { - name: "both single and multiple: invalid single", - headers: map[string]string{ - b3Context: fmt.Sprintf("%s-%s-", traceIDStr, spanIDStr), - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "0", - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - }, - }, - // Invalid Mult Header should not be noticed as Single takes precedence. - { - name: "both single and multiple: invalid multiple", - headers: map[string]string{ - b3Context: fmt.Sprintf("%s-%s-1", traceIDStr, spanIDStr), - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "invalid", - }, - wantSc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }, - }, -} - -var extractInvalidHeaders = []extractTest{ - { - name: "multiple: trace ID length > 32", - headers: map[string]string{ - b3TraceID: "ab00000000000000000000000000000000", - b3SpanID: "cd00000000000000", - b3Sampled: "1", - }, - }, - { - name: "multiple: trace ID length >16 and <32", - headers: map[string]string{ - b3TraceID: "ab0000000000000000000000000000", - b3SpanID: "cd00000000000000", - b3Sampled: "1", - }, - }, - { - name: "multiple: trace ID length <16", - headers: map[string]string{ - b3TraceID: "ab0000000000", - b3SpanID: "cd00000000000000", - b3Sampled: "1", - }, - }, - { - name: "multiple: wrong span ID length", - headers: map[string]string{ - b3TraceID: "ab000000000000000000000000000000", - b3SpanID: "cd0000000000000000", - b3Sampled: "1", - }, - }, - { - name: "multiple: wrong sampled flag length", - headers: map[string]string{ - b3TraceID: "ab000000000000000000000000000000", - b3SpanID: "cd00000000000000", - b3Sampled: "10", - }, - }, - { - name: "multiple: bogus trace ID", - headers: map[string]string{ - b3TraceID: "qw000000000000000000000000000000", - b3SpanID: "cd00000000000000", - b3Sampled: "1", - }, - }, - { - name: "multiple: bogus span ID", - headers: map[string]string{ - b3TraceID: "ab000000000000000000000000000000", - b3SpanID: "qw00000000000000", - b3Sampled: "1", - }, - }, - { - name: "multiple: bogus sampled flag", - headers: map[string]string{ - b3TraceID: "ab000000000000000000000000000000", - b3SpanID: "cd00000000000000", - b3Sampled: "d", - }, - }, - { - name: "multiple: upper case trace ID", - headers: map[string]string{ - b3TraceID: "AB000000000000000000000000000000", - b3SpanID: "cd00000000000000", - b3Sampled: "1", - }, - }, - { - name: "multiple: upper case span ID", - headers: map[string]string{ - b3TraceID: "ab000000000000000000000000000000", - b3SpanID: "CD00000000000000", - b3Sampled: "1", - }, - }, - { - name: "multiple: zero trace ID", - headers: map[string]string{ - b3TraceID: "00000000000000000000000000000000", - b3SpanID: "cd00000000000000", - b3Sampled: "1", - }, - }, - { - name: "multiple: zero span ID", - headers: map[string]string{ - b3TraceID: "ab000000000000000000000000000000", - b3SpanID: "0000000000000000", - b3Sampled: "1", - }, - }, - { - name: "multiple: missing span ID", - headers: map[string]string{ - b3TraceID: "ab000000000000000000000000000000", - b3Sampled: "1", - }, - }, - { - name: "multiple: missing trace ID", - headers: map[string]string{ - b3SpanID: "cd00000000000000", - b3Sampled: "1", - }, - }, - { - name: "multiple: sampled header set to 1 but trace ID and span ID are missing", - headers: map[string]string{ - b3Sampled: "1", - }, - }, - { - name: "single: wrong trace ID length", - headers: map[string]string{ - b3Context: "ab00000000000000000000000000000000-cd00000000000000-1", - }, - }, - { - name: "single: wrong span ID length", - headers: map[string]string{ - b3Context: "ab000000000000000000000000000000-cd0000000000000000-1", - }, - }, - { - name: "single: wrong sampled state length", - headers: map[string]string{ - b3Context: "00-ab000000000000000000000000000000-cd00000000000000-01", - }, - }, - { - name: "single: wrong parent span ID length", - headers: map[string]string{ - b3Context: "ab000000000000000000000000000000-cd00000000000000-1-cd0000000000000000", - }, - }, - { - name: "single: bogus trace ID", - headers: map[string]string{ - b3Context: "qw000000000000000000000000000000-cd00000000000000-1", - }, - }, - { - name: "single: bogus span ID", - headers: map[string]string{ - b3Context: "ab000000000000000000000000000000-qw00000000000000-1", - }, - }, - { - name: "single: bogus sampled flag", - headers: map[string]string{ - b3Context: "ab000000000000000000000000000000-cd00000000000000-q", - }, - }, - { - name: "single: bogus parent span ID", - headers: map[string]string{ - b3Context: "ab000000000000000000000000000000-cd00000000000000-1-qw00000000000000", - }, - }, - { - name: "single: upper case trace ID", - headers: map[string]string{ - b3Context: "AB000000000000000000000000000000-cd00000000000000-1", - }, - }, - { - name: "single: upper case span ID", - headers: map[string]string{ - b3Context: "ab000000000000000000000000000000-CD00000000000000-1", - }, - }, - { - name: "single: upper case parent span ID", - headers: map[string]string{ - b3Context: "ab000000000000000000000000000000-cd00000000000000-1-EF00000000000000", - }, - }, - { - name: "single: zero trace ID and span ID", - headers: map[string]string{ - b3Context: "00000000000000000000000000000000-0000000000000000-1", - }, - }, - { - name: "single: with sampling set to true", - headers: map[string]string{ - b3Context: "ab000000000000000000000000000000-cd00000000000000-true", - }, - }, -} - -type injectTest struct { - name string - encoding propagators.B3Encoding - sc trace.SpanContext - wantHeaders map[string]string - doNotWantHeaders []string -} - -var injectHeader = []injectTest{ - { - name: "none: sampled", - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "1", - }, - doNotWantHeaders: []string{ - b3ParentSpanID, - b3Flags, - b3Context, - }, - }, - { - name: "none: not sampled", - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "0", - }, - doNotWantHeaders: []string{ - b3ParentSpanID, - b3Flags, - b3Context, - }, - }, - { - name: "none: unset sampled", - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsDeferred, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - }, - doNotWantHeaders: []string{ - b3Sampled, - b3ParentSpanID, - b3Flags, - b3Context, - }, - }, - { - name: "none: sampled only", - sc: trace.SpanContext{ - TraceFlags: trace.FlagsSampled, - }, - wantHeaders: map[string]string{ - b3Sampled: "1", - }, - doNotWantHeaders: []string{ - b3TraceID, - b3SpanID, - b3ParentSpanID, - b3Flags, - b3Context, - }, - }, - { - name: "none: debug", - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsDebug, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Flags: "1", - }, - doNotWantHeaders: []string{ - b3Sampled, - b3ParentSpanID, - b3Context, - }, - }, - { - name: "none: debug omitting sample", - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled | trace.FlagsDebug, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Flags: "1", - }, - doNotWantHeaders: []string{ - b3Sampled, - b3ParentSpanID, - b3Context, - }, - }, - { - name: "multiple: sampled", - encoding: propagators.B3MultipleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "1", - }, - doNotWantHeaders: []string{ - b3ParentSpanID, - b3Flags, - b3Context, - }, - }, - { - name: "multiple: not sampled", - encoding: propagators.B3MultipleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "0", - }, - doNotWantHeaders: []string{ - b3ParentSpanID, - b3Flags, - b3Context, - }, - }, - { - name: "multiple: unset sampled", - encoding: propagators.B3MultipleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsDeferred, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - }, - doNotWantHeaders: []string{ - b3Sampled, - b3ParentSpanID, - b3Flags, - b3Context, - }, - }, - { - name: "multiple: sampled only", - encoding: propagators.B3MultipleHeader, - sc: trace.SpanContext{ - TraceFlags: trace.FlagsSampled, - }, - wantHeaders: map[string]string{ - b3Sampled: "1", - }, - doNotWantHeaders: []string{ - b3TraceID, - b3SpanID, - b3ParentSpanID, - b3Flags, - b3Context, - }, - }, - { - name: "multiple: debug", - encoding: propagators.B3MultipleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsDebug, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Flags: "1", - }, - doNotWantHeaders: []string{ - b3Sampled, - b3ParentSpanID, - b3Context, - }, - }, - { - name: "multiple: debug omitting sample", - encoding: propagators.B3MultipleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled | trace.FlagsDebug, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Flags: "1", - }, - doNotWantHeaders: []string{ - b3Sampled, - b3ParentSpanID, - b3Context, - }, - }, - { - name: "single: sampled", - encoding: propagators.B3SingleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }, - wantHeaders: map[string]string{ - b3Context: fmt.Sprintf("%s-%s-1", traceIDStr, spanIDStr), - }, - doNotWantHeaders: []string{ - b3TraceID, - b3SpanID, - b3Sampled, - b3ParentSpanID, - b3Flags, - }, - }, - { - name: "single: not sampled", - encoding: propagators.B3SingleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - }, - wantHeaders: map[string]string{ - b3Context: fmt.Sprintf("%s-%s-0", traceIDStr, spanIDStr), - }, - doNotWantHeaders: []string{ - b3TraceID, - b3SpanID, - b3Sampled, - b3ParentSpanID, - b3Flags, - }, - }, - { - name: "single: unset sampled", - encoding: propagators.B3SingleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsDeferred, - }, - wantHeaders: map[string]string{ - b3Context: fmt.Sprintf("%s-%s", traceIDStr, spanIDStr), - }, - doNotWantHeaders: []string{ - b3TraceID, - b3SpanID, - b3Sampled, - b3ParentSpanID, - b3Flags, - }, - }, - { - name: "single: sampled only", - encoding: propagators.B3SingleHeader, - sc: trace.SpanContext{ - TraceFlags: trace.FlagsSampled, - }, - wantHeaders: map[string]string{ - b3Context: "1", - }, - doNotWantHeaders: []string{ - b3Sampled, - b3TraceID, - b3SpanID, - b3ParentSpanID, - b3Flags, - b3Context, - }, - }, - { - name: "single: debug", - encoding: propagators.B3SingleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsDebug, - }, - wantHeaders: map[string]string{ - b3Context: fmt.Sprintf("%s-%s-d", traceIDStr, spanIDStr), - }, - doNotWantHeaders: []string{ - b3TraceID, - b3SpanID, - b3Flags, - b3Sampled, - b3ParentSpanID, - b3Context, - }, - }, - { - name: "single: debug omitting sample", - encoding: propagators.B3SingleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled | trace.FlagsDebug, - }, - wantHeaders: map[string]string{ - b3Context: fmt.Sprintf("%s-%s-d", traceIDStr, spanIDStr), - }, - doNotWantHeaders: []string{ - b3TraceID, - b3SpanID, - b3Flags, - b3Sampled, - b3ParentSpanID, - b3Context, - }, - }, - { - name: "single+multiple: sampled", - encoding: propagators.B3SingleHeader | propagators.B3MultipleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "1", - b3Context: fmt.Sprintf("%s-%s-1", traceIDStr, spanIDStr), - }, - doNotWantHeaders: []string{ - b3ParentSpanID, - b3Flags, - }, - }, - { - name: "single+multiple: not sampled", - encoding: propagators.B3SingleHeader | propagators.B3MultipleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Sampled: "0", - b3Context: fmt.Sprintf("%s-%s-0", traceIDStr, spanIDStr), - }, - doNotWantHeaders: []string{ - b3ParentSpanID, - b3Flags, - }, - }, - { - name: "single+multiple: unset sampled", - encoding: propagators.B3SingleHeader | propagators.B3MultipleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsDeferred, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Context: fmt.Sprintf("%s-%s", traceIDStr, spanIDStr), - }, - doNotWantHeaders: []string{ - b3Sampled, - b3ParentSpanID, - b3Flags, - }, - }, - { - name: "single+multiple: sampled only", - encoding: propagators.B3SingleHeader | propagators.B3MultipleHeader, - sc: trace.SpanContext{ - TraceFlags: trace.FlagsSampled, - }, - wantHeaders: map[string]string{ - b3Context: "1", - b3Sampled: "1", - }, - doNotWantHeaders: []string{ - b3TraceID, - b3SpanID, - b3ParentSpanID, - b3Flags, - }, - }, - { - name: "single+multiple: debug", - encoding: propagators.B3SingleHeader | propagators.B3MultipleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsDebug, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Flags: "1", - b3Context: fmt.Sprintf("%s-%s-d", traceIDStr, spanIDStr), - }, - doNotWantHeaders: []string{ - b3Sampled, - b3ParentSpanID, - }, - }, - { - name: "single+multiple: debug omitting sample", - encoding: propagators.B3SingleHeader | propagators.B3MultipleHeader, - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled | trace.FlagsDebug, - }, - wantHeaders: map[string]string{ - b3TraceID: traceIDStr, - b3SpanID: spanIDStr, - b3Flags: "1", - b3Context: fmt.Sprintf("%s-%s-d", traceIDStr, spanIDStr), - }, - doNotWantHeaders: []string{ - b3Sampled, - b3ParentSpanID, - }, - }, -} - -var injectInvalidHeaderGenerator = []injectTest{ - { - name: "empty", - sc: trace.SpanContext{}, - }, - { - name: "missing traceID", - sc: trace.SpanContext{ - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }, - }, - { - name: "missing spanID", - sc: trace.SpanContext{ - TraceID: traceID, - TraceFlags: trace.FlagsSampled, - }, - }, - { - name: "missing traceID and spanID", - sc: trace.SpanContext{ - TraceFlags: trace.FlagsSampled, - }, - }, -} - -var injectInvalidHeader []injectTest - -func init() { - // Preform a test for each invalid injectTest with all combinations of - // encoding values. - injectInvalidHeader = make([]injectTest, 0, len(injectInvalidHeaderGenerator)*4) - allHeaders := []string{ - b3TraceID, - b3SpanID, - b3Sampled, - b3ParentSpanID, - b3Flags, - b3Context, - } - // Nothing should be set for any header regardless of encoding. - for _, t := range injectInvalidHeaderGenerator { - injectInvalidHeader = append(injectInvalidHeader, injectTest{ - name: "none: " + t.name, - sc: t.sc, - doNotWantHeaders: allHeaders, - }) - injectInvalidHeader = append(injectInvalidHeader, injectTest{ - name: "multiple: " + t.name, - encoding: propagators.B3MultipleHeader, - sc: t.sc, - doNotWantHeaders: allHeaders, - }) - injectInvalidHeader = append(injectInvalidHeader, injectTest{ - name: "single: " + t.name, - encoding: propagators.B3SingleHeader, - sc: t.sc, - doNotWantHeaders: allHeaders, - }) - injectInvalidHeader = append(injectInvalidHeader, injectTest{ - name: "single+multiple: " + t.name, - encoding: propagators.B3SingleHeader | propagators.B3MultipleHeader, - sc: t.sc, - doNotWantHeaders: allHeaders, - }) - } -} diff --git a/propagators/b3_example_test.go b/propagators/b3_example_test.go deleted file mode 100644 index ddeb4c599..000000000 --- a/propagators/b3_example_test.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package propagators_test - -import ( - "go.opentelemetry.io/otel/api/global" - "go.opentelemetry.io/otel/api/propagation" - "go.opentelemetry.io/otel/propagators" -) - -func ExampleB3() { - b3 := propagators.B3{} - // Register the B3 propagator globally. - global.SetPropagators(propagation.New( - propagation.WithExtractors(b3), - propagation.WithInjectors(b3), - )) -} - -func ExampleB3_injectEncoding() { - // Create a B3 propagator configured to inject context with both multiple - // and single header B3 HTTP encoding. - b3 := propagators.B3{ - InjectEncoding: propagators.B3MultipleHeader | propagators.B3SingleHeader, - } - global.SetPropagators(propagation.New( - propagation.WithExtractors(b3), - propagation.WithInjectors(b3), - )) -} diff --git a/propagators/b3_integration_test.go b/propagators/b3_integration_test.go deleted file mode 100644 index 9675ab482..000000000 --- a/propagators/b3_integration_test.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package propagators_test - -import ( - "context" - "net/http" - "testing" - - "github.com/google/go-cmp/cmp" - - "go.opentelemetry.io/otel/api/propagation" - "go.opentelemetry.io/otel/api/trace" - "go.opentelemetry.io/otel/internal/trace/noop" - "go.opentelemetry.io/otel/propagators" -) - -func TestExtractB3(t *testing.T) { - testGroup := []struct { - name string - tests []extractTest - }{ - { - name: "valid extract headers", - tests: extractHeaders, - }, - { - name: "invalid extract headers", - tests: extractInvalidHeaders, - }, - } - - for _, tg := range testGroup { - propagator := propagators.B3{} - props := propagation.New(propagation.WithExtractors(propagator)) - - for _, tt := range tg.tests { - t.Run(tt.name, func(t *testing.T) { - req, _ := http.NewRequest("GET", "http://example.com", nil) - for h, v := range tt.headers { - req.Header.Set(h, v) - } - - ctx := context.Background() - ctx = propagation.ExtractHTTP(ctx, props, req.Header) - gotSc := trace.RemoteSpanContextFromContext(ctx) - if diff := cmp.Diff(gotSc, tt.wantSc); diff != "" { - t.Errorf("%s: %s: -got +want %s", tg.name, tt.name, diff) - } - }) - } - } -} - -type testSpan struct { - trace.Span - sc trace.SpanContext -} - -func (s testSpan) SpanContext() trace.SpanContext { - return s.sc -} - -func TestInjectB3(t *testing.T) { - testGroup := []struct { - name string - tests []injectTest - }{ - { - name: "valid inject headers", - tests: injectHeader, - }, - { - name: "invalid inject headers", - tests: injectInvalidHeader, - }, - } - - for _, tg := range testGroup { - for _, tt := range tg.tests { - propagator := propagators.B3{InjectEncoding: tt.encoding} - t.Run(tt.name, func(t *testing.T) { - req, _ := http.NewRequest("GET", "http://example.com", nil) - ctx := trace.ContextWithSpan( - context.Background(), - testSpan{ - Span: noop.Span, - sc: tt.sc, - }, - ) - propagator.Inject(ctx, req.Header) - - for h, v := range tt.wantHeaders { - got, want := req.Header.Get(h), v - if diff := cmp.Diff(got, want); diff != "" { - t.Errorf("%s: %s, header=%s: -got +want %s", tg.name, tt.name, h, diff) - } - } - for _, h := range tt.doNotWantHeaders { - v, gotOk := req.Header[h] - if diff := cmp.Diff(gotOk, false); diff != "" { - t.Errorf("%s: %s, header=%s: -got +want %s, value=%s", tg.name, tt.name, h, diff, v) - } - } - }) - } - } -} - -func TestB3Propagator_GetAllKeys(t *testing.T) { - tests := []struct { - name string - propagator propagators.B3 - want []string - }{ - { - name: "no encoding specified", - propagator: propagators.B3{}, - want: []string{ - b3TraceID, - b3SpanID, - b3Sampled, - b3Flags, - }, - }, - { - name: "B3MultipleHeader encoding specified", - propagator: propagators.B3{InjectEncoding: propagators.B3MultipleHeader}, - want: []string{ - b3TraceID, - b3SpanID, - b3Sampled, - b3Flags, - }, - }, - { - name: "B3SingleHeader encoding specified", - propagator: propagators.B3{InjectEncoding: propagators.B3SingleHeader}, - want: []string{ - b3Context, - }, - }, - { - name: "B3SingleHeader and B3MultipleHeader encoding specified", - propagator: propagators.B3{InjectEncoding: propagators.B3SingleHeader | propagators.B3MultipleHeader}, - want: []string{ - b3Context, - b3TraceID, - b3SpanID, - b3Sampled, - b3Flags, - }, - }, - } - - for _, test := range tests { - if diff := cmp.Diff(test.propagator.GetAllKeys(), test.want); diff != "" { - t.Errorf("%s: GetAllKeys: -got +want %s", test.name, diff) - } - } -} diff --git a/propagators/b3_test.go b/propagators/b3_test.go deleted file mode 100644 index 4ad111316..000000000 --- a/propagators/b3_test.go +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package propagators - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "go.opentelemetry.io/otel/api/trace" -) - -var ( - traceID = trace.ID{0, 0, 0, 0, 0, 0, 0, 0x7b, 0, 0, 0, 0, 0, 0, 0x1, 0xc8} - traceIDStr = "000000000000007b00000000000001c8" - spanID = trace.SpanID{0, 0, 0, 0, 0, 0, 0, 0x7b} - spanIDStr = "000000000000007b" -) - -func TestExtractMultiple(t *testing.T) { - tests := []struct { - traceID string - spanID string - parentSpanID string - sampled string - flags string - expected trace.SpanContext - err error - }{ - { - "", "", "", "0", "", - trace.SpanContext{}, - nil, - }, - { - "", "", "", "", "", - trace.SpanContext{TraceFlags: trace.FlagsDeferred}, - nil, - }, - { - "", "", "", "1", "", - trace.SpanContext{TraceFlags: trace.FlagsSampled}, - nil, - }, - { - "", "", "", "", "1", - trace.SpanContext{TraceFlags: trace.FlagsDeferred | trace.FlagsDebug}, - nil, - }, - { - "", "", "", "0", "1", - trace.SpanContext{TraceFlags: trace.FlagsDebug}, - nil, - }, - { - "", "", "", "1", "1", - trace.SpanContext{TraceFlags: trace.FlagsSampled | trace.FlagsDebug}, - nil, - }, - { - traceIDStr, spanIDStr, "", "", "", - trace.SpanContext{TraceID: traceID, SpanID: spanID, TraceFlags: trace.FlagsDeferred}, - nil, - }, - { - traceIDStr, spanIDStr, "", "0", "", - trace.SpanContext{TraceID: traceID, SpanID: spanID}, - nil, - }, - // Ensure backwards compatibility. - { - traceIDStr, spanIDStr, "", "false", "", - trace.SpanContext{TraceID: traceID, SpanID: spanID}, - nil, - }, - { - traceIDStr, spanIDStr, "", "1", "", - trace.SpanContext{TraceID: traceID, SpanID: spanID, TraceFlags: trace.FlagsSampled}, - nil, - }, - // Ensure backwards compatibility. - { - traceIDStr, spanIDStr, "", "true", "", - trace.SpanContext{TraceID: traceID, SpanID: spanID, TraceFlags: trace.FlagsSampled}, - nil, - }, - { - traceIDStr, spanIDStr, "", "a", "", - empty, - errInvalidSampledHeader, - }, - { - traceIDStr, spanIDStr, "", "1", "1", - trace.SpanContext{TraceID: traceID, SpanID: spanID, TraceFlags: trace.FlagsSampled | trace.FlagsDebug}, - nil, - }, - // Invalid flags are discarded. - { - traceIDStr, spanIDStr, "", "1", "invalid", - trace.SpanContext{TraceID: traceID, SpanID: spanID, TraceFlags: trace.FlagsSampled}, - nil, - }, - // Support short trace IDs. - { - "00000000000001c8", spanIDStr, "", "0", "", - trace.SpanContext{ - TraceID: trace.ID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0xc8}, - SpanID: spanID, - }, - nil, - }, - { - "00000000000001c", spanIDStr, "", "0", "", - empty, - errInvalidTraceIDHeader, - }, - { - "00000000000001c80", spanIDStr, "", "0", "", - empty, - errInvalidTraceIDHeader, - }, - { - traceIDStr[:len(traceIDStr)-2], spanIDStr, "", "0", "", - empty, - errInvalidTraceIDHeader, - }, - { - traceIDStr + "0", spanIDStr, "", "0", "", - empty, - errInvalidTraceIDHeader, - }, - { - traceIDStr, "00000000000001c", "", "0", "", - empty, - errInvalidSpanIDHeader, - }, - { - traceIDStr, "00000000000001c80", "", "0", "", - empty, - errInvalidSpanIDHeader, - }, - { - traceIDStr, "", "", "0", "", - empty, - errInvalidScope, - }, - { - "", spanIDStr, "", "0", "", - empty, - errInvalidScope, - }, - { - "", "", spanIDStr, "0", "", - empty, - errInvalidScopeParent, - }, - { - traceIDStr, spanIDStr, "00000000000001c8", "0", "", - trace.SpanContext{TraceID: traceID, SpanID: spanID}, - nil, - }, - { - traceIDStr, spanIDStr, "00000000000001c", "0", "", - empty, - errInvalidParentSpanIDHeader, - }, - { - traceIDStr, spanIDStr, "00000000000001c80", "0", "", - empty, - errInvalidParentSpanIDHeader, - }, - } - - for _, test := range tests { - actual, err := extractMultiple( - test.traceID, - test.spanID, - test.parentSpanID, - test.sampled, - test.flags, - ) - info := []interface{}{ - "trace ID: %q, span ID: %q, parent span ID: %q, sampled: %q, flags: %q", - test.traceID, - test.spanID, - test.parentSpanID, - test.sampled, - test.flags, - } - if !assert.Equal(t, test.err, err, info...) { - continue - } - assert.Equal(t, test.expected, actual, info...) - } -} - -func TestExtractSingle(t *testing.T) { - tests := []struct { - header string - expected trace.SpanContext - err error - }{ - {"0", trace.SpanContext{}, nil}, - {"1", trace.SpanContext{TraceFlags: trace.FlagsSampled}, nil}, - {"d", trace.SpanContext{TraceFlags: trace.FlagsDebug}, nil}, - {"a", empty, errInvalidSampledByte}, - {"3", empty, errInvalidSampledByte}, - {"000000000000007b", empty, errInvalidScope}, - {"000000000000007b00000000000001c8", empty, errInvalidScope}, - // Support short trace IDs. - { - "00000000000001c8-000000000000007b", - trace.SpanContext{ - TraceID: trace.ID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0xc8}, - SpanID: spanID, - TraceFlags: trace.FlagsDeferred, - }, - nil, - }, - { - "000000000000007b00000000000001c8-000000000000007b", - trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsDeferred, - }, - nil, - }, - { - "000000000000007b00000000000001c8-000000000000007b-", - empty, - errInvalidSampledByte, - }, - { - "000000000000007b00000000000001c8-000000000000007b-3", - empty, - errInvalidSampledByte, - }, - { - "000000000000007b00000000000001c8-000000000000007b-00000000000001c8", - empty, - errInvalidScopeParentSingle, - }, - { - "000000000000007b00000000000001c8-000000000000007b-1", - trace.SpanContext{TraceID: traceID, SpanID: spanID, TraceFlags: trace.FlagsSampled}, - nil, - }, - // ParentSpanID is discarded, but should still restult in a parsable - // header. - { - "000000000000007b00000000000001c8-000000000000007b-1-00000000000001c8", - trace.SpanContext{TraceID: traceID, SpanID: spanID, TraceFlags: trace.FlagsSampled}, - nil, - }, - { - "000000000000007b00000000000001c8-000000000000007b-1-00000000000001c", - empty, - errInvalidParentSpanIDValue, - }, - {"", empty, errEmptyContext}, - } - - for _, test := range tests { - actual, err := extractSingle(test.header) - if !assert.Equal(t, test.err, err, "header: %s", test.header) { - continue - } - assert.Equal(t, test.expected, actual, "header: %s", test.header) - } -} - -func TestB3EncodingOperations(t *testing.T) { - encodings := []B3Encoding{ - B3MultipleHeader, - B3SingleHeader, - B3Unspecified, - } - - // Test for overflow (or something really unexpected). - for i, e := range encodings { - for j := i + 1; j < i+len(encodings); j++ { - o := encodings[j%len(encodings)] - assert.False(t, e == o, "%v == %v", e, o) - } - } - - // B3Unspecified is a special case, it supports only itself, but is - // supported by everything. - assert.True(t, B3Unspecified.supports(B3Unspecified)) - for _, e := range encodings[:len(encodings)-1] { - assert.False(t, B3Unspecified.supports(e), e) - assert.True(t, e.supports(B3Unspecified), e) - } - - // Skip the special case for B3Unspecified. - for i, e := range encodings[:len(encodings)-1] { - // Everything should support itself. - assert.True(t, e.supports(e)) - for j := i + 1; j < i+len(encodings); j++ { - o := encodings[j%len(encodings)] - // Any "or" combination should be supportive of an operand. - assert.True(t, (e | o).supports(e), "(%[0]v|%[1]v).supports(%[0]v)", e, o) - // Bitmasks should be unique. - assert.False(t, o.supports(e), "%v.supports(%v)", o, e) - } - } - - // B3Encoding.supports should be more inclusive than equality. - all := ^B3Unspecified - for _, e := range encodings { - assert.True(t, all.supports(e)) - } -} diff --git a/propagators/doc.go b/propagators/doc.go index 641eca607..5672a9887 100644 --- a/propagators/doc.go +++ b/propagators/doc.go @@ -16,9 +16,7 @@ Package propagators contains OpenTelemetry context propagators. OpenTelemetry propagators are used to extract and inject context data from and -into messages exchanged by applications. The propagators supported by this -package includes are the B3 single and multiple header HTTP encoding -(https://github.com/openzipkin/b3-propagation) and the W3C Trace Context -encoding (https://www.w3.org/TR/trace-context/). +into messages exchanged by applications. The propagator supported by this +package is the W3C Trace Context encoding (https://www.w3.org/TR/trace-context/). */ package propagators // import "go.opentelemetry.io/otel/propagators" diff --git a/propagators/propagators_test.go b/propagators/propagators_test.go index 25ad57cf0..06a2f2c11 100644 --- a/propagators/propagators_test.go +++ b/propagators/propagators_test.go @@ -91,9 +91,6 @@ func TestMultiplePropagators(t *testing.T) { ns := nilSupplier{} testProps := []propagation.HTTPPropagator{ propagators.TraceContext{}, - propagators.B3{}, - propagators.B3{InjectEncoding: propagators.B3SingleHeader}, - propagators.B3{InjectEncoding: propagators.B3SingleHeader | propagators.B3MultipleHeader}, } bg := context.Background() // sanity check of oota propagator, ensuring that it really