Class: Errorgap::SpanCollector

Inherits:
Object
  • Object
show all
Defined in:
lib/errorgap/span_collector.rb

Constant Summary collapse

THREAD_KEY =
:errorgap_spans
NORMALIZE_PATTERN =

Quoted strings and standalone numeric literals → ?

/
  '(?:[^'\\]|\\.)*'   # single-quoted string literals
  |
  \b\d+(?:\.\d+)?\b   # integer and float literals
/x
SKIP_NAMES =
%w[SCHEMA EXPLAIN CACHE].freeze

Class Method Summary collapse

Class Method Details

.flushObject



37
38
39
40
41
# File 'lib/errorgap/span_collector.rb', line 37

def flush
  spans = Thread.current[THREAD_KEY] || []
  Thread.current[THREAD_KEY] = nil
  spans
end

.installObject

Call once at boot (from Railtie) when APM is enabled.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/errorgap/span_collector.rb', line 18

def install
  return unless defined?(ActiveSupport::Notifications)

  ActiveSupport::Notifications.subscribe("sql.active_record") do |*, payload|
    next unless Thread.current[THREAD_KEY]
    next if SKIP_NAMES.any? { |n| payload[:name]&.start_with?(n) }
    next if payload[:cached]

    duration_ms = payload[:duration] || 0.0
    sql = normalize_sql(payload[:sql].to_s)

    store << Span.new(kind: "db", sql: sql, duration_ms: duration_ms.round(3))
  end
end

.normalize_sql(sql) ⇒ Object



47
48
49
# File 'lib/errorgap/span_collector.rb', line 47

def normalize_sql(sql)
  sql.gsub(NORMALIZE_PATTERN, "?").gsub(/\s+/, " ").strip
end

.startObject



33
34
35
# File 'lib/errorgap/span_collector.rb', line 33

def start
  Thread.current[THREAD_KEY] = []
end

.storeObject



43
44
45
# File 'lib/errorgap/span_collector.rb', line 43

def store
  Thread.current[THREAD_KEY] ||= []
end