| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- // Copyright (c) 2017 Uber Technologies, Inc.
- //
- // 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 zipkin
- import (
- "strconv"
- "strings"
- opentracing "github.com/opentracing/opentracing-go"
- "github.com/uber/jaeger-client-go"
- )
- // Option is a function that sets an option on Propagator
- type Option func(propagator *Propagator)
- // BaggagePrefix is a function that sets baggage prefix on Propagator
- func BaggagePrefix(prefix string) Option {
- return func(propagator *Propagator) {
- propagator.baggagePrefix = prefix
- }
- }
- // Propagator is an Injector and Extractor
- type Propagator struct {
- baggagePrefix string
- }
- // NewZipkinB3HTTPHeaderPropagator creates a Propagator for extracting and injecting
- // Zipkin HTTP B3 headers into SpanContexts. Baggage is by default enabled and uses prefix
- // 'baggage-'.
- func NewZipkinB3HTTPHeaderPropagator(opts ...Option) Propagator {
- p := Propagator{baggagePrefix: "baggage-"}
- for _, opt := range opts {
- opt(&p)
- }
- return p
- }
- // Inject conforms to the Injector interface for decoding Zipkin HTTP B3 headers
- func (p Propagator) Inject(
- sc jaeger.SpanContext,
- abstractCarrier interface{},
- ) error {
- textMapWriter, ok := abstractCarrier.(opentracing.TextMapWriter)
- if !ok {
- return opentracing.ErrInvalidCarrier
- }
- textMapWriter.Set("x-b3-traceid", sc.TraceID().String())
- if sc.ParentID() != 0 {
- textMapWriter.Set("x-b3-parentspanid", strconv.FormatUint(uint64(sc.ParentID()), 16))
- }
- textMapWriter.Set("x-b3-spanid", strconv.FormatUint(uint64(sc.SpanID()), 16))
- if sc.IsSampled() {
- textMapWriter.Set("x-b3-sampled", "1")
- } else {
- textMapWriter.Set("x-b3-sampled", "0")
- }
- sc.ForeachBaggageItem(func(k, v string) bool {
- textMapWriter.Set(p.baggagePrefix+k, v)
- return true
- })
- return nil
- }
- // Extract conforms to the Extractor interface for encoding Zipkin HTTP B3 headers
- func (p Propagator) Extract(abstractCarrier interface{}) (jaeger.SpanContext, error) {
- textMapReader, ok := abstractCarrier.(opentracing.TextMapReader)
- if !ok {
- return jaeger.SpanContext{}, opentracing.ErrInvalidCarrier
- }
- var traceID jaeger.TraceID
- var spanID uint64
- var parentID uint64
- sampled := false
- var baggage map[string]string
- err := textMapReader.ForeachKey(func(rawKey, value string) error {
- key := strings.ToLower(rawKey) // TODO not necessary for plain TextMap
- var err error
- if key == "x-b3-traceid" {
- traceID, err = jaeger.TraceIDFromString(value)
- } else if key == "x-b3-parentspanid" {
- parentID, err = strconv.ParseUint(value, 16, 64)
- } else if key == "x-b3-spanid" {
- spanID, err = strconv.ParseUint(value, 16, 64)
- } else if key == "x-b3-sampled" && (value == "1" || value == "true") {
- sampled = true
- } else if strings.HasPrefix(key, p.baggagePrefix) {
- if baggage == nil {
- baggage = make(map[string]string)
- }
- baggage[key[len(p.baggagePrefix):]] = value
- }
- return err
- })
- if err != nil {
- return jaeger.SpanContext{}, err
- }
- if !traceID.IsValid() {
- return jaeger.SpanContext{}, opentracing.ErrSpanContextNotFound
- }
- return jaeger.NewSpanContext(
- traceID,
- jaeger.SpanID(spanID),
- jaeger.SpanID(parentID),
- sampled, baggage), nil
- }
|