Skip to content
This repository has been archived by the owner on May 23, 2024. It is now read-only.

Commit

Permalink
Upgrade to OpenTracing API with SpanContext (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
yurishkuro authored Jul 9, 2016
1 parent d812e6a commit 6020091
Show file tree
Hide file tree
Showing 24 changed files with 417 additions and 417 deletions.
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ THRIFT=docker run -v "${PWD}:/data" $(THRIFT_IMG) thrift
THRIFT_GO_ARGS=thrift_import="github.com/apache/thrift/lib/go/thrift"
THRIFT_GEN_DIR=thrift-gen

PASS=$(shell printf "\033[32mPASS\033[0m")
FAIL=$(shell printf "\033[31mFAIL\033[0m")
COLORIZE=sed ''/PASS/s//$(PASS)/'' | sed ''/FAIL/s//$(FAIL)/''

.PHONY: test
test:
$(GOTEST) $(PACKAGES)

$(GOTEST) $(PACKAGES) | $(COLORIZE)

.PHONY: fmt
fmt:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ this interface can be set on the `Config` object before calling the

Since this tracer is fully compliant with OpenTracing API 1.0,
all code instrumentation should only use the API itself, as described
in [opentracing-go]
in the [opentracing-go]
(https://github.com/opentracing/opentracing-go) documentation.

## Features
Expand Down
3 changes: 2 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ func (c Configuration) New(
serviceName,
sampler,
reporter,
jaeger.TracerOptions.Metrics(metrics))
jaeger.TracerOptions.Metrics(metrics),
jaeger.TracerOptions.Logger(c.Logger))

return tracer, closer, nil
}
Expand Down
97 changes: 79 additions & 18 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import (
"fmt"
"strconv"
"strings"
"sync"

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

const (
Expand All @@ -37,8 +40,10 @@ var (
errMalformedTracerStateString = errors.New("String does not match tracer state format")
)

// TraceContext represents propagated span identity and state
type TraceContext struct {
// SpanContext represents propagated span identity and state
type SpanContext struct {
sync.RWMutex

// traceID represents globally unique ID of the trace.
// Usually generated as a random number.
traceID uint64
Expand All @@ -53,70 +58,126 @@ type TraceContext struct {

// flags is a bitmap containing such bits as 'sampled' and 'debug'.
flags byte

// Distributed Context baggage
baggage map[string]string
}

// SetBaggageItem implements SetBaggageItem() of opentracing.SpanContext
func (c *SpanContext) SetBaggageItem(key, value string) opentracing.SpanContext {
key = normalizeBaggageKey(key)
c.Lock()
defer c.Unlock()
if c.baggage == nil {
c.baggage = make(map[string]string)
}
c.baggage[key] = value
return c
}

// BaggageItem implements BaggageItem() of opentracing.SpanContext
func (c *SpanContext) BaggageItem(key string) string {
key = normalizeBaggageKey(key)
c.RLock()
defer c.RUnlock()
return c.baggage[key]
}

// ForeachBaggageItem implements ForeachBaggageItem() of opentracing.SpanContext
func (c *SpanContext) ForeachBaggageItem(handler func(k, v string) bool) {
c.RLock()
defer c.RUnlock()
for k, v := range c.baggage {
if !handler(k, v) {
break
}
}
}

// IsSampled returns whether this trace was chosen for permanent storage
// by the sampling mechanism of the tracer.
func (c *TraceContext) IsSampled() bool {
func (c *SpanContext) IsSampled() bool {
return (c.flags & flagSampled) == flagSampled
}

func (c *TraceContext) String() string {
func (c *SpanContext) String() string {
return fmt.Sprintf("%x:%x:%x:%x", c.traceID, c.spanID, c.parentID, c.flags)
}

// ContextFromString reconstructs the Context encoded in a string
func ContextFromString(value string) (TraceContext, error) {
var context TraceContext
func ContextFromString(value string) (*SpanContext, error) {
var context = new(SpanContext)
if value == "" {
return context, errEmptyTracerStateString
return nil, errEmptyTracerStateString
}
parts := strings.Split(value, ":")
if len(parts) != 4 {
return context, errMalformedTracerStateString
return nil, errMalformedTracerStateString
}
var err error
if context.traceID, err = strconv.ParseUint(parts[0], 16, 64); err != nil {
return context, err
return nil, err
}
if context.spanID, err = strconv.ParseUint(parts[1], 16, 64); err != nil {
return context, err
return nil, err
}
if context.parentID, err = strconv.ParseUint(parts[2], 16, 64); err != nil {
return context, err
return nil, err
}
flags, err := strconv.ParseUint(parts[3], 10, 8)
if err != nil {
return context, err
return nil, err
}
context.flags = byte(flags)
return context, nil
}

// TraceID implements TraceID() of SpanID
func (c TraceContext) TraceID() uint64 {
func (c *SpanContext) TraceID() uint64 {
return c.traceID
}

// SpanID implements SpanID() of SpanID
func (c TraceContext) SpanID() uint64 {
func (c *SpanContext) SpanID() uint64 {
return c.spanID
}

// ParentID implements ParentID() of SpanID
func (c TraceContext) ParentID() uint64 {
func (c *SpanContext) ParentID() uint64 {
return c.parentID
}

// NewTraceContext creates a new instance of TraceContext
func NewTraceContext(traceID, spanID, parentID uint64, sampled bool) *TraceContext {
// NewSpanContext creates a new instance of SpanContext
func NewSpanContext(traceID, spanID, parentID uint64, sampled bool) *SpanContext {
flags := byte(0)
if sampled {
flags = flagSampled
}
return &TraceContext{
return &SpanContext{
traceID: traceID,
spanID: spanID,
parentID: parentID,
flags: flags}
}

// CopyFrom copies data from ctx into this context, including span identity and baggage.
func (c *SpanContext) CopyFrom(ctx *SpanContext) {
c.Lock()
defer c.Unlock()

ctx.RLock()
defer ctx.RUnlock()

c.traceID = ctx.traceID
c.spanID = ctx.spanID
c.parentID = ctx.parentID
c.flags = ctx.flags
if l := len(ctx.baggage); l > 0 {
c.baggage = make(map[string]string, l)
for k, v := range ctx.baggage {
c.baggage[k] = v
}
} else {
c.baggage = nil
}
}
2 changes: 1 addition & 1 deletion context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func TestContextFromString(t *testing.T) {
assert.EqualValues(t, 1, ctx.spanID)
assert.EqualValues(t, 1, ctx.parentID)
assert.EqualValues(t, 1, ctx.flags)
ctx = *NewTraceContext(1, 1, 1, true)
ctx = NewSpanContext(1, 1, 1, true)
assert.EqualValues(t, 1, ctx.traceID)
assert.EqualValues(t, 1, ctx.spanID)
assert.EqualValues(t, 1, ctx.parentID)
Expand Down
6 changes: 3 additions & 3 deletions crossdock/common/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ func injectSpan(ctx context.Context, req *http.Request) (opentracing.Span, error
if span == nil {
return nil, nil
}
span = opentracing.StartChildSpan(span, "post")
ext.SpanKind.Set(span, ext.SpanKindRPCClient)
span = span.Tracer().StartSpan("post", opentracing.ChildOf(span.Context()))
ext.SpanKindRPCClient.Set(span)
c := opentracing.HTTPHeaderTextMapCarrier(req.Header)
err := span.Tracer().Inject(span, opentracing.TextMap, c)
err := span.Tracer().Inject(span.Context(), opentracing.TextMap, c)
return span, err
}
12 changes: 4 additions & 8 deletions crossdock/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,18 +126,14 @@ func (s *Server) handleJSON(
newReq func() interface{},
handle func(ctx context.Context, req interface{}) (interface{}, error),
) {
span, err := s.Tracer.Join("post", opentracing.TextMap, opentracing.HTTPHeaderTextMapCarrier(r.Header))
if err != nil && err != opentracing.ErrTraceNotFound {
spanCtx, err := s.Tracer.Extract(opentracing.TextMap, opentracing.HTTPHeaderTextMapCarrier(r.Header))
if err != nil && err != opentracing.ErrSpanContextNotFound {
http.Error(w, fmt.Sprintf("Cannot read request body: %+v", err), http.StatusBadRequest)
return
}
if span != nil {
ext.SpanKind.Set(span, ext.SpanKindRPCServer)
}
span := s.Tracer.StartSpan("post", ext.RPCServerOption(spanCtx))
ctx := opentracing.ContextWithSpan(context.Background(), span)
if span != nil {
defer span.Finish()
}
defer span.Finish()

body, err := ioutil.ReadAll(r.Body)
if err != nil {
Expand Down
22 changes: 12 additions & 10 deletions crossdock/server/tchannel.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"time"

"github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/ext"
"github.com/uber/tchannel-go"
"github.com/uber/tchannel-go/thrift"
"golang.org/x/net/context"
Expand Down Expand Up @@ -115,15 +116,15 @@ func convertOpenTracingSpan(ctx context.Context, builder *tchannel.ContextBuilde
if span == nil {
return
}
carrier := &jaeger.TraceContextCarrier{}
if err := span.Tracer().Inject(span, jaeger.TraceContextFormat, carrier); err != nil {
sc := new(jaeger.SpanContext)
if err := span.Tracer().Inject(span.Context(), jaeger.TraceContextFormat, sc); err != nil {
return
}
sc := carrier.TraceContext
builder.SetExternalSpan(sc.TraceID(), sc.SpanID(), sc.ParentID(), sc.IsSampled())
for k, v := range carrier.Baggage {
sc.ForeachBaggageItem(func(k, v string) bool {
builder.AddHeader(k, v)
}
return true
})
}

// setupOpenTracingContext extracts a TChannel tracing Span from the context, converts
Expand All @@ -143,15 +144,16 @@ func setupOpenTracingContext(tracer opentracing.Tracer, ctx context.Context, met
tSpan := tchannel.CurrentSpan(ctx)
if tSpan != nil {
// populate a fake carrier and try to create OpenTracing Span
carrier := &jaeger.TraceContextCarrier{Baggage: headers}
carrier.TraceContext = *jaeger.NewTraceContext(
sc := jaeger.NewSpanContext(
tSpan.TraceID(), tSpan.SpanID(), tSpan.ParentID(), tSpan.TracingEnabled())
for k, v := range headers {
sc.SetBaggageItem(k, v)
}
if tracer == nil {
tracer = opentracing.GlobalTracer()
}
if span, err := tracer.Join(method, jaeger.TraceContextFormat, carrier); err == nil {
ctx = opentracing.ContextWithSpan(ctx, span)
}
span := tracer.StartSpan(method, ext.RPCServerOption(sc))
ctx = opentracing.ContextWithSpan(ctx, span)
}
return thrift.WithHeaders(ctx, headers)
}
13 changes: 5 additions & 8 deletions crossdock/server/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (s *Server) doStartTrace(req *tracetest.StartTraceRequest) (*tracetest.Trac
if req.Sampled {
ext.SamplingPriority.Set(span, 1)
}
span.SetBaggageItem(BaggageKey, req.Baggage)
span.Context().SetBaggageItem(BaggageKey, req.Baggage)
defer span.Finish()

ctx := opentracing.ContextWithSpan(context.Background(), span)
Expand Down Expand Up @@ -98,13 +98,10 @@ func observeSpan(ctx context.Context, tracer opentracing.Tracer) (*tracetest.Obs
if span == nil {
return nil, errNoSpanObserved
}
c := jaeger.TraceContextCarrier{}
if err := tracer.Inject(span, jaeger.TraceContextFormat, &c); err != nil {
return nil, err
}
sc := span.Context().(*jaeger.SpanContext)
observedSpan := tracetest.NewObservedSpan()
observedSpan.TraceId = fmt.Sprintf("%x", c.TraceContext.TraceID())
observedSpan.Sampled = c.TraceContext.IsSampled()
observedSpan.Baggage = span.BaggageItem(BaggageKey)
observedSpan.TraceId = fmt.Sprintf("%x", sc.TraceID())
observedSpan.Sampled = sc.IsSampled()
observedSpan.Baggage = sc.BaggageItem(BaggageKey)
return observedSpan, nil
}
6 changes: 3 additions & 3 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import:
subpackages:
- lib/go/thrift
- package: github.com/opentracing/opentracing-go
version: d5b9be1fcf7d467664d3b8f9cb4f3c8c5ac0a753
version: 4281ca32dbd11726bca3581fc06a9bc94365ec85
subpackages:
- ext
- package: golang.org/x/net
Expand Down
Loading

0 comments on commit 6020091

Please sign in to comment.