func spanContextFromXCTCHeader()

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
}