Skip to content

Commit 831161b

Browse files
committed
feat(ddtrace/tracer): introduce ExtractCtx to support propagated context
1 parent 4d47dd6 commit 831161b

File tree

3 files changed

+36
-0
lines changed

3 files changed

+36
-0
lines changed

ddtrace/tracer/context.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ func ContextWithSpan(ctx context.Context, s *Span) context.Context {
1818
return orchestrion.CtxWithValue(ctx, internal.ActiveSpanKey, s)
1919
}
2020

21+
// contextWithSpanContext returns a copy of the given context which includes the span context sctx.
22+
func contextWithSpanContext(ctx context.Context, sctx *SpanContext) context.Context {
23+
return orchestrion.CtxWithValue(ctx, internal.ActiveSpanContextKey, sctx)
24+
}
25+
2126
// SpanFromContext returns the span contained in the given context. A second return
2227
// value indicates if a span was found in the context. If no span is found, a no-op
2328
// span is returned.
@@ -35,6 +40,19 @@ func SpanFromContext(ctx context.Context) (*Span, bool) {
3540
return nil, false
3641
}
3742

43+
// spanContextFromContext returns the span context contained in the given context. A second return
44+
// value indicates if a span context was found in the context. If no span context is found, a nil is returned.
45+
func spanContextFromContext(ctx context.Context) (*SpanContext, bool) {
46+
if ctx == nil {
47+
return nil, false
48+
}
49+
v := orchestrion.WrapContext(ctx).Value(internal.ActiveSpanContextKey)
50+
if sctx, ok := v.(*SpanContext); ok {
51+
return sctx, true
52+
}
53+
return nil, false
54+
}
55+
3856
// StartSpanFromContext returns a new span with the given operation name and options. If a span
3957
// is found in the context, it will be used as the parent of the resulting span. If the ChildOf
4058
// option is passed, it will only be used as the parent if there is no span found in `ctx`.
@@ -47,6 +65,8 @@ func StartSpanFromContext(ctx context.Context, operationName string, opts ...Sta
4765
ctx = context.Background()
4866
} else if s, ok := SpanFromContext(ctx); ok {
4967
optsLocal = append(optsLocal, ChildOf(s.Context()))
68+
} else if sctx, ok := spanContextFromContext(ctx); ok {
69+
optsLocal = append(optsLocal, ChildOf(sctx))
5070
}
5171
optsLocal = append(optsLocal, withContext(ctx))
5272
s := StartSpan(operationName, optsLocal...)

ddtrace/tracer/tracer.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,19 @@ func Extract(carrier interface{}) (*SpanContext, error) {
312312
return getGlobalTracer().Extract(carrier)
313313
}
314314

315+
// ExtractCtx extracts a span context from the carrier and returns a copy of
316+
// the given context which includes the span context.
317+
func ExtractCtx(ctx gocontext.Context, carrier interface{}) (gocontext.Context, error) {
318+
sctx, err := Extract(carrier)
319+
if err != nil {
320+
return nil, err
321+
}
322+
if sctx == nil {
323+
return ctx, nil
324+
}
325+
return contextWithSpanContext(ctx, sctx), nil
326+
}
327+
315328
// Inject injects the given SpanContext into the carrier. The carrier is
316329
// expected to implement TextMapWriter, otherwise an error is returned.
317330
// If the tracer is not started, calling this function is a no-op.

internal/active_span_key.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@ type contextKey struct{}
99

1010
// ActiveSpanKey is used to set tracer context on a context.Context objects with a unique key
1111
var ActiveSpanKey = contextKey{}
12+
13+
// ActiveSpanContextKey is used to set span context on a context.Context objects with a unique key
14+
var ActiveSpanContextKey = contextKey{}

0 commit comments

Comments
 (0)