2020-03-24 07:41:10 +02:00
|
|
|
// Copyright The OpenTelemetry Authors
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2020-11-16 19:30:54 +02:00
|
|
|
package global_test
|
2020-01-02 23:20:38 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2021-03-10 18:45:31 +02:00
|
|
|
"sync/atomic"
|
2020-01-02 23:20:38 +02:00
|
|
|
"testing"
|
2021-03-10 18:45:31 +02:00
|
|
|
"time"
|
2020-01-02 23:20:38 +02:00
|
|
|
|
2020-07-28 19:47:08 +02:00
|
|
|
"github.com/stretchr/testify/assert"
|
2020-01-02 23:20:38 +02:00
|
|
|
|
2020-11-16 19:30:54 +02:00
|
|
|
"go.opentelemetry.io/otel"
|
|
|
|
"go.opentelemetry.io/otel/internal/global"
|
2020-11-17 20:02:21 +02:00
|
|
|
"go.opentelemetry.io/otel/trace"
|
2020-01-02 23:20:38 +02:00
|
|
|
)
|
|
|
|
|
2021-07-22 18:12:21 +02:00
|
|
|
type fnTracerProvider struct {
|
|
|
|
tracer func(string, ...trace.TracerOption) trace.Tracer
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fn fnTracerProvider) Tracer(instrumentationName string, opts ...trace.TracerOption) trace.Tracer {
|
|
|
|
return fn.tracer(instrumentationName, opts...)
|
|
|
|
}
|
|
|
|
|
|
|
|
type fnTracer struct {
|
|
|
|
start func(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fn fnTracer) Start(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
|
|
|
|
return fn.start(ctx, spanName, opts...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTraceProviderDelegation(t *testing.T) {
|
2020-11-16 19:30:54 +02:00
|
|
|
global.ResetForTest()
|
2020-01-02 23:20:38 +02:00
|
|
|
|
2021-07-22 18:12:21 +02:00
|
|
|
// Map of tracers to expected span names.
|
|
|
|
expected := map[string][]string{
|
|
|
|
"pre": {"span2"},
|
|
|
|
"post": {"span3"},
|
|
|
|
"fromSpan": {"span4"},
|
|
|
|
}
|
|
|
|
|
2020-01-02 23:20:38 +02:00
|
|
|
ctx := context.Background()
|
2020-11-16 19:30:54 +02:00
|
|
|
gtp := otel.GetTracerProvider()
|
2020-01-02 23:20:38 +02:00
|
|
|
tracer1 := gtp.Tracer("pre")
|
2020-08-08 21:10:36 +02:00
|
|
|
// This is started before an SDK was registered and should be dropped.
|
2020-01-02 23:20:38 +02:00
|
|
|
_, span1 := tracer1.Start(ctx, "span1")
|
|
|
|
|
2021-07-22 18:12:21 +02:00
|
|
|
otel.SetTracerProvider(fnTracerProvider{
|
|
|
|
tracer: func(name string, opts ...trace.TracerOption) trace.Tracer {
|
|
|
|
spans, ok := expected[name]
|
|
|
|
assert.Truef(t, ok, "invalid tracer: %s", name)
|
|
|
|
return fnTracer{
|
|
|
|
start: func(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
|
|
|
|
if ok {
|
|
|
|
if len(spans) == 0 {
|
|
|
|
t.Errorf("unexpected span: %s", spanName)
|
|
|
|
} else {
|
|
|
|
var want string
|
|
|
|
want, spans = spans[0], spans[1:]
|
|
|
|
assert.Equal(t, want, spanName)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return trace.NewNoopTracerProvider().Tracer(name).Start(ctx, spanName)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
})
|
2020-01-02 23:20:38 +02:00
|
|
|
|
|
|
|
// This span was started before initialization, it is expected to be dropped.
|
|
|
|
span1.End()
|
|
|
|
|
|
|
|
// The existing Tracer should have been configured to now use the configured SDK.
|
|
|
|
_, span2 := tracer1.Start(ctx, "span2")
|
|
|
|
span2.End()
|
|
|
|
|
2020-09-24 00:16:13 +02:00
|
|
|
// The global TracerProvider should now create Tracers that also use the newly configured SDK.
|
2020-01-02 23:20:38 +02:00
|
|
|
tracer2 := gtp.Tracer("post")
|
|
|
|
_, span3 := tracer2.Start(ctx, "span3")
|
|
|
|
span3.End()
|
|
|
|
|
2021-06-17 18:05:44 +02:00
|
|
|
// The noop-span should still provide access to a usable TracerProvider.
|
|
|
|
_, span4 := span1.TracerProvider().Tracer("fromSpan").Start(ctx, "span4")
|
|
|
|
span4.End()
|
2021-03-10 18:45:31 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 20:02:21 +02:00
|
|
|
func TestTraceProviderDelegates(t *testing.T) {
|
|
|
|
global.ResetForTest()
|
|
|
|
|
|
|
|
// Retrieve the placeholder TracerProvider.
|
|
|
|
gtp := otel.GetTracerProvider()
|
|
|
|
|
|
|
|
// Configure it with a spy.
|
|
|
|
called := false
|
|
|
|
otel.SetTracerProvider(fnTracerProvider{
|
|
|
|
tracer: func(name string, opts ...trace.TracerOption) trace.Tracer {
|
|
|
|
called = true
|
|
|
|
assert.Equal(t, "abc", name)
|
|
|
|
return trace.NewNoopTracerProvider().Tracer("")
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
gtp.Tracer("abc", trace.WithInstrumentationVersion("xyz"))
|
|
|
|
assert.True(t, called, "expected configured TraceProvider to be called")
|
|
|
|
}
|
2021-03-10 18:45:31 +02:00
|
|
|
|
|
|
|
func TestTraceProviderDelegatesConcurrentSafe(t *testing.T) {
|
|
|
|
global.ResetForTest()
|
|
|
|
|
|
|
|
// Retrieve the placeholder TracerProvider.
|
|
|
|
gtp := otel.GetTracerProvider()
|
|
|
|
|
|
|
|
done := make(chan struct{})
|
|
|
|
quit := make(chan struct{})
|
|
|
|
go func() {
|
|
|
|
defer close(done)
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-time.After(1 * time.Millisecond):
|
|
|
|
gtp.Tracer("abc", trace.WithInstrumentationVersion("xyz"))
|
|
|
|
case <-quit:
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Wait for the goroutine to make some calls before installing the provider.
|
|
|
|
<-time.After(100 * time.Millisecond)
|
|
|
|
|
|
|
|
// Configure it with a spy.
|
|
|
|
called := int32(0)
|
|
|
|
otel.SetTracerProvider(fnTracerProvider{
|
|
|
|
tracer: func(name string, opts ...trace.TracerOption) trace.Tracer {
|
|
|
|
newVal := atomic.AddInt32(&called, 1)
|
|
|
|
assert.Equal(t, "abc", name)
|
|
|
|
if newVal == 10 {
|
|
|
|
// Signal the goroutine to finish.
|
|
|
|
close(quit)
|
|
|
|
}
|
|
|
|
return trace.NewNoopTracerProvider().Tracer("")
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
// Wait for the go routine to finish
|
|
|
|
<-done
|
|
|
|
|
|
|
|
assert.LessOrEqual(t, int32(10), atomic.LoadInt32(&called), "expected configured TraceProvider to be called")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTracerDelegatesConcurrentSafe(t *testing.T) {
|
|
|
|
global.ResetForTest()
|
|
|
|
|
|
|
|
// Retrieve the placeholder TracerProvider.
|
|
|
|
gtp := otel.GetTracerProvider()
|
|
|
|
tracer := gtp.Tracer("abc", trace.WithInstrumentationVersion("xyz"))
|
|
|
|
|
|
|
|
done := make(chan struct{})
|
|
|
|
quit := make(chan struct{})
|
|
|
|
go func() {
|
|
|
|
defer close(done)
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-time.After(1 * time.Millisecond):
|
|
|
|
tracer.Start(context.Background(), "name")
|
|
|
|
case <-quit:
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Wait for the goroutine to make some calls before installing the provider.
|
|
|
|
<-time.After(100 * time.Millisecond)
|
|
|
|
|
|
|
|
// Configure it with a spy.
|
|
|
|
called := int32(0)
|
|
|
|
otel.SetTracerProvider(fnTracerProvider{
|
|
|
|
tracer: func(name string, opts ...trace.TracerOption) trace.Tracer {
|
|
|
|
assert.Equal(t, "abc", name)
|
|
|
|
return fnTracer{
|
2021-05-27 16:53:56 +02:00
|
|
|
start: func(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
|
2021-03-10 18:45:31 +02:00
|
|
|
newVal := atomic.AddInt32(&called, 1)
|
|
|
|
assert.Equal(t, "name", spanName)
|
|
|
|
if newVal == 10 {
|
|
|
|
// Signal the goroutine to finish.
|
|
|
|
close(quit)
|
|
|
|
}
|
|
|
|
return trace.NewNoopTracerProvider().Tracer("").Start(ctx, spanName)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
// Wait for the go routine to finish
|
|
|
|
<-done
|
|
|
|
|
|
|
|
assert.LessOrEqual(t, int32(10), atomic.LoadInt32(&called), "expected configured TraceProvider to be called")
|
|
|
|
}
|
2021-03-10 21:04:05 +02:00
|
|
|
|
|
|
|
func TestTraceProviderDelegatesSameInstance(t *testing.T) {
|
|
|
|
global.ResetForTest()
|
|
|
|
|
|
|
|
// Retrieve the placeholder TracerProvider.
|
|
|
|
gtp := otel.GetTracerProvider()
|
|
|
|
tracer := gtp.Tracer("abc", trace.WithInstrumentationVersion("xyz"))
|
|
|
|
assert.Same(t, tracer, gtp.Tracer("abc", trace.WithInstrumentationVersion("xyz")))
|
|
|
|
assert.Same(t, tracer, gtp.Tracer("abc", trace.WithInstrumentationVersion("xyz")))
|
|
|
|
|
|
|
|
otel.SetTracerProvider(fnTracerProvider{
|
|
|
|
tracer: func(name string, opts ...trace.TracerOption) trace.Tracer {
|
|
|
|
return trace.NewNoopTracerProvider().Tracer("")
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
assert.NotSame(t, tracer, gtp.Tracer("abc", trace.WithInstrumentationVersion("xyz")))
|
|
|
|
}
|
2021-05-12 19:11:56 +02:00
|
|
|
|
|
|
|
func TestSpanContextPropagatedWithNonRecordingSpan(t *testing.T) {
|
|
|
|
global.ResetForTest()
|
|
|
|
|
|
|
|
sc := trace.NewSpanContext(trace.SpanContextConfig{
|
|
|
|
TraceID: [16]byte{0x01},
|
|
|
|
SpanID: [8]byte{0x01},
|
|
|
|
TraceFlags: trace.FlagsSampled,
|
|
|
|
Remote: true,
|
|
|
|
})
|
|
|
|
ctx := trace.ContextWithSpanContext(context.Background(), sc)
|
|
|
|
_, span := otel.Tracer("test").Start(ctx, "test")
|
|
|
|
|
|
|
|
assert.Equal(t, sc, span.SpanContext())
|
|
|
|
assert.False(t, span.IsRecording())
|
|
|
|
}
|