From 1e86b93188446c9cd249e3969ad7c485ca2a4033 Mon Sep 17 00:00:00 2001 From: Robert Laurin Date: Wed, 13 May 2020 14:42:48 -0400 Subject: [PATCH 01/13] Add support for automated resource detection This adds support for populating a resource with with Telemetry data as well as Google Cloud Platform environment metata data. For #230 --- sdk/lib/opentelemetry/sdk/configurator.rb | 14 +- sdk/lib/opentelemetry/sdk/resources.rb | 2 + .../sdk/resources/auto_detector.rb | 31 +++++ .../opentelemetry/sdk/resources/constants.rb | 122 ++++++++++++++++++ .../detectors/google_cloud_platform.rb | 54 ++++++++ .../sdk/resources/detectors/telemetry.rb | 26 ++++ sdk/lib/opentelemetry/sdk/trace/tracer.rb | 6 +- .../sdk/trace/tracer_provider.rb | 6 +- sdk/opentelemetry-sdk.gemspec | 1 + .../sdk/resources/auto_detector_test.rb | 27 ++++ .../detectors/google_cloud_platform_test.rb | 62 +++++++++ .../sdk/resources/detectors/telemetry_test.rb | 28 ++++ .../sdk/trace/tracer_provider_test.rb | 3 +- .../opentelemetry/sdk/trace/tracer_test.rb | 12 +- sdk/test/test_helper.rb | 9 ++ 15 files changed, 382 insertions(+), 21 deletions(-) create mode 100644 sdk/lib/opentelemetry/sdk/resources/auto_detector.rb create mode 100644 sdk/lib/opentelemetry/sdk/resources/constants.rb create mode 100644 sdk/lib/opentelemetry/sdk/resources/detectors/google_cloud_platform.rb create mode 100644 sdk/lib/opentelemetry/sdk/resources/detectors/telemetry.rb create mode 100644 sdk/test/opentelemetry/sdk/resources/auto_detector_test.rb create mode 100644 sdk/test/opentelemetry/sdk/resources/detectors/google_cloud_platform_test.rb create mode 100644 sdk/test/opentelemetry/sdk/resources/detectors/telemetry_test.rb diff --git a/sdk/lib/opentelemetry/sdk/configurator.rb b/sdk/lib/opentelemetry/sdk/configurator.rb index 1713e8ae4..925a21fd6 100644 --- a/sdk/lib/opentelemetry/sdk/configurator.rb +++ b/sdk/lib/opentelemetry/sdk/configurator.rb @@ -8,7 +8,7 @@ module OpenTelemetry module SDK # The configurator provides defaults and facilitates configuring the # SDK for use. - class Configurator + class Configurator # rubocop:disable Metrics/ClassLength USE_MODE_UNSPECIFIED = 0 USE_MODE_ONE = 1 USE_MODE_ALL = 2 @@ -16,7 +16,7 @@ class Configurator private_constant :USE_MODE_UNSPECIFIED, :USE_MODE_ONE, :USE_MODE_ALL attr_writer :logger, :http_extractors, :http_injectors, :text_extractors, - :text_injectors + :text_injectors, :resource def initialize @adapter_names = [] @@ -27,7 +27,7 @@ def initialize @text_injectors = nil @span_processors = [] @use_mode = USE_MODE_UNSPECIFIED - @tracer_provider = Trace::TracerProvider.new + @resource = OpenTelemetry::SDK::Resources::Resource.create end def logger @@ -83,12 +83,16 @@ def configure OpenTelemetry.correlations = CorrelationContext::Manager.new configure_propagation configure_span_processors - OpenTelemetry.tracer_provider = @tracer_provider + OpenTelemetry.tracer_provider = tracer_provider install_instrumentation end private + def tracer_provider + @tracer_provider ||= Trace::TracerProvider.new(@resource) + end + def check_use_mode!(mode) @use_mode = mode if @use_mode == USE_MODE_UNSPECIFIED raise 'Use either `use_all` or `use`, but not both' unless @use_mode == mode @@ -105,7 +109,7 @@ def install_instrumentation def configure_span_processors processors = @span_processors.empty? ? [default_span_processor] : @span_processors - processors.each { |p| @tracer_provider.add_span_processor(p) } + processors.each { |p| tracer_provider.add_span_processor(p) } end def default_span_processor diff --git a/sdk/lib/opentelemetry/sdk/resources.rb b/sdk/lib/opentelemetry/sdk/resources.rb index 7155df90c..bea8fe9af 100644 --- a/sdk/lib/opentelemetry/sdk/resources.rb +++ b/sdk/lib/opentelemetry/sdk/resources.rb @@ -13,3 +13,5 @@ module Resources end require 'opentelemetry/sdk/resources/resource' +require 'opentelemetry/sdk/resources/constants' +require 'opentelemetry/sdk/resources/auto_detector' diff --git a/sdk/lib/opentelemetry/sdk/resources/auto_detector.rb b/sdk/lib/opentelemetry/sdk/resources/auto_detector.rb new file mode 100644 index 000000000..961f97c26 --- /dev/null +++ b/sdk/lib/opentelemetry/sdk/resources/auto_detector.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +require 'opentelemetry/sdk/resources/detectors/google_cloud_platform' +require 'opentelemetry/sdk/resources/detectors/telemetry' + +module OpenTelemetry + module SDK + module Resources + # AutoDetector contains detect class method for running all detectors + module AutoDetector + extend self + + DETECTORS = [ + OpenTelemetry::SDK::Resources::Detectors::GoogleCloudPlatform, + OpenTelemetry::SDK::Resources::Detectors::Telemetry + ] + + def detect + resources = DETECTORS.map(&:detect) + resources.reduce(OpenTelemetry::SDK::Resources::Resource.create) do |empty_resource, detected_resource| + empty_resource.merge(detected_resource) + end + end + end + end + end +end diff --git a/sdk/lib/opentelemetry/sdk/resources/constants.rb b/sdk/lib/opentelemetry/sdk/resources/constants.rb new file mode 100644 index 000000000..ef245731a --- /dev/null +++ b/sdk/lib/opentelemetry/sdk/resources/constants.rb @@ -0,0 +1,122 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +module OpenTelemetry + module SDK + module Resources + # Attributes describing a service instance. + SERVICE_RESOURCE = { + # Logical name of the service. + name: 'service.name', + + # A namespace for `service.name`. + namespace: 'service.namespace', + + # The string ID of the service instance. + instance_id: 'service.instance.id', + + # The version string of the service API or implementation. + version: 'service.version' + }.freeze + + # Attributes describing the telemetry library. + TELEMETRY_SDK_RESOURCE = { + # The name of the telemetry library. + name: 'telemetry.sdk.name', + + # The language of telemetry library and of the code instrumented with it. + language: 'telemetry.sdk.language', + + # The version string of the telemetry library + version: 'telemetry.sdk.version' + }.freeze + + # Attributes defining a compute unit (e.g. Container, Process, Lambda + # Function). + CONTAINER_RESOURCE = { + # The container name. + name: 'container.name', + + # The name of the image the container was built on. + image_name: 'container.image.name', + + # The container image tag. + image_tag: 'container.image.tag' + }.freeze + + FAAS_RESOURCE = { + # The name of the function being executed. + name: 'faas.name', + + # The unique name of the function being executed. + id: 'faas.id', + + # The version string of the function being executed. + version: 'faas.version', + + # The execution environment ID as a string. + instance: 'faas.instance' + }.freeze + + # Attributes defining a deployment service (e.g. Kubernetes). + K8S_RESOURCE = { + # The name of the cluster that the pod is running in. + cluster_name: 'k8s.cluster.name', + + # The name of the namespace that the pod is running in. + namespace_name: 'k8s.namespace.name', + + # The name of the pod. + pod_name: 'k8s.pod.name', + + # The name of the deployment. + deployment_name: 'k8s.deployment.name' + }.freeze + + # Attributes defining a computing instance (e.g. host). + HOST_RESOURCE = { + # Hostname of the host. It contains what the hostname command returns on the + # host machine. + hostname: 'host.hostname', + + # Unique host id. For Cloud this must be the instance_id assigned by the + # cloud provider + id: 'host.id', + + # Name of the host. It may contain what hostname returns on Unix systems, + # the fully qualified, or a name specified by the user. + name: 'host.name', + + # Type of host. For Cloud this must be the machine type. + type: 'host.type', + + # Name of the VM image or OS install the host was instantiated from. + image_name: 'host.image.name', + + # VM image id. For Cloud, this value is from the provider. + image_id: 'host.image.id', + + # The version string of the VM image. + image_version: 'host.image.version' + }.freeze + + # Attributes defining a running environment (e.g. Cloud, Data Center). + CLOUD_RESOURCE = { + # Name of the cloud provider. Example values are aws, azure, gcp. + provider: 'cloud.provider', + + # The cloud account id used to identify different entities. + account_id: 'cloud.account.id', + + # A specific geographical location where different entities can run. + region: 'cloud.region', + + # Zones are a sub set of the region connected through low-latency links. + zone: 'cloud.zone' + }.freeze + end + end +end diff --git a/sdk/lib/opentelemetry/sdk/resources/detectors/google_cloud_platform.rb b/sdk/lib/opentelemetry/sdk/resources/detectors/google_cloud_platform.rb new file mode 100644 index 000000000..34bcdaa37 --- /dev/null +++ b/sdk/lib/opentelemetry/sdk/resources/detectors/google_cloud_platform.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +require 'google-cloud-env' + +module OpenTelemetry + module SDK + module Resources + module Detectors + # GoogleCloudPlatform contains detect class method for determining gcp environment resource labels + module GoogleCloudPlatform + extend self + + def detect + gcp_env = Google::Cloud::Env.new + resource_labels = {} + + if gcp_env.compute_engine? + resource_labels[CLOUD_RESOURCE[:provider]] = 'gcp' + resource_labels[CLOUD_RESOURCE[:account_id]] = gcp_env.project_id || '' + resource_labels[CLOUD_RESOURCE[:region]] = gcp_env.instance_attribute('cluster-location') || '' + resource_labels[CLOUD_RESOURCE[:zone]] = gcp_env.instance_zone || '' + + resource_labels[HOST_RESOURCE[:hostname]] = hostname + resource_labels[HOST_RESOURCE[:id]] = gcp_env.lookup_metadata('instance', 'id') || '' + resource_labels[HOST_RESOURCE[:name]] = gcp_env.lookup_metadata('instance', 'hostname') || '' + end + + if gcp_env.kubernetes_engine? + resource_labels[K8S_RESOURCE[:cluster_name]] = gcp_env.instance_attribute('cluster-name') || '' + resource_labels[K8S_RESOURCE[:namespace_name]] = gcp_env.kubernetes_engine_namespace_id || '' + resource_labels[K8S_RESOURCE[:pod_name]] = hostname + + resource_labels[CONTAINER_RESOURCE[:name]] = ENV['CONTAINER_NAME'] || '' + end + + Resource.create(resource_labels) + end + + private + + def hostname + ENV['HOSTNAME'] || `hostname`&.strip + rescue StandardError => e + '' + end + end + end + end + end +end diff --git a/sdk/lib/opentelemetry/sdk/resources/detectors/telemetry.rb b/sdk/lib/opentelemetry/sdk/resources/detectors/telemetry.rb new file mode 100644 index 000000000..b028c9f32 --- /dev/null +++ b/sdk/lib/opentelemetry/sdk/resources/detectors/telemetry.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +module OpenTelemetry + module SDK + module Resources + module Detectors + # Telemetry contains detect class method for determining instrumentation resource labels + module Telemetry + extend self + + def detect + resource_labels = {} + resource_labels[TELEMETRY_SDK_RESOURCE[:name]] = 'OpenTelemetry' + resource_labels[TELEMETRY_SDK_RESOURCE[:language]] = 'ruby' + resource_labels[TELEMETRY_SDK_RESOURCE[:version]] = "semver:#{OpenTelemetry::SDK::VERSION}" + Resource.create(resource_labels) + end + end + end + end + end +end diff --git a/sdk/lib/opentelemetry/sdk/trace/tracer.rb b/sdk/lib/opentelemetry/sdk/trace/tracer.rb index b12d7f8ac..56f928e62 100644 --- a/sdk/lib/opentelemetry/sdk/trace/tracer.rb +++ b/sdk/lib/opentelemetry/sdk/trace/tracer.rb @@ -9,15 +9,13 @@ module SDK module Trace # {Tracer} is the SDK implementation of {OpenTelemetry::Trace::Tracer}. class Tracer < OpenTelemetry::Trace::Tracer - attr_reader :name - attr_reader :version + attr_reader :resource # @api private # # Returns a new {Tracer} instance. # - # @param [String] name Instrumentation package name - # @param [String] version Instrumentation package version + # @param [Resource] resource Containing name and version arguments supplied to the TracerProvider # # @return [Tracer] def initialize(name, version) diff --git a/sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb b/sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb index d7da2f1b9..80feb5dc3 100644 --- a/sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb +++ b/sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb @@ -20,13 +20,14 @@ class TracerProvider < OpenTelemetry::Trace::TracerProvider # Returns a new {TracerProvider} instance. # # @return [TracerProvider] - def initialize + def initialize(resource = OpenTelemetry::SDK::Resources::Resource.create) @mutex = Mutex.new @registry = {} @active_span_processor = NoopSpanProcessor.instance @active_trace_config = Config::TraceConfig::DEFAULT @registered_span_processors = [] @stopped = false + @resource = resource end # Returns a {Tracer} instance. @@ -38,7 +39,8 @@ def initialize def tracer(name = nil, version = nil) name ||= '' version ||= '' - @mutex.synchronize { @registry[Key.new(name, version)] ||= Tracer.new(name, version) } + resource = @resource.merge(OpenTelemetry::SDK::Resources::Resource.create('name' => name, 'version' => version)) + @mutex.synchronize { @registry[Key.new(name, version)] ||= Tracer.new(resource) } end # Attempts to stop all the activity for this {Tracer}. Calls diff --git a/sdk/opentelemetry-sdk.gemspec b/sdk/opentelemetry-sdk.gemspec index 4e2e4a40d..a84b9981a 100644 --- a/sdk/opentelemetry-sdk.gemspec +++ b/sdk/opentelemetry-sdk.gemspec @@ -26,6 +26,7 @@ Gem::Specification.new do |spec| spec.required_ruby_version = '>= 2.5.0' spec.add_dependency 'opentelemetry-api', '~> 0.4.0' + spec.add_dependency 'google-cloud-env' spec.add_development_dependency 'bundler', '>= 1.17' spec.add_development_dependency 'faraday', '~> 0.13' diff --git a/sdk/test/opentelemetry/sdk/resources/auto_detector_test.rb b/sdk/test/opentelemetry/sdk/resources/auto_detector_test.rb new file mode 100644 index 000000000..45fc3453f --- /dev/null +++ b/sdk/test/opentelemetry/sdk/resources/auto_detector_test.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +require 'test_helper' + +describe OpenTelemetry::SDK::Resources::AutoDetector do + let(:auto_detector) { OpenTelemetry::SDK::Resources::AutoDetector } + let(:detected_resource) { auto_detector.detect } + let(:detected_resource_labels) { detected_resource.label_enumerator.to_h } + let(:expected_resource_labels) do + { + 'telemetry.sdk.name' => 'OpenTelemetry', + 'telemetry.sdk.language' => 'ruby', + 'telemetry.sdk.version' => 'semver:0.4.0' + } + end + + describe '.detect' do + it 'returns detected resources' do + _(detected_resource).must_be_instance_of(OpenTelemetry::SDK::Resources::Resource) + _(detected_resource_labels).must_equal(expected_resource_labels) + end + end +end diff --git a/sdk/test/opentelemetry/sdk/resources/detectors/google_cloud_platform_test.rb b/sdk/test/opentelemetry/sdk/resources/detectors/google_cloud_platform_test.rb new file mode 100644 index 000000000..30b78116b --- /dev/null +++ b/sdk/test/opentelemetry/sdk/resources/detectors/google_cloud_platform_test.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +require 'test_helper' + +describe OpenTelemetry::SDK::Resources::Detectors::GoogleCloudPlatform do + let(:detector) { OpenTelemetry::SDK::Resources::Detectors::GoogleCloudPlatform } + + describe '.detect' do + let(:detected_resource) { detector.detect } + let(:detected_resource_labels) { detected_resource.label_enumerator.to_h } + let(:expected_resource_labels) { {} } + + it 'returns an empty resource' do + _(detected_resource).must_be_instance_of(OpenTelemetry::SDK::Resources::Resource) + _(detected_resource_labels).must_equal(expected_resource_labels) + end + + describe 'when in a gcp environment' do + before do + mock = MiniTest::Mock.new + mock.expect(:compute_engine?, true) + mock.expect(:project_id, 'opentelemetry') + mock.expect(:instance_attribute, 'us-central1', %w(cluster-location)) + mock.expect(:instance_zone, 'us-central1-a') + mock.expect(:lookup_metadata, 'opentelemetry-test', %w(instance id)) + mock.expect(:lookup_metadata, 'opentelemetry-test', %w(instance hostname)) + mock.expect(:instance_attribute, 'opentelemetry-cluster', %w(cluster-name)) + mock.expect(:kubernetes_engine?, true) + mock.expect(:kubernetes_engine_namespace_id, 'default') + + with_env('HOSTNAME' => 'opentelemetry-test') do + Google::Cloud::Env.stub(:new, mock) { detected_resource } + end + end + + let(:expected_resource_labels) do + { + 'cloud.provider' => 'gcp', + 'cloud.account.id' => 'opentelemetry', + 'cloud.region' => 'us-central1', + 'cloud.zone' => 'us-central1-a', + 'host.hostname' => 'opentelemetry-test', + 'host.id' => 'opentelemetry-test', + 'host.name' => 'opentelemetry-test', + 'k8s.cluster.name' => 'opentelemetry-cluster', + 'k8s.namespace.name' => 'default', + 'k8s.pod.name' => 'opentelemetry-test', + 'container.name' => '' + } + end + + it 'returns a resource with gcp attributes' do + _(detected_resource).must_be_instance_of(OpenTelemetry::SDK::Resources::Resource) + _(detected_resource_labels).must_equal(expected_resource_labels) + end + end + end +end diff --git a/sdk/test/opentelemetry/sdk/resources/detectors/telemetry_test.rb b/sdk/test/opentelemetry/sdk/resources/detectors/telemetry_test.rb new file mode 100644 index 000000000..8b51dce81 --- /dev/null +++ b/sdk/test/opentelemetry/sdk/resources/detectors/telemetry_test.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +require 'test_helper' + +describe OpenTelemetry::SDK::Resources::Detectors::Telemetry do + let(:detector) { OpenTelemetry::SDK::Resources::Detectors::Telemetry } + + describe '.detect' do + let(:detected_resource) { detector.detect } + let(:detected_resource_labels) { detected_resource.label_enumerator.to_h } + let(:expected_resource_labels) do + { + 'telemetry.sdk.name' => 'OpenTelemetry', + 'telemetry.sdk.language' => 'ruby', + 'telemetry.sdk.version' => 'semver:0.4.0' + } + end + + it 'returns a resource with telemetry attributes' do + _(detected_resource).must_be_instance_of(OpenTelemetry::SDK::Resources::Resource) + _(detected_resource_labels).must_equal(expected_resource_labels) + end + end +end diff --git a/sdk/test/opentelemetry/sdk/trace/tracer_provider_test.rb b/sdk/test/opentelemetry/sdk/trace/tracer_provider_test.rb index bc5ad920f..59508e725 100644 --- a/sdk/test/opentelemetry/sdk/trace/tracer_provider_test.rb +++ b/sdk/test/opentelemetry/sdk/trace/tracer_provider_test.rb @@ -86,8 +86,7 @@ it 'returns a default name-less version-less tracer' do tracer = tracer_provider.tracer - _(tracer.name).must_equal('') - _(tracer.version).must_equal('') + _(tracer.resource.label_enumerator.to_h).must_equal('name' => '', 'version' => '') end it 'returns different tracers for different names' do diff --git a/sdk/test/opentelemetry/sdk/trace/tracer_test.rb b/sdk/test/opentelemetry/sdk/trace/tracer_test.rb index 5cca8540d..0c25c2141 100644 --- a/sdk/test/opentelemetry/sdk/trace/tracer_test.rb +++ b/sdk/test/opentelemetry/sdk/trace/tracer_test.rb @@ -18,15 +18,11 @@ Samplers::ConstantSampler.new(result: Result.new(decision: Decision::RECORD), description: 'RecordSampler') end - describe '#name' do - it 'reflects the name passed in' do - _(Tracer.new('component', 'semver:1.0').name).must_equal('component') - end - end + describe '#resource' do + let(:resource) { OpenTelemetry::SDK::Resources::Resource.create('name' => 'component', 'version' => 'semver:1.0') } - describe '#version' do - it 'reflects the version passed in' do - _(Tracer.new('component', 'semver:1.0').version).must_equal('semver:1.0') + it 'reflects the resource passed in' do + _(Tracer.new(resource).resource).must_equal(resource) end end diff --git a/sdk/test/test_helper.rb b/sdk/test/test_helper.rb index 7f8aa09ad..0d1fe14a8 100644 --- a/sdk/test/test_helper.rb +++ b/sdk/test/test_helper.rb @@ -12,3 +12,12 @@ require 'minitest/autorun' OpenTelemetry.logger = Logger.new('/dev/null') + +def with_env(new_env) + env_to_reset = ENV.select { |k, _| new_env.key?(k) } + keys_to_delete = new_env.keys - ENV.keys + new_env.each_pair { |k, v| ENV[k] = v } + yield + env_to_reset.each_pair { |k, v| ENV[k] = v } + keys_to_delete.each { |k| ENV.delete(k) } +end From eefd0fdb2fe44762a7a3ad5fc8e196c6f7aa6890 Mon Sep 17 00:00:00 2001 From: Robert Laurin Date: Thu, 14 May 2020 13:58:56 -0400 Subject: [PATCH 02/13] Fix typo typo in correlation context module --- sdk/lib/opentelemetry/sdk/correlation_context.rb | 2 +- sdk/lib/opentelemetry/sdk/resources/auto_detector.rb | 2 +- .../sdk/resources/detectors/google_cloud_platform.rb | 2 +- sdk/opentelemetry-sdk.gemspec | 2 +- .../sdk/resources/detectors/google_cloud_platform_test.rb | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sdk/lib/opentelemetry/sdk/correlation_context.rb b/sdk/lib/opentelemetry/sdk/correlation_context.rb index 2b0976846..66508368d 100644 --- a/sdk/lib/opentelemetry/sdk/correlation_context.rb +++ b/sdk/lib/opentelemetry/sdk/correlation_context.rb @@ -9,7 +9,7 @@ module OpenTelemetry module SDK - # Contains operational implementataions of the CorrelationContext::Manager + # Contains operational implementations of the CorrelationContext::Manager module CorrelationContext end end diff --git a/sdk/lib/opentelemetry/sdk/resources/auto_detector.rb b/sdk/lib/opentelemetry/sdk/resources/auto_detector.rb index 961f97c26..26d8bd503 100644 --- a/sdk/lib/opentelemetry/sdk/resources/auto_detector.rb +++ b/sdk/lib/opentelemetry/sdk/resources/auto_detector.rb @@ -17,7 +17,7 @@ module AutoDetector DETECTORS = [ OpenTelemetry::SDK::Resources::Detectors::GoogleCloudPlatform, OpenTelemetry::SDK::Resources::Detectors::Telemetry - ] + ].freeze def detect resources = DETECTORS.map(&:detect) diff --git a/sdk/lib/opentelemetry/sdk/resources/detectors/google_cloud_platform.rb b/sdk/lib/opentelemetry/sdk/resources/detectors/google_cloud_platform.rb index 34bcdaa37..33cfd68d1 100644 --- a/sdk/lib/opentelemetry/sdk/resources/detectors/google_cloud_platform.rb +++ b/sdk/lib/opentelemetry/sdk/resources/detectors/google_cloud_platform.rb @@ -44,7 +44,7 @@ def detect def hostname ENV['HOSTNAME'] || `hostname`&.strip - rescue StandardError => e + rescue StandardError '' end end diff --git a/sdk/opentelemetry-sdk.gemspec b/sdk/opentelemetry-sdk.gemspec index a84b9981a..40445ef28 100644 --- a/sdk/opentelemetry-sdk.gemspec +++ b/sdk/opentelemetry-sdk.gemspec @@ -25,8 +25,8 @@ Gem::Specification.new do |spec| spec.require_paths = ['lib'] spec.required_ruby_version = '>= 2.5.0' - spec.add_dependency 'opentelemetry-api', '~> 0.4.0' spec.add_dependency 'google-cloud-env' + spec.add_dependency 'opentelemetry-api', '~> 0.4.0' spec.add_development_dependency 'bundler', '>= 1.17' spec.add_development_dependency 'faraday', '~> 0.13' diff --git a/sdk/test/opentelemetry/sdk/resources/detectors/google_cloud_platform_test.rb b/sdk/test/opentelemetry/sdk/resources/detectors/google_cloud_platform_test.rb index 30b78116b..f6ab7da51 100644 --- a/sdk/test/opentelemetry/sdk/resources/detectors/google_cloud_platform_test.rb +++ b/sdk/test/opentelemetry/sdk/resources/detectors/google_cloud_platform_test.rb @@ -24,11 +24,11 @@ mock = MiniTest::Mock.new mock.expect(:compute_engine?, true) mock.expect(:project_id, 'opentelemetry') - mock.expect(:instance_attribute, 'us-central1', %w(cluster-location)) + mock.expect(:instance_attribute, 'us-central1', %w[cluster-location]) mock.expect(:instance_zone, 'us-central1-a') - mock.expect(:lookup_metadata, 'opentelemetry-test', %w(instance id)) - mock.expect(:lookup_metadata, 'opentelemetry-test', %w(instance hostname)) - mock.expect(:instance_attribute, 'opentelemetry-cluster', %w(cluster-name)) + mock.expect(:lookup_metadata, 'opentelemetry-test', %w[instance id]) + mock.expect(:lookup_metadata, 'opentelemetry-test', %w[instance hostname]) + mock.expect(:instance_attribute, 'opentelemetry-cluster', %w[cluster-name]) mock.expect(:kubernetes_engine?, true) mock.expect(:kubernetes_engine_namespace_id, 'default') From eafa97fa081ab25fadc9a2b6c9a0ca6dd9a1a2d3 Mon Sep 17 00:00:00 2001 From: Robert Laurin Date: Wed, 20 May 2020 17:41:37 -0400 Subject: [PATCH 03/13] Extract resource detection into a gem To avoid introducing third party dependencies to the SDK for optional functionality resource detection has been extracted into its own gem. --- resource-detectors/.rubocop.yml | 26 +++ resource-detectors/Gemfile | 14 ++ resource-detectors/LICENSE | 201 ++++++++++++++++++ resource-detectors/README.md | 35 +++ resource-detectors/Rakefile | 30 +++ .../lib/opentelemetry/resource/detectors.rb | 19 ++ .../resource/detectors}/auto_detector.rb | 14 +- .../detectors/google_cloud_platform.rb | 54 +++++ .../resource/detectors/version.rb | 13 ++ .../opentelemetry-resource-detectors.gemspec | 37 ++++ .../detectors}/auto_detector_test.rb | 12 +- .../detectors/google_cloud_platform_test.rb | 79 +++++++ resource-detectors/test/test_helper.rb | 12 ++ sdk/lib/opentelemetry/sdk/resources.rb | 1 - .../opentelemetry/sdk/resources/constants.rb | 166 ++++++++------- .../detectors/google_cloud_platform.rb | 54 ----- .../sdk/resources/detectors/telemetry.rb | 26 --- sdk/opentelemetry-sdk.gemspec | 1 - .../detectors/google_cloud_platform_test.rb | 62 ------ .../sdk/resources/detectors/telemetry_test.rb | 28 --- sdk/test/test_helper.rb | 9 - 21 files changed, 612 insertions(+), 281 deletions(-) create mode 100644 resource-detectors/.rubocop.yml create mode 100644 resource-detectors/Gemfile create mode 100644 resource-detectors/LICENSE create mode 100644 resource-detectors/README.md create mode 100644 resource-detectors/Rakefile create mode 100644 resource-detectors/lib/opentelemetry/resource/detectors.rb rename {sdk/lib/opentelemetry/sdk/resources => resource-detectors/lib/opentelemetry/resource/detectors}/auto_detector.rb (54%) create mode 100644 resource-detectors/lib/opentelemetry/resource/detectors/google_cloud_platform.rb create mode 100644 resource-detectors/lib/opentelemetry/resource/detectors/version.rb create mode 100644 resource-detectors/opentelemetry-resource-detectors.gemspec rename {sdk/test/opentelemetry/sdk/resources => resource-detectors/test/opentelemetry/detectors}/auto_detector_test.rb (61%) create mode 100644 resource-detectors/test/opentelemetry/detectors/google_cloud_platform_test.rb create mode 100644 resource-detectors/test/test_helper.rb delete mode 100644 sdk/lib/opentelemetry/sdk/resources/detectors/google_cloud_platform.rb delete mode 100644 sdk/lib/opentelemetry/sdk/resources/detectors/telemetry.rb delete mode 100644 sdk/test/opentelemetry/sdk/resources/detectors/google_cloud_platform_test.rb delete mode 100644 sdk/test/opentelemetry/sdk/resources/detectors/telemetry_test.rb diff --git a/resource-detectors/.rubocop.yml b/resource-detectors/.rubocop.yml new file mode 100644 index 000000000..7de9ab67f --- /dev/null +++ b/resource-detectors/.rubocop.yml @@ -0,0 +1,26 @@ +AllCops: + TargetRubyVersion: '2.5.0' + +Bundler/OrderedGems: + Exclude: + - gemfiles/**/* +Lint/UnusedMethodArgument: + Enabled: false +Metrics/AbcSize: + Max: 18 +Metrics/LineLength: + Enabled: false +Metrics/MethodLength: + Max: 20 +Metrics/ParameterLists: + Enabled: false +Style/FrozenStringLiteralComment: + Exclude: + - gemfiles/**/* +Style/ModuleFunction: + Enabled: false +Style/StringLiterals: + Exclude: + - gemfiles/**/* +Metrics/BlockLength: + Enabled: false diff --git a/resource-detectors/Gemfile b/resource-detectors/Gemfile new file mode 100644 index 000000000..eb2f2f9b3 --- /dev/null +++ b/resource-detectors/Gemfile @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +source 'https://rubygems.org' + +gemspec + +group :development, :test do + gem 'byebug' + gem 'pry' +end diff --git a/resource-detectors/LICENSE b/resource-detectors/LICENSE new file mode 100644 index 000000000..b7fbe3acd --- /dev/null +++ b/resource-detectors/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 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. diff --git a/resource-detectors/README.md b/resource-detectors/README.md new file mode 100644 index 000000000..c3f901107 --- /dev/null +++ b/resource-detectors/README.md @@ -0,0 +1,35 @@ +# Opentelemetry::Resource::Detectors + +Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/opentelemetry/resource/detectors`. To experiment with that code, run `bin/console` for an interactive prompt. + +TODO: Delete this and the text above, and describe your gem + +## Installation + +Add this line to your application's Gemfile: + +```ruby +gem 'opentelemetry-resource-detectors' +``` + +And then execute: + + $ bundle + +Or install it yourself as: + + $ gem install opentelemetry-resource-detectors + +## Usage + +TODO: Write usage instructions here + +## Development + +After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment. + +To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). + +## Contributing + +Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/opentelemetry-resource-detectors. diff --git a/resource-detectors/Rakefile b/resource-detectors/Rakefile new file mode 100644 index 000000000..a9de14408 --- /dev/null +++ b/resource-detectors/Rakefile @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +# Copyright 2020 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +require 'bundler/gem_tasks' +require 'rake/testtask' +require 'yard' +require 'rubocop/rake_task' + +RuboCop::RakeTask.new + +Rake::TestTask.new :test do |t| + t.libs << '../sdk/lib' + t.libs << '../api/lib' + t.libs << 'test' + t.libs << 'lib' + t.test_files = FileList['test/**/*_test.rb'] +end + +YARD::Rake::YardocTask.new do |t| + t.stats_options = ['--list-undoc'] +end + +if RUBY_ENGINE == 'truffleruby' + task default: %i[test] +else + task default: %i[test rubocop yard] +end diff --git a/resource-detectors/lib/opentelemetry/resource/detectors.rb b/resource-detectors/lib/opentelemetry/resource/detectors.rb new file mode 100644 index 000000000..b86b19e82 --- /dev/null +++ b/resource-detectors/lib/opentelemetry/resource/detectors.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +require 'opentelemetry/sdk' +require 'opentelemetry/resource/detectors/version' +require 'opentelemetry/resource/detectors/google_cloud_platform' +require 'opentelemetry/resource/detectors/auto_detector' + +module OpenTelemetry + module Resource + # Detectors contains the resource detectors as well as the AutoDetector + # that can run all the detectors and return an accumlated resource + module Detectors + end + end +end diff --git a/sdk/lib/opentelemetry/sdk/resources/auto_detector.rb b/resource-detectors/lib/opentelemetry/resource/detectors/auto_detector.rb similarity index 54% rename from sdk/lib/opentelemetry/sdk/resources/auto_detector.rb rename to resource-detectors/lib/opentelemetry/resource/detectors/auto_detector.rb index 26d8bd503..12f5ac832 100644 --- a/sdk/lib/opentelemetry/sdk/resources/auto_detector.rb +++ b/resource-detectors/lib/opentelemetry/resource/detectors/auto_detector.rb @@ -4,25 +4,21 @@ # # SPDX-License-Identifier: Apache-2.0 -require 'opentelemetry/sdk/resources/detectors/google_cloud_platform' -require 'opentelemetry/sdk/resources/detectors/telemetry' - module OpenTelemetry - module SDK - module Resources + module Resource + module Detectors # AutoDetector contains detect class method for running all detectors module AutoDetector extend self DETECTORS = [ - OpenTelemetry::SDK::Resources::Detectors::GoogleCloudPlatform, - OpenTelemetry::SDK::Resources::Detectors::Telemetry + OpenTelemetry::Resource::Detectors::GoogleCloudPlatform ].freeze def detect resources = DETECTORS.map(&:detect) - resources.reduce(OpenTelemetry::SDK::Resources::Resource.create) do |empty_resource, detected_resource| - empty_resource.merge(detected_resource) + resources.reduce(OpenTelemetry::SDK::Resources::Resource.create) do |accumulated, detected| + accumulated.merge(detected) end end end diff --git a/resource-detectors/lib/opentelemetry/resource/detectors/google_cloud_platform.rb b/resource-detectors/lib/opentelemetry/resource/detectors/google_cloud_platform.rb new file mode 100644 index 000000000..e9ff7359e --- /dev/null +++ b/resource-detectors/lib/opentelemetry/resource/detectors/google_cloud_platform.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +require 'google-cloud-env' + +module OpenTelemetry + module Resource + module Detectors + # GoogleCloudPlatform contains detect class method for determining gcp environment resource labels + module GoogleCloudPlatform + extend self + + def detect # rubocop:disable Metrics/AbcSize + gcp_env = Google::Cloud::Env.new + resource_labels = {} + resource_constants = OpenTelemetry::SDK::Resources::Constants + + if gcp_env.compute_engine? + resource_labels[resource_constants::CLOUD_RESOURCE[:provider]] = 'gcp' + resource_labels[resource_constants::CLOUD_RESOURCE[:account_id]] = gcp_env.project_id + resource_labels[resource_constants::CLOUD_RESOURCE[:region]] = gcp_env.instance_attribute('cluster-location') + resource_labels[resource_constants::CLOUD_RESOURCE[:zone]] = gcp_env.instance_zone + + resource_labels[resource_constants::HOST_RESOURCE[:hostname]] = hostname + resource_labels[resource_constants::HOST_RESOURCE[:id]] = gcp_env.lookup_metadata('instance', 'id') + resource_labels[resource_constants::HOST_RESOURCE[:name]] = gcp_env.lookup_metadata('instance', 'hostname') + end + + if gcp_env.kubernetes_engine? + resource_labels[resource_constants::K8S_RESOURCE[:cluster_name]] = gcp_env.instance_attribute('cluster-name') + resource_labels[resource_constants::K8S_RESOURCE[:namespace_name]] = gcp_env.kubernetes_engine_namespace_id + resource_labels[resource_constants::K8S_RESOURCE[:pod_name]] = hostname + + resource_labels[resource_constants::CONTAINER_RESOURCE[:name]] = ENV['CONTAINER_NAME'] + end + + resource_labels.delete_if { |_key, value| value.nil? || value.empty? } + OpenTelemetry::SDK::Resources::Resource.create(resource_labels) + end + + private + + def hostname + ENV['HOSTNAME'] || Socket.gethostname + rescue StandardError + '' + end + end + end + end +end diff --git a/resource-detectors/lib/opentelemetry/resource/detectors/version.rb b/resource-detectors/lib/opentelemetry/resource/detectors/version.rb new file mode 100644 index 000000000..c422b3ad6 --- /dev/null +++ b/resource-detectors/lib/opentelemetry/resource/detectors/version.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +module OpenTelemetry + module Resource + module Detectors + VERSION = '0.0.0' + end + end +end diff --git a/resource-detectors/opentelemetry-resource-detectors.gemspec b/resource-detectors/opentelemetry-resource-detectors.gemspec new file mode 100644 index 000000000..d612ebf19 --- /dev/null +++ b/resource-detectors/opentelemetry-resource-detectors.gemspec @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +# Copyright 2020 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +lib = File.expand_path('lib', __dir__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require 'opentelemetry/resource/detectors/version' + +Gem::Specification.new do |spec| + spec.name = 'opentelemetry-resource-detectors' + spec.version = OpenTelemetry::Resource::Detectors::VERSION + spec.authors = ['OpenTelemetry Authors'] + spec.email = ['cncf-opentelemetry-contributors@lists.cncf.io'] + + spec.summary = 'Resource detection helpers for OpenTelemetry' + spec.description = 'Resource detection helpers for OpenTelemetry' + spec.homepage = 'https://github.com/open-telemetry/opentelemetry-ruby' + spec.license = 'Apache-2.0' + + spec.files = ::Dir.glob('lib/**/*.rb') + + ::Dir.glob('*.md') + + ['LICENSE', '.yardopts'] + spec.require_paths = ['lib'] + spec.required_ruby_version = '>= 2.5.0' + + spec.add_dependency 'google-cloud-env' + + spec.add_development_dependency 'bundler', '>= 1.17' + spec.add_development_dependency 'minitest', '~> 5.0' + spec.add_development_dependency 'rake', '~> 12.0' + spec.add_development_dependency 'rubocop', '~> 0.73.0' + spec.add_development_dependency 'simplecov', '~> 0.17' + spec.add_development_dependency 'yard', '~> 0.9' + spec.add_development_dependency 'yard-doctest', '~> 0.1.6' +end diff --git a/sdk/test/opentelemetry/sdk/resources/auto_detector_test.rb b/resource-detectors/test/opentelemetry/detectors/auto_detector_test.rb similarity index 61% rename from sdk/test/opentelemetry/sdk/resources/auto_detector_test.rb rename to resource-detectors/test/opentelemetry/detectors/auto_detector_test.rb index 45fc3453f..bcff0aa06 100644 --- a/sdk/test/opentelemetry/sdk/resources/auto_detector_test.rb +++ b/resource-detectors/test/opentelemetry/detectors/auto_detector_test.rb @@ -6,17 +6,11 @@ require 'test_helper' -describe OpenTelemetry::SDK::Resources::AutoDetector do - let(:auto_detector) { OpenTelemetry::SDK::Resources::AutoDetector } +describe OpenTelemetry::Resource::Detectors::AutoDetector do + let(:auto_detector) { OpenTelemetry::Resource::Detectors::AutoDetector } let(:detected_resource) { auto_detector.detect } let(:detected_resource_labels) { detected_resource.label_enumerator.to_h } - let(:expected_resource_labels) do - { - 'telemetry.sdk.name' => 'OpenTelemetry', - 'telemetry.sdk.language' => 'ruby', - 'telemetry.sdk.version' => 'semver:0.4.0' - } - end + let(:expected_resource_labels) { {} } describe '.detect' do it 'returns detected resources' do diff --git a/resource-detectors/test/opentelemetry/detectors/google_cloud_platform_test.rb b/resource-detectors/test/opentelemetry/detectors/google_cloud_platform_test.rb new file mode 100644 index 000000000..074476e96 --- /dev/null +++ b/resource-detectors/test/opentelemetry/detectors/google_cloud_platform_test.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +require 'test_helper' + +describe OpenTelemetry::Resource::Detectors::GoogleCloudPlatform do + let(:detector) { OpenTelemetry::Resource::Detectors::GoogleCloudPlatform } + + describe '.detect' do + let(:detected_resource) { detector.detect } + let(:detected_resource_labels) { detected_resource.label_enumerator.to_h } + let(:expected_resource_labels) { {} } + + it 'returns an empty resource' do + _(detected_resource).must_be_instance_of(OpenTelemetry::SDK::Resources::Resource) + _(detected_resource_labels).must_equal(expected_resource_labels) + end + + describe 'when in a gcp environment' do + let(:project_id) { 'opentelemetry' } + + before do + gcp_env_mock = MiniTest::Mock.new + gcp_env_mock.expect(:compute_engine?, true) + gcp_env_mock.expect(:project_id, project_id) + gcp_env_mock.expect(:instance_attribute, 'us-central1', %w[cluster-location]) + gcp_env_mock.expect(:instance_zone, 'us-central1-a') + gcp_env_mock.expect(:lookup_metadata, 'opentelemetry-test', %w[instance id]) + gcp_env_mock.expect(:lookup_metadata, 'opentelemetry-test', %w[instance hostname]) + gcp_env_mock.expect(:instance_attribute, 'opentelemetry-cluster', %w[cluster-name]) + gcp_env_mock.expect(:kubernetes_engine?, true) + gcp_env_mock.expect(:kubernetes_engine_namespace_id, 'default') + + Socket.stub(:gethostname, 'opentelemetry-test') do + Google::Cloud::Env.stub(:new, gcp_env_mock) { detected_resource } + end + end + + let(:expected_resource_labels) do + { + 'cloud.provider' => 'gcp', + 'cloud.account.id' => 'opentelemetry', + 'cloud.region' => 'us-central1', + 'cloud.zone' => 'us-central1-a', + 'host.hostname' => 'opentelemetry-test', + 'host.id' => 'opentelemetry-test', + 'host.name' => 'opentelemetry-test', + 'k8s.cluster.name' => 'opentelemetry-cluster', + 'k8s.namespace.name' => 'default', + 'k8s.pod.name' => 'opentelemetry-test' + } + end + + it 'returns a resource with gcp attributes' do + _(detected_resource).must_be_instance_of(OpenTelemetry::SDK::Resources::Resource) + _(detected_resource_labels).must_equal(expected_resource_labels) + end + + describe 'and a nil resource value is detected' do + let(:project_id) { nil } + + it 'returns a with that label' do + _(detected_resource_labels.key?('cloud.account.id')).must_equal(false) + end + end + + describe 'and an empty string resource value is detected' do + let(:project_id) { '' } + + it 'returns a with that label' do + _(detected_resource_labels.key?('cloud.account.id')).must_equal(false) + end + end + end + end +end diff --git a/resource-detectors/test/test_helper.rb b/resource-detectors/test/test_helper.rb new file mode 100644 index 000000000..cd4c67241 --- /dev/null +++ b/resource-detectors/test/test_helper.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +require 'simplecov' +SimpleCov.start + +require 'opentelemetry/resource/detectors' +require 'minitest/autorun' +require 'pry' diff --git a/sdk/lib/opentelemetry/sdk/resources.rb b/sdk/lib/opentelemetry/sdk/resources.rb index bea8fe9af..07a98dc47 100644 --- a/sdk/lib/opentelemetry/sdk/resources.rb +++ b/sdk/lib/opentelemetry/sdk/resources.rb @@ -14,4 +14,3 @@ module Resources require 'opentelemetry/sdk/resources/resource' require 'opentelemetry/sdk/resources/constants' -require 'opentelemetry/sdk/resources/auto_detector' diff --git a/sdk/lib/opentelemetry/sdk/resources/constants.rb b/sdk/lib/opentelemetry/sdk/resources/constants.rb index ef245731a..6a3cd7c28 100644 --- a/sdk/lib/opentelemetry/sdk/resources/constants.rb +++ b/sdk/lib/opentelemetry/sdk/resources/constants.rb @@ -7,116 +7,118 @@ module OpenTelemetry module SDK module Resources - # Attributes describing a service instance. - SERVICE_RESOURCE = { - # Logical name of the service. - name: 'service.name', + module Constants + # Attributes describing a service instance. + SERVICE_RESOURCE = { + # Logical name of the service. + name: 'service.name', - # A namespace for `service.name`. - namespace: 'service.namespace', + # A namespace for `service.name`. + namespace: 'service.namespace', - # The string ID of the service instance. - instance_id: 'service.instance.id', + # The string ID of the service instance. + instance_id: 'service.instance.id', - # The version string of the service API or implementation. - version: 'service.version' - }.freeze + # The version string of the service API or implementation. + version: 'service.version' + }.freeze - # Attributes describing the telemetry library. - TELEMETRY_SDK_RESOURCE = { - # The name of the telemetry library. - name: 'telemetry.sdk.name', + # Attributes describing the telemetry library. + TELEMETRY_SDK_RESOURCE = { + # The name of the telemetry library. + name: 'telemetry.sdk.name', - # The language of telemetry library and of the code instrumented with it. - language: 'telemetry.sdk.language', + # The language of telemetry library and of the code instrumented with it. + language: 'telemetry.sdk.language', - # The version string of the telemetry library - version: 'telemetry.sdk.version' - }.freeze + # The version string of the telemetry library + version: 'telemetry.sdk.version' + }.freeze - # Attributes defining a compute unit (e.g. Container, Process, Lambda - # Function). - CONTAINER_RESOURCE = { - # The container name. - name: 'container.name', + # Attributes defining a compute unit (e.g. Container, Process, Lambda + # Function). + CONTAINER_RESOURCE = { + # The container name. + name: 'container.name', - # The name of the image the container was built on. - image_name: 'container.image.name', + # The name of the image the container was built on. + image_name: 'container.image.name', - # The container image tag. - image_tag: 'container.image.tag' - }.freeze + # The container image tag. + image_tag: 'container.image.tag' + }.freeze - FAAS_RESOURCE = { - # The name of the function being executed. - name: 'faas.name', + FAAS_RESOURCE = { + # The name of the function being executed. + name: 'faas.name', - # The unique name of the function being executed. - id: 'faas.id', + # The unique name of the function being executed. + id: 'faas.id', - # The version string of the function being executed. - version: 'faas.version', + # The version string of the function being executed. + version: 'faas.version', - # The execution environment ID as a string. - instance: 'faas.instance' - }.freeze + # The execution environment ID as a string. + instance: 'faas.instance' + }.freeze - # Attributes defining a deployment service (e.g. Kubernetes). - K8S_RESOURCE = { - # The name of the cluster that the pod is running in. - cluster_name: 'k8s.cluster.name', + # Attributes defining a deployment service (e.g. Kubernetes). + K8S_RESOURCE = { + # The name of the cluster that the pod is running in. + cluster_name: 'k8s.cluster.name', - # The name of the namespace that the pod is running in. - namespace_name: 'k8s.namespace.name', + # The name of the namespace that the pod is running in. + namespace_name: 'k8s.namespace.name', - # The name of the pod. - pod_name: 'k8s.pod.name', + # The name of the pod. + pod_name: 'k8s.pod.name', - # The name of the deployment. - deployment_name: 'k8s.deployment.name' - }.freeze + # The name of the deployment. + deployment_name: 'k8s.deployment.name' + }.freeze - # Attributes defining a computing instance (e.g. host). - HOST_RESOURCE = { - # Hostname of the host. It contains what the hostname command returns on the - # host machine. - hostname: 'host.hostname', + # Attributes defining a computing instance (e.g. host). + HOST_RESOURCE = { + # Hostname of the host. It contains what the hostname command returns on the + # host machine. + hostname: 'host.hostname', - # Unique host id. For Cloud this must be the instance_id assigned by the - # cloud provider - id: 'host.id', + # Unique host id. For Cloud this must be the instance_id assigned by the + # cloud provider + id: 'host.id', - # Name of the host. It may contain what hostname returns on Unix systems, - # the fully qualified, or a name specified by the user. - name: 'host.name', + # Name of the host. It may contain what hostname returns on Unix systems, + # the fully qualified, or a name specified by the user. + name: 'host.name', - # Type of host. For Cloud this must be the machine type. - type: 'host.type', + # Type of host. For Cloud this must be the machine type. + type: 'host.type', - # Name of the VM image or OS install the host was instantiated from. - image_name: 'host.image.name', + # Name of the VM image or OS install the host was instantiated from. + image_name: 'host.image.name', - # VM image id. For Cloud, this value is from the provider. - image_id: 'host.image.id', + # VM image id. For Cloud, this value is from the provider. + image_id: 'host.image.id', - # The version string of the VM image. - image_version: 'host.image.version' - }.freeze + # The version string of the VM image. + image_version: 'host.image.version' + }.freeze - # Attributes defining a running environment (e.g. Cloud, Data Center). - CLOUD_RESOURCE = { - # Name of the cloud provider. Example values are aws, azure, gcp. - provider: 'cloud.provider', + # Attributes defining a running environment (e.g. Cloud, Data Center). + CLOUD_RESOURCE = { + # Name of the cloud provider. Example values are aws, azure, gcp. + provider: 'cloud.provider', - # The cloud account id used to identify different entities. - account_id: 'cloud.account.id', + # The cloud account id used to identify different entities. + account_id: 'cloud.account.id', - # A specific geographical location where different entities can run. - region: 'cloud.region', + # A specific geographical location where different entities can run. + region: 'cloud.region', - # Zones are a sub set of the region connected through low-latency links. - zone: 'cloud.zone' - }.freeze + # Zones are a sub set of the region connected through low-latency links. + zone: 'cloud.zone' + }.freeze + end end end end diff --git a/sdk/lib/opentelemetry/sdk/resources/detectors/google_cloud_platform.rb b/sdk/lib/opentelemetry/sdk/resources/detectors/google_cloud_platform.rb deleted file mode 100644 index 33cfd68d1..000000000 --- a/sdk/lib/opentelemetry/sdk/resources/detectors/google_cloud_platform.rb +++ /dev/null @@ -1,54 +0,0 @@ -# frozen_string_literal: true - -# Copyright 2019 OpenTelemetry Authors -# -# SPDX-License-Identifier: Apache-2.0 - -require 'google-cloud-env' - -module OpenTelemetry - module SDK - module Resources - module Detectors - # GoogleCloudPlatform contains detect class method for determining gcp environment resource labels - module GoogleCloudPlatform - extend self - - def detect - gcp_env = Google::Cloud::Env.new - resource_labels = {} - - if gcp_env.compute_engine? - resource_labels[CLOUD_RESOURCE[:provider]] = 'gcp' - resource_labels[CLOUD_RESOURCE[:account_id]] = gcp_env.project_id || '' - resource_labels[CLOUD_RESOURCE[:region]] = gcp_env.instance_attribute('cluster-location') || '' - resource_labels[CLOUD_RESOURCE[:zone]] = gcp_env.instance_zone || '' - - resource_labels[HOST_RESOURCE[:hostname]] = hostname - resource_labels[HOST_RESOURCE[:id]] = gcp_env.lookup_metadata('instance', 'id') || '' - resource_labels[HOST_RESOURCE[:name]] = gcp_env.lookup_metadata('instance', 'hostname') || '' - end - - if gcp_env.kubernetes_engine? - resource_labels[K8S_RESOURCE[:cluster_name]] = gcp_env.instance_attribute('cluster-name') || '' - resource_labels[K8S_RESOURCE[:namespace_name]] = gcp_env.kubernetes_engine_namespace_id || '' - resource_labels[K8S_RESOURCE[:pod_name]] = hostname - - resource_labels[CONTAINER_RESOURCE[:name]] = ENV['CONTAINER_NAME'] || '' - end - - Resource.create(resource_labels) - end - - private - - def hostname - ENV['HOSTNAME'] || `hostname`&.strip - rescue StandardError - '' - end - end - end - end - end -end diff --git a/sdk/lib/opentelemetry/sdk/resources/detectors/telemetry.rb b/sdk/lib/opentelemetry/sdk/resources/detectors/telemetry.rb deleted file mode 100644 index b028c9f32..000000000 --- a/sdk/lib/opentelemetry/sdk/resources/detectors/telemetry.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -# Copyright 2019 OpenTelemetry Authors -# -# SPDX-License-Identifier: Apache-2.0 - -module OpenTelemetry - module SDK - module Resources - module Detectors - # Telemetry contains detect class method for determining instrumentation resource labels - module Telemetry - extend self - - def detect - resource_labels = {} - resource_labels[TELEMETRY_SDK_RESOURCE[:name]] = 'OpenTelemetry' - resource_labels[TELEMETRY_SDK_RESOURCE[:language]] = 'ruby' - resource_labels[TELEMETRY_SDK_RESOURCE[:version]] = "semver:#{OpenTelemetry::SDK::VERSION}" - Resource.create(resource_labels) - end - end - end - end - end -end diff --git a/sdk/opentelemetry-sdk.gemspec b/sdk/opentelemetry-sdk.gemspec index 40445ef28..4e2e4a40d 100644 --- a/sdk/opentelemetry-sdk.gemspec +++ b/sdk/opentelemetry-sdk.gemspec @@ -25,7 +25,6 @@ Gem::Specification.new do |spec| spec.require_paths = ['lib'] spec.required_ruby_version = '>= 2.5.0' - spec.add_dependency 'google-cloud-env' spec.add_dependency 'opentelemetry-api', '~> 0.4.0' spec.add_development_dependency 'bundler', '>= 1.17' diff --git a/sdk/test/opentelemetry/sdk/resources/detectors/google_cloud_platform_test.rb b/sdk/test/opentelemetry/sdk/resources/detectors/google_cloud_platform_test.rb deleted file mode 100644 index f6ab7da51..000000000 --- a/sdk/test/opentelemetry/sdk/resources/detectors/google_cloud_platform_test.rb +++ /dev/null @@ -1,62 +0,0 @@ -# frozen_string_literal: true - -# Copyright 2019 OpenTelemetry Authors -# -# SPDX-License-Identifier: Apache-2.0 - -require 'test_helper' - -describe OpenTelemetry::SDK::Resources::Detectors::GoogleCloudPlatform do - let(:detector) { OpenTelemetry::SDK::Resources::Detectors::GoogleCloudPlatform } - - describe '.detect' do - let(:detected_resource) { detector.detect } - let(:detected_resource_labels) { detected_resource.label_enumerator.to_h } - let(:expected_resource_labels) { {} } - - it 'returns an empty resource' do - _(detected_resource).must_be_instance_of(OpenTelemetry::SDK::Resources::Resource) - _(detected_resource_labels).must_equal(expected_resource_labels) - end - - describe 'when in a gcp environment' do - before do - mock = MiniTest::Mock.new - mock.expect(:compute_engine?, true) - mock.expect(:project_id, 'opentelemetry') - mock.expect(:instance_attribute, 'us-central1', %w[cluster-location]) - mock.expect(:instance_zone, 'us-central1-a') - mock.expect(:lookup_metadata, 'opentelemetry-test', %w[instance id]) - mock.expect(:lookup_metadata, 'opentelemetry-test', %w[instance hostname]) - mock.expect(:instance_attribute, 'opentelemetry-cluster', %w[cluster-name]) - mock.expect(:kubernetes_engine?, true) - mock.expect(:kubernetes_engine_namespace_id, 'default') - - with_env('HOSTNAME' => 'opentelemetry-test') do - Google::Cloud::Env.stub(:new, mock) { detected_resource } - end - end - - let(:expected_resource_labels) do - { - 'cloud.provider' => 'gcp', - 'cloud.account.id' => 'opentelemetry', - 'cloud.region' => 'us-central1', - 'cloud.zone' => 'us-central1-a', - 'host.hostname' => 'opentelemetry-test', - 'host.id' => 'opentelemetry-test', - 'host.name' => 'opentelemetry-test', - 'k8s.cluster.name' => 'opentelemetry-cluster', - 'k8s.namespace.name' => 'default', - 'k8s.pod.name' => 'opentelemetry-test', - 'container.name' => '' - } - end - - it 'returns a resource with gcp attributes' do - _(detected_resource).must_be_instance_of(OpenTelemetry::SDK::Resources::Resource) - _(detected_resource_labels).must_equal(expected_resource_labels) - end - end - end -end diff --git a/sdk/test/opentelemetry/sdk/resources/detectors/telemetry_test.rb b/sdk/test/opentelemetry/sdk/resources/detectors/telemetry_test.rb deleted file mode 100644 index 8b51dce81..000000000 --- a/sdk/test/opentelemetry/sdk/resources/detectors/telemetry_test.rb +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: true - -# Copyright 2019 OpenTelemetry Authors -# -# SPDX-License-Identifier: Apache-2.0 - -require 'test_helper' - -describe OpenTelemetry::SDK::Resources::Detectors::Telemetry do - let(:detector) { OpenTelemetry::SDK::Resources::Detectors::Telemetry } - - describe '.detect' do - let(:detected_resource) { detector.detect } - let(:detected_resource_labels) { detected_resource.label_enumerator.to_h } - let(:expected_resource_labels) do - { - 'telemetry.sdk.name' => 'OpenTelemetry', - 'telemetry.sdk.language' => 'ruby', - 'telemetry.sdk.version' => 'semver:0.4.0' - } - end - - it 'returns a resource with telemetry attributes' do - _(detected_resource).must_be_instance_of(OpenTelemetry::SDK::Resources::Resource) - _(detected_resource_labels).must_equal(expected_resource_labels) - end - end -end diff --git a/sdk/test/test_helper.rb b/sdk/test/test_helper.rb index 0d1fe14a8..7f8aa09ad 100644 --- a/sdk/test/test_helper.rb +++ b/sdk/test/test_helper.rb @@ -12,12 +12,3 @@ require 'minitest/autorun' OpenTelemetry.logger = Logger.new('/dev/null') - -def with_env(new_env) - env_to_reset = ENV.select { |k, _| new_env.key?(k) } - keys_to_delete = new_env.keys - ENV.keys - new_env.each_pair { |k, v| ENV[k] = v } - yield - env_to_reset.each_pair { |k, v| ENV[k] = v } - keys_to_delete.each { |k| ENV.delete(k) } -end From 219f382118a72bbac7f06dcc2b6bfe5d02746a94 Mon Sep 17 00:00:00 2001 From: Robert Laurin Date: Wed, 20 May 2020 18:52:30 -0400 Subject: [PATCH 04/13] Add resource-detectors README --- resource-detectors/README.md | 58 +++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/resource-detectors/README.md b/resource-detectors/README.md index c3f901107..7d12fcb86 100644 --- a/resource-detectors/README.md +++ b/resource-detectors/README.md @@ -1,35 +1,59 @@ # Opentelemetry::Resource::Detectors -Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/opentelemetry/resource/detectors`. To experiment with that code, run `bin/console` for an interactive prompt. +The `opentelemetry-resource-detectors` gem provides resource detectors for OpenTelemetry. -TODO: Delete this and the text above, and describe your gem +## What is OpenTelemetry? -## Installation +[OpenTelemetry][opentelemetry-home] is an open source observability framework, providing a general-purpose API, SDK, and related tools required for the instrumentation of cloud-native software, frameworks, and libraries. -Add this line to your application's Gemfile: +OpenTelemetry provides a single set of APIs, libraries, agents, and collector services to capture distributed traces and metrics from your application. You can analyze them using Prometheus, Jaeger, and other observability tools. -```ruby -gem 'opentelemetry-resource-detectors' +## How does this gem fit in? + +The `opentelemetry-resource-detectors` gem provides a means of retrieving a [resource](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/resource/sdk.md) for supported environments following the [resource semantic conventions](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/resource/semantic_conventions/README.md). + +## How do I get started? + +Install the gem using: + +``` +gem install opentelemetry-sdk +gem install opentelemetry-resource-detectors ``` -And then execute: +Or, if you use [bundler][bundler-home], include `opentelemetry-sdk` and `opentelemetry-resource-detectors` in your `Gemfile`. - $ bundle +```rb +require 'opentelemetry/sdk' +require 'opentelemetry/resource/detectors' -Or install it yourself as: +# For a specific platform +OpenTelemetry::SDK.configure do |c| + c.resource = OpenTelemetry::Resource::Detectors::GoogleCloudPlatform.detect +end - $ gem install opentelemetry-resource-detectors +# Or if you would like for it to run all detectors available +OpenTelemetry::SDK.configure do |c| + c.resource = OpenTelemetry::Resource::Detectors::AutoDetector.detect +end +``` -## Usage +## How can I get involved? -TODO: Write usage instructions here +The `opentelemetry-resource-detectors` gem source is [on github][repo-github], along with related gems. -## Development +The OpenTelemetry Ruby gems are maintained by the OpenTelemetry-Ruby special interest group (SIG). You can get involved by joining us on our [gitter channel][ruby-gitter] or attending our weekly meeting. See the [meeting calendar][community-meetings] for dates and times. For more information on this and other language SIGs, see the OpenTelemetry [community page][ruby-sig]. -After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment. +## License -To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). +The `opentelemetry-resource-detectors` gem is distributed under the Apache 2.0 license. See [LICENSE][license-github] for more information. -## Contributing -Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/opentelemetry-resource-detectors. +[opentelemetry-home]: https://opentelemetry.io +[bundler-home]: https://bundler.io +[repo-github]: https://github.com/open-telemetry/opentelemetry-ruby +[license-github]: https://github.com/open-telemetry/opentelemetry-ruby/blob/master/LICENSE +[examples-github]: https://github.com/open-telemetry/opentelemetry-ruby/tree/master/examples +[ruby-sig]: https://github.com/open-telemetry/community#ruby-sig +[community-meetings]: https://github.com/open-telemetry/community#community-meetings +[ruby-gitter]: https://gitter.im/open-telemetry/opentelemetry-ruby From 794e73d3023a1c333dc17cd8004922e0b90f1ba6 Mon Sep 17 00:00:00 2001 From: Robert Laurin Date: Wed, 20 May 2020 20:14:54 -0400 Subject: [PATCH 05/13] Add default Telemetry SDK resource create method The specification requires a Telemetry::SDK resource, this adds a method for create it directly from the resource class. This also initializes it by default on the configurator. The resource setter on the configurator class will merge the default resource with the one provided. --- sdk/lib/opentelemetry/sdk/configurator.rb | 8 ++++++-- .../opentelemetry/sdk/resources/resource.rb | 10 +++++++++- .../opentelemetry/sdk/configurator_test.rb | 18 ++++++++++++++++++ .../sdk/resources/resource_test.rb | 9 +++++++++ 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/sdk/lib/opentelemetry/sdk/configurator.rb b/sdk/lib/opentelemetry/sdk/configurator.rb index 925a21fd6..96bb90acd 100644 --- a/sdk/lib/opentelemetry/sdk/configurator.rb +++ b/sdk/lib/opentelemetry/sdk/configurator.rb @@ -16,7 +16,7 @@ class Configurator # rubocop:disable Metrics/ClassLength private_constant :USE_MODE_UNSPECIFIED, :USE_MODE_ONE, :USE_MODE_ALL attr_writer :logger, :http_extractors, :http_injectors, :text_extractors, - :text_injectors, :resource + :text_injectors def initialize @adapter_names = [] @@ -27,13 +27,17 @@ def initialize @text_injectors = nil @span_processors = [] @use_mode = USE_MODE_UNSPECIFIED - @resource = OpenTelemetry::SDK::Resources::Resource.create + @resource = Resources::Resource.telemetry_sdk end def logger @logger ||= Logger.new(STDOUT) end + def resource=(new_resource) + @resource = @resource.merge(new_resource) + end + # Install an instrumentation adapter with specificied optional +config+. # Use can be called multiple times to install multiple instrumentation # adapters. Only +use+ or +use_all+, but not both when installing diff --git a/sdk/lib/opentelemetry/sdk/resources/resource.rb b/sdk/lib/opentelemetry/sdk/resources/resource.rb index ebaf32e37..0390383da 100644 --- a/sdk/lib/opentelemetry/sdk/resources/resource.rb +++ b/sdk/lib/opentelemetry/sdk/resources/resource.rb @@ -11,7 +11,7 @@ module Resources # for which telemetry (metrics or traces) is reported. class Resource class << self - private :new # rubocop:disable Style/AccessModifierDeclarations + private :new # Returns a newly created {Resource} with the specified labels # @@ -29,6 +29,14 @@ def create(labels = {}) new(frozen_labels) end + + def telemetry_sdk + create( + Constants::TELEMETRY_SDK_RESOURCE[:name] => 'opentelemetry', + Constants::TELEMETRY_SDK_RESOURCE[:language] => 'ruby', + Constants::TELEMETRY_SDK_RESOURCE[:version] => "semver:#{OpenTelemetry::SDK::VERSION}" + ) + end end # @api private diff --git a/sdk/test/opentelemetry/sdk/configurator_test.rb b/sdk/test/opentelemetry/sdk/configurator_test.rb index 26bf22b97..c332720b9 100644 --- a/sdk/test/opentelemetry/sdk/configurator_test.rb +++ b/sdk/test/opentelemetry/sdk/configurator_test.rb @@ -15,6 +15,24 @@ end end + describe '#resource=' do + let(:configurator_resource) { configurator.instance_variable_get(:@resource) } + let(:configurator_resource_labels) { configurator_resource.label_enumerator.to_h } + let(:expected_resource_labels) do + { + 'telemetry.sdk.name' => 'opentelemetry', + 'telemetry.sdk.language' => 'ruby', + 'telemetry.sdk.version' => "semver:#{OpenTelemetry::SDK::VERSION}", + 'test_key' => 'test_value' + } + end + + it 'merges the resource' do + configurator.resource = OpenTelemetry::SDK::Resources::Resource.create('test_key' => 'test_value') + _(configurator_resource_labels).must_equal(expected_resource_labels) + end + end + describe '#use' do it 'can be called multiple times' do configurator.use('TestAdapter', enabled: true) diff --git a/sdk/test/opentelemetry/sdk/resources/resource_test.rb b/sdk/test/opentelemetry/sdk/resources/resource_test.rb index 4896f02c1..e1d27be11 100644 --- a/sdk/test/opentelemetry/sdk/resources/resource_test.rb +++ b/sdk/test/opentelemetry/sdk/resources/resource_test.rb @@ -41,6 +41,15 @@ end end + describe '.telemetry_sdk' do + it 'returns a resource for the telemetry sdk' do + resource_labels = Resource.telemetry_sdk.label_enumerator.to_h + _(resource_labels['telemetry.sdk.name']).must_equal('opentelemetry') + _(resource_labels['telemetry.sdk.language']).must_equal('ruby') + _(resource_labels['telemetry.sdk.version']).must_match(/semver:\b\d{1,3}\.\d{1,3}\.\d{1,3}/) + end + end + describe '#merge' do it 'merges two resources into a third' do res1 = Resource.create('k1' => 'v1', 'k2' => 'v2') From 8cf9f9dfd30c073b4ce453c1b1ae658f9d6583f9 Mon Sep 17 00:00:00 2001 From: Robert Laurin Date: Wed, 20 May 2020 20:30:29 -0400 Subject: [PATCH 06/13] Add comment to disable Style/AccessModifierDeclarations in resource class --- sdk/lib/opentelemetry/sdk/resources/resource.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/lib/opentelemetry/sdk/resources/resource.rb b/sdk/lib/opentelemetry/sdk/resources/resource.rb index 0390383da..9981c96c2 100644 --- a/sdk/lib/opentelemetry/sdk/resources/resource.rb +++ b/sdk/lib/opentelemetry/sdk/resources/resource.rb @@ -11,7 +11,7 @@ module Resources # for which telemetry (metrics or traces) is reported. class Resource class << self - private :new + private :new # rubocop:disable Style/AccessModifierDeclarations # Returns a newly created {Resource} with the specified labels # From 22c047ea77b125fcee0198eda352cd19bc7c94cc Mon Sep 17 00:00:00 2001 From: Robert Laurin Date: Mon, 25 May 2020 12:05:09 -0400 Subject: [PATCH 07/13] Adjust tracer to use instrumentation library --- sdk/lib/opentelemetry/sdk/trace/tracer.rb | 9 +++++---- sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb | 6 ++---- sdk/test/opentelemetry/sdk/trace/tracer_provider_test.rb | 3 ++- sdk/test/opentelemetry/sdk/trace/tracer_test.rb | 8 -------- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/sdk/lib/opentelemetry/sdk/trace/tracer.rb b/sdk/lib/opentelemetry/sdk/trace/tracer.rb index 56f928e62..243bc74ee 100644 --- a/sdk/lib/opentelemetry/sdk/trace/tracer.rb +++ b/sdk/lib/opentelemetry/sdk/trace/tracer.rb @@ -9,19 +9,19 @@ module SDK module Trace # {Tracer} is the SDK implementation of {OpenTelemetry::Trace::Tracer}. class Tracer < OpenTelemetry::Trace::Tracer - attr_reader :resource + attr_reader :name + attr_reader :version # @api private # # Returns a new {Tracer} instance. # - # @param [Resource] resource Containing name and version arguments supplied to the TracerProvider + # @param [InstrumentationLibrary] resource Containing name and version arguments supplied to the TracerProvider # # @return [Tracer] def initialize(name, version) @name = name @version = version - @resource = Resources::Resource.create('name' => name, 'version' => version) @instrumentation_library = InstrumentationLibrary.new(name, version) end @@ -54,7 +54,8 @@ def internal_create_span(result, name, kind, trace_id, span_id, parent_span_id, attributes = attributes&.merge(result.attributes) || result.attributes active_trace_config = OpenTelemetry.tracer_provider.active_trace_config active_span_processor = OpenTelemetry.tracer_provider.active_span_processor - Span.new(context, name, kind, parent_span_id, active_trace_config, active_span_processor, attributes, links, start_timestamp || Time.now, @resource, @instrumentation_library) + resource = OpenTelemetry.tracer_provider.resource + Span.new(context, name, kind, parent_span_id, active_trace_config, active_span_processor, attributes, links, start_timestamp || Time.now, resource, @instrumentation_library) else OpenTelemetry::Trace::Span.new(span_context: OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id)) end diff --git a/sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb b/sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb index 80feb5dc3..ce0aeb43a 100644 --- a/sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb +++ b/sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb @@ -13,8 +13,7 @@ class TracerProvider < OpenTelemetry::Trace::TracerProvider private_constant(:Key) attr_accessor :active_trace_config - attr_reader :active_span_processor - attr_reader :stopped + attr_reader :active_span_processor, :stopped, :resource alias stopped? stopped # Returns a new {TracerProvider} instance. @@ -39,8 +38,7 @@ def initialize(resource = OpenTelemetry::SDK::Resources::Resource.create) def tracer(name = nil, version = nil) name ||= '' version ||= '' - resource = @resource.merge(OpenTelemetry::SDK::Resources::Resource.create('name' => name, 'version' => version)) - @mutex.synchronize { @registry[Key.new(name, version)] ||= Tracer.new(resource) } + @mutex.synchronize { @registry[Key.new(name, version)] ||= Tracer.new(name, version) } end # Attempts to stop all the activity for this {Tracer}. Calls diff --git a/sdk/test/opentelemetry/sdk/trace/tracer_provider_test.rb b/sdk/test/opentelemetry/sdk/trace/tracer_provider_test.rb index 59508e725..bc5ad920f 100644 --- a/sdk/test/opentelemetry/sdk/trace/tracer_provider_test.rb +++ b/sdk/test/opentelemetry/sdk/trace/tracer_provider_test.rb @@ -86,7 +86,8 @@ it 'returns a default name-less version-less tracer' do tracer = tracer_provider.tracer - _(tracer.resource.label_enumerator.to_h).must_equal('name' => '', 'version' => '') + _(tracer.name).must_equal('') + _(tracer.version).must_equal('') end it 'returns different tracers for different names' do diff --git a/sdk/test/opentelemetry/sdk/trace/tracer_test.rb b/sdk/test/opentelemetry/sdk/trace/tracer_test.rb index 0c25c2141..0a0d9ce0f 100644 --- a/sdk/test/opentelemetry/sdk/trace/tracer_test.rb +++ b/sdk/test/opentelemetry/sdk/trace/tracer_test.rb @@ -18,14 +18,6 @@ Samplers::ConstantSampler.new(result: Result.new(decision: Decision::RECORD), description: 'RecordSampler') end - describe '#resource' do - let(:resource) { OpenTelemetry::SDK::Resources::Resource.create('name' => 'component', 'version' => 'semver:1.0') } - - it 'reflects the resource passed in' do - _(Tracer.new(resource).resource).must_equal(resource) - end - end - describe '#start_root_span' do it 'provides a default name' do _(tracer.start_root_span(nil).name).wont_be_nil From 9e2bcd47ee53b80bd524f5946897c9baef322839 Mon Sep 17 00:00:00 2001 From: Robert Laurin Date: Mon, 25 May 2020 12:17:22 -0400 Subject: [PATCH 08/13] Re-add tracer_tests for name and version --- sdk/test/opentelemetry/sdk/trace/tracer_test.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sdk/test/opentelemetry/sdk/trace/tracer_test.rb b/sdk/test/opentelemetry/sdk/trace/tracer_test.rb index 0a0d9ce0f..5cca8540d 100644 --- a/sdk/test/opentelemetry/sdk/trace/tracer_test.rb +++ b/sdk/test/opentelemetry/sdk/trace/tracer_test.rb @@ -18,6 +18,18 @@ Samplers::ConstantSampler.new(result: Result.new(decision: Decision::RECORD), description: 'RecordSampler') end + describe '#name' do + it 'reflects the name passed in' do + _(Tracer.new('component', 'semver:1.0').name).must_equal('component') + end + end + + describe '#version' do + it 'reflects the version passed in' do + _(Tracer.new('component', 'semver:1.0').version).must_equal('semver:1.0') + end + end + describe '#start_root_span' do it 'provides a default name' do _(tracer.start_root_span(nil).name).wont_be_nil From c7e10c43e6b55182e1f1ab8be44676d41d91b0d7 Mon Sep 17 00:00:00 2001 From: Robert Laurin Date: Tue, 2 Jun 2020 13:26:34 -0400 Subject: [PATCH 09/13] Add method documentation, update comments Add resource documentation for configurator. Update comments for resource constants. Simplify resource merging in auto detector. --- .../lib/opentelemetry/resource/detectors/auto_detector.rb | 5 +---- sdk/lib/opentelemetry/sdk/configurator.rb | 5 +++++ sdk/lib/opentelemetry/sdk/resources/constants.rb | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/resource-detectors/lib/opentelemetry/resource/detectors/auto_detector.rb b/resource-detectors/lib/opentelemetry/resource/detectors/auto_detector.rb index 12f5ac832..ec3201428 100644 --- a/resource-detectors/lib/opentelemetry/resource/detectors/auto_detector.rb +++ b/resource-detectors/lib/opentelemetry/resource/detectors/auto_detector.rb @@ -16,10 +16,7 @@ module AutoDetector ].freeze def detect - resources = DETECTORS.map(&:detect) - resources.reduce(OpenTelemetry::SDK::Resources::Resource.create) do |accumulated, detected| - accumulated.merge(detected) - end + DETECTORS.map(&:detect).reduce(:merge) end end end diff --git a/sdk/lib/opentelemetry/sdk/configurator.rb b/sdk/lib/opentelemetry/sdk/configurator.rb index 96bb90acd..4dab018b6 100644 --- a/sdk/lib/opentelemetry/sdk/configurator.rb +++ b/sdk/lib/opentelemetry/sdk/configurator.rb @@ -34,6 +34,11 @@ def logger @logger ||= Logger.new(STDOUT) end + # Accepts a resource object that is merged with the default telemetry sdk + # resource. The use of this method is optional, and is provided as means + # to add additional resource information. + # + # @param [Resource] new_resource The resource to be merged def resource=(new_resource) @resource = @resource.merge(new_resource) end diff --git a/sdk/lib/opentelemetry/sdk/resources/constants.rb b/sdk/lib/opentelemetry/sdk/resources/constants.rb index 6a3cd7c28..8a02fdb6e 100644 --- a/sdk/lib/opentelemetry/sdk/resources/constants.rb +++ b/sdk/lib/opentelemetry/sdk/resources/constants.rb @@ -28,7 +28,7 @@ module Constants # The name of the telemetry library. name: 'telemetry.sdk.name', - # The language of telemetry library and of the code instrumented with it. + # The language of the telemetry library and of the code instrumented with it. language: 'telemetry.sdk.language', # The version string of the telemetry library From c986362fe4004bc04c364df40d82b99ddfd0b19f Mon Sep 17 00:00:00 2001 From: Robert Laurin Date: Tue, 16 Jun 2020 12:06:20 -0400 Subject: [PATCH 10/13] Update copyright year, revert incorrect comment --- resource-detectors/Gemfile | 2 +- resource-detectors/lib/opentelemetry/resource/detectors.rb | 2 +- .../lib/opentelemetry/resource/detectors/auto_detector.rb | 2 +- .../resource/detectors/google_cloud_platform.rb | 2 +- .../lib/opentelemetry/resource/detectors/version.rb | 2 +- .../test/opentelemetry/detectors/auto_detector_test.rb | 2 +- .../opentelemetry/detectors/google_cloud_platform_test.rb | 2 +- resource-detectors/test/test_helper.rb | 2 +- sdk/lib/opentelemetry/sdk/resources/constants.rb | 2 +- sdk/lib/opentelemetry/sdk/trace/tracer.rb | 5 +++-- 10 files changed, 12 insertions(+), 11 deletions(-) diff --git a/resource-detectors/Gemfile b/resource-detectors/Gemfile index eb2f2f9b3..4ef4addd6 100644 --- a/resource-detectors/Gemfile +++ b/resource-detectors/Gemfile @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright 2019 OpenTelemetry Authors +# Copyright 2020 OpenTelemetry Authors # # SPDX-License-Identifier: Apache-2.0 diff --git a/resource-detectors/lib/opentelemetry/resource/detectors.rb b/resource-detectors/lib/opentelemetry/resource/detectors.rb index b86b19e82..acb08aacd 100644 --- a/resource-detectors/lib/opentelemetry/resource/detectors.rb +++ b/resource-detectors/lib/opentelemetry/resource/detectors.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright 2019 OpenTelemetry Authors +# Copyright 2020 OpenTelemetry Authors # # SPDX-License-Identifier: Apache-2.0 diff --git a/resource-detectors/lib/opentelemetry/resource/detectors/auto_detector.rb b/resource-detectors/lib/opentelemetry/resource/detectors/auto_detector.rb index ec3201428..98cb23e69 100644 --- a/resource-detectors/lib/opentelemetry/resource/detectors/auto_detector.rb +++ b/resource-detectors/lib/opentelemetry/resource/detectors/auto_detector.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright 2019 OpenTelemetry Authors +# Copyright 2020 OpenTelemetry Authors # # SPDX-License-Identifier: Apache-2.0 diff --git a/resource-detectors/lib/opentelemetry/resource/detectors/google_cloud_platform.rb b/resource-detectors/lib/opentelemetry/resource/detectors/google_cloud_platform.rb index e9ff7359e..612e90fc8 100644 --- a/resource-detectors/lib/opentelemetry/resource/detectors/google_cloud_platform.rb +++ b/resource-detectors/lib/opentelemetry/resource/detectors/google_cloud_platform.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright 2019 OpenTelemetry Authors +# Copyright 2020 OpenTelemetry Authors # # SPDX-License-Identifier: Apache-2.0 diff --git a/resource-detectors/lib/opentelemetry/resource/detectors/version.rb b/resource-detectors/lib/opentelemetry/resource/detectors/version.rb index c422b3ad6..85a01c109 100644 --- a/resource-detectors/lib/opentelemetry/resource/detectors/version.rb +++ b/resource-detectors/lib/opentelemetry/resource/detectors/version.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright 2019 OpenTelemetry Authors +# Copyright 2020 OpenTelemetry Authors # # SPDX-License-Identifier: Apache-2.0 diff --git a/resource-detectors/test/opentelemetry/detectors/auto_detector_test.rb b/resource-detectors/test/opentelemetry/detectors/auto_detector_test.rb index bcff0aa06..ce2653089 100644 --- a/resource-detectors/test/opentelemetry/detectors/auto_detector_test.rb +++ b/resource-detectors/test/opentelemetry/detectors/auto_detector_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright 2019 OpenTelemetry Authors +# Copyright 2020 OpenTelemetry Authors # # SPDX-License-Identifier: Apache-2.0 diff --git a/resource-detectors/test/opentelemetry/detectors/google_cloud_platform_test.rb b/resource-detectors/test/opentelemetry/detectors/google_cloud_platform_test.rb index 074476e96..7fd5a8c0d 100644 --- a/resource-detectors/test/opentelemetry/detectors/google_cloud_platform_test.rb +++ b/resource-detectors/test/opentelemetry/detectors/google_cloud_platform_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright 2019 OpenTelemetry Authors +# Copyright 2020 OpenTelemetry Authors # # SPDX-License-Identifier: Apache-2.0 diff --git a/resource-detectors/test/test_helper.rb b/resource-detectors/test/test_helper.rb index cd4c67241..4d73d382e 100644 --- a/resource-detectors/test/test_helper.rb +++ b/resource-detectors/test/test_helper.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright 2019 OpenTelemetry Authors +# Copyright 2020 OpenTelemetry Authors # # SPDX-License-Identifier: Apache-2.0 diff --git a/sdk/lib/opentelemetry/sdk/resources/constants.rb b/sdk/lib/opentelemetry/sdk/resources/constants.rb index 8a02fdb6e..6f7637292 100644 --- a/sdk/lib/opentelemetry/sdk/resources/constants.rb +++ b/sdk/lib/opentelemetry/sdk/resources/constants.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright 2019 OpenTelemetry Authors +# Copyright 2020 OpenTelemetry Authors # # SPDX-License-Identifier: Apache-2.0 diff --git a/sdk/lib/opentelemetry/sdk/trace/tracer.rb b/sdk/lib/opentelemetry/sdk/trace/tracer.rb index 243bc74ee..337233986 100644 --- a/sdk/lib/opentelemetry/sdk/trace/tracer.rb +++ b/sdk/lib/opentelemetry/sdk/trace/tracer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright 2019 OpenTelemetry Authors +# Copyright 2020 OpenTelemetry Authors # # SPDX-License-Identifier: Apache-2.0 @@ -16,7 +16,8 @@ class Tracer < OpenTelemetry::Trace::Tracer # # Returns a new {Tracer} instance. # - # @param [InstrumentationLibrary] resource Containing name and version arguments supplied to the TracerProvider + # @param [String] name Instrumentation package name + # @param [String] version Instrumentation package version # # @return [Tracer] def initialize(name, version) From 7a8a9c6429d5d2f6a79247ca94d288a3c3949d6a Mon Sep 17 00:00:00 2001 From: Robert Laurin Date: Tue, 16 Jun 2020 13:22:08 -0400 Subject: [PATCH 11/13] Fix typo in gcp resource detector test --- .../opentelemetry/detectors/google_cloud_platform_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resource-detectors/test/opentelemetry/detectors/google_cloud_platform_test.rb b/resource-detectors/test/opentelemetry/detectors/google_cloud_platform_test.rb index 7fd5a8c0d..38aef9144 100644 --- a/resource-detectors/test/opentelemetry/detectors/google_cloud_platform_test.rb +++ b/resource-detectors/test/opentelemetry/detectors/google_cloud_platform_test.rb @@ -62,7 +62,7 @@ describe 'and a nil resource value is detected' do let(:project_id) { nil } - it 'returns a with that label' do + it 'returns a resource without that label' do _(detected_resource_labels.key?('cloud.account.id')).must_equal(false) end end @@ -70,7 +70,7 @@ describe 'and an empty string resource value is detected' do let(:project_id) { '' } - it 'returns a with that label' do + it 'returns a resource without that label' do _(detected_resource_labels.key?('cloud.account.id')).must_equal(false) end end From 3674ce5d1acca9794ff8bb1c167290bce7f70c9f Mon Sep 17 00:00:00 2001 From: Robert Laurin Date: Tue, 16 Jun 2020 13:33:57 -0400 Subject: [PATCH 12/13] Set tracer resource in initializer --- sdk/lib/opentelemetry/sdk/trace/tracer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/lib/opentelemetry/sdk/trace/tracer.rb b/sdk/lib/opentelemetry/sdk/trace/tracer.rb index 337233986..9329c0b33 100644 --- a/sdk/lib/opentelemetry/sdk/trace/tracer.rb +++ b/sdk/lib/opentelemetry/sdk/trace/tracer.rb @@ -24,6 +24,7 @@ def initialize(name, version) @name = name @version = version @instrumentation_library = InstrumentationLibrary.new(name, version) + @resource = OpenTelemetry.tracer_provider.resource end def start_root_span(name, attributes: nil, links: nil, start_timestamp: nil, kind: nil) @@ -55,8 +56,7 @@ def internal_create_span(result, name, kind, trace_id, span_id, parent_span_id, attributes = attributes&.merge(result.attributes) || result.attributes active_trace_config = OpenTelemetry.tracer_provider.active_trace_config active_span_processor = OpenTelemetry.tracer_provider.active_span_processor - resource = OpenTelemetry.tracer_provider.resource - Span.new(context, name, kind, parent_span_id, active_trace_config, active_span_processor, attributes, links, start_timestamp || Time.now, resource, @instrumentation_library) + Span.new(context, name, kind, parent_span_id, active_trace_config, active_span_processor, attributes, links, start_timestamp || Time.now, @resource, @instrumentation_library) else OpenTelemetry::Trace::Span.new(span_context: OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id)) end From 83780db3bd616a120e6b5953fd82fb8e5d8c9f8c Mon Sep 17 00:00:00 2001 From: Robert Laurin Date: Wed, 17 Jun 2020 09:06:10 -0400 Subject: [PATCH 13/13] Add tracer_provider reference to tracer The tracer carries a reference to the tracer_provider that initialized it to begin supporting multiple tracer providers. --- sdk/lib/opentelemetry/sdk/trace/tracer.rb | 27 +++++++++++++------ .../sdk/trace/tracer_provider.rb | 2 +- .../opentelemetry/sdk/trace/tracer_test.rb | 10 +++++-- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/sdk/lib/opentelemetry/sdk/trace/tracer.rb b/sdk/lib/opentelemetry/sdk/trace/tracer.rb index 9329c0b33..d840a4fe3 100644 --- a/sdk/lib/opentelemetry/sdk/trace/tracer.rb +++ b/sdk/lib/opentelemetry/sdk/trace/tracer.rb @@ -11,6 +11,7 @@ module Trace class Tracer < OpenTelemetry::Trace::Tracer attr_reader :name attr_reader :version + attr_reader :tracer_provider # @api private # @@ -18,13 +19,14 @@ class Tracer < OpenTelemetry::Trace::Tracer # # @param [String] name Instrumentation package name # @param [String] version Instrumentation package version + # @param [TracerProvider] tracer_provider TracerProvider that initialized the tracer # # @return [Tracer] - def initialize(name, version) + def initialize(name, version, tracer_provider) @name = name @version = version @instrumentation_library = InstrumentationLibrary.new(name, version) - @resource = OpenTelemetry.tracer_provider.resource + @tracer_provider = tracer_provider end def start_root_span(name, attributes: nil, links: nil, start_timestamp: nil, kind: nil) @@ -41,22 +43,31 @@ def start_span(name, with_parent: nil, with_parent_context: nil, attributes: nil trace_id = parent_span_context&.trace_id trace_id ||= OpenTelemetry::Trace.generate_trace_id span_id = OpenTelemetry::Trace.generate_span_id - sampler = OpenTelemetry.tracer_provider.active_trace_config.sampler + sampler = tracer_provider.active_trace_config.sampler result = sampler.should_sample?(trace_id: trace_id, parent_context: parent_span_context, links: links, name: name, kind: kind, attributes: attributes) - internal_create_span(result, name, kind, trace_id, span_id, parent_span_id, attributes, links, start_timestamp, tracestate) end private def internal_create_span(result, name, kind, trace_id, span_id, parent_span_id, attributes, links, start_timestamp, tracestate) # rubocop:disable Metrics/AbcSize - if result.recording? && !OpenTelemetry.tracer_provider.stopped? + if result.recording? && !tracer_provider.stopped? trace_flags = result.sampled? ? OpenTelemetry::Trace::TraceFlags::SAMPLED : OpenTelemetry::Trace::TraceFlags::DEFAULT context = OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id, trace_flags: trace_flags, tracestate: tracestate) attributes = attributes&.merge(result.attributes) || result.attributes - active_trace_config = OpenTelemetry.tracer_provider.active_trace_config - active_span_processor = OpenTelemetry.tracer_provider.active_span_processor - Span.new(context, name, kind, parent_span_id, active_trace_config, active_span_processor, attributes, links, start_timestamp || Time.now, @resource, @instrumentation_library) + Span.new( + context, + name, + kind, + parent_span_id, + tracer_provider.active_trace_config, + tracer_provider.active_span_processor, + attributes, + links, + start_timestamp || Time.now, + tracer_provider.resource, + @instrumentation_library + ) else OpenTelemetry::Trace::Span.new(span_context: OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id)) end diff --git a/sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb b/sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb index ce0aeb43a..8492b15c3 100644 --- a/sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb +++ b/sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb @@ -38,7 +38,7 @@ def initialize(resource = OpenTelemetry::SDK::Resources::Resource.create) def tracer(name = nil, version = nil) name ||= '' version ||= '' - @mutex.synchronize { @registry[Key.new(name, version)] ||= Tracer.new(name, version) } + @mutex.synchronize { @registry[Key.new(name, version)] ||= Tracer.new(name, version, self) } end # Attempts to stop all the activity for this {Tracer}. Calls diff --git a/sdk/test/opentelemetry/sdk/trace/tracer_test.rb b/sdk/test/opentelemetry/sdk/trace/tracer_test.rb index 5cca8540d..4ce31fe13 100644 --- a/sdk/test/opentelemetry/sdk/trace/tracer_test.rb +++ b/sdk/test/opentelemetry/sdk/trace/tracer_test.rb @@ -20,13 +20,19 @@ describe '#name' do it 'reflects the name passed in' do - _(Tracer.new('component', 'semver:1.0').name).must_equal('component') + _(Tracer.new('component', 'semver:1.0', tracer_provider).name).must_equal('component') end end describe '#version' do it 'reflects the version passed in' do - _(Tracer.new('component', 'semver:1.0').version).must_equal('semver:1.0') + _(Tracer.new('component', 'semver:1.0', tracer_provider).version).must_equal('semver:1.0') + end + end + + describe '#tracer_provider' do + it 'reflects the tracer_provider passed in' do + _(Tracer.new('component', 'semver:1.0', tracer_provider).tracer_provider).must_equal(tracer_provider) end end