diff --git a/ddtrace/tracer/context.go b/ddtrace/tracer/context.go index f33f0048a8b..78e830cfe78 100644 --- a/ddtrace/tracer/context.go +++ b/ddtrace/tracer/context.go @@ -11,11 +11,17 @@ import ( "github.com/DataDog/dd-trace-go/v2/instrumentation/options" "github.com/DataDog/dd-trace-go/v2/internal" illmobs "github.com/DataDog/dd-trace-go/v2/internal/llmobs" + "github.com/DataDog/dd-trace-go/v2/internal/log" "github.com/DataDog/dd-trace-go/v2/internal/orchestrion" ) // ContextWithSpan returns a copy of the given context which includes the span s. +// If ctx is nil, a new background context is created to avoid panicking. func ContextWithSpan(ctx context.Context, s *Span) context.Context { + if ctx == nil { + log.Warn("ContextWithSpan: received nil context, falling back to context.Background()") + ctx = context.Background() + } newCtx := orchestrion.CtxWithValue(ctx, internal.ActiveSpanKey, s) return contextWithPropagatedLLMSpan(newCtx, s) } diff --git a/ddtrace/tracer/context_test.go b/ddtrace/tracer/context_test.go index a6b4ad952f2..3e98bb613fc 100644 --- a/ddtrace/tracer/context_test.go +++ b/ddtrace/tracer/context_test.go @@ -17,11 +17,23 @@ import ( ) func TestContextWithSpan(t *testing.T) { - want := &Span{spanID: 123} - ctx := ContextWithSpan(context.Background(), want) - got := ctx.Value(internal.ActiveSpanKey) - assert := assert.New(t) - assert.Equal(got, want) + t.Run("OK", func(t *testing.T) { + want := &Span{spanID: 123} + ctx := ContextWithSpan(context.Background(), want) + got := ctx.Value(internal.ActiveSpanKey) + assert := assert.New(t) + assert.Equal(got, want) + }) + + t.Run("nil context", func(t *testing.T) { + assert.NotPanics(t, func() { + want := &Span{spanID: 123} + ctx := ContextWithSpan(nil, want) + got := ctx.Value(internal.ActiveSpanKey) + assert := assert.New(t) + assert.Equal(got, want) + }) + }) } func TestSpanFromContext(t *testing.T) {