Class: ActiveRecordQueryCounter::TransactionDetails

Inherits:
Object
  • Object
show all
Defined in:
lib/active_record_query_counter/transaction_details.rb

Overview

Data structure with the full details about a transaction, including the queries executed within it. Note that the start and end times are monotonic time and not wall clock time.

This object is transient. It is created when a transaction is recorded to build the transaction_time notification payload and to derive the retained TransactionInfo, and is then released so the query details do not accumulate in memory.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(start_time:, end_time:, trace:, queries: [], gc_time: 0.0, cpu_time: 0.0) ⇒ TransactionDetails

Returns a new instance of TransactionDetails.



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

def initialize(start_time:, end_time:, trace:, queries: [], gc_time: 0.0, cpu_time: 0.0)
  @start_time = start_time
  @end_time = end_time
  @trace = trace
  @queries = queries
  @gc_time = gc_time
  @cpu_time = cpu_time
end

Instance Attribute Details

#cpu_timeObject (readonly)

Returns the value of attribute cpu_time.



12
13
14
# File 'lib/active_record_query_counter/transaction_details.rb', line 12

def cpu_time
  @cpu_time
end

#end_timeObject (readonly)

Returns the value of attribute end_time.



12
13
14
# File 'lib/active_record_query_counter/transaction_details.rb', line 12

def end_time
  @end_time
end

#gc_timeObject (readonly)

Returns the value of attribute gc_time.



12
13
14
# File 'lib/active_record_query_counter/transaction_details.rb', line 12

def gc_time
  @gc_time
end

#queriesObject (readonly)

Returns the value of attribute queries.



12
13
14
# File 'lib/active_record_query_counter/transaction_details.rb', line 12

def queries
  @queries
end

#start_timeObject (readonly)

Returns the value of attribute start_time.



12
13
14
# File 'lib/active_record_query_counter/transaction_details.rb', line 12

def start_time
  @start_time
end

#traceObject (readonly)

Returns the value of attribute trace.



12
13
14
# File 'lib/active_record_query_counter/transaction_details.rb', line 12

def trace
  @trace
end

Instance Method Details

#elapsed_timeFloat

Return the time spent in the transaction.

Returns:

  • (Float)


26
27
28
# File 'lib/active_record_query_counter/transaction_details.rb', line 26

def elapsed_time
  end_time - start_time
end

#idle_timeFloat

Estimate the time the transaction was open but not spent executing queries, running Ruby code, or paused for garbage collection. A large value indicates the process was waiting on something other than the database (an HTTP request, a sleep, a lock, etc.) while it held the transaction open.

The wall clock time of each query is subtracted first since it already includes any GC and CPU time that occurred while the query ran. Only the GC and CPU time that occurred outside of queries is then subtracted from the remainder. GC and CPU time normally cover distinct intervals, but they overlap when this thread triggers a GC; when subtracting both would drive the result negative, only the larger of the two is subtracted so the shared interval is removed once (the same heuristic used for the query time). The result is clamped so it is never negative and never exceeds the elapsed time.

Returns:

  • (Float)


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/active_record_query_counter/transaction_details.rb', line 51

def idle_time
  return 0.0 if elapsed_time <= 0.0

  queries_elapsed_time = 0.0
  queries_gc_time = 0.0
  queries_cpu_time = 0.0
  queries.each do |query|
    queries_elapsed_time += query.elapsed_time
    queries_gc_time += query.gc_time
    queries_cpu_time += query.cpu_time
  end

  remaining_time = elapsed_time - queries_elapsed_time
  return 0.0 if remaining_time <= 0.0

  other_gc_time = (gc_time - queries_gc_time).clamp(0.0, remaining_time)
  other_cpu_time = (cpu_time - queries_cpu_time).clamp(0.0, remaining_time)

  idle_time = remaining_time - (other_gc_time + other_cpu_time)
  idle_time = remaining_time - [other_gc_time, other_cpu_time].max if idle_time.negative?
  idle_time.clamp(0.0, remaining_time)
end

#query_countInteger

Return the number of queries executed within the transaction.

Returns:

  • (Integer)


33
34
35
# File 'lib/active_record_query_counter/transaction_details.rb', line 33

def query_count
  queries.size
end