Class: Gitlab::Metrics::Subscribers::ActiveRecord

Inherits:
ActiveSupport::Subscriber
  • Object
show all
Extended by:
Utils::StrongMemoize
Defined in:
lib/gitlab/metrics/subscribers/active_record.rb

Overview

Class for tracking the total query duration of a transaction.

Constant Summary collapse

DB_COUNTERS =
%i[count write_count cached_count].freeze
SQL_COMMANDS_WITH_COMMENTS_REGEX =
%r{\A(/\*.*\*/\s)?((?!(.*[^\w'"](DELETE|UPDATE|INSERT INTO)[^\w'"])))(WITH.*)?(SELECT)((?!(FOR UPDATE|FOR SHARE)).)*$}i
SQL_DURATION_BUCKET =
[0.05, 0.1, 0.25].freeze
TRANSACTION_DURATION_BUCKET =
[0.1, 0.25, 1].freeze
DB_LOAD_BALANCING_ROLES =
%i[replica primary].freeze
DB_LOAD_BALANCING_COUNTERS =
%i[count cached_count wal_count wal_cached_count].freeze
DB_LOAD_BALANCING_DURATIONS =
%i[duration_s].freeze
SQL_WAL_LOCATION_REGEX =
/(pg_current_wal_insert_lsn\(\)::text|pg_last_wal_replay_lsn\(\)::text)/

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.db_counter_payloadObject



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/gitlab/metrics/subscribers/active_record.rb', line 58

def self.db_counter_payload
  return {} unless Gitlab::SafeRequestStore.active?

  {}.tap do |payload|
    db_counter_keys.each do |key|
      payload[key] = Gitlab::SafeRequestStore[key].to_i
    end

    if ::Gitlab::SafeRequestStore.active?
      load_balancing_metric_counter_keys.each do |counter|
        payload[counter] = ::Gitlab::SafeRequestStore[counter].to_i
      end

      load_balancing_metric_duration_keys.each do |duration|
        payload[duration] = ::Gitlab::SafeRequestStore[duration].to_f.round(3)
      end
    end
  end
end

Instance Method Details

#sql(event) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/gitlab/metrics/subscribers/active_record.rb', line 33

def sql(event)
  # Mark this thread as requiring a database connection. This is used
  # by the Gitlab::Metrics::Samplers::ThreadsSampler to count threads
  # using a connection.
  Thread.current[:uses_db_connection] = true

  payload = event.payload
  return if ignored_query?(payload)

  db_config_name = db_config_name(event.payload)
  increment(:count, db_config_name: db_config_name)
  increment(:cached_count, db_config_name: db_config_name) if cached_query?(payload)
  increment(:write_count, db_config_name: db_config_name) unless select_sql_command?(payload)

  observe(:gitlab_sql_duration_seconds, event) do
    buckets SQL_DURATION_BUCKET
  end

  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

#transaction(event) ⇒ Object

This event is published from ActiveRecordBaseTransactionMetrics and used to record a database transaction duration when calling ApplicationRecord.transaction {} block.



27
28
29
30
31
# File 'lib/gitlab/metrics/subscribers/active_record.rb', line 27

def transaction(event)
  observe(:gitlab_database_transaction_seconds, event) do
    buckets TRANSACTION_DURATION_BUCKET
  end
end