Skip to content

Commit

Permalink
Fix issue #1490, apply same logic as in the SDK
Browse files Browse the repository at this point in the history
Signed-off-by: Bogdan Drutu <bogdandrutu@gmail.com>
  • Loading branch information
bogdandrutu committed Mar 10, 2021
1 parent 66b1135 commit 4922f43
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- `SamplingResult.TraceState` is correctly propagated to a newly created
span's `SpanContext`. (#1655)
- Jaeger Exporter: Ensure mapping between OTEL and Jaeger span data complies with the specification. (#1626)
- Issue #1490, apply same logic as in the SDK. (#1687)

## [0.18.0] - 2020-03-03

Expand Down
40 changes: 32 additions & 8 deletions internal/global/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ import (
// All TracerProvider functionality is forwarded to a delegate once
// configured.
type tracerProvider struct {
mtx sync.Mutex
tracers []*tracer

mtx sync.Mutex
tracers map[il]*tracer
delegate trace.TracerProvider
}

Expand All @@ -63,14 +62,15 @@ var _ trace.TracerProvider = &tracerProvider{}
// Delegation only happens on the first call to this method. All subsequent
// calls result in no delegation changes.
func (p *tracerProvider) setDelegate(provider trace.TracerProvider) {
if p.delegate != nil {
return
}

p.mtx.Lock()
defer p.mtx.Unlock()

p.delegate = provider

if len(p.tracers) == 0 {
return
}

for _, t := range p.tracers {
t.setDelegate(provider)
}
Expand All @@ -87,11 +87,35 @@ func (p *tracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.T
return p.delegate.Tracer(name, opts...)
}

// At this moment it is guaranteed that no sdk is installed, save the tracer in the tracers map.

key := createKey(name, opts...)

if p.tracers == nil {
p.tracers = make(map[il]*tracer)
}

if val, ok := p.tracers[key]; ok {
return val
}

t := &tracer{name: name, opts: opts}
p.tracers = append(p.tracers, t)
p.tracers[key] = t
return t
}

type il struct {
name string
version string
}

func createKey(name string, opts ...trace.TracerOption) il {
return il{
name: name,
version: trace.NewTracerConfig(opts...).InstrumentationVersion,
}
}

// tracer is a placeholder for a trace.Tracer.
//
// All Tracer functionality is forwarded to a delegate once configured.
Expand Down
19 changes: 19 additions & 0 deletions internal/global/trace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,22 @@ func TestTraceProviderDelegates(t *testing.T) {
gtp.Tracer("abc", trace.WithInstrumentationVersion("xyz"))
assert.True(t, called, "expected configured TraceProvider to be called")
}

func TestTraceProviderDelegates_SameInstance(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")))
}

0 comments on commit 4922f43

Please sign in to comment.