From c0d4d025e2905b990781377a0b2554df180f9d8f Mon Sep 17 00:00:00 2001 From: Francis Bogsanyi Date: Tue, 8 Oct 2019 14:24:47 -0400 Subject: [PATCH] Implement TracerFactory --- api/lib/opentelemetry.rb | 11 +++--- api/lib/opentelemetry/trace.rb | 1 + api/lib/opentelemetry/trace/tracer_factory.rb | 22 +++++++++++ .../trace/tracer_factory_test.rb | 19 ++++++++++ api/test/opentelemetry_test.rb | 22 +++++------ sdk/lib/opentelemetry/sdk/trace.rb | 1 + sdk/lib/opentelemetry/sdk/trace/tracer.rb | 11 +++++- .../opentelemetry/sdk/trace/tracer_factory.rb | 37 +++++++++++++++++++ .../sdk/trace/tracer_factory_test.rb | 37 +++++++++++++++++++ .../opentelemetry/sdk/trace/tracer_test.rb | 18 +++++++-- 10 files changed, 159 insertions(+), 20 deletions(-) create mode 100644 api/lib/opentelemetry/trace/tracer_factory.rb create mode 100644 api/test/opentelemetry/trace/tracer_factory_test.rb create mode 100644 sdk/lib/opentelemetry/sdk/trace/tracer_factory.rb create mode 100644 sdk/test/opentelemetry/sdk/trace/tracer_factory_test.rb diff --git a/api/lib/opentelemetry.rb b/api/lib/opentelemetry.rb index 1d541d7fa..d70af91cb 100644 --- a/api/lib/opentelemetry.rb +++ b/api/lib/opentelemetry.rb @@ -17,13 +17,14 @@ module OpenTelemetry extend self - attr_writer :tracer, :meter, :distributed_context_manager + attr_writer :tracer_factory, :meter, :distributed_context_manager attr_accessor :logger - # @return [Object, Trace::Tracer] registered tracer or a default no-op - # implementation of the tracer - def tracer - @tracer ||= Trace::Tracer.new + + # @return [Object, Trace::TracerFactory] registered tracer factory or a + # default no-op implementation of the tracer factory. + def tracer_factory + @tracer_factory ||= Trace::TracerFactory.new end # @return [Object, Metrics::Meter] registered meter or a default no-op diff --git a/api/lib/opentelemetry/trace.rb b/api/lib/opentelemetry/trace.rb index 60bef6562..4bc1c9e92 100644 --- a/api/lib/opentelemetry/trace.rb +++ b/api/lib/opentelemetry/trace.rb @@ -50,3 +50,4 @@ def self.generate_span_id require 'opentelemetry/trace/sampling_hint' require 'opentelemetry/trace/status' require 'opentelemetry/trace/tracer' +require 'opentelemetry/trace/tracer_factory' diff --git a/api/lib/opentelemetry/trace/tracer_factory.rb b/api/lib/opentelemetry/trace/tracer_factory.rb new file mode 100644 index 000000000..732a9e754 --- /dev/null +++ b/api/lib/opentelemetry/trace/tracer_factory.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +module OpenTelemetry + module Trace + # No-op implementation of a tracer factory. + class TracerFactory + # Returns a {Tracer} instance. + # + # @param [optional String] name Instrumentation package name + # @param [optional String] version Instrumentation package version + # + # @return [Tracer] + def tracer(name = nil, version = nil) + @tracer ||= Tracer.new + end + end + end +end diff --git a/api/test/opentelemetry/trace/tracer_factory_test.rb b/api/test/opentelemetry/trace/tracer_factory_test.rb new file mode 100644 index 000000000..121d25d73 --- /dev/null +++ b/api/test/opentelemetry/trace/tracer_factory_test.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +require 'test_helper' + +describe OpenTelemetry::Trace::TracerFactory do + let(:tracer_factory) { OpenTelemetry::Trace::TracerFactory.new } + + describe '.tracer' do + it 'returns the same tracer for the same arguments' do + tracer1 = tracer_factory.tracer('component', 'semver:1.0') + tracer2 = tracer_factory.tracer('component', 'semver:1.0') + _(tracer1).must_equal(tracer2) + end + end +end diff --git a/api/test/opentelemetry_test.rb b/api/test/opentelemetry_test.rb index e49bd5bc4..3e9289a0b 100644 --- a/api/test/opentelemetry_test.rb +++ b/api/test/opentelemetry_test.rb @@ -8,25 +8,25 @@ require 'tempfile' describe OpenTelemetry do - describe '.tracer' do + describe '.tracer_factory' do after do - # Ensure we don't leak custom tracers to other tests - OpenTelemetry.tracer = nil + # Ensure we don't leak custom tracer factories and tracers to other tests + OpenTelemetry.tracer_factory = nil end - it 'returns instance of Trace::Tracer by default' do - tracer = OpenTelemetry.tracer - tracer.must_be_instance_of(OpenTelemetry::Trace::Tracer) + it 'returns instance of Trace::TracerFactory by default' do + tracer_factory = OpenTelemetry.tracer_factory + _(tracer_factory).must_be_instance_of(OpenTelemetry::Trace::TracerFactory) end it 'returns the same instance when accessed multiple times' do - OpenTelemetry.tracer.must_equal(OpenTelemetry.tracer) + _(OpenTelemetry.tracer_factory).must_equal(OpenTelemetry.tracer_factory) end - it 'returns user specified tracer' do - custom_tracer = 'a custom tracer' - OpenTelemetry.tracer = custom_tracer - OpenTelemetry.tracer.must_equal(custom_tracer) + it 'returns user specified tracer factory' do + custom_tracer_factory = 'a custom tracer factory' + OpenTelemetry.tracer_factory = custom_tracer_factory + _(OpenTelemetry.tracer_factory).must_equal(custom_tracer_factory) end end diff --git a/sdk/lib/opentelemetry/sdk/trace.rb b/sdk/lib/opentelemetry/sdk/trace.rb index 337b57dae..735c326eb 100644 --- a/sdk/lib/opentelemetry/sdk/trace.rb +++ b/sdk/lib/opentelemetry/sdk/trace.rb @@ -21,3 +21,4 @@ module Trace require 'opentelemetry/sdk/trace/span_data' require 'opentelemetry/sdk/trace/span' require 'opentelemetry/sdk/trace/tracer' +require 'opentelemetry/sdk/trace/tracer_factory' diff --git a/sdk/lib/opentelemetry/sdk/trace/tracer.rb b/sdk/lib/opentelemetry/sdk/trace/tracer.rb index 80d385077..8b930c9ec 100644 --- a/sdk/lib/opentelemetry/sdk/trace/tracer.rb +++ b/sdk/lib/opentelemetry/sdk/trace/tracer.rb @@ -11,11 +11,20 @@ module Trace class Tracer < OpenTelemetry::Trace::Tracer attr_accessor :active_trace_config attr_accessor :resource # TODO: should this be read-only? If not, how should exporters know when it is updated? + attr_reader :name + attr_reader :version + # @api private + # # Returns a new {Tracer} instance. # + # @param [String] name Instrumentation package name + # @param [String] version Instrumentation package version + # # @return [Tracer] - def initialize + def initialize(name, version) + @name = name + @version = version @active_span_processor = NoopSpanProcessor.instance @active_trace_config = Config::TraceConfig::DEFAULT @registered_span_processors = [] diff --git a/sdk/lib/opentelemetry/sdk/trace/tracer_factory.rb b/sdk/lib/opentelemetry/sdk/trace/tracer_factory.rb new file mode 100644 index 000000000..3523c9281 --- /dev/null +++ b/sdk/lib/opentelemetry/sdk/trace/tracer_factory.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +module OpenTelemetry + module SDK + module Trace + # No-op implementation of a tracer factory. + class TracerFactory + Key = Struct.new(:name, :version) + private_constant(:Key) + + # Returns a new {TracerFactory} instance. + # + # @return [TracerFactory] + def initialize + @mutex = Mutex.new + @registry = {} + end + + # Returns a {Tracer} instance. + # + # @param [optional String] name Instrumentation package name + # @param [optional String] version Instrumentation package version + # + # @return [Tracer] + def tracer(name = nil, version = nil) + name ||= '' + version ||= '' + @mutex.synchronize { @registry[Key.new(name, version)] ||= Tracer.new(name, version) } + end + end + end + end +end diff --git a/sdk/test/opentelemetry/sdk/trace/tracer_factory_test.rb b/sdk/test/opentelemetry/sdk/trace/tracer_factory_test.rb new file mode 100644 index 000000000..61afb7939 --- /dev/null +++ b/sdk/test/opentelemetry/sdk/trace/tracer_factory_test.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +require 'test_helper' + +describe OpenTelemetry::SDK::Trace::TracerFactory do + let(:tracer_factory) { OpenTelemetry::SDK::Trace::TracerFactory.new } + + describe '.tracer' do + it 'returns the same tracer for the same arguments' do + tracer1 = tracer_factory.tracer('component', 'semver:1.0') + tracer2 = tracer_factory.tracer('component', 'semver:1.0') + _(tracer1).must_equal(tracer2) + end + + it 'returns a default name-less version-less tracer' do + tracer = tracer_factory.tracer + _(tracer.name).must_equal('') + _(tracer.version).must_equal('') + end + + it 'returns different tracers for different names' do + tracer1 = tracer_factory.tracer('component1', 'semver:1.0') + tracer2 = tracer_factory.tracer('component2', 'semver:1.0') + _(tracer1).wont_equal(tracer2) + end + + it 'returns different tracers for different versions' do + tracer1 = tracer_factory.tracer('component', 'semver:1.0') + tracer2 = tracer_factory.tracer('component', 'semver:2.0') + _(tracer1).wont_equal(tracer2) + end + end +end diff --git a/sdk/test/opentelemetry/sdk/trace/tracer_test.rb b/sdk/test/opentelemetry/sdk/trace/tracer_test.rb index b36bf2b46..920c11365 100644 --- a/sdk/test/opentelemetry/sdk/trace/tracer_test.rb +++ b/sdk/test/opentelemetry/sdk/trace/tracer_test.rb @@ -9,18 +9,30 @@ describe OpenTelemetry::SDK::Trace::Tracer do Tracer = OpenTelemetry::SDK::Trace::Tracer - let(:tracer) { Tracer.new } + let(:tracer) { Tracer.new('', '') } let(:record_sampler) do ->(trace_id:, span_id:, parent_context:, hint:, links:, name:, kind:, attributes:) { Result.new(decision: Decision::RECORD) } # rubocop:disable Lint/UnusedBlockArgument end describe '#initialize' do it 'installs a Resource' do - Tracer.new.resource.wont_be_nil + _(Tracer.new(nil, nil).resource).wont_be_nil end it 'activates a default TraceConfig' do - Tracer.new.active_trace_config.must_equal(TraceConfig::DEFAULT) + _(Tracer.new(nil, nil).active_trace_config).must_equal(TraceConfig::DEFAULT) + end + end + + describe '#name' do + it 'reflects the name passed in' do + _(Tracer.new('component', nil).name).must_equal('component') + end + end + + describe '#version' do + it 'reflects the version passed in' do + _(Tracer.new(nil, 'semver:1.0').version).must_equal('semver:1.0') end end