Class: Errorgap::SpanCollector
- Inherits:
-
Object
- Object
- Errorgap::SpanCollector
- 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
- .flush ⇒ Object
-
.install ⇒ Object
Call once at boot (from Railtie).
- .normalize_sql(sql) ⇒ Object
- .start ⇒ Object
- .store ⇒ Object
Class Method Details
.flush ⇒ Object
55 56 57 58 59 |
# File 'lib/errorgap/span_collector.rb', line 55 def flush spans = Thread.current[THREAD_KEY] || [] Thread.current[THREAD_KEY] = nil spans end |
.install ⇒ Object
Call once at boot (from Railtie). Subscribers only record while a transaction is being collected (the middleware starts one per request when APM is enabled), so installing unconditionally is safe — and required, since app initializers that enable APM run after railtie initializers.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/errorgap/span_collector.rb', line 22 def install return unless defined?(ActiveSupport::Notifications) return if @installed @installed = true 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 # Rails reports view_runtime with database time already subtracted, so # this does not double count the db spans above. ActiveSupport::Notifications.subscribe("process_action.action_controller") do |*, payload| next unless Thread.current[THREAD_KEY] view_ms = payload[:view_runtime] next unless view_ms&.positive? store << Span.new(kind: "view", duration_ms: view_ms.round(3)) end end |
.normalize_sql(sql) ⇒ Object
65 66 67 |
# File 'lib/errorgap/span_collector.rb', line 65 def normalize_sql(sql) sql.gsub(NORMALIZE_PATTERN, "?").gsub(/\s+/, " ").strip end |
.start ⇒ Object
51 52 53 |
# File 'lib/errorgap/span_collector.rb', line 51 def start Thread.current[THREAD_KEY] = [] end |
.store ⇒ Object
61 62 63 |
# File 'lib/errorgap/span_collector.rb', line 61 def store Thread.current[THREAD_KEY] ||= [] end |