diff --git a/exporter/otlp-common/lib/opentelemetry/exporter/otlp/common.rb b/exporter/otlp-common/lib/opentelemetry/exporter/otlp/common.rb index 87eca2d5ea..d9abb6e6ab 100644 --- a/exporter/otlp-common/lib/opentelemetry/exporter/otlp/common.rb +++ b/exporter/otlp-common/lib/opentelemetry/exporter/otlp/common.rb @@ -5,6 +5,7 @@ # SPDX-License-Identifier: Apache-2.0 require 'opentelemetry' +require 'opentelemetry/exporter/otlp/common/utilities' require 'opentelemetry/exporter/otlp/common/version' require 'google/rpc/status_pb' diff --git a/exporter/otlp-common/lib/opentelemetry/exporter/otlp/common/utilities.rb b/exporter/otlp-common/lib/opentelemetry/exporter/otlp/common/utilities.rb new file mode 100644 index 0000000000..9a03d2dc80 --- /dev/null +++ b/exporter/otlp-common/lib/opentelemetry/exporter/otlp/common/utilities.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +# Copyright The OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +require 'opentelemetry/common' + +module OpenTelemetry + module Exporter + module OTLP + module Common + # Contains common utilities used by the otlp exporters + module Utilities + extend self + + # Builds a url using the endpoint defined and if not present uses the configured sources + def build_uri(endpoint, path = '', primary_src = '', secondary_src = '', default = nil) + env_endpoint = OpenTelemetry::Common::Utilities.config_opt(primary_src, secondary_src, default: default) unless endpoint + endpoint ||= env_endpoint + raise ArgumentError, "invalid url for OTLPExporter #{endpoint}" unless OpenTelemetry::Common::Utilities.valid_url?(endpoint) + + if !env_endpoint.nil? && env_endpoint != ENV[primary_src] + env_endpoint += '/' unless env_endpoint.end_with?('/') + URI.join(env_endpoint, path) + else + URI(endpoint) + end + end + end + end + end + end +end diff --git a/exporter/otlp-common/opentelemetry-exporter-otlp-common.gemspec b/exporter/otlp-common/opentelemetry-exporter-otlp-common.gemspec index 864f1687b3..4b2882c7bb 100644 --- a/exporter/otlp-common/opentelemetry-exporter-otlp-common.gemspec +++ b/exporter/otlp-common/opentelemetry-exporter-otlp-common.gemspec @@ -28,6 +28,7 @@ Gem::Specification.new do |spec| spec.add_dependency 'googleapis-common-protos-types', '~> 1.3' spec.add_dependency 'google-protobuf', '~> 3.19' spec.add_dependency 'opentelemetry-api', '~> 1.1' + spec.add_dependency 'opentelemetry-common' if spec.respond_to?(:metadata) spec.metadata['changelog_uri'] = "https://rubydoc.info/gems/#{spec.name}/#{spec.version}/file/CHANGELOG.md" diff --git a/exporter/otlp-common/test/opentelemetry/exporter/otlp/common/utilities_test.rb b/exporter/otlp-common/test/opentelemetry/exporter/otlp/common/utilities_test.rb new file mode 100644 index 0000000000..7c2b94cdae --- /dev/null +++ b/exporter/otlp-common/test/opentelemetry/exporter/otlp/common/utilities_test.rb @@ -0,0 +1,102 @@ +# frozen_string_literal: true + +# Copyright The OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +require 'test_helper' + +describe OpenTelemetry::Exporter::OTLP::Common::Utilities do + describe 'IPv4/IPv6 compatibility' do + it 'handles IPv6 loopback address with brackets' do + exp = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri('http://[::1]:4318/v1/logs') + _(exp.host).must_equal '[::1]' + _(exp.port).must_equal 4318 + _(exp.path).must_equal '/v1/logs' + end + + it 'handles IPv6 full address with brackets' do + exp = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri('http://[2001:db8::1]:4318/v1/logs') + _(exp.host).must_equal '[2001:db8::1]' + _(exp.port).must_equal 4318 + end + + it 'handles IPv6 address with https' do + exp = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri('https://[::1]:4318/v1/logs') + _(exp.host).must_equal '[::1]' + _(exp.port).must_equal 4318 + _(exp.scheme).must_equal 'https' + end + + it 'handles IPv6 address with custom path' do + exp = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri('http://[::1]:8080/custom/path') + _(exp.host).must_equal '[::1]' + _(exp.port).must_equal 8080 + _(exp.path).must_equal '/custom/path' + end + + it 'handles IPv4 loopback address' do + exp = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri('http://127.0.0.1:4318/v1/logs') + _(exp.host).must_equal '127.0.0.1' + _(exp.port).must_equal 4318 + _(exp.path).must_equal '/v1/logs' + end + + it 'handles IPv4 address with custom port' do + exp = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri('http://192.168.1.100:8080/v1/logs') + _(exp.host).must_equal '192.168.1.100' + _(exp.port).must_equal 8080 + end + + it 'handles IPv4 address with https' do + exp = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri('https://10.0.0.1:4318/v1/logs') + _(exp.host).must_equal '10.0.0.1' + _(exp.port).must_equal 4318 + _(exp.scheme).must_equal 'https' + end + + it 'handles IPv4 address with custom path' do + exp = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri('http://127.0.0.1:9090/custom/path') + _(exp.host).must_equal '127.0.0.1' + _(exp.port).must_equal 9090 + _(exp.path).must_equal '/custom/path' + end + + it 'handles IPv4 address from environment variable' do + exp = OpenTelemetry::TestHelpers.with_env('OTEL_EXPORTER_OTLP_ENDPOINT' => 'http://192.168.1.1:4318') do + OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri(nil, 'v1/logs', 'OTEL_EXPORTER_OTLP_LOGS_ENDPOINT', 'OTEL_EXPORTER_OTLP_ENDPOINT') + end + _(exp.host).must_equal '192.168.1.1' + _(exp.port).must_equal 4318 + _(exp.path).must_equal '/v1/logs' + end + + it 'handles hostnames' do + exp = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri('http://localhost:4318/v1/logs') + _(exp.host).must_equal 'localhost' + _(exp.port).must_equal 4318 + end + + it 'handles fully qualified domain names' do + exp = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri('http://otel.example.com:4318/v1/logs') + _(exp.host).must_equal 'otel.example.com' + _(exp.port).must_equal 4318 + end + + it 'handles hostnames with https' do + exp = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri('https://otel-collector.prod.example.com:443/v1/logs') + _(exp.host).must_equal 'otel-collector.prod.example.com' + _(exp.port).must_equal 443 + _(exp.scheme).must_equal 'https' + end + + it 'handles IPv6 address from environment variable' do + exp = OpenTelemetry::TestHelpers.with_env('OTEL_EXPORTER_OTLP_ENDPOINT' => 'http://[::1]:4318') do + OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri(nil, 'v1/logs', 'OTEL_EXPORTER_OTLP_LOGS_ENDPOINT', 'OTEL_EXPORTER_OTLP_ENDPOINT') + end + _(exp.host).must_equal '[::1]' + _(exp.port).must_equal 4318 + _(exp.path).must_equal '/v1/logs' + end + end +end diff --git a/exporter/otlp-grpc/lib/opentelemetry/exporter/otlp/grpc/trace_exporter.rb b/exporter/otlp-grpc/lib/opentelemetry/exporter/otlp/grpc/trace_exporter.rb index 2772873e52..875bf2d565 100644 --- a/exporter/otlp-grpc/lib/opentelemetry/exporter/otlp/grpc/trace_exporter.rb +++ b/exporter/otlp-grpc/lib/opentelemetry/exporter/otlp/grpc/trace_exporter.rb @@ -22,15 +22,13 @@ class TraceExporter FAILURE = OpenTelemetry::SDK::Trace::Export::FAILURE private_constant(:SUCCESS, :FAILURE) - def initialize(endpoint: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', 'OTEL_EXPORTER_OTLP_ENDPOINT', default: 'http://localhost:4317/v1/traces'), + def initialize(endpoint: nil, timeout: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_TRACES_TIMEOUT', 'OTEL_EXPORTER_OTLP_TIMEOUT', default: 10), certificate_file: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE', 'OTEL_EXPORTER_OTLP_CERTIFICATE'), client_certificate_file: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_TRACES_CLIENT_CERTIFICATE', 'OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE'), client_key_file: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_TRACES_CLIENT_KEY', 'OTEL_EXPORTER_OTLP_CLIENT_KEY'), metrics_reporter: nil) - raise ArgumentError, "invalid url for OTLP::Exporter #{endpoint}" unless OpenTelemetry::Common::Utilities.valid_url?(endpoint) - - uri = URI(endpoint) + uri = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri(endpoint, 'v1/traces', 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', 'OTEL_EXPORTER_OTLP_ENDPOINT', 'http://localhost:4318/') creds = if !client_key_file.nil? && !client_certificate_file.nil? # Permits constructing with nil root cert. diff --git a/exporter/otlp-http/lib/opentelemetry/exporter/otlp/http/trace_exporter.rb b/exporter/otlp-http/lib/opentelemetry/exporter/otlp/http/trace_exporter.rb index f38e0134db..014c5646d1 100644 --- a/exporter/otlp-http/lib/opentelemetry/exporter/otlp/http/trace_exporter.rb +++ b/exporter/otlp-http/lib/opentelemetry/exporter/otlp/http/trace_exporter.rb @@ -40,7 +40,7 @@ def initialize(endpoint: nil, timeout: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_TRACES_TIMEOUT', 'OTEL_EXPORTER_OTLP_TIMEOUT', default: 10)) raise ArgumentError, "unsupported compression key #{compression}" unless compression.nil? || %w[gzip none].include?(compression) - @uri = prepare_endpoint(endpoint) + @uri = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri(endpoint, 'v1/traces', 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', 'OTEL_EXPORTER_OTLP_ENDPOINT', 'http://localhost:4318/') @http = http_connection(@uri, ssl_verify_mode, certificate_file, client_certificate_file, client_key_file) @@ -258,21 +258,6 @@ def prepare_headers(config_headers) headers end - def prepare_endpoint(endpoint) - endpoint ||= ENV.fetch('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', nil) - if endpoint.nil? - endpoint = ENV['OTEL_EXPORTER_OTLP_ENDPOINT'] || 'http://localhost:4318' - endpoint += '/' unless endpoint.end_with?('/') - URI.join(endpoint, 'v1/traces') - elsif endpoint.strip.empty? - raise ArgumentError, "invalid url for OTLP::Exporter #{endpoint}" - else - URI(endpoint) - end - rescue URI::InvalidURIError - raise ArgumentError, "invalid url for OTLP::Exporter #{endpoint}" - end - def parse_headers(raw) entries = raw.split(',') raise ArgumentError, ERROR_MESSAGE_INVALID_HEADERS if entries.empty? diff --git a/exporter/otlp-http/test/opentelemetry/exporter/otlp/http/trace_exporter_test.rb b/exporter/otlp-http/test/opentelemetry/exporter/otlp/http/trace_exporter_test.rb index 39cf6d8b67..9745366f6a 100644 --- a/exporter/otlp-http/test/opentelemetry/exporter/otlp/http/trace_exporter_test.rb +++ b/exporter/otlp-http/test/opentelemetry/exporter/otlp/http/trace_exporter_test.rb @@ -356,112 +356,6 @@ end end - describe 'IPv4/IPv6 compatibility' do - it 'handles IPv6 loopback address with brackets' do - exp = OpenTelemetry::Exporter::OTLP::HTTP::TraceExporter.new(endpoint: 'http://[::1]:4318/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/traces' - end - - it 'handles IPv6 full address with brackets' do - exp = OpenTelemetry::Exporter::OTLP::HTTP::TraceExporter.new(endpoint: 'http://[2001:db8::1]:4318/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '2001:db8::1' - _(http.port).must_equal 4318 - end - - it 'handles IPv6 address with https' do - exp = OpenTelemetry::Exporter::OTLP::HTTP::TraceExporter.new(endpoint: 'https://[::1]:4318/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 4318 - _(http.use_ssl?).must_equal true - end - - it 'handles IPv6 address with custom path' do - exp = OpenTelemetry::Exporter::OTLP::HTTP::TraceExporter.new(endpoint: 'http://[::1]:8080/custom/path') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 8080 - _(exp.instance_variable_get(:@path)).must_equal '/custom/path' - end - - it 'handles IPv4 loopback address' do - exp = OpenTelemetry::Exporter::OTLP::HTTP::TraceExporter.new(endpoint: 'http://127.0.0.1:4318/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '127.0.0.1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/traces' - end - - it 'handles IPv4 address with custom port' do - exp = OpenTelemetry::Exporter::OTLP::HTTP::TraceExporter.new(endpoint: 'http://192.168.1.100:8080/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '192.168.1.100' - _(http.port).must_equal 8080 - end - - it 'handles IPv4 address with https' do - exp = OpenTelemetry::Exporter::OTLP::HTTP::TraceExporter.new(endpoint: 'https://10.0.0.1:4318/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '10.0.0.1' - _(http.port).must_equal 4318 - _(http.use_ssl?).must_equal true - end - - it 'handles IPv4 address with custom path' do - exp = OpenTelemetry::Exporter::OTLP::HTTP::TraceExporter.new(endpoint: 'http://127.0.0.1:9090/custom/path') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '127.0.0.1' - _(http.port).must_equal 9090 - _(exp.instance_variable_get(:@path)).must_equal '/custom/path' - end - - it 'handles IPv4 address from environment variable' do - exp = OpenTelemetry::TestHelpers.with_env('OTEL_EXPORTER_OTLP_ENDPOINT' => 'http://192.168.1.1:4318') do - OpenTelemetry::Exporter::OTLP::HTTP::TraceExporter.new - end - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '192.168.1.1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/traces' - end - - it 'handles hostnames' do - exp = OpenTelemetry::Exporter::OTLP::HTTP::TraceExporter.new(endpoint: 'http://localhost:4318/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal 'localhost' - _(http.port).must_equal 4318 - end - - it 'handles fully qualified domain names' do - exp = OpenTelemetry::Exporter::OTLP::HTTP::TraceExporter.new(endpoint: 'http://otel.example.com:4318/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal 'otel.example.com' - _(http.port).must_equal 4318 - end - - it 'handles hostnames with https' do - exp = OpenTelemetry::Exporter::OTLP::HTTP::TraceExporter.new(endpoint: 'https://otel-collector.prod.example.com:443/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal 'otel-collector.prod.example.com' - _(http.port).must_equal 443 - _(http.use_ssl?).must_equal true - end - - it 'handles IPv6 address from environment variable' do - exp = OpenTelemetry::TestHelpers.with_env('OTEL_EXPORTER_OTLP_ENDPOINT' => 'http://[::1]:4318') do - OpenTelemetry::Exporter::OTLP::HTTP::TraceExporter.new - end - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/traces' - end - end - describe '#export' do let(:exporter) { OpenTelemetry::Exporter::OTLP::HTTP::TraceExporter.new } diff --git a/exporter/otlp-logs/Gemfile b/exporter/otlp-logs/Gemfile index 2796de0df0..4809f1254c 100644 --- a/exporter/otlp-logs/Gemfile +++ b/exporter/otlp-logs/Gemfile @@ -23,6 +23,7 @@ group :test, :development do gem 'yard-doctest', '~> 0.1.6' gem 'opentelemetry-api', path: '../../api', require: false gem 'opentelemetry-common', path: '../../common', require: false + gem 'opentelemetry-exporter-otlp-common', path: '../otlp-common', require: false gem 'opentelemetry-logs-api', path: '../../logs_api', require: false gem 'opentelemetry-logs-sdk', path: '../../logs_sdk', require: false gem 'opentelemetry-registry', path: '../../registry', require: false diff --git a/exporter/otlp-logs/lib/opentelemetry/exporter/otlp/logs/logs_exporter.rb b/exporter/otlp-logs/lib/opentelemetry/exporter/otlp/logs/logs_exporter.rb index f9e9e670df..353c59d928 100644 --- a/exporter/otlp-logs/lib/opentelemetry/exporter/otlp/logs/logs_exporter.rb +++ b/exporter/otlp-logs/lib/opentelemetry/exporter/otlp/logs/logs_exporter.rb @@ -5,6 +5,7 @@ # SPDX-License-Identifier: Apache-2.0 require 'opentelemetry/common' +require 'opentelemetry/exporter/otlp/common' require 'opentelemetry/sdk' require 'opentelemetry-logs-api' # the sdk isn't loading the api, but not sure why require 'opentelemetry/sdk/logs' @@ -50,7 +51,7 @@ def self.ssl_verify_mode end # rubocop:enable Lint/DuplicateBranch - def initialize(endpoint: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_LOGS_ENDPOINT', 'OTEL_EXPORTER_OTLP_ENDPOINT', default: 'http://localhost:4318/v1/logs'), + def initialize(endpoint: nil, certificate_file: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE', 'OTEL_EXPORTER_OTLP_CERTIFICATE'), client_certificate_file: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_LOGS_CLIENT_CERTIFICATE', 'OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE'), client_key_file: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_LOGS_CLIENT_KEY', 'OTEL_EXPORTER_OTLP_CLIENT_KEY'), @@ -58,16 +59,9 @@ def initialize(endpoint: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPOR headers: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_LOGS_HEADERS', 'OTEL_EXPORTER_OTLP_HEADERS', default: {}), compression: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_LOGS_COMPRESSION', 'OTEL_EXPORTER_OTLP_COMPRESSION', default: 'gzip'), timeout: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_LOGS_TIMEOUT', 'OTEL_EXPORTER_OTLP_TIMEOUT', default: 10)) - raise ArgumentError, "invalid url for OTLP::Logs::LogsExporter #{endpoint}" unless OpenTelemetry::Common::Utilities.valid_url?(endpoint) raise ArgumentError, "unsupported compression key #{compression}" unless compression.nil? || %w[gzip none].include?(compression) - @uri = if endpoint == ENV['OTEL_EXPORTER_OTLP_ENDPOINT'] - endpoint += '/' unless endpoint.end_with?('/') - URI.join(endpoint, 'v1/logs') - else - URI(endpoint) - end - + @uri = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri(endpoint, 'v1/logs', 'OTEL_EXPORTER_OTLP_LOGS_ENDPOINT', 'OTEL_EXPORTER_OTLP_ENDPOINT', 'http://localhost:4318/') @http = http_connection(@uri, ssl_verify_mode, certificate_file, client_certificate_file, client_key_file) @path = @uri.path diff --git a/exporter/otlp-logs/opentelemetry-exporter-otlp-logs.gemspec b/exporter/otlp-logs/opentelemetry-exporter-otlp-logs.gemspec index 8b79a26a13..94da1ddf7e 100644 --- a/exporter/otlp-logs/opentelemetry-exporter-otlp-logs.gemspec +++ b/exporter/otlp-logs/opentelemetry-exporter-otlp-logs.gemspec @@ -29,6 +29,7 @@ Gem::Specification.new do |spec| spec.add_dependency 'google-protobuf', '>= 3.18' spec.add_dependency 'opentelemetry-api', '~> 1.1' spec.add_dependency 'opentelemetry-common', '~> 0.20' + spec.add_dependency 'opentelemetry-exporter-otlp-common' spec.add_dependency 'opentelemetry-logs-api', '~> 0.1' spec.add_dependency 'opentelemetry-logs-sdk', '~> 0.1' spec.add_dependency 'opentelemetry-sdk' diff --git a/exporter/otlp-logs/test/opentelemetry/exporter/otlp/logs_exporter_test.rb b/exporter/otlp-logs/test/opentelemetry/exporter/otlp/logs_exporter_test.rb index 4d37bef293..aa393b95cb 100644 --- a/exporter/otlp-logs/test/opentelemetry/exporter/otlp/logs_exporter_test.rb +++ b/exporter/otlp-logs/test/opentelemetry/exporter/otlp/logs_exporter_test.rb @@ -355,112 +355,6 @@ end end - describe 'IPv4/IPv6 compatibility' do - it 'handles IPv6 loopback address with brackets' do - exp = OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new(endpoint: 'http://[::1]:4318/v1/logs') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/logs' - end - - it 'handles IPv6 full address with brackets' do - exp = OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new(endpoint: 'http://[2001:db8::1]:4318/v1/logs') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '2001:db8::1' - _(http.port).must_equal 4318 - end - - it 'handles IPv6 address with https' do - exp = OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new(endpoint: 'https://[::1]:4318/v1/logs') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 4318 - _(http.use_ssl?).must_equal true - end - - it 'handles IPv6 address with custom path' do - exp = OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new(endpoint: 'http://[::1]:8080/custom/path') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 8080 - _(exp.instance_variable_get(:@path)).must_equal '/custom/path' - end - - it 'handles IPv4 loopback address' do - exp = OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new(endpoint: 'http://127.0.0.1:4318/v1/logs') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '127.0.0.1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/logs' - end - - it 'handles IPv4 address with custom port' do - exp = OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new(endpoint: 'http://192.168.1.100:8080/v1/logs') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '192.168.1.100' - _(http.port).must_equal 8080 - end - - it 'handles IPv4 address with https' do - exp = OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new(endpoint: 'https://10.0.0.1:4318/v1/logs') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '10.0.0.1' - _(http.port).must_equal 4318 - _(http.use_ssl?).must_equal true - end - - it 'handles IPv4 address with custom path' do - exp = OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new(endpoint: 'http://127.0.0.1:9090/custom/path') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '127.0.0.1' - _(http.port).must_equal 9090 - _(exp.instance_variable_get(:@path)).must_equal '/custom/path' - end - - it 'handles IPv4 address from environment variable' do - exp = OpenTelemetry::TestHelpers.with_env('OTEL_EXPORTER_OTLP_ENDPOINT' => 'http://192.168.1.1:4318') do - OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new - end - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '192.168.1.1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/logs' - end - - it 'handles hostnames' do - exp = OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new(endpoint: 'http://localhost:4318/v1/logs') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal 'localhost' - _(http.port).must_equal 4318 - end - - it 'handles fully qualified domain names' do - exp = OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new(endpoint: 'http://otel.example.com:4318/v1/logs') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal 'otel.example.com' - _(http.port).must_equal 4318 - end - - it 'handles hostnames with https' do - exp = OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new(endpoint: 'https://otel-collector.prod.example.com:443/v1/logs') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal 'otel-collector.prod.example.com' - _(http.port).must_equal 443 - _(http.use_ssl?).must_equal true - end - - it 'handles IPv6 address from environment variable' do - exp = OpenTelemetry::TestHelpers.with_env('OTEL_EXPORTER_OTLP_ENDPOINT' => 'http://[::1]:4318') do - OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new - end - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/logs' - end - end - describe '#export' do let(:exporter) { OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new } # TODO: replace with a before block to set a global logger provider through OpenTelemetry.logger_provider when the API code is merged diff --git a/exporter/otlp-metrics/Gemfile b/exporter/otlp-metrics/Gemfile index f2b0ed1074..79ee282afc 100644 --- a/exporter/otlp-metrics/Gemfile +++ b/exporter/otlp-metrics/Gemfile @@ -23,6 +23,7 @@ group :test, :development do gem 'yard-doctest', '~> 0.1.6' gem 'opentelemetry-api', path: '../../api', require: false gem 'opentelemetry-common', path: '../../common', require: false + gem 'opentelemetry-exporter-otlp-common', path: '../otlp-common', require: false gem 'opentelemetry-metrics-api', path: '../../metrics_api', require: false gem 'opentelemetry-metrics-sdk', path: '../../metrics_sdk', require: false gem 'opentelemetry-registry', path: '../../registry', require: false diff --git a/exporter/otlp-metrics/lib/opentelemetry/exporter/otlp/metrics/metrics_exporter.rb b/exporter/otlp-metrics/lib/opentelemetry/exporter/otlp/metrics/metrics_exporter.rb index 1d5396b13d..afc323c462 100644 --- a/exporter/otlp-metrics/lib/opentelemetry/exporter/otlp/metrics/metrics_exporter.rb +++ b/exporter/otlp-metrics/lib/opentelemetry/exporter/otlp/metrics/metrics_exporter.rb @@ -5,6 +5,7 @@ # SPDX-License-Identifier: Apache-2.0 require 'opentelemetry/common' +require 'opentelemetry/exporter/otlp/common' require 'opentelemetry/sdk' require 'net/http' require 'zlib' @@ -48,7 +49,7 @@ def self.ssl_verify_mode end # rubocop:enable Lint/DuplicateBranch - def initialize(endpoint: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_METRICS_ENDPOINT', 'OTEL_EXPORTER_OTLP_ENDPOINT', default: 'http://localhost:4318/v1/metrics'), + def initialize(endpoint: nil, certificate_file: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE', 'OTEL_EXPORTER_OTLP_CERTIFICATE'), client_certificate_file: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE', 'OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE'), client_key_file: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY', 'OTEL_EXPORTER_OTLP_CLIENT_KEY'), @@ -57,19 +58,12 @@ def initialize(endpoint: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPOR compression: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_METRICS_COMPRESSION', 'OTEL_EXPORTER_OTLP_COMPRESSION', default: 'gzip'), timeout: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_METRICS_TIMEOUT', 'OTEL_EXPORTER_OTLP_TIMEOUT', default: 10), aggregation_cardinality_limit: nil) - raise ArgumentError, "invalid url for OTLP::MetricsExporter #{endpoint}" unless OpenTelemetry::Common::Utilities.valid_url?(endpoint) raise ArgumentError, "unsupported compression key #{compression}" unless compression.nil? || %w[gzip none].include?(compression) # create the MetricStore object super(aggregation_cardinality_limit: aggregation_cardinality_limit) - @uri = if endpoint == ENV['OTEL_EXPORTER_OTLP_ENDPOINT'] - endpoint += '/' unless endpoint.end_with?('/') - URI.join(endpoint, 'v1/metrics') - else - URI(endpoint) - end - + @uri = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri(endpoint, 'v1/metrics', 'OTEL_EXPORTER_OTLP_METRICS_ENDPOINT', 'OTEL_EXPORTER_OTLP_ENDPOINT', 'http://localhost:4318/') @http = http_connection(@uri, ssl_verify_mode, certificate_file, client_certificate_file, client_key_file) @path = @uri.path diff --git a/exporter/otlp-metrics/opentelemetry-exporter-otlp-metrics.gemspec b/exporter/otlp-metrics/opentelemetry-exporter-otlp-metrics.gemspec index 739bc33763..498b29159f 100644 --- a/exporter/otlp-metrics/opentelemetry-exporter-otlp-metrics.gemspec +++ b/exporter/otlp-metrics/opentelemetry-exporter-otlp-metrics.gemspec @@ -29,6 +29,7 @@ Gem::Specification.new do |spec| spec.add_dependency 'google-protobuf', '>= 3.18', '< 5.0' spec.add_dependency 'opentelemetry-api', '~> 1.1' spec.add_dependency 'opentelemetry-common', '~> 0.20' + spec.add_dependency 'opentelemetry-exporter-otlp-common' spec.add_dependency 'opentelemetry-metrics-api', '~> 0.2' spec.add_dependency 'opentelemetry-metrics-sdk', '~> 0.5' spec.add_dependency 'opentelemetry-sdk', '~> 1.2' diff --git a/exporter/otlp-metrics/test/opentelemetry/exporter/otlp/metrics/metrics_exporter_test.rb b/exporter/otlp-metrics/test/opentelemetry/exporter/otlp/metrics/metrics_exporter_test.rb index 1c57517bd1..5bc8a65815 100644 --- a/exporter/otlp-metrics/test/opentelemetry/exporter/otlp/metrics/metrics_exporter_test.rb +++ b/exporter/otlp-metrics/test/opentelemetry/exporter/otlp/metrics/metrics_exporter_test.rb @@ -352,112 +352,6 @@ end end - describe 'IPv4/IPv6 compatibility' do - it 'handles IPv6 loopback address with brackets' do - exp = OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new(endpoint: 'http://[::1]:4318/v1/metrics') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/metrics' - end - - it 'handles IPv6 full address with brackets' do - exp = OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new(endpoint: 'http://[2001:db8::1]:4318/v1/metrics') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '2001:db8::1' - _(http.port).must_equal 4318 - end - - it 'handles IPv6 address with https' do - exp = OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new(endpoint: 'https://[::1]:4318/v1/metrics') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 4318 - _(http.use_ssl?).must_equal true - end - - it 'handles IPv6 address with custom path' do - exp = OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new(endpoint: 'http://[::1]:8080/custom/path') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 8080 - _(exp.instance_variable_get(:@path)).must_equal '/custom/path' - end - - it 'handles IPv4 loopback address' do - exp = OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new(endpoint: 'http://127.0.0.1:4318/v1/metrics') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '127.0.0.1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/metrics' - end - - it 'handles IPv4 address with custom port' do - exp = OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new(endpoint: 'http://192.168.1.100:8080/v1/metrics') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '192.168.1.100' - _(http.port).must_equal 8080 - end - - it 'handles IPv4 address with https' do - exp = OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new(endpoint: 'https://10.0.0.1:4318/v1/metrics') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '10.0.0.1' - _(http.port).must_equal 4318 - _(http.use_ssl?).must_equal true - end - - it 'handles IPv4 address with custom path' do - exp = OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new(endpoint: 'http://127.0.0.1:9090/custom/path') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '127.0.0.1' - _(http.port).must_equal 9090 - _(exp.instance_variable_get(:@path)).must_equal '/custom/path' - end - - it 'handles IPv4 address from environment variable' do - exp = OpenTelemetry::TestHelpers.with_env('OTEL_EXPORTER_OTLP_ENDPOINT' => 'http://192.168.1.1:4318') do - OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new - end - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '192.168.1.1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/metrics' - end - - it 'handles hostnames' do - exp = OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new(endpoint: 'http://localhost:4318/v1/metrics') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal 'localhost' - _(http.port).must_equal 4318 - end - - it 'handles fully qualified domain names' do - exp = OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new(endpoint: 'http://otel.example.com:4318/v1/metrics') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal 'otel.example.com' - _(http.port).must_equal 4318 - end - - it 'handles hostnames with https' do - exp = OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new(endpoint: 'https://otel-collector.prod.example.com:443/v1/metrics') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal 'otel-collector.prod.example.com' - _(http.port).must_equal 443 - _(http.use_ssl?).must_equal true - end - - it 'handles IPv6 address from environment variable' do - exp = OpenTelemetry::TestHelpers.with_env('OTEL_EXPORTER_OTLP_ENDPOINT' => 'http://[::1]:4318') do - OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new - end - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/metrics' - end - end - describe '#export' do let(:exporter) { OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new } let(:meter_provider) { OpenTelemetry::SDK::Metrics::MeterProvider.new(resource: OpenTelemetry::SDK::Resources::Resource.telemetry_sdk) } diff --git a/exporter/otlp/lib/opentelemetry/exporter/otlp/exporter.rb b/exporter/otlp/lib/opentelemetry/exporter/otlp/exporter.rb index cd192e2178..8e245b0732 100644 --- a/exporter/otlp/lib/opentelemetry/exporter/otlp/exporter.rb +++ b/exporter/otlp/lib/opentelemetry/exporter/otlp/exporter.rb @@ -57,10 +57,9 @@ def initialize(endpoint: nil, compression: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_TRACES_COMPRESSION', 'OTEL_EXPORTER_OTLP_COMPRESSION', default: 'gzip'), timeout: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_TRACES_TIMEOUT', 'OTEL_EXPORTER_OTLP_TIMEOUT', default: 10), metrics_reporter: nil) - @uri = prepare_endpoint(endpoint) - raise ArgumentError, "unsupported compression key #{compression}" unless compression.nil? || %w[gzip none].include?(compression) + @uri = OpenTelemetry::Exporter::OTLP::Common::Utilities.build_uri(endpoint, 'v1/traces', 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', 'OTEL_EXPORTER_OTLP_ENDPOINT', 'http://localhost:4318/') @http = http_connection(@uri, ssl_verify_mode, certificate_file, client_certificate_file, client_key_file) @path = @uri.path @@ -287,21 +286,6 @@ def encode(span_data) value: duration_ms) end - def prepare_endpoint(endpoint) - endpoint ||= ENV.fetch('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', nil) - if endpoint.nil? - endpoint = ENV['OTEL_EXPORTER_OTLP_ENDPOINT'] || 'http://localhost:4318' - endpoint += '/' unless endpoint.end_with?('/') - URI.join(endpoint, 'v1/traces') - elsif endpoint.strip.empty? - raise ArgumentError, "invalid url for OTLP::Exporter #{endpoint}" - else - URI(endpoint) - end - rescue URI::InvalidURIError - raise ArgumentError, "invalid url for OTLP::Exporter #{endpoint}" - end - def prepare_headers(config_headers) headers = case config_headers when String then parse_headers(config_headers) diff --git a/exporter/otlp/test/opentelemetry/exporter/otlp/exporter_test.rb b/exporter/otlp/test/opentelemetry/exporter/otlp/exporter_test.rb index 93c37899cc..4bddf96bd7 100644 --- a/exporter/otlp/test/opentelemetry/exporter/otlp/exporter_test.rb +++ b/exporter/otlp/test/opentelemetry/exporter/otlp/exporter_test.rb @@ -357,112 +357,6 @@ end end - describe 'IPv4/IPv6 compatibility' do - it 'handles IPv6 loopback address with brackets' do - exp = OpenTelemetry::Exporter::OTLP::Exporter.new(endpoint: 'http://[::1]:4318/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/traces' - end - - it 'handles IPv6 full address with brackets' do - exp = OpenTelemetry::Exporter::OTLP::Exporter.new(endpoint: 'http://[2001:db8::1]:4318/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '2001:db8::1' - _(http.port).must_equal 4318 - end - - it 'handles IPv6 address with https' do - exp = OpenTelemetry::Exporter::OTLP::Exporter.new(endpoint: 'https://[::1]:4318/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 4318 - _(http.use_ssl?).must_equal true - end - - it 'handles IPv6 address with custom path' do - exp = OpenTelemetry::Exporter::OTLP::Exporter.new(endpoint: 'http://[::1]:8080/custom/path') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 8080 - _(exp.instance_variable_get(:@path)).must_equal '/custom/path' - end - - it 'handles IPv4 loopback address' do - exp = OpenTelemetry::Exporter::OTLP::Exporter.new(endpoint: 'http://127.0.0.1:4318/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '127.0.0.1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/traces' - end - - it 'handles IPv4 address with custom port' do - exp = OpenTelemetry::Exporter::OTLP::Exporter.new(endpoint: 'http://192.168.1.100:8080/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '192.168.1.100' - _(http.port).must_equal 8080 - end - - it 'handles IPv4 address with https' do - exp = OpenTelemetry::Exporter::OTLP::Exporter.new(endpoint: 'https://10.0.0.1:4318/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '10.0.0.1' - _(http.port).must_equal 4318 - _(http.use_ssl?).must_equal true - end - - it 'handles IPv4 address with custom path' do - exp = OpenTelemetry::Exporter::OTLP::Exporter.new(endpoint: 'http://127.0.0.1:9090/custom/path') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '127.0.0.1' - _(http.port).must_equal 9090 - _(exp.instance_variable_get(:@path)).must_equal '/custom/path' - end - - it 'handles IPv4 address from environment variable' do - exp = OpenTelemetry::TestHelpers.with_env('OTEL_EXPORTER_OTLP_ENDPOINT' => 'http://192.168.1.1:4318') do - OpenTelemetry::Exporter::OTLP::Exporter.new - end - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '192.168.1.1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/traces' - end - - it 'handles hostnames' do - exp = OpenTelemetry::Exporter::OTLP::Exporter.new(endpoint: 'http://localhost:4318/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal 'localhost' - _(http.port).must_equal 4318 - end - - it 'handles fully qualified domain names' do - exp = OpenTelemetry::Exporter::OTLP::Exporter.new(endpoint: 'http://otel.example.com:4318/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal 'otel.example.com' - _(http.port).must_equal 4318 - end - - it 'handles hostnames with https' do - exp = OpenTelemetry::Exporter::OTLP::Exporter.new(endpoint: 'https://otel-collector.prod.example.com:443/v1/traces') - http = exp.instance_variable_get(:@http) - _(http.address).must_equal 'otel-collector.prod.example.com' - _(http.port).must_equal 443 - _(http.use_ssl?).must_equal true - end - - it 'handles IPv6 address from environment variable' do - exp = OpenTelemetry::TestHelpers.with_env('OTEL_EXPORTER_OTLP_ENDPOINT' => 'http://[::1]:4318') do - OpenTelemetry::Exporter::OTLP::Exporter.new - end - http = exp.instance_variable_get(:@http) - _(http.address).must_equal '::1' - _(http.port).must_equal 4318 - _(exp.instance_variable_get(:@path)).must_equal '/v1/traces' - end - end - describe 'ssl_verify_mode:' do it 'can be set to VERIFY_NONE by an envvar' do exp = OpenTelemetry::TestHelpers.with_env('OTEL_RUBY_EXPORTER_OTLP_SSL_VERIFY_NONE' => 'true') do diff --git a/logs_sdk/Gemfile b/logs_sdk/Gemfile index 3db0008711..e5a9283bd1 100644 --- a/logs_sdk/Gemfile +++ b/logs_sdk/Gemfile @@ -20,6 +20,7 @@ group :test, :development do gem 'yard', '~> 0.9.0' gem 'yard-doctest', '~> 0.1.17' gem 'opentelemetry-api', path: '../api', require: false + gem 'opentelemetry-exporter-otlp-common', path: '../exporter/otlp-common', require: false gem 'opentelemetry-exporter-otlp-logs', path: '../exporter/otlp-logs', require: false gem 'opentelemetry-logs-api', path: '../logs_api', require: false gem 'opentelemetry-sdk', path: '../sdk', require: false diff --git a/metrics_sdk/Gemfile b/metrics_sdk/Gemfile index 2324ac6004..10335fbbb0 100644 --- a/metrics_sdk/Gemfile +++ b/metrics_sdk/Gemfile @@ -21,6 +21,7 @@ group :test, :development do gem 'yard-doctest', '~> 0.1.6' gem 'opentelemetry-api', path: '../api', require: false gem 'opentelemetry-common', path: '../common', require: false + gem 'opentelemetry-exporter-otlp-common', path: '../exporter/otlp-common', require: false gem 'opentelemetry-exporter-otlp-metrics', path: '../exporter/otlp-metrics', require: false unless RUBY_ENGINE == 'jruby' gem 'opentelemetry-metrics-api', path: '../metrics_api', require: false gem 'opentelemetry-registry', path: '../registry', require: false