lib/opentelemetry/exporter/zipkin/exporter.rb in opentelemetry-exporter-zipkin-0.21.0 vs lib/opentelemetry/exporter/zipkin/exporter.rb in opentelemetry-exporter-zipkin-0.22.0
- old
+ new
@@ -27,11 +27,12 @@
WRITE_TIMEOUT_SUPPORTED = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.6')
private_constant(:KEEP_ALIVE_TIMEOUT, :RETRY_COUNT, :WRITE_TIMEOUT_SUPPORTED)
def initialize(endpoint: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_ZIPKIN_ENDPOINT', default: 'http://localhost:9411/api/v2/spans'),
headers: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_ZIPKIN_TRACES_HEADERS', 'OTEL_EXPORTER_ZIPKIN_HEADERS'),
- timeout: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_ZIPKIN_TRACES_TIMEOUT', 'OTEL_EXPORTER_ZIPKIN_TIMEOUT', default: 10))
+ timeout: OpenTelemetry::Common::Utilities.config_opt('OTEL_EXPORTER_ZIPKIN_TRACES_TIMEOUT', 'OTEL_EXPORTER_ZIPKIN_TIMEOUT', default: 10),
+ metrics_reporter: nil)
raise ArgumentError, "invalid url for Zipkin::Exporter #{endpoint}" unless OpenTelemetry::Common::Utilities.valid_url?(endpoint)
raise ArgumentError, 'headers must be comma-separated k=v pairs or a Hash' unless valid_headers?(headers)
@uri = if endpoint == ENV['OTEL_EXPORTER_ZIPKIN_ENDPOINT']
URI("#{endpoint}/api/v2/spans")
@@ -48,10 +49,11 @@
@headers = case headers
when String then CSV.parse(headers, col_sep: '=', row_sep: ',').to_h
when Hash then headers
end
+ @metrics_reporter = metrics_reporter || OpenTelemetry::SDK::Trace::Export::MetricsReporter
@shutdown = false
end
# Called to export sampled {OpenTelemetry::SDK::Trace::SpanData} structs.
#
@@ -64,10 +66,11 @@
return FAILURE if @shutdown
zipkin_spans = encode_spans(span_data)
send_spans(zipkin_spans, timeout: timeout)
rescue StandardError => e
+ @metrics_reporter.add_to_counter('otel.zipkin_exporter.failure', labels: { 'reason' => e.class.to_s })
OpenTelemetry.handle_error(exception: e, message: 'unexpected error in Zipkin::Exporter#export')
FAILURE
end
# Called when {OpenTelemetry::SDK::Trace::TracerProvider#force_flush} is called, if
@@ -110,11 +113,11 @@
true
rescue ArgumentError
false
end
- def send_spans(zipkin_spans, timeout: nil) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
+ def send_spans(zipkin_spans, timeout: nil) # rubocop:disable Metrics/MethodLength
retry_count = 0
timeout ||= @timeout
start_time = OpenTelemetry::Common::Utilities.timeout_timestamp
around_request do # rubocop:disable Metrics/BlockLength
request = Net::HTTP::Post.new(@path)
@@ -128,11 +131,11 @@
@http.open_timeout = remaining_timeout
@http.read_timeout = remaining_timeout
@http.write_timeout = remaining_timeout if WRITE_TIMEOUT_SUPPORTED
@http.start unless @http.started?
- response = @http.request(request)
+ response = measure_request_duration { @http.request(request) }
response.body # Read and discard body
# in opentelemetry-js 200-399 is succcess, in opentelemetry-collector zipkin exporter,200-299 is a success
# zipkin api docs list 202 as default success code
# https://zipkin.io/zipkin-api/#/default/post_spans
# TODO: redirect
@@ -169,11 +172,11 @@
def handle_redirect(location)
# TODO: figure out destination and reinitialize @http and @path
end
- def backoff?(retry_after: nil, retry_count:, reason:)
+ def backoff?(retry_count:, reason:, retry_after: nil)
return false if retry_count > RETRY_COUNT
# TODO: metric exporter
sleep_interval = nil
@@ -194,9 +197,22 @@
end
sleep_interval ||= rand(2**retry_count)
sleep(sleep_interval)
true
+ end
+
+ def measure_request_duration
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ begin
+ response = yield
+ ensure
+ stop = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ duration_ms = 1000.0 * (stop - start)
+ @metrics_reporter.record_value('otel.zipkin_exporter.request_duration',
+ value: duration_ms,
+ labels: { 'status' => response&.code || 'unknown' })
+ end
end
end
end
end
end