Skip to content

Commit 57b25ae

Browse files
pellaredpull[bot]
authored andcommitted
trace: SpanFromContext and SpanContextFromContext make no allocs (#5049)
1 parent eff4111 commit 57b25ae

4 files changed

Lines changed: 18 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
88

99
## [Unreleased]
1010

11+
### Changed
12+
13+
- `SpanFromContext` and `SpanContextFromContext` in `go.opentelemetry.io/otel/trace` no longer make a heap allocation when the passed context has no span. (#5049)
14+
1115
### Fixed
1216

1317
- Clarify the documentation about equivalence guarantees for the `Set` and `Distinct` types in `go.opentelemetry.io/otel/attribute`. (#5027)

trace/context.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ func ContextWithRemoteSpanContext(parent context.Context, rsc SpanContext) conte
3636
// performs no operations is returned.
3737
func SpanFromContext(ctx context.Context) Span {
3838
if ctx == nil {
39-
return noopSpan{}
39+
return noopSpanInstance
4040
}
4141
if span, ok := ctx.Value(currentSpanKey).(Span); ok {
4242
return span
4343
}
44-
return noopSpan{}
44+
return noopSpanInstance
4545
}
4646

4747
// SpanContextFromContext returns the current Span's SpanContext.

trace/context_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ func TestSpanFromContext(t *testing.T) {
7777
// Ensure SpanContextFromContext is just
7878
// SpanFromContext(…).SpanContext().
7979
assert.Equal(t, tc.expectedSpan.SpanContext(), SpanContextFromContext(tc.context))
80+
81+
// Check that SpanFromContext does not produce any heap allocation.
82+
assert.Equal(t, 0.0, testing.AllocsPerRun(5, func() {
83+
SpanFromContext(tc.context)
84+
}), "SpanFromContext allocs")
85+
86+
// Check that SpanContextFromContext does not produce any heap allocation.
87+
assert.Equal(t, 0.0, testing.AllocsPerRun(5, func() {
88+
SpanContextFromContext(tc.context)
89+
}), "SpanContextFromContext allocs")
8090
})
8191
}
8292
}

trace/noop.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ func (t noopTracer) Start(ctx context.Context, name string, _ ...SpanStartOption
4141
span := SpanFromContext(ctx)
4242
if _, ok := span.(nonRecordingSpan); !ok {
4343
// span is likely already a noopSpan, but let's be sure
44-
span = noopSpan{}
44+
span = noopSpanInstance
4545
}
4646
return ContextWithSpan(ctx, span), span
4747
}
4848

4949
// noopSpan is an implementation of Span that performs no operations.
5050
type noopSpan struct{ embedded.Span }
5151

52-
var _ Span = noopSpan{}
52+
var noopSpanInstance Span = noopSpan{}
5353

5454
// SpanContext returns an empty span context.
5555
func (noopSpan) SpanContext() SpanContext { return SpanContext{} }

0 commit comments

Comments
 (0)