Class: QueryOwl::Middleware

Inherits:
Object
  • Object
show all
Defined in:
lib/query_owl/middleware.rb

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ Middleware

Returns a new instance of Middleware.



3
4
5
# File 'lib/query_owl/middleware.rb', line 3

def initialize(app)
  @app = app
end

Instance Method Details

#call(env) ⇒ Object



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
# File 'lib/query_owl/middleware.rb', line 7

def call(env)
  tracking = false
  return @app.call(env) unless QueryOwl.config.enabled
  return @app.call(env) if ignored_path?(env["PATH_INFO"])

  tracking = true
  QueryTracker.start!
  EagerLoadTracker.start!
  @app.call(env)
ensure
  if tracking
    params     = env["action_dispatch.request.path_parameters"] || {}
    RequestContext.set(controller: params[:controller], action: params[:action], path: env["PATH_INFO"])
    queries    = QueryTracker.stop!
    eager_data = EagerLoadTracker.stop!
    context    = RequestContext.current
    RequestContext.clear

    unless ignored_controller?(context[:controller])
      events = (Detector.detect_n_plus_one(queries) +
                Detector.detect_slow_queries(queries) +
                Detector.detect_unused_eager_loads(eager_data))
               .map { |e| e.merge(context) }
      events.each do |event|
        QueryOwl.config.notifiers.each do |notifier|
          notifier.call(event)
        rescue => e
          Rails.logger.error "[QueryOwl] Notifier #{notifier.class} raised: #{e.message}"
        end
      end
      Logger.log_summary(events)
      events.each { |e| EventStore.push(e) }
      FileLogger.append(events)
      raise_on_n_plus_one!(events) if QueryOwl.config.raise_on_n_plus_one
    end
  end
end

#raise_on_n_plus_one!(events) ⇒ Object

Raises:



45
46
47
48
49
50
# File 'lib/query_owl/middleware.rb', line 45

def raise_on_n_plus_one!(events)
  event = events.find { |e| e[:type] == :n_plus_one }
  return unless event

  raise NPlusOneError, "N+1 detected: #{event[:sql]} (#{event[:count]} times) #{event[:backtrace].first}"
end