From 640a0cd8bc3844453976c2619c40bee4a1e4a07c Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 11 Jan 2023 16:59:06 -0800 Subject: [PATCH] bridge/opentracing: introduce NewTracerProvider that wraps TracerProvider instead of Tracer (#3116) * bridge/opentracing: add NewDynamicWrappedTracerProvider for named tracers * bridge/opentelmeetry: cache created Tracers, add tests * bridge/opentracing: rename constructor to NewTracerProvider * add license header * Update docstring Co-authored-by: Tyler Yahn * fix deprecated docstring * rewrite new lookup TracerProvider as separate type * update docstring * add changelog entries * Update bridge/opentracing/provider.go Co-authored-by: Damien Mathieu <42@dmathieu.com> Co-authored-by: Tyler Yahn Co-authored-by: Damien Mathieu <42@dmathieu.com> --- CHANGELOG.md | 2 + bridge/opentracing/provider.go | 71 ++++++++++++++++++++++++ bridge/opentracing/provider_test.go | 85 +++++++++++++++++++++++++++++ bridge/opentracing/wrapper.go | 9 ++- 4 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 bridge/opentracing/provider.go create mode 100644 bridge/opentracing/provider_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 33d3cf58bde..4bc79e6543d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - `Int64Counter` replaces the `syncint64.Counter` - `Int64UpDownCounter` replaces the `syncint64.UpDownCounter` - `Int64Histogram` replaces the `syncint64.Histogram` +- Add `NewTracerProvider` to `go.opentelemetry.io/otel/bridge/opentracing` to create `WrapperTracer` instances from a `TracerProvider`. (#3316) ### Changed @@ -111,6 +112,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm Use the instruments from `go.opentelemetry.io/otel/metric/instrument` instead. (#3575) - The `go.opentelemetry.io/otel/metric/instrument/syncint64` package is deprecated. Use the instruments from `go.opentelemetry.io/otel/metric/instrument` instead. (#3575) +- The `NewWrappedTracerProvider` in `go.opentelemetry.io/otel/bridge/opentracing` is now deprecated. Use `NewTracerProvider` instead. (#3316) ### Removed diff --git a/bridge/opentracing/provider.go b/bridge/opentracing/provider.go new file mode 100644 index 00000000000..941e277baf8 --- /dev/null +++ b/bridge/opentracing/provider.go @@ -0,0 +1,71 @@ +// 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. + +package opentracing // import "go.opentelemetry.io/otel/bridge/opentracing" + +import ( + "sync" + + "go.opentelemetry.io/otel/trace" +) + +// TracerProvider is an OpenTelemetry TracerProvider that wraps an OpenTracing +// Tracer. +type TracerProvider struct { + bridge *BridgeTracer + provider trace.TracerProvider + + tracers map[wrappedTracerKey]*WrapperTracer + mtx sync.Mutex +} + +var _ trace.TracerProvider = (*TracerProvider)(nil) + +// NewTracerProvider returns a new TracerProvider that creates new instances of +// WrapperTracer from the given TracerProvider. +func NewTracerProvider(bridge *BridgeTracer, provider trace.TracerProvider) *TracerProvider { + return &TracerProvider{ + bridge: bridge, + provider: provider, + + tracers: make(map[wrappedTracerKey]*WrapperTracer), + } +} + +type wrappedTracerKey struct { + name string + version string +} + +// Tracer creates a WrappedTracer that wraps the OpenTelemetry tracer for each call to +// Tracer(). Repeated calls to Tracer() with the same configuration will look up and +// return an existing instance of WrapperTracer. +func (p *TracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + p.mtx.Lock() + defer p.mtx.Unlock() + + c := trace.NewTracerConfig(opts...) + key := wrappedTracerKey{ + name: name, + version: c.InstrumentationVersion(), + } + + if t, ok := p.tracers[key]; ok { + return t + } + + wrapper := NewWrapperTracer(p.bridge, p.provider.Tracer(name, opts...)) + p.tracers[key] = wrapper + return wrapper +} diff --git a/bridge/opentracing/provider_test.go b/bridge/opentracing/provider_test.go new file mode 100644 index 00000000000..8af3796e031 --- /dev/null +++ b/bridge/opentracing/provider_test.go @@ -0,0 +1,85 @@ +// 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. + +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 TestTracerProvider(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 = NewTracerProvider(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") + } + }) +} diff --git a/bridge/opentracing/wrapper.go b/bridge/opentracing/wrapper.go index 8016ea2a87c..3e348c45523 100644 --- a/bridge/opentracing/wrapper.go +++ b/bridge/opentracing/wrapper.go @@ -22,7 +22,9 @@ import ( ) // WrapperTracerProvider is an OpenTelemetry TracerProvider that wraps an -// OpenTracing Tracer. +// OpenTracing Tracer, created by the deprecated NewWrappedTracerProvider. +// +// Deprecated: Use the TracerProvider from NewTracerProvider(...) instead. type WrapperTracerProvider struct { wTracer *WrapperTracer } @@ -35,7 +37,10 @@ func (p *WrapperTracerProvider) Tracer(_ string, _ ...trace.TracerOption) trace. } // NewWrappedTracerProvider creates a new trace provider that creates a single -// instance of WrapperTracer that wraps OpenTelemetry tracer. +// instance of WrapperTracer that wraps OpenTelemetry tracer, and always returns +// it unmodified from Tracer(). +// +// Deprecated: Use NewTracerProvider(...) instead. func NewWrappedTracerProvider(bridge *BridgeTracer, tracer trace.Tracer) *WrapperTracerProvider { return &WrapperTracerProvider{ wTracer: NewWrapperTracer(bridge, tracer),