lib/opentelemetry/exporter/otlp/exporter.rb in opentelemetry-exporter-otlp-0.26.1 vs lib/opentelemetry/exporter/otlp/exporter.rb in opentelemetry-exporter-otlp-0.26.2

- old
+ new

@@ -5,11 +5,10 @@ # SPDX-License-Identifier: Apache-2.0 require 'opentelemetry/common' require 'opentelemetry/sdk' require 'net/http' -require 'csv' require 'zlib' require 'google/rpc/status_pb' require 'opentelemetry/proto/common/v1/common_pb' @@ -45,26 +44,21 @@ else OpenSSL::SSL::VERIFY_PEER end end - def initialize(endpoint: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', 'OTEL_EXPORTER_OTLP_ENDPOINT', default: 'http://localhost:4318/v1/traces'), + def initialize(endpoint: nil, certificate_file: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE', 'OTEL_EXPORTER_OTLP_CERTIFICATE'), ssl_verify_mode: Exporter.ssl_verify_mode, headers: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_OTLP_TRACES_HEADERS', 'OTEL_EXPORTER_OTLP_HEADERS', default: {}), 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) - raise ArgumentError, "invalid url for OTLP::Exporter #{endpoint}" unless OpenTelemetry::Common::Utilities.valid_url?(endpoint) + @uri = prepare_endpoint(endpoint) + raise ArgumentError, "unsupported compression key #{compression}" unless compression.nil? || %w[gzip none].include?(compression) - @uri = if endpoint == ENV['OTEL_EXPORTER_OTLP_ENDPOINT'] - URI.join(endpoint, 'v1/traces') - else - URI(endpoint) - end - @http = http_connection(@uri, ssl_verify_mode, certificate_file) @path = @uri.path @headers = prepare_headers(headers) @timeout = timeout.to_f @@ -170,12 +164,11 @@ when Net::HTTPRequestTimeOut, Net::HTTPGatewayTimeOut, Net::HTTPBadGateway response.body # Read and discard body redo if backoff?(retry_count: retry_count += 1, reason: response.code) FAILURE when Net::HTTPNotFound - OpenTelemetry.handle_error(message: "OTLP exporter received http.code=404 for uri: '#{@path}'") - @metrics_reporter.add_to_counter('otel.otlp_exporter.failure', labels: { 'reason' => response.code }) + log_request_failure(response.code) FAILURE when Net::HTTPBadRequest, Net::HTTPClientError, Net::HTTPServerError log_status(response.body) @metrics_reporter.add_to_counter('otel.otlp_exporter.failure', labels: { 'reason' => response.code }) FAILURE @@ -183,10 +176,11 @@ @http.finish handle_redirect(response['location']) redo if backoff?(retry_after: 0, retry_count: retry_count += 1, reason: response.code) else @http.finish + log_request_failure(response.code) FAILURE end rescue Net::OpenTimeout, Net::ReadTimeout retry if backoff?(retry_count: retry_count += 1, reason: 'timeout') return FAILURE @@ -225,15 +219,20 @@ status = Google::Rpc::Status.decode(body) details = status.details.map do |detail| klass_or_nil = ::Google::Protobuf::DescriptorPool.generated_pool.lookup(detail.type_name).msgclass detail.unpack(klass_or_nil) if klass_or_nil end.compact - OpenTelemetry.handle_error(message: "OTLP exporter received rpc.Status{message=#{status.message}, details=#{details}}") + OpenTelemetry.handle_error(message: "OTLP exporter received rpc.Status{message=#{status.message}, details=#{details}} for uri=#{@uri}") rescue StandardError => e OpenTelemetry.handle_error(exception: e, message: 'unexpected error decoding rpc.Status in OTLP::Exporter#log_status') end + def log_request_failure(response_code) + OpenTelemetry.handle_error(message: "OTLP exporter received http.code=#{response_code} for uri='#{@uri}' in OTLP::Exporter#send_bytes") + @metrics_reporter.add_to_counter('otel.otlp_exporter.failure', labels: { 'reason' => response_code }) + end + def measure_request_duration start = Process.clock_gettime(Process::CLOCK_MONOTONIC) begin response = yield ensure @@ -244,11 +243,11 @@ labels: { 'status' => response&.code || 'unknown' }) end end def backoff?(retry_count:, reason:, retry_after: nil) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity - @metrics_reporter.add_to_counter('otel.otlp_exporter.failure', labels: { 'reason' => reason }) + log_request_failure(reason) return false if retry_count > RETRY_COUNT sleep_interval = nil unless retry_after.nil? sleep_interval = @@ -382,9 +381,24 @@ 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 prepare_endpoint(endpoint) + endpoint ||= ENV['OTEL_EXPORTER_OTLP_TRACES_ENDPOINT'] + 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)