Skip to content

Commit

Permalink
bridge/opentelmeetry: cache created Tracers, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
bobheadxi committed Aug 29, 2022
1 parent 0ffe14b commit 8a83e1f
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 1 deletion.
28 changes: 27 additions & 1 deletion bridge/opentracing/wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package opentracing // import "go.opentelemetry.io/otel/bridge/opentracing"

import (
"context"
"sync"

"go.opentelemetry.io/otel/bridge/opentracing/migration"
"go.opentelemetry.io/otel/trace"
Expand Down Expand Up @@ -46,12 +47,37 @@ func NewWrappedTracerProvider(bridge *BridgeTracer, tracer trace.Tracer) *Wrappe
}
}

type wrappedTracerKey struct {
name string
version string
}

// NewDynamicWrappedTracerProvider creates a new trace provider that creates new
// instances of WrapperTracer that wraps OpenTelemetry tracer for each call to Tracer().
func NewDynamicWrappedTracerProvider(bridge *BridgeTracer, provider trace.TracerProvider) *WrapperTracerProvider {
var (
mtx sync.Mutex
tracers = make(map[wrappedTracerKey]*WrapperTracer)
)

return &WrapperTracerProvider{
getWrappedTracer: func(name string, opts ...trace.TracerOption) *WrapperTracer {
return NewWrapperTracer(bridge, provider.Tracer(name, opts...))
mtx.Lock()
defer mtx.Unlock()

c := trace.NewTracerConfig(opts...)
key := wrappedTracerKey{
name: name,
version: c.InstrumentationVersion(),
}

if t, ok := tracers[key]; ok {
return t
}

wrapper := NewWrapperTracer(bridge, provider.Tracer(name, opts...))
tracers[key] = wrapper
return wrapper
},
}
}
Expand Down
71 changes: 71 additions & 0 deletions bridge/opentracing/wrapper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package opentracing

import (
"testing"

"go.opentelemetry.io/otel/bridge/opentracing/internal"
"go.opentelemetry.io/otel/trace"
)

type namedMockTracer struct {
name string
*internal.MockTracer
}

type namedMockTracerProvider struct{}

var _ trace.TracerProvider = (*namedMockTracerProvider)(nil)

// Tracer returns the WrapperTracer associated with the WrapperTracerProvider.
func (p *namedMockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer {
return &namedMockTracer{
name: name,
MockTracer: internal.NewMockTracer(),
}
}

func TestDynamicWrappedTracerProvider(t *testing.T) {
// assertMockTracerName casts tracer into a named mock tracer provided by
// namedMockTracerProvider, and asserts against its name
assertMockTracerName := func(t *testing.T, tracer trace.Tracer, name string) {
// Unwrap the tracer
wrapped := tracer.(*WrapperTracer)
tracer = wrapped.tracer

// Cast into the underlying type and assert
if mock, ok := tracer.(*namedMockTracer); ok {
if name != mock.name {
t.Errorf("expected name %q, got %q", name, mock.name)
}
} else if !ok {
t.Errorf("expected *namedMockTracer, got %T", mock)
}
}

var (
foobar = "foobar"
bazbar = "bazbar"
provider = NewDynamicWrappedTracerProvider(nil, &namedMockTracerProvider{})
)

t.Run("Tracers should be created with foobar from provider", func(t *testing.T) {
tracer := provider.Tracer(foobar)
assertMockTracerName(t, tracer, foobar)
})

t.Run("Repeated requests to create a tracer should provide the existing tracer", func(t *testing.T) {
tracer1 := provider.Tracer(foobar)
assertMockTracerName(t, tracer1, foobar)
tracer2 := provider.Tracer(foobar)
assertMockTracerName(t, tracer2, foobar)
tracer3 := provider.Tracer(bazbar)
assertMockTracerName(t, tracer3, bazbar)

if tracer1 != tracer2 {
t.Errorf("expected the same tracer, got different tracers")
}
if tracer1 == tracer3 || tracer2 == tracer3 {
t.Errorf("expected different tracers, got the same tracer")
}
})
}

0 comments on commit 8a83e1f

Please sign in to comment.