summaryrefslogtreecommitdiff
path: root/lib/gitlab/metrics
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-06-16 18:25:58 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-06-16 18:25:58 +0000
commita5f4bba440d7f9ea47046a0a561d49adf0a1e6d4 (patch)
treefb69158581673816a8cd895f9d352dcb3c678b1e /lib/gitlab/metrics
parentd16b2e8639e99961de6ddc93909f3bb5c1445ba1 (diff)
downloadgitlab-ce-a5f4bba440d7f9ea47046a0a561d49adf0a1e6d4.tar.gz
Add latest changes from gitlab-org/gitlab@14-0-stable-eev14.0.0-rc42
Diffstat (limited to 'lib/gitlab/metrics')
-rw-r--r--lib/gitlab/metrics/exporter/web_exporter.rb3
-rw-r--r--lib/gitlab/metrics/requests_rack_middleware.rb13
-rw-r--r--lib/gitlab/metrics/samplers/database_sampler.rb4
-rw-r--r--lib/gitlab/metrics/samplers/ruby_sampler.rb2
-rw-r--r--lib/gitlab/metrics/samplers/unicorn_sampler.rb73
-rw-r--r--lib/gitlab/metrics/subscribers/active_record.rb57
-rw-r--r--lib/gitlab/metrics/subscribers/external_http.rb2
-rw-r--r--lib/gitlab/metrics/transaction.rb23
-rw-r--r--lib/gitlab/metrics/web_transaction.rb25
9 files changed, 84 insertions, 118 deletions
diff --git a/lib/gitlab/metrics/exporter/web_exporter.rb b/lib/gitlab/metrics/exporter/web_exporter.rb
index 558454eaa1c..756e6b0641a 100644
--- a/lib/gitlab/metrics/exporter/web_exporter.rb
+++ b/lib/gitlab/metrics/exporter/web_exporter.rb
@@ -30,8 +30,7 @@ module Gitlab
# application: https://gitlab.com/gitlab-org/gitlab/issues/35343
self.readiness_checks = [
WebExporter::ExporterCheck.new(self),
- Gitlab::HealthChecks::PumaCheck,
- Gitlab::HealthChecks::UnicornCheck
+ Gitlab::HealthChecks::PumaCheck
]
end
diff --git a/lib/gitlab/metrics/requests_rack_middleware.rb b/lib/gitlab/metrics/requests_rack_middleware.rb
index 19a835b9fc4..b99261b5c4d 100644
--- a/lib/gitlab/metrics/requests_rack_middleware.rb
+++ b/lib/gitlab/metrics/requests_rack_middleware.rb
@@ -15,7 +15,6 @@ module Gitlab
HEALTH_ENDPOINT = /^\/-\/(liveness|readiness|health|metrics)\/?$/.freeze
- FEATURE_CATEGORY_HEADER = 'X-Gitlab-Feature-Category'
FEATURE_CATEGORY_DEFAULT = 'unknown'
# These were the top 5 categories at a point in time, chosen as a
@@ -67,18 +66,16 @@ module Gitlab
def call(env)
method = env['REQUEST_METHOD'].downcase
method = 'INVALID' unless HTTP_METHODS.key?(method)
- started = Time.now.to_f
+ started = Gitlab::Metrics::System.monotonic_time
health_endpoint = health_endpoint?(env['PATH_INFO'])
status = 'undefined'
- feature_category = nil
begin
status, headers, body = @app.call(env)
- elapsed = Time.now.to_f - started
- feature_category = headers&.fetch(FEATURE_CATEGORY_HEADER, nil)
+ elapsed = Gitlab::Metrics::System.monotonic_time - started
- unless health_endpoint
+ if !health_endpoint && Gitlab::Metrics.record_duration_for_status?(status)
RequestsRackMiddleware.http_request_duration_seconds.observe({ method: method }, elapsed)
end
@@ -104,6 +101,10 @@ module Gitlab
HEALTH_ENDPOINT.match?(CGI.unescape(path))
end
+
+ def feature_category
+ ::Gitlab::ApplicationContext.current_context_attribute(:feature_category)
+ end
end
end
end
diff --git a/lib/gitlab/metrics/samplers/database_sampler.rb b/lib/gitlab/metrics/samplers/database_sampler.rb
index 0a0ac6c5386..5d7f434b660 100644
--- a/lib/gitlab/metrics/samplers/database_sampler.rb
+++ b/lib/gitlab/metrics/samplers/database_sampler.rb
@@ -45,8 +45,8 @@ module Gitlab
def labels_for_class(klass)
{
- host: klass.connection_config[:host],
- port: klass.connection_config[:port],
+ host: klass.connection_db_config.host,
+ port: klass.connection_db_config.configuration_hash[:port],
class: klass.to_s
}
end
diff --git a/lib/gitlab/metrics/samplers/ruby_sampler.rb b/lib/gitlab/metrics/samplers/ruby_sampler.rb
index 3d29d38fa1f..b1c5e9800da 100644
--- a/lib/gitlab/metrics/samplers/ruby_sampler.rb
+++ b/lib/gitlab/metrics/samplers/ruby_sampler.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require 'prometheus/client/support/unicorn'
-
module Gitlab
module Metrics
module Samplers
diff --git a/lib/gitlab/metrics/samplers/unicorn_sampler.rb b/lib/gitlab/metrics/samplers/unicorn_sampler.rb
deleted file mode 100644
index 2fa324f3fea..00000000000
--- a/lib/gitlab/metrics/samplers/unicorn_sampler.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Metrics
- module Samplers
- class UnicornSampler < BaseSampler
- DEFAULT_SAMPLING_INTERVAL_SECONDS = 5
-
- def metrics
- @metrics ||= init_metrics
- end
-
- def init_metrics
- {
- unicorn_active_connections: ::Gitlab::Metrics.gauge(:unicorn_active_connections, 'Unicorn active connections', {}, :max),
- unicorn_queued_connections: ::Gitlab::Metrics.gauge(:unicorn_queued_connections, 'Unicorn queued connections', {}, :max),
- unicorn_workers: ::Gitlab::Metrics.gauge(:unicorn_workers, 'Unicorn workers')
- }
- end
-
- def enabled?
- # Raindrops::Linux.tcp_listener_stats is only present on Linux
- unicorn_with_listeners? && Raindrops::Linux.respond_to?(:tcp_listener_stats)
- end
-
- def sample
- Raindrops::Linux.tcp_listener_stats(tcp_listeners).each do |addr, stats|
- set_unicorn_connection_metrics('tcp', addr, stats)
- end
- Raindrops::Linux.unix_listener_stats(unix_listeners).each do |addr, stats|
- set_unicorn_connection_metrics('unix', addr, stats)
- end
-
- metrics[:unicorn_workers].set({}, unicorn_workers_count)
- end
-
- private
-
- def tcp_listeners
- @tcp_listeners ||= Unicorn.listener_names.grep(%r{\A[^/]+:\d+\z})
- end
-
- def set_unicorn_connection_metrics(type, addr, stats)
- labels = { socket_type: type, socket_address: addr }
-
- metrics[:unicorn_active_connections].set(labels, stats.active)
- metrics[:unicorn_queued_connections].set(labels, stats.queued)
- end
-
- def unix_listeners
- @unix_listeners ||= Unicorn.listener_names - tcp_listeners
- end
-
- def unicorn_with_listeners?
- defined?(Unicorn) && Unicorn.listener_names.any?
- end
-
- def unicorn_workers_count
- http_servers.sum(&:worker_processes)
- end
-
- # Traversal of ObjectSpace is expensive, on fully loaded application
- # it takes around 80ms. The instances of HttpServers are not a subject
- # to change so we can cache the list of servers.
- def http_servers
- return [] unless Gitlab::Runtime.unicorn?
-
- @http_servers ||= ObjectSpace.each_object(::Unicorn::HttpServer).to_a
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/metrics/subscribers/active_record.rb b/lib/gitlab/metrics/subscribers/active_record.rb
index 3db3317e833..9f7884e1364 100644
--- a/lib/gitlab/metrics/subscribers/active_record.rb
+++ b/lib/gitlab/metrics/subscribers/active_record.rb
@@ -14,6 +14,14 @@ module Gitlab
SQL_DURATION_BUCKET = [0.05, 0.1, 0.25].freeze
TRANSACTION_DURATION_BUCKET = [0.1, 0.25, 1].freeze
+ DB_LOAD_BALANCING_COUNTERS = %i{
+ db_replica_count db_replica_cached_count db_replica_wal_count
+ db_primary_count db_primary_cached_count db_primary_wal_count
+ }.freeze
+ DB_LOAD_BALANCING_DURATIONS = %i{db_primary_duration_s db_replica_duration_s}.freeze
+
+ SQL_WAL_LOCATION_REGEX = /(pg_current_wal_insert_lsn\(\)::text|pg_last_wal_replay_lsn\(\)::text)/.freeze
+
# This event is published from ActiveRecordBaseTransactionMetrics and
# used to record a database transaction duration when calling
# ActiveRecord::Base.transaction {} block.
@@ -39,23 +47,56 @@ module Gitlab
observe(:gitlab_sql_duration_seconds, event) do
buckets SQL_DURATION_BUCKET
end
+
+ if ::Gitlab::Database::LoadBalancing.enable?
+ db_role = ::Gitlab::Database::LoadBalancing.db_role_for_connection(payload[:connection])
+ return if db_role.blank?
+
+ increment_db_role_counters(db_role, payload)
+ observe_db_role_duration(db_role, event)
+ end
end
def self.db_counter_payload
return {} unless Gitlab::SafeRequestStore.active?
- payload = {}
- DB_COUNTERS.each do |counter|
- payload[counter] = Gitlab::SafeRequestStore[counter].to_i
+ {}.tap do |payload|
+ DB_COUNTERS.each do |counter|
+ payload[counter] = Gitlab::SafeRequestStore[counter].to_i
+ end
+
+ if ::Gitlab::SafeRequestStore.active? && ::Gitlab::Database::LoadBalancing.enable?
+ DB_LOAD_BALANCING_COUNTERS.each do |counter|
+ payload[counter] = ::Gitlab::SafeRequestStore[counter].to_i
+ end
+ DB_LOAD_BALANCING_DURATIONS.each do |duration|
+ payload[duration] = ::Gitlab::SafeRequestStore[duration].to_f.round(3)
+ end
+ end
end
- payload
end
- def self.known_payload_keys
- DB_COUNTERS
+ private
+
+ def wal_command?(payload)
+ payload[:sql].match(SQL_WAL_LOCATION_REGEX)
+ end
+
+ def increment_db_role_counters(db_role, payload)
+ increment("db_#{db_role}_count".to_sym)
+ increment("db_#{db_role}_cached_count".to_sym) if cached_query?(payload)
+ increment("db_#{db_role}_wal_count".to_sym) if !cached_query?(payload) && wal_command?(payload)
end
- private
+ def observe_db_role_duration(db_role, event)
+ observe("gitlab_sql_#{db_role}_duration_seconds".to_sym, event) do
+ buckets ::Gitlab::Metrics::Subscribers::ActiveRecord::SQL_DURATION_BUCKET
+ end
+
+ duration = event.duration / 1000.0
+ duration_key = "db_#{db_role}_duration_s".to_sym
+ ::Gitlab::SafeRequestStore[duration_key] = (::Gitlab::SafeRequestStore[duration_key].presence || 0) + duration
+ end
def ignored_query?(payload)
payload[:name] == 'SCHEMA' || IGNORABLE_SQL.include?(payload[:sql])
@@ -86,5 +127,3 @@ module Gitlab
end
end
end
-
-Gitlab::Metrics::Subscribers::ActiveRecord.prepend_mod_with('Gitlab::Metrics::Subscribers::ActiveRecord')
diff --git a/lib/gitlab/metrics/subscribers/external_http.rb b/lib/gitlab/metrics/subscribers/external_http.rb
index 0df64f2897e..60a1b084345 100644
--- a/lib/gitlab/metrics/subscribers/external_http.rb
+++ b/lib/gitlab/metrics/subscribers/external_http.rb
@@ -14,8 +14,6 @@ module Gitlab
COUNTER = :external_http_count
DURATION = :external_http_duration_s
- KNOWN_PAYLOAD_KEYS = [COUNTER, DURATION].freeze
-
def self.detail_store
::Gitlab::SafeRequestStore[DETAIL_STORE] ||= []
end
diff --git a/lib/gitlab/metrics/transaction.rb b/lib/gitlab/metrics/transaction.rb
index 3ebafb5c5e4..97cc8bed564 100644
--- a/lib/gitlab/metrics/transaction.rb
+++ b/lib/gitlab/metrics/transaction.rb
@@ -13,8 +13,6 @@ module Gitlab
THREAD_KEY = :_gitlab_metrics_transaction
- SMALL_BUCKETS = [0.1, 0.25, 0.5, 1.0, 2.5, 5.0].freeze
-
# The series to store events (e.g. Git pushes) in.
EVENT_SERIES = 'events'
@@ -39,29 +37,10 @@ module Gitlab
def initialize
@methods = {}
-
- @started_at = nil
- @finished_at = nil
- end
-
- def duration
- @finished_at ? (@finished_at - @started_at) : 0.0
end
def run
- Thread.current[THREAD_KEY] = self
-
- @started_at = System.monotonic_time
-
- yield
- ensure
- @finished_at = System.monotonic_time
-
- observe(:gitlab_transaction_duration_seconds, duration) do
- buckets SMALL_BUCKETS
- end
-
- Thread.current[THREAD_KEY] = nil
+ raise NotImplementedError
end
# Tracks a business level event
diff --git a/lib/gitlab/metrics/web_transaction.rb b/lib/gitlab/metrics/web_transaction.rb
index ee9e6f449d3..3ebfcc43b0b 100644
--- a/lib/gitlab/metrics/web_transaction.rb
+++ b/lib/gitlab/metrics/web_transaction.rb
@@ -6,12 +6,29 @@ module Gitlab
CONTROLLER_KEY = 'action_controller.instance'
ENDPOINT_KEY = 'api.endpoint'
ALLOWED_SUFFIXES = Set.new(%w[json js atom rss xml zip])
+ SMALL_BUCKETS = [0.1, 0.25, 0.5, 1.0, 2.5, 5.0].freeze
def initialize(env)
super()
@env = env
end
+ def run
+ Thread.current[THREAD_KEY] = self
+
+ started_at = System.monotonic_time
+
+ status, _, _ = retval = yield
+
+ finished_at = System.monotonic_time
+ duration = finished_at - started_at
+ record_duration_if_needed(status, duration)
+
+ retval
+ ensure
+ Thread.current[THREAD_KEY] = nil
+ end
+
def labels
return @labels if @labels
@@ -27,6 +44,14 @@ module Gitlab
private
+ def record_duration_if_needed(status, duration)
+ return unless Gitlab::Metrics.record_duration_for_status?(status)
+
+ observe(:gitlab_transaction_duration_seconds, duration) do
+ buckets SMALL_BUCKETS
+ end
+ end
+
def labels_from_controller
controller = @env[CONTROLLER_KEY]