lib/opentelemetry/exporter/otlp/exporter.rb in opentelemetry-exporter-otlp-0.20.3 vs lib/opentelemetry/exporter/otlp/exporter.rb in opentelemetry-exporter-otlp-0.20.4
- old
+ new
@@ -29,30 +29,32 @@
KEEP_ALIVE_TIMEOUT = 30
RETRY_COUNT = 5
WRITE_TIMEOUT_SUPPORTED = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.6')
private_constant(:KEEP_ALIVE_TIMEOUT, :RETRY_COUNT, :WRITE_TIMEOUT_SUPPORTED)
+ ERROR_MESSAGE_INVALID_HEADERS = 'headers must be a String with comma-separated URL Encoded UTF-8 k=v pairs or a Hash'
+ private_constant(:ERROR_MESSAGE_INVALID_HEADERS)
+
def self.ssl_verify_mode
if ENV.key?('OTEL_RUBY_EXPORTER_OTLP_SSL_VERIFY_PEER')
OpenSSL::SSL::VERIFY_PEER
elsif ENV.key?('OTEL_RUBY_EXPORTER_OTLP_SSL_VERIFY_NONE')
OpenSSL::SSL::VERIFY_NONE
else
OpenSSL::SSL::VERIFY_PEER
end
end
- def initialize(endpoint: config_opt('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', 'OTEL_EXPORTER_OTLP_ENDPOINT', default: 'https://localhost:4317/v1/traces'), # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
+ def initialize(endpoint: config_opt('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', 'OTEL_EXPORTER_OTLP_ENDPOINT', default: 'https://localhost:4317/v1/traces'), # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
certificate_file: config_opt('OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE', 'OTEL_EXPORTER_OTLP_CERTIFICATE'),
ssl_verify_mode: Exporter.ssl_verify_mode,
- headers: config_opt('OTEL_EXPORTER_OTLP_TRACES_HEADERS', 'OTEL_EXPORTER_OTLP_HEADERS'),
+ headers: config_opt('OTEL_EXPORTER_OTLP_TRACES_HEADERS', 'OTEL_EXPORTER_OTLP_HEADERS', default: {}),
compression: config_opt('OTEL_EXPORTER_OTLP_TRACES_COMPRESSION', 'OTEL_EXPORTER_OTLP_COMPRESSION'),
timeout: config_opt('OTEL_EXPORTER_OTLP_TRACES_TIMEOUT', 'OTEL_EXPORTER_OTLP_TIMEOUT', default: 10),
metrics_reporter: nil)
raise ArgumentError, "invalid url for OTLP::Exporter #{endpoint}" if invalid_url?(endpoint)
raise ArgumentError, "unsupported compression key #{compression}" unless compression.nil? || compression == 'gzip'
- raise ArgumentError, 'headers must be comma-separated k=v pairs or a Hash' unless valid_headers?(headers)
@uri = if endpoint == ENV['OTEL_EXPORTER_OTLP_ENDPOINT']
URI("#{endpoint}/v1/traces")
else
URI(endpoint)
@@ -64,12 +66,14 @@
@http.ca_file = certificate_file unless certificate_file.nil?
@http.keep_alive_timeout = KEEP_ALIVE_TIMEOUT
@path = @uri.path
@headers = case headers
- when String then CSV.parse(headers, col_sep: '=', row_sep: ',').to_h
+ when String then parse_headers(headers)
when Hash then headers
+ else
+ raise ArgumentError, ERROR_MESSAGE_INVALID_HEADERS
end
@timeout = timeout.to_f
@compression = compression
@metrics_reporter = metrics_reporter || OpenTelemetry::SDK::Trace::Export::MetricsReporter
@shutdown = false
@@ -116,20 +120,10 @@
return val unless val.nil?
end
default
end
- def valid_headers?(headers)
- return true if headers.nil? || headers.is_a?(Hash)
- return false unless headers.is_a?(String)
-
- CSV.parse(headers, col_sep: '=', row_sep: ',').to_h
- true
- rescue ArgumentError
- false
- end
-
def invalid_url?(url)
return true if url.nil? || url.strip.empty?
URI(url)
false
@@ -159,11 +153,11 @@
Zlib.gzip(bytes)
else
bytes
end
request.add_field('Content-Type', 'application/x-protobuf')
- @headers&.each { |key, value| request.add_field(key, value) }
+ @headers.each { |key, value| request.add_field(key, value) }
remaining_timeout = OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time)
return TIMEOUT if remaining_timeout.zero?
@http.open_timeout = remaining_timeout
@@ -364,9 +358,27 @@
when Array
values = value.map { |element| as_otlp_any_value(element) }
result.array_value = Opentelemetry::Proto::Common::V1::ArrayValue.new(values: values)
end
result
+ end
+
+ def parse_headers(raw)
+ entries = raw.split(',')
+ raise ArgumentError, ERROR_MESSAGE_INVALID_HEADERS if entries.empty?
+
+ entries.each_with_object({}) do |entry, headers|
+ k, v = entry.split('=', 2).map(&CGI.method(:unescape))
+ begin
+ k = k.to_s.strip
+ v = v.to_s.strip
+ rescue ArgumentError => e
+ raise e, ERROR_MESSAGE_INVALID_HEADERS
+ end
+ raise ArgumentError, ERROR_MESSAGE_INVALID_HEADERS if k.empty? || v.empty?
+
+ headers[k] = v
+ end
end
end
end
end
end