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

IGNORABLE_SQL =
%w{BEGIN COMMIT}.freeze
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.freeze
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)/.freeze

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils::StrongMemoize

clear_memoization, strong_memoize, strong_memoized?

Class Method Details

.db_counter_payloadObject


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

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


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

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 ActiveRecord::Base.transaction {} block.


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

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