Module: ActiveRecordQueryCounter::ConnectionAdapterExtension

Defined in:
lib/active_record_query_counter/connection_adapter_extension.rb

Overview

Module to prepend to the connection adapter to inject the counting behavior.

Defined Under Namespace

Modules: ConnectionSetupExtension, InternalExecQuery

Constant Summary collapse

CONNECTION_SETUP_METHODS =

Connection adapter methods that establish, verify, or reconnect the underlying database connection. When these run inside a query (for example when a stale connection is re-established after an idle period or a database failover), the wall clock time they consume is spent setting up the connection rather than executing the query. It is measured separately so it can be subtracted from the reported query time.

%i[connect! reconnect! verify!].freeze

Class Method Summary collapse

Class Method Details

.inject(connection_class) ⇒ Object



14
15
16
17
18
19
20
21
22
# File 'lib/active_record_query_counter/connection_adapter_extension.rb', line 14

def inject(connection_class)
  unless connection_class.include?(InternalExecQuery)
    connection_class.prepend(InternalExecQuery)
  end

  unless connection_class.include?(ConnectionSetupExtension)
    connection_class.prepend(ConnectionSetupExtension)
  end
end

.measure_query(sql, name, binds, connection = nil) { ... } ⇒ Object

Measure a query by wrapping its execution. In addition to the wall clock time, the GC time, thread CPU time, and connection setup time spent while the query runs are captured so that the time actually spent waiting on the database can be isolated from time lost to garbage collection, Ruby VM work, and (re)establishing the database connection.

Parameters:

  • sql (String)

    the SQL statement being executed

  • name (String, nil)

    the name of the query

  • binds (Array)

    the bind parameters

  • connection (Object, nil) (defaults to: nil)

    the connection adapter the query is being executed on

Yields:

  • executes the query and returns its result

Returns:

  • (Object)

    the result of the query



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/active_record_query_counter/connection_adapter_extension.rb', line 35

def measure_query(sql, name, binds, connection = nil)
  gc_start = GC.total_time
  cpu_start = ActiveRecordQueryCounter.current_cpu_time
  previous_timer = ActiveRecordQueryCounter.start_connection_timer
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  begin
    result = yield
  ensure
    connection_time = ActiveRecordQueryCounter.stop_connection_timer(previous_timer)
  end
  if result.is_a?(ActiveRecord::Result)
    end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
    cpu_time = ActiveRecordQueryCounter.current_cpu_time - cpu_start
    gc_time = (GC.total_time - gc_start) / 1_000_000_000.0
    ActiveRecordQueryCounter.add_query(sql, name, binds, result.length, start_time, end_time, gc_time, cpu_time, connection_time, connection: connection)
  end
  result
end