Skip to content

Commit

Permalink
Merge pull request #29 from opentracing/bhs/span_context_revival
Browse files Browse the repository at this point in the history
Update to support opentracing.SpanContext (and References)
  • Loading branch information
bensigelman committed Jul 6, 2016
2 parents f061a1a + fdcf539 commit fb0d4fa
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 206 deletions.
56 changes: 51 additions & 5 deletions context.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,62 @@
package basictracer

// Context holds the basic Span metadata.
type Context struct {
import (
"sync"

"github.com/opentracing/opentracing-go"
)

// SpanContext holds the basic Span metadata.
type SpanContext struct {
// A probabilistically unique identifier for a [multi-span] trace.
TraceID uint64

// A probabilistically unique identifier for a span.
SpanID uint64

// The SpanID of this Context's parent, or 0 if there is no parent.
ParentSpanID uint64

// Whether the trace is sampled.
Sampled bool

// The span's associated baggage.
baggageLock sync.Mutex
Baggage map[string]string // initialized on first use
}

// BaggageItem belongs to the opentracing.SpanContext interface
func (c *SpanContext) BaggageItem(key string) string {
// TODO: if we want to support onBaggage, need a pointer to the bt.Span.
// s.onBaggage(canonicalKey, val)
// if s.trim() {
// return s
// }

c.baggageLock.Lock()
defer c.baggageLock.Unlock()

if c.Baggage == nil {
return ""
}
return c.Baggage[key]
}

// SetBaggageItem belongs to the opentracing.SpanContext interface
func (c *SpanContext) SetBaggageItem(key, val string) opentracing.SpanContext {
c.baggageLock.Lock()
defer c.baggageLock.Unlock()
if c.Baggage == nil {
c.Baggage = make(map[string]string)
}
c.Baggage[key] = val
return c
}

// ForeachBaggageItem belongs to the opentracing.SpanContext interface
func (c *SpanContext) ForeachBaggageItem(handler func(k, v string) bool) {
c.baggageLock.Lock()
defer c.baggageLock.Unlock()
for k, v := range c.Baggage {
if !handler(k, v) {
break
}
}
}
63 changes: 25 additions & 38 deletions propagation.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package basictracer

import (
"time"

opentracing "github.com/opentracing/opentracing-go"
)
import opentracing "github.com/opentracing/opentracing-go"

type accessorPropagator struct {
tracer *tracerImpl
Expand All @@ -21,54 +17,45 @@ type DelegatingCarrier interface {
}

func (p *accessorPropagator) Inject(
sp opentracing.Span,
spanContext opentracing.SpanContext,
carrier interface{},
) error {
ac, ok := carrier.(DelegatingCarrier)
if !ok || ac == nil {
dc, ok := carrier.(DelegatingCarrier)
if !ok || dc == nil {
return opentracing.ErrInvalidCarrier
}
si, ok := sp.(*spanImpl)
sc, ok := spanContext.(*SpanContext)
if !ok {
return opentracing.ErrInvalidSpan
return opentracing.ErrInvalidSpanContext
}
meta := si.raw.Context
ac.SetState(meta.TraceID, meta.SpanID, meta.Sampled)
for k, v := range si.raw.Baggage {
ac.SetBaggageItem(k, v)
dc.SetState(sc.TraceID, sc.SpanID, sc.Sampled)
for k, v := range sc.Baggage {
dc.SetBaggageItem(k, v)
}
return nil
}

func (p *accessorPropagator) Join(
operationName string,
func (p *accessorPropagator) Extract(
carrier interface{},
) (opentracing.Span, error) {
ac, ok := carrier.(DelegatingCarrier)
if !ok || ac == nil {
) (opentracing.SpanContext, error) {
dc, ok := carrier.(DelegatingCarrier)
if !ok || dc == nil {
return nil, opentracing.ErrInvalidCarrier
}

sp := p.tracer.getSpan()
ac.GetBaggage(func(k, v string) {
if sp.raw.Baggage == nil {
sp.raw.Baggage = map[string]string{}
traceID, spanID, sampled := dc.State()
sc := &SpanContext{
TraceID: traceID,
SpanID: spanID,
Sampled: sampled,
Baggage: nil,
}
dc.GetBaggage(func(k, v string) {
if sc.Baggage == nil {
sc.Baggage = map[string]string{}
}
sp.raw.Baggage[k] = v
sc.Baggage[k] = v
})

traceID, parentSpanID, sampled := ac.State()
sp.raw.Context = Context{
TraceID: traceID,
SpanID: randomID(),
ParentSpanID: parentSpanID,
Sampled: sampled,
}

return p.tracer.startSpanInternal(
sp,
operationName,
time.Now(),
nil,
), nil
return sc, nil
}
110 changes: 42 additions & 68 deletions propagation_ot.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"io"
"strconv"
"strings"
"time"

"github.com/gogo/protobuf/proto"
"github.com/opentracing/basictracer-go/wire"
Expand All @@ -30,39 +29,38 @@ const (
)

func (p *textMapPropagator) Inject(
sp opentracing.Span,
spanContext opentracing.SpanContext,
opaqueCarrier interface{},
) error {
sc, ok := sp.(*spanImpl)
sc, ok := spanContext.(*SpanContext)
if !ok {
return opentracing.ErrInvalidSpan
return opentracing.ErrInvalidSpanContext
}
carrier, ok := opaqueCarrier.(opentracing.TextMapWriter)
if !ok {
return opentracing.ErrInvalidCarrier
}
carrier.Set(fieldNameTraceID, strconv.FormatUint(sc.raw.TraceID, 16))
carrier.Set(fieldNameSpanID, strconv.FormatUint(sc.raw.SpanID, 16))
carrier.Set(fieldNameSampled, strconv.FormatBool(sc.raw.Sampled))
carrier.Set(fieldNameTraceID, strconv.FormatUint(sc.TraceID, 16))
carrier.Set(fieldNameSpanID, strconv.FormatUint(sc.SpanID, 16))
carrier.Set(fieldNameSampled, strconv.FormatBool(sc.Sampled))

sc.Lock()
for k, v := range sc.raw.Baggage {
sc.baggageLock.Lock()
for k, v := range sc.Baggage {
carrier.Set(prefixBaggage+k, v)
}
sc.Unlock()
sc.baggageLock.Unlock()
return nil
}

func (p *textMapPropagator) Join(
operationName string,
func (p *textMapPropagator) Extract(
opaqueCarrier interface{},
) (opentracing.Span, error) {
) (opentracing.SpanContext, error) {
carrier, ok := opaqueCarrier.(opentracing.TextMapReader)
if !ok {
return nil, opentracing.ErrInvalidCarrier
}
requiredFieldCount := 0
var traceID, propagatedSpanID uint64
var traceID, spanID uint64
var sampled bool
var err error
decodedBaggage := make(map[string]string)
Expand All @@ -71,17 +69,17 @@ func (p *textMapPropagator) Join(
case fieldNameTraceID:
traceID, err = strconv.ParseUint(v, 16, 64)
if err != nil {
return opentracing.ErrTraceCorrupted
return opentracing.ErrSpanContextCorrupted
}
case fieldNameSpanID:
propagatedSpanID, err = strconv.ParseUint(v, 16, 64)
spanID, err = strconv.ParseUint(v, 16, 64)
if err != nil {
return opentracing.ErrTraceCorrupted
return opentracing.ErrSpanContextCorrupted
}
case fieldNameSampled:
sampled, err = strconv.ParseBool(v)
if err != nil {
return opentracing.ErrTraceCorrupted
return opentracing.ErrSpanContextCorrupted
}
default:
lowercaseK := strings.ToLower(k)
Expand All @@ -99,48 +97,37 @@ func (p *textMapPropagator) Join(
}
if requiredFieldCount < tracerStateFieldCount {
if requiredFieldCount == 0 {
return nil, opentracing.ErrTraceNotFound
return nil, opentracing.ErrSpanContextNotFound
}
return nil, opentracing.ErrTraceCorrupted
return nil, opentracing.ErrSpanContextCorrupted
}

sp := p.tracer.getSpan()
sp.raw = RawSpan{
Context: Context{
TraceID: traceID,
SpanID: randomID(),
ParentSpanID: propagatedSpanID,
Sampled: sampled,
},
return &SpanContext{
TraceID: traceID,
SpanID: spanID,
Sampled: sampled,
Baggage: decodedBaggage,
}

return p.tracer.startSpanInternal(
sp,
operationName,
time.Now(),
nil,
), nil
}, nil
}

func (p *binaryPropagator) Inject(
sp opentracing.Span,
spanContext opentracing.SpanContext,
opaqueCarrier interface{},
) error {
sc, ok := sp.(*spanImpl)
sc, ok := spanContext.(*SpanContext)
if !ok {
return opentracing.ErrInvalidSpan
return opentracing.ErrInvalidSpanContext
}
carrier, ok := opaqueCarrier.(io.Writer)
if !ok {
return opentracing.ErrInvalidCarrier
}

state := wire.TracerState{}
state.TraceId = sc.raw.TraceID
state.SpanId = sc.raw.SpanID
state.Sampled = sc.raw.Sampled
state.BaggageItems = sc.raw.Baggage
state.TraceId = sc.TraceID
state.SpanId = sc.SpanID
state.Sampled = sc.Sampled
state.BaggageItems = sc.Baggage

b, err := proto.Marshal(&state)
if err != nil {
Expand All @@ -157,10 +144,9 @@ func (p *binaryPropagator) Inject(
return err
}

func (p *binaryPropagator) Join(
operationName string,
func (p *binaryPropagator) Extract(
opaqueCarrier interface{},
) (opentracing.Span, error) {
) (opentracing.SpanContext, error) {
carrier, ok := opaqueCarrier.(io.Reader)
if !ok {
return nil, opentracing.ErrInvalidCarrier
Expand All @@ -172,37 +158,25 @@ func (p *binaryPropagator) Join(
// the exact amount of bytes into it.
var length uint32
if err := binary.Read(carrier, binary.BigEndian, &length); err != nil {
return nil, opentracing.ErrTraceCorrupted
return nil, opentracing.ErrSpanContextCorrupted
}
buf := make([]byte, length)
if n, err := carrier.Read(buf); err != nil {
if n > 0 {
return nil, opentracing.ErrTraceCorrupted
return nil, opentracing.ErrSpanContextCorrupted
}
return nil, opentracing.ErrTraceNotFound
return nil, opentracing.ErrSpanContextNotFound
}

ctx := wire.TracerState{}
if err := proto.Unmarshal(buf, &ctx); err != nil {
return nil, opentracing.ErrTraceCorrupted
return nil, opentracing.ErrSpanContextCorrupted
}

sp := p.tracer.getSpan()
sp.raw = RawSpan{
Context: Context{
TraceID: ctx.TraceId,
SpanID: randomID(),
ParentSpanID: ctx.SpanId,
Sampled: ctx.Sampled,
},
}

sp.raw.Baggage = ctx.BaggageItems

return p.tracer.startSpanInternal(
sp,
operationName,
time.Now(),
nil,
), nil
return &SpanContext{
TraceID: ctx.TraceId,
SpanID: ctx.SpanId,
Sampled: ctx.Sampled,
Baggage: ctx.BaggageItems,
}, nil
}
13 changes: 7 additions & 6 deletions raw.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ import (

// RawSpan encapsulates all state associated with a (finished) Span.
type RawSpan struct {
// The RawSpan embeds its Context. Those recording the RawSpan
// should also record the contents of its Context.
Context
// The RawSpan embeds its SpanContext. Those recording the RawSpan
// should also record the contents of its SpanContext.
*SpanContext

// The SpanID of this SpanContext's first intra-trace reference (i.e.,
// "parent"), or 0 if there is no parent.
ParentSpanID uint64

// The name of the "operation" this span is an instance of. (Called a "span
// name" in some implementations)
Expand All @@ -27,7 +31,4 @@ type RawSpan struct {

// The span's "microlog".
Logs []opentracing.LogData

// The span's associated baggage.
Baggage map[string]string // initialized on first use
}
Loading

0 comments on commit fb0d4fa

Please sign in to comment.