Skip to content

Commit

Permalink
Use map instead of string to configure propagators (#239)
Browse files Browse the repository at this point in the history
* Use map instead of string to configure propagators
* Adding PropagatorStack
  • Loading branch information
alrex authored Nov 18, 2019
1 parent a411674 commit eb40dd3
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 14 deletions.
9 changes: 7 additions & 2 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,13 @@ type Options struct {
UseHttp bool `yaml:"use_http"`
UseGRPC bool `yaml:"usegrpc"`

// Propagator provides support for different types of headers. Supported options: ls, b3
Propagator string `yaml:"propagator"`
// Propagators allow inject/extract to use custom propagators for different formats. This
// package includes a `B3Propagator` that supports B3 headers on text maps and http headers.
// Defaults:
// opentracing.HTTPHeaders: LightStepPropagator
// opentracing.TextMap: LightStepPropagator,
// opentracing.Binary: LightStepPropagator
Propagators map[opentracing.BuiltinFormat]Propagator `yaml:"-"`

// CustomCollector allows customizing the Protobuf transport.
// This is an advanced feature that avoids reconnect logic.
Expand Down
3 changes: 2 additions & 1 deletion propagation_b3.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ const (
b3FieldNameSampled = b3Prefix + "sampled"
)

var theB3Propagator b3Propagator
// B3Propagator propagates context in the b3 format
var B3Propagator b3Propagator

type b3Propagator struct{}

Expand Down
3 changes: 2 additions & 1 deletion propagation_binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import (
// BinaryCarrier is used as the format parameter in inject/extract for lighstep binary propagation.
const BinaryCarrier = opentracing.Binary

var theBinaryPropagator binaryPropagator
// BinaryPropagator propagates context in binary format
var BinaryPropagator binaryPropagator

type binaryPropagator struct{}

Expand Down
3 changes: 2 additions & 1 deletion propagation_lightstep.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ const (
fieldNameSampled = prefixTracerState + "sampled"
)

var theLightStepPropagator lightstepPropagator
// LightStepPropagator propagates context in the LightStep format
var LightStepPropagator lightstepPropagator

type lightstepPropagator struct{}

Expand Down
52 changes: 52 additions & 0 deletions propagation_stack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package lightstep

import (
"errors"

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

// PropagatorStack provides a Propagator interface that supports
// multiple propagators per format.
type PropagatorStack struct {
propagators []Propagator
}

// PushPropagator adds a Propagator to a list of configured propagators
func (stack *PropagatorStack) PushPropagator(p Propagator) {
stack.propagators = append(stack.propagators, p)
}

// Inject iterates through configured propagators and calls
// their Inject functions
func (stack PropagatorStack) Inject(
spanContext opentracing.SpanContext,
opaqueCarrier interface{},
) error {
if len(stack.propagators) == 0 {
return errors.New("No valid propagator configured")
}
for _, propagator := range stack.propagators {
propagator.Inject(spanContext, opaqueCarrier)
}
return nil
}

// Extract iterates through configured propagators and
// returns the first successfully extracted context
func (stack PropagatorStack) Extract(
opaqueCarrier interface{},
) (opentracing.SpanContext, error) {
if len(stack.propagators) == 0 {
return nil, errors.New("No valid propagator configured")
}

for _, propagator := range stack.propagators {
context, err := propagator.Extract(opaqueCarrier)
if err == nil {
return context, nil
}
}

return nil, errors.New("No valid propagator configured")
}
134 changes: 134 additions & 0 deletions propagation_stack_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package lightstep_test

import (
. "github.com/lightstep/lightstep-tracer-go"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/opentracing/opentracing-go"
)

var _ = Describe("Propagator Stack", func() {
var stack PropagatorStack
Context("With no propagators", func() {
var knownCarrier1 opentracing.TextMapCarrier

var knownContext1 = SpanContext{
SpanID: 6397081719746291766,
TraceID: 506100417967962170,
Baggage: map[string]string{"checked": "baggage"},
}
BeforeEach(func() {
stack = PropagatorStack{}
})

It("should return error on inject", func() {
err := stack.Inject(knownContext1, knownCarrier1)
Expect(err).ToNot(BeNil())
})

It("should return error on extract", func() {
_, err := stack.Extract(knownCarrier1)
Expect(err).ToNot(BeNil())
})
})
Context("With one propagator", func() {
var knownCarrier1 opentracing.TextMapCarrier

var knownContext1 = SpanContext{
SpanID: 6397081719746291766,
TraceID: 506100417967962170,
Baggage: map[string]string{"checked": "baggage"},
}
BeforeEach(func() {
knownCarrier1 = opentracing.TextMapCarrier{}
stack = PropagatorStack{}
stack.PushPropagator(LightStepPropagator)
})

It("should inject trace", func() {
err := stack.Inject(knownContext1, knownCarrier1)
Expect(err).To(BeNil())
Expect(len(knownCarrier1)).To(Equal(4))
Expect(knownCarrier1["ot-tracer-traceid"]).To(Equal("70607a611a8383a"))
Expect(knownCarrier1["ot-tracer-spanid"]).To(Equal("58c6ffee509f6836"))
Expect(knownCarrier1["ot-tracer-sampled"]).To(Equal("true"))
Expect(knownCarrier1["ot-baggage-checked"]).To(Equal("baggage"))
})

It("should extract trace", func() {
knownCarrier2 := opentracing.TextMapCarrier{
"ot-tracer-traceid": "70607a611a8383a",
"ot-tracer-spanid": "58c6ffee509f6836",
"ot-tracer-sampled": "true",
"ot-baggage-checked": "baggage",
}
ctx, err := stack.Extract(knownCarrier2)
Expect(err).To(BeNil())
// check if spancontext is correct
spanContext, _ := ctx.(SpanContext)

Expect(spanContext.TraceID).To(Equal(knownContext1.TraceID))
Expect(spanContext.SpanID).To(Equal(knownContext1.SpanID))
Expect(spanContext.Baggage).To(Equal(knownContext1.Baggage))
})
})
Context("With multiple propagator", func() {
var knownCarrier1 opentracing.TextMapCarrier

var knownContext1 = SpanContext{
SpanID: 6397081719746291766,
TraceID: 506100417967962170,
Baggage: map[string]string{"checked": "baggage"},
}
BeforeEach(func() {
knownCarrier1 = opentracing.TextMapCarrier{}
stack = PropagatorStack{}
stack.PushPropagator(LightStepPropagator)
stack.PushPropagator(B3Propagator)
})

It("should inject trace using both propagators", func() {
err := stack.Inject(knownContext1, knownCarrier1)
Expect(err).To(BeNil())
Expect(len(knownCarrier1)).To(Equal(7))

Expect(knownCarrier1["ot-tracer-traceid"]).To(Equal("70607a611a8383a"))
Expect(knownCarrier1["ot-tracer-spanid"]).To(Equal("58c6ffee509f6836"))
Expect(knownCarrier1["ot-tracer-sampled"]).To(Equal("true"))
Expect(knownCarrier1["x-b3-traceid"]).To(Equal("70607a611a8383a"))
Expect(knownCarrier1["x-b3-spanid"]).To(Equal("58c6ffee509f6836"))
Expect(knownCarrier1["x-b3-sampled"]).To(Equal("1"))
Expect(knownCarrier1["ot-baggage-checked"]).To(Equal("baggage"))
})

It("should extract trace", func() {
knownCarrier2 := opentracing.TextMapCarrier{
"ot-tracer-traceid": "70607a611a8383a",
"ot-tracer-spanid": "58c6ffee509f6836",
"ot-tracer-sampled": "true",
"ot-baggage-checked": "baggage",
}
ctx, err := stack.Extract(knownCarrier2)
Expect(err).To(BeNil())
spanContext, _ := ctx.(SpanContext)

Expect(spanContext.TraceID).To(Equal(knownContext1.TraceID))
Expect(spanContext.SpanID).To(Equal(knownContext1.SpanID))
Expect(spanContext.Baggage).To(Equal(knownContext1.Baggage))

knownCarrier3 := opentracing.TextMapCarrier{
"x-b3-traceid": "70607a611a8383a",
"x-b3-spanid": "58c6ffee509f6836",
"x-b3-sampled": "true",
"ot-baggage-checked": "baggage",
}
ctx, err = stack.Extract(knownCarrier3)
Expect(err).To(BeNil())
spanContext, _ = ctx.(SpanContext)

Expect(spanContext.TraceID).To(Equal(knownContext1.TraceID))
Expect(spanContext.SpanID).To(Equal(knownContext1.SpanID))
Expect(spanContext.Baggage).To(Equal(knownContext1.Baggage))
})
})
})
14 changes: 6 additions & 8 deletions tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ type tracerImpl struct {
// In case of error, we emit event and return nil.
func NewTracer(opts Options) Tracer {
tr, err := CreateTracer(opts)
if err != nil {
if err != nil {
emitEvent(newEventStartError(err))
return nil
}
Expand Down Expand Up @@ -150,14 +150,12 @@ func CreateTracer(opts Options) (Tracer, error) {
go impl.reportLoop()

impl.propagators = map[opentracing.BuiltinFormat]Propagator{
opentracing.TextMap: theLightStepPropagator,
opentracing.HTTPHeaders: theLightStepPropagator,
opentracing.Binary: theBinaryPropagator,
opentracing.TextMap: LightStepPropagator,
opentracing.HTTPHeaders: LightStepPropagator,
opentracing.Binary: BinaryPropagator,
}

if opts.Propagator == "b3" {
impl.propagators[opentracing.TextMap] = theB3Propagator
impl.propagators[opentracing.HTTPHeaders] = theB3Propagator
for builtin, propagator := range opts.Propagators {
impl.propagators[builtin] = propagator
}

return impl, nil
Expand Down
5 changes: 4 additions & 1 deletion tracer_transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,10 @@ var _ = Describe("Tracer Transports", func() {
}

BeforeEach(func() {
options.Propagator = "b3"
options.Propagators = map[opentracing.BuiltinFormat]Propagator{
opentracing.HTTPHeaders: B3Propagator,
opentracing.TextMap: B3Propagator,
}
knownCarrier1 = opentracing.TextMapCarrier{}
})

Expand Down

0 comments on commit eb40dd3

Please sign in to comment.