Module: ActiveUsage::Instrumentation::RuntimeState

Defined in:
lib/active_usage/instrumentation/runtime_state.rb

Constant Summary collapse

SQL_FINGERPRINTS_KEY =
:activeusage_sql_fingerprints
MAX_SQL_QUERIES_PER_EVENT =
20

Class Method Summary collapse

Class Method Details

.accumulate_sql_fingerprint(fingerprints, payload:, duration_ms:) ⇒ Object



37
38
39
40
41
42
43
44
# File 'lib/active_usage/instrumentation/runtime_state.rb', line 37

def accumulate_sql_fingerprint(fingerprints, payload:, duration_ms:)
  fingerprint = normalize_sql(payload[:sql].to_s)
  return fingerprints if fingerprint.empty?

  entry = find_or_build_entry(fingerprints, fingerprint, payload)
  update_entry(entry, duration_ms, payload)
  fingerprints.merge(fingerprint => entry)
end

.add_sql_event(payload, started_at:, finished_at:) ⇒ Object



15
16
17
18
19
20
21
22
# File 'lib/active_usage/instrumentation/runtime_state.rb', line 15

def add_sql_event(payload, started_at:, finished_at:)
  duration_ms = ((finished_at - started_at) * 1000.0).round(3)
  ActiveSupport::IsolatedExecutionState[SQL_FINGERPRINTS_KEY] = accumulate_sql_fingerprint(
    sql_fingerprints,
    payload: payload,
    duration_ms: duration_ms
  )
end

.clear_sql_stateObject



24
25
26
# File 'lib/active_usage/instrumentation/runtime_state.rb', line 24

def clear_sql_state
  ActiveSupport::IsolatedExecutionState[SQL_FINGERPRINTS_KEY] = {}
end

.consume_sql_queriesObject



28
29
30
31
32
33
34
35
# File 'lib/active_usage/instrumentation/runtime_state.rb', line 28

def consume_sql_queries
  queries = sql_fingerprints
  ActiveSupport::IsolatedExecutionState[SQL_FINGERPRINTS_KEY] = {}
  queries.values
         .sort_by { |query| -query[:total_duration_ms].to_f }
         .first(MAX_SQL_QUERIES_PER_EVENT)
         .map { |query| format_sql_query(query) }
end

.normalize_sql(sql) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/active_usage/instrumentation/runtime_state.rb', line 46

def normalize_sql(sql)
  normalized = sql.dup
  normalized.gsub!(/'(?:[^']|'')*'/, "?")
  normalized.gsub!(/"([^"]*)"/, '\1')
  normalized.gsub!(/\$\d+/, "?")
  normalized.gsub!(/\b\d+(?:\.\d+)?\b/, "?")
  normalized.gsub!(/\(\s*\?(?:\s*,\s*\?)+\s*\)/, "(?)")
  normalized.gsub!(/\s+/, " ")
  normalized.strip!
  normalized
end

.sql_fingerprintsObject



11
12
13
# File 'lib/active_usage/instrumentation/runtime_state.rb', line 11

def sql_fingerprints
  ActiveSupport::IsolatedExecutionState[SQL_FINGERPRINTS_KEY] || {}
end