Source File
b3_propagator.go
Belonging Package
go.opentelemetry.io/otel/api/trace
package trace
import (
)
b3ContextHeader = "b3"
b3DebugFlagHeader = "x-b3-flags"
b3TraceIDHeader = "x-b3-traceid"
b3SpanIDHeader = "x-b3-spanid"
b3SampledHeader = "x-b3-sampled"
b3ParentSpanIDHeader = "x-b3-parentspanid"
b3TraceIDPadding = "0000000000000000"
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 = 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")
)
type B3Encoding uint8
func ( B3Encoding) ( B3Encoding) bool {
return & ==
}
B3Unspecified B3Encoding = 0
)
InjectEncoding B3Encoding
}
var _ propagation.HTTPPropagator = B3{}
func ( B3) ( context.Context, propagation.HTTPSupplier) {
:= SpanFromContext().SpanContext()
if .InjectEncoding.supports(B3SingleHeader) {
:= []string{}
if .TraceID.IsValid() && .SpanID.IsValid() {
= append(, .TraceID.String(), .SpanID.String())
}
if .isDebug() {
= append(, "d")
} else if !.isDeferred() {
if .IsSampled() {
= append(, "1")
} else {
= append(, "0")
}
}
.Set(b3ContextHeader, strings.Join(, "-"))
}
if .InjectEncoding.supports(B3MultipleHeader) || .InjectEncoding == B3Unspecified {
if .TraceID.IsValid() && .SpanID.IsValid() {
.Set(b3TraceIDHeader, .TraceID.String())
.Set(b3SpanIDHeader, .SpanID.String())
}
.Set(b3DebugFlagHeader, "1")
} else if !.isDeferred() {
if .IsSampled() {
.Set(b3SampledHeader, "1")
} else {
.Set(b3SampledHeader, "0")
}
}
}
}
func ( B3) ( context.Context, propagation.HTTPSupplier) context.Context {
var (
SpanContext
error
)
if := .Get(b3ContextHeader); != "" {
, = extractSingle()
if == nil && .IsValid() {
return ContextWithRemoteSpanContext(, )
}
var (
= .Get(b3TraceIDHeader)
= .Get(b3SpanIDHeader)
= .Get(b3ParentSpanIDHeader)
= .Get(b3SampledHeader)
= .Get(b3DebugFlagHeader)
)
, = extractMultiple(, , , , )
if != nil || !.IsValid() {
return
}
return ContextWithRemoteSpanContext(, )
}
func ( B3) () []string {
:= []string{}
if .InjectEncoding.supports(B3SingleHeader) {
= append(, b3ContextHeader)
}
if .InjectEncoding.supports(B3MultipleHeader) || .InjectEncoding == B3Unspecified {
= append(, b3TraceIDHeader, b3SpanIDHeader, b3SampledHeader, b3DebugFlagHeader)
}
return
}
func (, , , , string) (SpanContext, error) {
var (
error
int
= SpanContext{}
)
case "1", "true":
.TraceFlags = FlagsSampled
case "":
.TraceFlags = FlagsDeferred
default:
return empty, errInvalidSampledHeader
}
if == "1" {
.TraceFlags |= FlagsDebug
}
if != "" {
++
:=
= b3TraceIDPadding +
}
if .TraceID, = IDFromHex(); != nil {
return empty, errInvalidTraceIDHeader
}
}
if != "" {
++
if .SpanID, = SpanIDFromHex(); != nil {
return empty, errInvalidSpanIDHeader
}
}
if != 0 && != 2 {
return empty, errInvalidScope
}
if != "" {
if == 0 {
return empty, errInvalidScopeParent
if _, = SpanIDFromHex(); != nil {
return empty, errInvalidParentSpanIDHeader
}
}
return , nil
}
func ( string) (SpanContext, error) {
if == "" {
return empty, errEmptyContext
}
var (
= SpanContext{}
string
)
:= len()
if == samplingWidth {
=
return empty, errInvalidScope
} else if >= traceID64BitsWidth+spanIDWidth+separatorWidth {
:= 0
var string
+= traceID64BitsWidth // {traceID}
= b3TraceIDPadding + string([0:])
+= traceID128BitsWidth // {traceID}
= string([0:])
} else {
return empty, errInvalidTraceIDValue
}
var error
.TraceID, = IDFromHex()
if != nil {
return empty, errInvalidTraceIDValue
}
+= separatorWidth // {traceID}-
.SpanID, = SpanIDFromHex([ : +spanIDWidth])
if != nil {
return empty, errInvalidSpanIDValue
}
+= spanIDWidth // {traceID}-{spanID}
if > {
return empty, errInvalidSampledByte
}
+= separatorWidth // {traceID}-{spanID}-
if == +samplingWidth {
= string([])
return empty, errInvalidScopeParentSingle
} else if == +samplingWidth+separatorWidth+parentSpanIDWidth {
= string([])
+= samplingWidth + separatorWidth // {traceID}-{spanID}-{sampling}-
_, = SpanIDFromHex([:])
if != nil {
return empty, errInvalidParentSpanIDValue
}
} else {
return empty, errInvalidParentSpanIDValue
}
}
} else {
return empty, errInvalidTraceIDValue
}
switch {
case "":
.TraceFlags = FlagsDeferred
case "d":
.TraceFlags = FlagsDebug
case "1":
.TraceFlags = FlagsSampled
default:
return empty, errInvalidSampledByte
}
return , nil
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |