gitlab-org--gitlab-foss/lib/gitlab/metrics/subscribers/external_http.rb

98 lines
3 KiB
Ruby

# frozen_string_literal: true
module Gitlab
module Metrics
module Subscribers
# Class for tracking the total time spent in external HTTP
# See more at https://gitlab.com/gitlab-org/labkit-ruby/-/blob/v0.14.0/lib/gitlab-labkit.rb#L18
class ExternalHttp < ActiveSupport::Subscriber
attach_to :external_http
DEFAULT_STATUS_CODE = 'undefined'
DETAIL_STORE = :external_http_detail_store
COUNTER = :external_http_count
DURATION = :external_http_duration_s
def self.detail_store
::Gitlab::SafeRequestStore[DETAIL_STORE] ||= []
end
def self.duration
Gitlab::SafeRequestStore[DURATION].to_f
end
def self.request_count
Gitlab::SafeRequestStore[COUNTER].to_i
end
def self.payload
{
COUNTER => request_count,
DURATION => duration
}
end
def request(event)
payload = event.payload
add_to_detail_store(event.time, payload)
add_to_request_store(payload)
expose_metrics(payload)
end
private
def current_transaction
::Gitlab::Metrics::WebTransaction.current || ::Gitlab::Metrics::BackgroundTransaction.current
end
def add_to_detail_store(start, payload)
return unless Gitlab::PerformanceBar.enabled_for_request?
self.class.detail_store << {
start: start,
duration: payload[:duration],
scheme: payload[:scheme],
method: payload[:method],
host: payload[:host],
port: payload[:port],
path: payload[:path],
query: payload[:query],
code: payload[:code],
exception_object: payload[:exception_object],
backtrace: Gitlab::BacktraceCleaner.clean_backtrace(caller)
}
end
def add_to_request_store(payload)
return unless Gitlab::SafeRequestStore.active?
Gitlab::SafeRequestStore[COUNTER] = Gitlab::SafeRequestStore[COUNTER].to_i + 1
Gitlab::SafeRequestStore[DURATION] = Gitlab::SafeRequestStore[DURATION].to_f + payload[:duration].to_f
end
def expose_metrics(payload)
return unless current_transaction
labels = { method: payload[:method], code: payload[:code] || DEFAULT_STATUS_CODE }
current_transaction.increment(:gitlab_external_http_total, 1, labels) do
docstring 'External HTTP calls'
label_keys labels.keys
end
current_transaction.observe(:gitlab_external_http_duration_seconds, payload[:duration]) do
docstring 'External HTTP time'
buckets [0.001, 0.01, 0.1, 1.0, 2.0, 5.0]
end
if payload[:exception_object].present?
current_transaction.increment(:gitlab_external_http_exception_total, 1) do
docstring 'External HTTP exceptions'
end
end
end
end
end
end
end