diff --git a/CHANGELOG.md b/CHANGELOG.md index 508b6b30baa..0a044b0366a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - The exponential histogram mapping functions have been updated with exact upper-inclusive boundary support following the [corresponding specification change](https://github.com/open-telemetry/opentelemetry-specification/pull/2633). (#2982) +- Attempting to start a span with a nil `context` will no longer cause a panic. (#3110) ## [1.9.0/0.0.3] - 2022-08-01 diff --git a/sdk/trace/trace_test.go b/sdk/trace/trace_test.go index 8d95782115b..c6adbb77818 100644 --- a/sdk/trace/trace_test.go +++ b/sdk/trace/trace_test.go @@ -363,6 +363,16 @@ func TestStartSpanWithParent(t *testing.T) { } } +// Test we get a successful span as a new root if a nil context is sent in, as opposed to a panic. +// See https://github.com/open-telemetry/opentelemetry-go/issues/3109 +func TestStartSpanWithNilContext(t *testing.T) { + tp := NewTracerProvider() + tr := tp.Tracer("NoPanic") + + // nolint:staticcheck // no nil context, but that's the point of the test. + assert.NotPanics(t, func() { tr.Start(nil, "should-not-panic") }) +} + func TestStartSpanNewRootNotSampled(t *testing.T) { alwaysSampleTp := NewTracerProvider() sampledTr := alwaysSampleTp.Tracer("AlwaysSampled") diff --git a/sdk/trace/tracer.go b/sdk/trace/tracer.go index f4a1f96f3d6..7b11fc465c6 100644 --- a/sdk/trace/tracer.go +++ b/sdk/trace/tracer.go @@ -37,6 +37,11 @@ var _ trace.Tracer = &tracer{} func (tr *tracer) Start(ctx context.Context, name string, options ...trace.SpanStartOption) (context.Context, trace.Span) { config := trace.NewSpanStartConfig(options...) + if ctx == nil { + // Prevent trace.ContextWithSpan from panicking. + ctx = context.Background() + } + // For local spans created by this SDK, track child span count. if p := trace.SpanFromContext(ctx); p != nil { if sdkSpan, ok := p.(*recordingSpan); ok {