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

CPU_CLOCK_ID =

Clock used to measure the CPU time consumed by the current thread while a query runs. It is not available on every platform (e.g. Windows), in which case CPU time is not measured and is treated as zero.

(Process::CLOCK_THREAD_CPUTIME_ID))
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



19
20
21
22
23
24
25
26
27
# File 'lib/active_record_query_counter/connection_adapter_extension.rb', line 19

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) { ... } ⇒ 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

Yields:

  • executes the query and returns its result

Returns:

  • (Object)

    the result of the query



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/active_record_query_counter/connection_adapter_extension.rb', line 39

def measure_query(sql, name, binds)
  gc_start = GC.total_time
  cpu_start = 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 = 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)
  end
  result
end