Class: SqlEventAnalyzer

Inherits:
Object
  • Object
show all
Defined in:
lib/sql_event_analyzer.rb,
lib/sql_event_analyzer/version.rb

Overview

Captures Rails SQL events and crunches some statistics

Constant Summary collapse

VERSION =
'0.1.1'.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:) ⇒ SqlEventAnalyzer

Returns a new instance of SqlEventAnalyzer.



38
39
40
41
42
# File 'lib/sql_event_analyzer.rb', line 38

def initialize(name:)
  @name = name
  @root = Rails.root.to_s
  @stats = {}
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



8
9
10
# File 'lib/sql_event_analyzer.rb', line 8

def name
  @name
end

#statsObject (readonly)

Returns the value of attribute stats.



8
9
10
# File 'lib/sql_event_analyzer.rb', line 8

def stats
  @stats
end

Class Method Details

.start(name: Time.current) ⇒ File

captures the events and writes out the result

Returns:

  • (File)

    file containing html output



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/sql_event_analyzer.rb', line 12

def self.start(name: Time.current)
  instance = SqlEventAnalyzer.new(name: name)

  subscription_name = ActiveSupport::Notifications.subscribe('sql.active_record') do |*args|
    event = ActiveSupport::Notifications::Event.new(*args)
    instance.process_event(event)
  end

  if block_given?
    begin
      yield
    ensure
      ActiveSupport::Notifications.unsubscribe(subscription_name)
    end
    write_html(instance)
  end
end

.write_html(instance) ⇒ Object



30
31
32
33
34
35
36
# File 'lib/sql_event_analyzer.rb', line 30

def self.write_html(instance)
  output_dir = 'tmp/sql_event_analyzer'
  output_path = File.join(output_dir, "#{instance.name}.html")
  FileUtils.mkdir_p(output_dir)
  html = instance.render_as_html
  File.open(output_path, 'w') {|f| f << html}
end

Instance Method Details

#process_event(event) ⇒ Object

Parameters:

  • SQL (ActiveSupport::Notifications::Event)

    event from Rails



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/sql_event_analyzer.rb', line 45

def process_event(event)
  # Callers from Rails root and not the subscriber itself
  backtrace = caller.select{|line| relevent_caller?(line) }

  # Initialize a uniq SQL use.
  # `:payload` will always be the first instance of the call.
  stat = @stats[backtrace] ||= {
    order: @stats.size,
    count: 0,
    duration: 0,
    payload: event.payload
  }

  # increment stats
  stat[:count] += 1
  stat[:duration] += event.duration
end

#render_as_htmlObject



63
64
65
# File 'lib/sql_event_analyzer.rb', line 63

def render_as_html
  ERB.new(erb_template).result(binding)
end