Skip to content

Commit

Permalink
ddtrace/tracer: add support for span links on Span Context (#2973)
Browse files Browse the repository at this point in the history
  • Loading branch information
mhlidd authored Nov 8, 2024
1 parent 716a72c commit 591c40e
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 0 deletions.
12 changes: 12 additions & 0 deletions ddtrace/ddtrace.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ type SpanContextW3C interface {
TraceID128Bytes() [16]byte
}

// SpanContextWithLinks represents a SpanContext with additional methods for
// access to the SpanLinks on the span context, if present.
type SpanContextWithLinks interface {
SpanContext

// SpanLinks returns the span links on the SpanContext.
SpanLinks() []SpanLink

// Setlinks takes in a slice of SpanLinks and sets them to the SpanContext.
SetLinks(links []SpanLink)
}

// Tracer specifies an implementation of the Datadog tracer which allows starting
// and propagating spans. The official implementation if exposed as functions
// within the "tracer" package.
Expand Down
35 changes: 35 additions & 0 deletions ddtrace/tracer/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,41 @@ func TestStartSpanFromContext(t *testing.T) {
assert.Equal("/", got.Resource)
}

func TestStartSpanWithSpanLinks(t *testing.T) {
_, _, _, stop := startTestTracer(t)
defer stop()
spanLink := ddtrace.SpanLink{TraceID: 789, TraceIDHigh: 0, SpanID: 789, Attributes: map[string]string{"reason": "terminated_context", "context_headers": "datadog"}, Flags: 0}
var ctx ddtrace.SpanContext
ctx = &spanContext{spanID: 789, traceID: traceIDFrom64Bits(789), spanLinks: []ddtrace.SpanLink{spanLink}}

t.Run("spanContext with spanLinks satisfies SpanContextWithLinks interface", func(t *testing.T) {
ctxLink, ok := ctx.(ddtrace.SpanContextWithLinks)
assert.True(t, ok)
assert.Equal(t, len(ctxLink.SpanLinks()), 1)
assert.Equal(t, ctxLink.SpanLinks()[0], spanLink)
})

t.Run("create span from spancontext with links", func(t *testing.T) {
var s ddtrace.Span
s, _ = StartSpanFromContext(
context.Background(),
"http.request",
WithSpanLinks([]ddtrace.SpanLink{spanLink}),
ChildOf(ctx),
)
//checking that a span links are added to a child span that is created where span links are passed as an StartSpanOption
sp, ok := s.(*span)
if !ok {
assert.Fail(t, "couldn't cast to span")
}

assert.Equal(t, 1, len(sp.SpanLinks))
assert.Equal(t, spanLink, sp.SpanLinks[0])

assert.Equal(t, 0, len(sp.context.spanLinks)) // ensure that the span links are not added to the parent context
})
}

func TestStartSpanFromContextRace(t *testing.T) {
_, _, _, stop := startTestTracer(t)
defer stop()
Expand Down
12 changes: 12 additions & 0 deletions ddtrace/tracer/spancontext.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ type spanContext struct {
baggage map[string]string
hasBaggage uint32 // atomic int for quick checking presence of baggage. 0 indicates no baggage, otherwise baggage exists.
origin string // e.g. "synthetics"

spanLinks []ddtrace.SpanLink // links to related spans in separate|external|disconnected traces
}

// newSpanContext creates a new SpanContext to serve as context for the given
Expand Down Expand Up @@ -166,6 +168,8 @@ func (c *spanContext) SpanID() uint64 { return c.spanID }
// TraceID implements ddtrace.SpanContext.
func (c *spanContext) TraceID() uint64 { return c.traceID.Lower() }

func (c *spanContext) TraceIDUpper() uint64 { return c.traceID.Upper() }

// TraceID128 implements ddtrace.SpanContextW3C.
func (c *spanContext) TraceID128() string {
if c == nil {
Expand All @@ -179,6 +183,14 @@ func (c *spanContext) TraceID128Bytes() [16]byte {
return c.traceID
}

func (c *spanContext) SpanLinks() []ddtrace.SpanLink {
return c.spanLinks
}

func (c *spanContext) SetLinks(links []ddtrace.SpanLink) {
c.spanLinks = links
}

// ForeachBaggageItem implements ddtrace.SpanContext.
func (c *spanContext) ForeachBaggageItem(handler func(k, v string) bool) {
if atomic.LoadUint32(&c.hasBaggage) == 0 {
Expand Down

0 comments on commit 591c40e

Please sign in to comment.