in propagator/propagator.go [111:165]
func spanContextFromXCTCHeader(header string) (trace.SpanContext, error) {
match := traceContextHeaderRe.FindStringSubmatch(header)
if match == nil {
return trace.SpanContext{}, errInvalidHeader{header}
}
names := traceContextHeaderRe.SubexpNames()
var traceID, spanID, traceFlags string
for i, n := range names {
switch n {
case "trace_id":
traceID = match[i]
case "span_id":
spanID = match[i]
case "trace_flags":
traceFlags = match[i]
}
}
// non-recording Span
if traceID == strings.Repeat("0", 32) || spanID == "0" {
return trace.SpanContext{}, errInvalidHeader{header}
}
// https://cloud.google.com/trace/docs/setup#force-trace
// Trace ID: 32-char hexadecimal value representing a 128-bit number.
// Span ID: decimal representation of the unsigned interger.
tid, err := trace.TraceIDFromHex(traceID)
if err != nil {
log.Printf("CloudTraceFormatPropagator: invalid trace id %#v: %v", traceID, err)
return trace.SpanContext{}, errInvalidHeader{header}
}
sidUint, err := strconv.ParseUint(spanID, 10, 64)
if err != nil {
log.Printf("CloudTraceFormatPropagator: on span ID conversion: %v", err)
return trace.SpanContext{}, errInvalidHeader{header}
}
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, sidUint)
ary := [8]byte{}
copy(ary[:], buf)
sid := trace.SpanID(ary)
// XCTC's TRACE_TRUE option
// https://cloud.google.com/trace/docs/setup#force-trace
tf := trace.TraceFlags(0x01)
if traceFlags == "0" || traceFlags == "" {
tf = trace.TraceFlags(0x00)
}
scConfig := trace.SpanContextConfig{
TraceID: tid,
SpanID: sid,
TraceFlags: tf,
Remote: true,
}
return trace.NewSpanContext(scConfig), nil
}