Skip to content

Commit

Permalink
Merge pull request #18 from ExpediaDotCom/fix-issue17
Browse files Browse the repository at this point in the history
add HTTPHeadersCarrier support for tracer.Extract and tracer.Inject
  • Loading branch information
shreyaa-sharma authored Mar 15, 2019
2 parents 3ee3ba1 + a86c2bd commit e7edbdf
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 25 deletions.
18 changes: 17 additions & 1 deletion examples/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package main

import (
"fmt"
"net/http"
"time"

haystack "github.com/ExpediaDotCom/haystack-client-go"
Expand Down Expand Up @@ -56,7 +57,16 @@ func main() {
}
}()

span1 := tracer.StartSpan("operation1", opentracing.Tag{Key: "my-tag", Value: "something"})
carrier := opentracing.HTTPHeadersCarrier(http.Header(map[string][]string{
"Trace-Id": {"409dec0e-473e-11e9-81cc-186590cf29af"},
"Span-Id": {"509df8d3-473e-11e9-81cc-186590cf29af"},
"Parent-Id": {"609df88c-473e-11e9-81cc-186590cf29af"},
}))
clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier)
if err != nil {
panic(err)
}
span1 := tracer.StartSpan("operation1", opentracing.ChildOf(clientContext), opentracing.Tag{Key: "my-tag", Value: "something"})
span1.SetTag(string(ext.SpanKind), ext.SpanKindRPCServerEnum)
span1.SetTag(string(ext.Error), false)
span1.SetTag(string(ext.HTTPStatusCode), 200)
Expand All @@ -68,6 +78,12 @@ func main() {
ext.Error.Set(span2, true)
ext.HTTPStatusCode.Set(span1, 404)

// inject the span context in http header using tracer.Inject(...)
req, _ := http.NewRequest(http.MethodGet, "https://expediadotcom.github.io/haystack/", nil)
tracer.Inject(span2.Context(), opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Header))
//
//log.Println(req.Header)

span2.Finish()
span1.Finish()

Expand Down
41 changes: 29 additions & 12 deletions propagator.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"fmt"
"net/url"
"strings"

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

/*Propagator defines the interface for injecting and extracing the SpanContext from the carrier*/
Expand Down Expand Up @@ -113,13 +115,17 @@ type TextMapPropagator struct {

/*Inject injects the span context in the carrier*/
func (p *TextMapPropagator) Inject(ctx *SpanContext, carrier interface{}) error {
carrierMap := carrier.(map[string]string)
carrierMap[p.opts.TraceIDKEY()] = ctx.TraceID
carrierMap[p.opts.SpanIDKEY()] = ctx.SpanID
carrierMap[p.opts.ParentSpanIDKEY()] = ctx.ParentID
textMapWriter, ok := carrier.(opentracing.TextMapWriter)
if !ok {
return opentracing.ErrInvalidCarrier
}

textMapWriter.Set(p.opts.TraceIDKEY(), ctx.TraceID)
textMapWriter.Set(p.opts.SpanIDKEY(), ctx.SpanID)
textMapWriter.Set(p.opts.ParentSpanIDKEY(), ctx.ParentID)

ctx.ForeachBaggageItem(func(key, value string) bool {
carrierMap[fmt.Sprintf("%s%s", p.opts.BaggageKeyPrefix(), key)] = p.codex.Encode(ctx.Baggage[key])
textMapWriter.Set(fmt.Sprintf("%s%s", p.opts.BaggageKeyPrefix(), key), p.codex.Encode(ctx.Baggage[key]))
return true
})

Expand All @@ -128,8 +134,11 @@ func (p *TextMapPropagator) Inject(ctx *SpanContext, carrier interface{}) error

/*Extract the span context from the carrier*/
func (p *TextMapPropagator) Extract(carrier interface{}) (*SpanContext, error) {
baggage := make(map[string](string))
carrierMap := carrier.(map[string]string)
textMapReader, ok := carrier.(opentracing.TextMapReader)

if !ok {
return nil, opentracing.ErrInvalidCarrier
}

baggageKeyLowerCasePrefix := strings.ToLower(p.opts.BaggageKeyPrefix())
traceIDKeyLowerCase := strings.ToLower(p.opts.TraceIDKEY())
Expand All @@ -140,19 +149,27 @@ func (p *TextMapPropagator) Extract(carrier interface{}) (*SpanContext, error) {
spanID := ""
parentSpanID := ""

for k, v := range carrierMap {
baggage := make(map[string]string)
err := textMapReader.ForeachKey(func(k, v string) error {
lcKey := strings.ToLower(k)

if strings.HasPrefix(lcKey, baggageKeyLowerCasePrefix) {
keySansPrefix := k[len(p.opts.BaggageKeyPrefix()):]
keySansPrefix := lcKey[len(p.opts.BaggageKeyPrefix()):]
baggage[keySansPrefix] = p.codex.Decode(v)
} else if lcKey == traceIDKeyLowerCase {
traceID = carrierMap[k]
traceID = v
} else if lcKey == spanIDKeyLowerCase {
spanID = carrierMap[k]
spanID = v
} else if lcKey == parentSpanIDKeyLowerCase {
parentSpanID = carrierMap[k]
parentSpanID = v
}
return nil
})

if err != nil {
return nil, err
}

return &SpanContext{
TraceID: traceID,
SpanID: spanID,
Expand Down
38 changes: 26 additions & 12 deletions tracer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ package haystack

import (
"io"
"strings"
"testing"

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

"github.com/stretchr/testify/suite"
)

Expand Down Expand Up @@ -90,14 +92,15 @@ func (suite *TracerTestSuite) TestTracerProperties() {
func (suite *TracerTestSuite) TestTracerWithDualSpanMode_1() {
serverTag := opentracing.Tag{Key: "span.kind", Value: "server"}
clientTag := opentracing.Tag{Key: "span.kind", Value: "client"}
carrier := map[string]string{
headerMap := map[string]string{
"trace-id": "T1",
"Span-ID": "S1",
"Parent-ID": "P1",
"Baggage-myKey": "myVal",
"baggage-mykey-1": "myval",
}
upstreamSpanContext, _ := suite.dualSpanModeTracer.Extract(opentracing.HTTPHeaders, carrier)

upstreamSpanContext, _ := suite.dualSpanModeTracer.Extract(opentracing.HTTPHeaders, buildHTTPHeaderCarrier(headerMap))
serverSpan := suite.dualSpanModeTracer.StartSpan("op1", serverTag, opentracing.ChildOf(upstreamSpanContext))
clientSpan := suite.dualSpanModeTracer.StartSpan("op2", clientTag, opentracing.ChildOf(serverSpan.Context()))

Expand All @@ -112,8 +115,8 @@ func (suite *TracerTestSuite) TestTracerWithDualSpanMode_1() {
receivedServerSpan := dispatcher.spans[1]
receivedServerSpanCtx := receivedServerSpan.Context().(*SpanContext)
suite.Equal(receivedServerSpanCtx.TraceID, "T1", "Trace Ids should match")
suite.Equal(receivedServerSpanCtx.Baggage["myKey"], "myVal", "baggage key should match")
suite.Equal(receivedServerSpanCtx.Baggage["mykey-1"], "myval", "baggage lowercase key should match")
suite.Equal(receivedServerSpanCtx.Baggage[strings.ToLower("myKey")], "myVal", "baggage key should match")
suite.Equal(receivedServerSpanCtx.Baggage[strings.ToLower("mykey-1")], "myval", "baggage lowercase key should match")
suite.NotEqual(receivedServerSpanCtx.SpanID, "S1", "SpanId should be newly created")
suite.NotEqual(receivedServerSpanCtx.SpanID, "P1", "SpanId should be newly created")
suite.NotEqual(receivedServerSpanCtx.SpanID, "T1", "SpanId should be newly created")
Expand All @@ -131,12 +134,13 @@ func (suite *TracerTestSuite) TestTracerWithDualSpanMode_1() {
func (suite *TracerTestSuite) TestTracerWithSingleSpanMode_1() {
serverTag := opentracing.Tag{Key: "span.kind", Value: "server"}
clientTag := opentracing.Tag{Key: "span.kind", Value: "client"}
carrier := map[string]string{
headerMap := map[string]string{
"Trace-ID": "T1",
"Span-ID": "S1",
"Parent-ID": "P1",
}
upstreamSpanContext, _ := suite.tracer.Extract(opentracing.HTTPHeaders, carrier)

upstreamSpanContext, _ := suite.tracer.Extract(opentracing.HTTPHeaders, buildHTTPHeaderCarrier(headerMap))
serverSpan := suite.tracer.StartSpan("op1", serverTag, opentracing.ChildOf(upstreamSpanContext))
clientSpan := suite.tracer.StartSpan("op2", clientTag, opentracing.ChildOf(serverSpan.Context()))

Expand Down Expand Up @@ -166,12 +170,13 @@ func (suite *TracerTestSuite) TestTracerWithSingleSpanMode_1() {
func (suite *TracerTestSuite) TestTracerWithSingleSpanMode_2() {
serverTag := opentracing.Tag{Key: "error", Value: true}
clientTag := opentracing.Tag{Key: "error", Value: false}
carrier := map[string]string{
headerMap := map[string]string{
"Trace-ID": "T1",
"Span-ID": "S1",
"Parent-ID": "P1",
}
upstreamSpanContext, _ := suite.tracer.Extract(opentracing.HTTPHeaders, carrier)

upstreamSpanContext, _ := suite.tracer.Extract(opentracing.HTTPHeaders, buildHTTPHeaderCarrier(headerMap))
serverSpan := suite.tracer.StartSpan("op1", serverTag, opentracing.ChildOf(upstreamSpanContext))
clientSpan := suite.tracer.StartSpan("op2", clientTag, opentracing.ChildOf(serverSpan.Context()))

Expand Down Expand Up @@ -202,7 +207,8 @@ func (suite *TracerTestSuite) TestTracerWithSingleSpanMode_2() {
}

func (suite *TracerTestSuite) TestTracerInject() {
carrier := make(map[string]string)
carrier := opentracing.HTTPHeadersCarrier(make(map[string][]string))

span1 := suite.tracer.StartSpan("op1")
err := suite.tracer.Inject(span1.Context(), opentracing.HTTPHeaders, carrier)
if err != nil {
Expand All @@ -215,12 +221,20 @@ func (suite *TracerTestSuite) TestTracerInject() {
panic(err)
}

suite.Equal(carrier["Trace-ID"], ctx.(*SpanContext).TraceID)
suite.Equal(carrier["Span-ID"], ctx.(*SpanContext).SpanID)
suite.Equal(carrier["Parent-ID"], ctx.(*SpanContext).ParentID)
suite.NotEqual("", ctx.(*SpanContext).TraceID)
suite.NotEqual("", ctx.(*SpanContext).SpanID)
suite.Equal("", ctx.(*SpanContext).ParentID)
suite.Equal(true, ctx.(*SpanContext).IsExtractedContext)
}

func buildHTTPHeaderCarrier(headerMap map[string]string) *opentracing.HTTPHeadersCarrier {
httpHeaderCarrier := opentracing.HTTPHeadersCarrier(make(map[string][]string))
for k, v := range headerMap {
httpHeaderCarrier.Set(k, v)
}
return &httpHeaderCarrier
}

func TestUnitTracerSuite(t *testing.T) {
suite.Run(t, new(TracerTestSuite))
}

0 comments on commit e7edbdf

Please sign in to comment.