Module: Furia

Defined in:
lib/furia.rb,
lib/furia/engine.rb,
lib/furia/version.rb,
app/models/furia/sample.rb,
app/helpers/furia/application_helper.rb,
app/controllers/furia/samples_controller.rb,
app/controllers/furia/application_controller.rb

Defined Under Namespace

Modules: ApplicationHelper Classes: ApplicationController, Engine, Group, Query, Sample, SamplesController

Constant Summary collapse

VERSION =
"0.0.4"

Class Method Summary collapse

Class Method Details

.clear_storeObject



92
93
94
# File 'lib/furia.rb', line 92

def self.clear_store
  Thread.current[:furia_store] = {}
end

.create_subscriberObject



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/furia.rb', line 59

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

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

    store[:current_group][:entries] << entry
    store[:current_group][:total_duration_ms] += duration_ms
    store[:root_group][:total_queries_num] += 1
  end
end

.entry_from_hash(hash) ⇒ Object



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

def self.entry_from_hash(hash)
  symbolized = hash.transform_keys(&:to_sym)

  case symbolized[:type]
  when "group"
    Group.from_hash(symbolized)
  when "query"
    Query.from_hash(symbolized)
  else
    raise "Unsupported type: `#{symbolized[:type]}'"
  end
end

.storeObject



88
89
90
# File 'lib/furia.rb', line 88

def self.store
  Thread.current[:furia_store] ||= {}
end

.trace_cleanerObject



79
80
81
82
83
84
85
86
# File 'lib/furia.rb', line 79

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



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/furia.rb', line 32

def self.wrap(scope)
  parent_group = store[:current_group]
  if parent_group
    store[:current_group] = { uid: SecureRandom.hex(16), type: "group", scope: scope, total_duration_ms: 0, entries: [] }
    parent_group[:entries] << store[:current_group]
  else
    store[:root_group] = { uid: "root", type: "group", scope: scope, total_queries_num: 0, total_duration_ms: 0, entries: [] }
    store[:current_group] = store[:root_group]
  end

  subscriber = create_subscriber unless parent_group

  yield.tap do
    if parent_group
      parent_group[:total_duration_ms] += store[:current_group][:total_duration_ms]
      store[:current_group] = parent_group
    else
      Furia::Sample.create!(data: store[:root_group])
    end
  end
ensure
  if subscriber
    ActiveSupport::Notifications.unsubscribe(subscriber)
    clear_store
  end
end