113 lines
2.6 KiB
Go
113 lines
2.6 KiB
Go
|
package lightstep
|
||
|
|
||
|
import (
|
||
|
"encoding/base64"
|
||
|
"io"
|
||
|
"io/ioutil"
|
||
|
|
||
|
"github.com/gogo/protobuf/proto"
|
||
|
lightstep "github.com/lightstep/lightstep-tracer-common/golang/gogo/lightsteppb"
|
||
|
"github.com/opentracing/opentracing-go"
|
||
|
)
|
||
|
|
||
|
// BinaryCarrier is used as the format parameter in inject/extract for lighstep binary propagation.
|
||
|
const BinaryCarrier = opentracing.Binary
|
||
|
|
||
|
// BinaryPropagator propagates context in binary format
|
||
|
var BinaryPropagator binaryPropagator
|
||
|
|
||
|
type binaryPropagator struct{}
|
||
|
|
||
|
func (binaryPropagator) Inject(
|
||
|
spanContext opentracing.SpanContext,
|
||
|
opaqueCarrier interface{},
|
||
|
) error {
|
||
|
sc, ok := spanContext.(SpanContext)
|
||
|
if !ok {
|
||
|
return opentracing.ErrInvalidSpanContext
|
||
|
}
|
||
|
data, err := proto.Marshal(&lightstep.BinaryCarrier{
|
||
|
BasicCtx: &lightstep.BasicTracerCarrier{
|
||
|
TraceId: sc.TraceID,
|
||
|
SpanId: sc.SpanID,
|
||
|
Sampled: true,
|
||
|
BaggageItems: sc.Baggage,
|
||
|
},
|
||
|
})
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
switch carrier := opaqueCarrier.(type) {
|
||
|
case io.Writer:
|
||
|
buf := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
|
||
|
base64.StdEncoding.Encode(buf, data)
|
||
|
_, err = carrier.Write(buf)
|
||
|
return err
|
||
|
case *string:
|
||
|
*carrier = base64.StdEncoding.EncodeToString(data)
|
||
|
case *[]byte:
|
||
|
*carrier = make([]byte, base64.StdEncoding.EncodedLen(len(data)))
|
||
|
base64.StdEncoding.Encode(*carrier, data)
|
||
|
default:
|
||
|
return opentracing.ErrInvalidCarrier
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (binaryPropagator) Extract(
|
||
|
opaqueCarrier interface{},
|
||
|
) (opentracing.SpanContext, error) {
|
||
|
var data []byte
|
||
|
var err error
|
||
|
|
||
|
// Decode from string, *string, *[]byte, or []byte
|
||
|
switch carrier := opaqueCarrier.(type) {
|
||
|
case io.Reader:
|
||
|
buf, err := ioutil.ReadAll(carrier)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
data, err = decodeBase64Bytes(buf)
|
||
|
case *string:
|
||
|
if carrier != nil {
|
||
|
data, err = base64.StdEncoding.DecodeString(*carrier)
|
||
|
}
|
||
|
case string:
|
||
|
data, err = base64.StdEncoding.DecodeString(carrier)
|
||
|
case *[]byte:
|
||
|
if carrier != nil {
|
||
|
data, err = decodeBase64Bytes(*carrier)
|
||
|
}
|
||
|
case []byte:
|
||
|
data, err = decodeBase64Bytes(carrier)
|
||
|
default:
|
||
|
return nil, opentracing.ErrInvalidCarrier
|
||
|
}
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
pb := &lightstep.BinaryCarrier{}
|
||
|
if err := proto.Unmarshal(data, pb); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if pb.BasicCtx == nil {
|
||
|
return nil, opentracing.ErrInvalidCarrier
|
||
|
}
|
||
|
|
||
|
return SpanContext{
|
||
|
TraceID: pb.BasicCtx.TraceId,
|
||
|
SpanID: pb.BasicCtx.SpanId,
|
||
|
Baggage: pb.BasicCtx.BaggageItems,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func decodeBase64Bytes(in []byte) ([]byte, error) {
|
||
|
data := make([]byte, base64.StdEncoding.DecodedLen(len(in)))
|
||
|
n, err := base64.StdEncoding.Decode(data, in)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return data[:n], nil
|
||
|
}
|