mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-02-13 13:48:28 +02:00
86df763d90
trace/noop/noop.Span should be instance. This will reduce memory waste. Benchmark results with changes: new.txt ``` goos: darwin goarch: arm64 pkg: go.opentelemetry.io/otel/trace/noop BenchmarkNoopInstance-10 29894822 39.94 ns/op 48 B/op 1 allocs/op BenchmarkNoopInstance-10 29675424 39.99 ns/op 48 B/op 1 allocs/op BenchmarkNoopInstance-10 30064700 39.98 ns/op 48 B/op 1 allocs/op BenchmarkNoopInstance-10 29962016 40.03 ns/op 48 B/op 1 allocs/op BenchmarkNoopInstance-10 30060465 40.02 ns/op 48 B/op 1 allocs/op BenchmarkNoopInstance-10 29916855 40.04 ns/op 48 B/op 1 allocs/op BenchmarkNoopInstance-10 29829998 40.28 ns/op 48 B/op 1 allocs/op BenchmarkNoopInstance-10 30084706 39.99 ns/op 48 B/op 1 allocs/op BenchmarkNoopInstance-10 30087441 40.02 ns/op 48 B/op 1 allocs/op BenchmarkNoopInstance-10 29864365 40.14 ns/op 48 B/op 1 allocs/op ``` without changes on `main`: old.txt ``` goos: darwin goarch: arm64 pkg: go.opentelemetry.io/otel/trace/noop BenchmarkNoopInstance-10 14813442 67.64 ns/op 128 B/op 2 allocs/op BenchmarkNoopInstance-10 17714486 68.17 ns/op 128 B/op 2 allocs/op BenchmarkNoopInstance-10 17701257 67.66 ns/op 128 B/op 2 allocs/op BenchmarkNoopInstance-10 17805859 67.69 ns/op 128 B/op 2 allocs/op BenchmarkNoopInstance-10 17912841 67.43 ns/op 128 B/op 2 allocs/op BenchmarkNoopInstance-10 17864120 67.58 ns/op 128 B/op 2 allocs/op BenchmarkNoopInstance-10 17663130 68.41 ns/op 128 B/op 2 allocs/op BenchmarkNoopInstance-10 17740423 67.57 ns/op 128 B/op 2 allocs/op BenchmarkNoopInstance-10 17751040 67.56 ns/op 128 B/op 2 allocs/op BenchmarkNoopInstance-10 17738064 67.91 ns/op 128 B/op 2 allocs/op ``` benchstat: ``` goos: darwin goarch: arm64 pkg: go.opentelemetry.io/otel/trace/noop │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ NoopInstance-10 67.65n ± 1% 40.02n ± 0% -40.84% (p=0.000 n=10) │ old.txt │ new.txt │ │ B/op │ B/op vs base │ NoopInstance-10 128.00 ± 0% 48.00 ± 0% -62.50% (p=0.000 n=10) │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ NoopInstance-10 2.000 ± 0% 1.000 ± 0% -50.00% (p=0.000 n=10) ``` Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
120 lines
3.8 KiB
Go
120 lines
3.8 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package noop // import "go.opentelemetry.io/otel/trace/noop"
|
|
|
|
import (
|
|
"context"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"go.opentelemetry.io/otel/trace"
|
|
)
|
|
|
|
func TestImplementationNoPanics(t *testing.T) {
|
|
// Check that if type has an embedded interface and that interface has
|
|
// methods added to it than the No-Op implementation implements them.
|
|
t.Run("TracerProvider", assertAllExportedMethodNoPanic(
|
|
reflect.ValueOf(TracerProvider{}),
|
|
reflect.TypeOf((*trace.TracerProvider)(nil)).Elem(),
|
|
))
|
|
t.Run("Tracer", assertAllExportedMethodNoPanic(
|
|
reflect.ValueOf(Tracer{}),
|
|
reflect.TypeOf((*trace.Tracer)(nil)).Elem(),
|
|
))
|
|
t.Run("Span", assertAllExportedMethodNoPanic(
|
|
reflect.ValueOf(Span{}),
|
|
reflect.TypeOf((*trace.Span)(nil)).Elem(),
|
|
))
|
|
}
|
|
|
|
func assertAllExportedMethodNoPanic(rVal reflect.Value, rType reflect.Type) func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
for n := 0; n < rType.NumMethod(); n++ {
|
|
mType := rType.Method(n)
|
|
if !mType.IsExported() {
|
|
t.Logf("ignoring unexported %s", mType.Name)
|
|
continue
|
|
}
|
|
m := rVal.MethodByName(mType.Name)
|
|
if !m.IsValid() {
|
|
t.Errorf("unknown method for %s: %s", rVal.Type().Name(), mType.Name)
|
|
}
|
|
|
|
numIn := mType.Type.NumIn()
|
|
if mType.Type.IsVariadic() {
|
|
numIn--
|
|
}
|
|
args := make([]reflect.Value, numIn)
|
|
ctx := context.Background()
|
|
for i := range args {
|
|
aType := mType.Type.In(i)
|
|
if aType.Name() == "Context" {
|
|
// Do not panic on a nil context.
|
|
args[i] = reflect.ValueOf(ctx)
|
|
} else {
|
|
args[i] = reflect.New(aType).Elem()
|
|
}
|
|
}
|
|
|
|
assert.NotPanicsf(t, func() {
|
|
_ = m.Call(args)
|
|
}, "%s.%s", rVal.Type().Name(), mType.Name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNewTracerProvider(t *testing.T) {
|
|
tp := NewTracerProvider()
|
|
assert.Equal(t, tp, TracerProvider{})
|
|
tracer := tp.Tracer("")
|
|
assert.Equal(t, tracer, Tracer{})
|
|
}
|
|
|
|
func TestTracerStartPropagatesSpanContext(t *testing.T) {
|
|
tracer := NewTracerProvider().Tracer("")
|
|
spanCtx := trace.SpanContext{}
|
|
|
|
ctx := trace.ContextWithSpanContext(context.Background(), spanCtx)
|
|
ctx, span := tracer.Start(ctx, "test_span")
|
|
assert.Equal(t, spanCtx, trace.SpanContextFromContext(ctx), "empty span context not set in context")
|
|
assert.IsType(t, Span{}, span, "non-noop span returned")
|
|
assert.Equal(t, spanCtx, span.SpanContext(), "empty span context not returned from span")
|
|
assert.False(t, span.IsRecording(), "empty span context returned recording span")
|
|
|
|
spanCtx = spanCtx.WithTraceID(trace.TraceID([16]byte{1}))
|
|
spanCtx = spanCtx.WithSpanID(trace.SpanID([8]byte{1}))
|
|
ctx = trace.ContextWithSpanContext(context.Background(), spanCtx)
|
|
ctx, span = tracer.Start(ctx, "test_span")
|
|
assert.Equal(t, spanCtx, trace.SpanContextFromContext(ctx), "non-empty span context not set in context")
|
|
assert.Equal(t, spanCtx, span.SpanContext(), "non-empty span context not returned from span")
|
|
assert.False(t, span.IsRecording(), "non-empty span context returned recording span")
|
|
|
|
rSpan := recordingSpan{Span: Span{sc: spanCtx}}
|
|
ctx = trace.ContextWithSpan(context.Background(), rSpan)
|
|
ctx, span = tracer.Start(ctx, "test_span")
|
|
assert.Equal(t, spanCtx, trace.SpanContextFromContext(ctx), "recording span's span context not set in context")
|
|
assert.IsType(t, Span{}, span, "non-noop span returned")
|
|
assert.Equal(t, spanCtx, span.SpanContext(), "recording span's span context not returned from span")
|
|
assert.False(t, span.IsRecording(), "recording span returned")
|
|
}
|
|
|
|
func BenchmarkNoopInstance(b *testing.B) {
|
|
tracer := NewTracerProvider().Tracer("")
|
|
ctx := trace.ContextWithSpanContext(context.Background(), trace.SpanContext{})
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, span := tracer.Start(ctx, "")
|
|
span.End()
|
|
}
|
|
}
|
|
|
|
type recordingSpan struct{ Span }
|
|
|
|
func (recordingSpan) IsRecording() bool { return true }
|