Module: OpenTelemetry::Exporter::OTLP::Metrics::Util
- Included in:
- MetricsExporter
- Defined in:
- lib/opentelemetry/exporter/otlp/metrics/util.rb
Overview
Util module provide essential functionality for exporter
Constant Summary collapse
- KEEP_ALIVE_TIMEOUT =
30- RETRY_COUNT =
5- ERROR_MESSAGE_INVALID_HEADERS =
'headers must be a String with comma-separated URL Encoded UTF-8 k=v pairs or a Hash'- DEFAULT_USER_AGENT =
"OTel-OTLP-MetricsExporter-Ruby/#{OpenTelemetry::Exporter::OTLP::Metrics::VERSION} Ruby/#{RUBY_VERSION} (#{RUBY_PLATFORM}; #{RUBY_ENGINE}/#{RUBY_ENGINE_VERSION})".freeze
Instance Method Summary collapse
-
#around_request ⇒ Object
Yields the block with OpenTelemetry instrumentation suppressed.
-
#as_otlp_any_value(value) ⇒ Object
Converts a Ruby value to its OTLP proto AnyValue representation.
-
#as_otlp_key_value(key, value) ⇒ Object
Converts a key/value pair to an OTLP proto KeyValue.
-
#backoff?(retry_count:, reason:, retry_after: nil) ⇒ Boolean
Sleeps for a computed backoff interval and returns whether a retry should happen.
-
#handle_redirect(location) ⇒ Object
No-op: HTTP redirects are not followed.
-
#http_connection(uri, ssl_verify_mode, certificate_file, client_certificate_file, client_key_file) ⇒ Object
Builds a configured Net::HTTP connection for the given URI.
-
#log_status(body) ⇒ Object
Decodes and logs an rpc.Status error response body.
-
#parse_headers(raw) ⇒ Object
Parses a comma-separated, URL-encoded header string into a Hash.
-
#prepare_headers(config_headers) ⇒ Object
Normalizes config_headers into a Hash, appending the default User-Agent.
Instance Method Details
#around_request ⇒ Object
Yields the block with OpenTelemetry instrumentation suppressed.
31 32 33 |
# File 'lib/opentelemetry/exporter/otlp/metrics/util.rb', line 31 def around_request OpenTelemetry::Common::Utilities.untraced { yield } # rubocop:disable Style/ExplicitBlockArgument end |
#as_otlp_any_value(value) ⇒ Object
Converts a Ruby value to its OTLP proto AnyValue representation.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/opentelemetry/exporter/otlp/metrics/util.rb', line 46 def as_otlp_any_value(value) result = Opentelemetry::Proto::Common::V1::AnyValue.new case value when String result.string_value = OpenTelemetry::Common::Utilities.utf8_encode(value, placeholder: value) when Integer result.int_value = value when Float result.double_value = value when true, false result.bool_value = value 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 |
#as_otlp_key_value(key, value) ⇒ Object
Converts a key/value pair to an OTLP proto KeyValue.
36 37 38 39 40 41 42 43 |
# File 'lib/opentelemetry/exporter/otlp/metrics/util.rb', line 36 def as_otlp_key_value(key, value) key = OpenTelemetry::Common::Utilities.utf8_encode(key, placeholder: 'Encoding Error') Opentelemetry::Proto::Common::V1::KeyValue.new(key: key, value: as_otlp_any_value(value)) rescue Encoding::UndefinedConversionError => e encoded_value = value.to_s.encode('UTF-8', invalid: :replace, undef: :replace, replace: '�') OpenTelemetry.handle_error(exception: e, message: "encoding error for key #{key} and value #{encoded_value}") Opentelemetry::Proto::Common::V1::KeyValue.new(key: key, value: as_otlp_any_value('Encoding Error')) end |
#backoff?(retry_count:, reason:, retry_after: nil) ⇒ Boolean
Sleeps for a computed backoff interval and returns whether a retry should happen.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/opentelemetry/exporter/otlp/metrics/util.rb', line 100 def backoff?(retry_count:, reason:, retry_after: nil) return false if retry_count > RETRY_COUNT sleep_interval = nil unless retry_after.nil? sleep_interval = Integer(retry_after, exception: false) sleep_interval ||= begin Time.httpdate(retry_after) - Time.now rescue # rubocop:disable Style/RescueStandardError nil end sleep_interval = nil unless sleep_interval&.positive? end sleep_interval ||= rand(2**retry_count) sleep(sleep_interval) true end |
#handle_redirect(location) ⇒ Object
No-op: HTTP redirects are not followed.
136 |
# File 'lib/opentelemetry/exporter/otlp/metrics/util.rb', line 136 def handle_redirect(location); end |
#http_connection(uri, ssl_verify_mode, certificate_file, client_certificate_file, client_key_file) ⇒ Object
Builds a configured Net::HTTP connection for the given URI.
19 20 21 22 23 24 25 26 27 28 |
# File 'lib/opentelemetry/exporter/otlp/metrics/util.rb', line 19 def http_connection(uri, ssl_verify_mode, certificate_file, client_certificate_file, client_key_file) http = Net::HTTP.new(uri.hostname, uri.port) http.use_ssl = uri.scheme == 'https' http.verify_mode = ssl_verify_mode http.ca_file = certificate_file unless certificate_file.nil? http.cert = OpenSSL::X509::Certificate.new(File.read(client_certificate_file)) unless client_certificate_file.nil? http.key = OpenSSL::PKey::RSA.new(File.read(client_key_file)) unless client_key_file.nil? http.keep_alive_timeout = KEEP_ALIVE_TIMEOUT http end |
#log_status(body) ⇒ Object
Decodes and logs an rpc.Status error response body.
122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/opentelemetry/exporter/otlp/metrics/util.rb', line 122 def log_status(body) status = Google::Rpc::Status.decode(body) pool = ::Google::Protobuf::DescriptorPool.generated_pool details = status.details.filter_map do |detail| type_name = detail.type_url.to_s.split('/').last.to_s klass = pool.lookup(type_name)&.msgclass detail.unpack(klass) if klass end OpenTelemetry.handle_error(message: "OTLP metrics_exporter received rpc.Status{message=#{status.}, details=#{details}}") rescue StandardError => e OpenTelemetry.handle_error(exception: e, message: 'unexpected error decoding rpc.Status in OTLP::MetricsExporter#log_status') end |
#parse_headers(raw) ⇒ Object
Parses a comma-separated, URL-encoded header string into a Hash.
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/opentelemetry/exporter/otlp/metrics/util.rb', line 79 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 { |part| URI.decode_uri_component part } begin k = k.to_s.strip v = v.to_s.strip rescue Encoding::CompatibilityError raise ArgumentError, ERROR_MESSAGE_INVALID_HEADERS 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 |
#prepare_headers(config_headers) ⇒ Object
Normalizes config_headers into a Hash, appending the default User-Agent.
65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/opentelemetry/exporter/otlp/metrics/util.rb', line 65 def prepare_headers(config_headers) headers = case config_headers when String then parse_headers(config_headers) when Hash then config_headers.dup else raise ArgumentError, ERROR_MESSAGE_INVALID_HEADERS end headers['User-Agent'] = "#{headers.fetch('User-Agent', '')} #{DEFAULT_USER_AGENT}".strip headers end |