Module: Furia::Observer

Defined in:
lib/furia/observer.rb

Class Method Summary collapse

Class Method Details

.trace_cleanerObject



48
49
50
51
52
53
54
55
# File 'lib/furia/observer.rb', line 48

def self.trace_cleaner
  @trace_cleaner ||=
    ActiveSupport::BacktraceCleaner.new.tap do |c|
      c.add_silencer { |line| line.include?("/gems/") }
      c.add_silencer { |line| line.include?("/ruby/") }
      c.add_silencer { |line| line.include?("/active_record/") }
    end
end

.wrap(scope) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
# File 'lib/furia/observer.rb', line 5

def self.wrap(scope)
  @root_scope ||= { uid: "root", type: "group", scope: scope, total_queries_num: 0, total_duration_ms: 0, entries: [] }
  parent_scope = @current_scope
  @current_scope =
    if parent_scope
      { uid: SecureRandom.hex(16), type: "group", scope: scope, total_duration_ms: 0, entries: [] }.tap do |new_scope|
        parent_scope[:entries] << new_scope
      end
    else
      @root_scope
    end

  subscriber =
    ActiveSupport::Notifications.subscribe("sql.active_record") do |_, started, finished, _, payload|
      next if payload[:name] == "SCHEMA"

      duration_ms = (finished - started) * 1000
      @current_scope[:total_duration_ms] += duration_ms
      entry = {
        uid: SecureRandom.hex(16),
        type: "query",
        sql: payload[:sql],
        cached: payload[:name] == "CACHE",
        duration_ms: duration_ms,
        stacktrace: trace_cleaner.clean(caller),
      }.freeze

      @current_scope[:entries] << entry
      @root_scope[:total_queries_num] += 1
    end

  yield

  if parent_scope
    parent_scope[:total_duration_ms] += @current_scope[:total_duration_ms]
    @current_scope = parent_scope
  else
    Furia::Sample.create!(data: @root_scope)
  end
ensure
  ActiveSupport::Notifications.unsubscribe(subscriber)
end