lib/prosopite.rb in prosopite-0.1.4 vs lib/prosopite.rb in prosopite-0.1.5
- old
+ new
@@ -8,28 +8,38 @@
:rails_logger,
:prosopite_logger,
:whitelist
def scan
+ @scan ||= false
return if scan?
+
subscribe
@query_counter = Hash.new(0)
@query_holder = Hash.new { |h, k| h[k] = [] }
@query_caller = {}
@whitelist ||= []
+
@scan = true
end
def scan?
@scan
end
def finish
return unless scan?
+ @scan = false
+
+ create_notifications
+ send_notifications if @notifications.present?
+ end
+
+ def create_notifications
@notifications = {}
@query_counter.each do |location_key, count|
if count > 1
fingerprints = @query_holder[location_key].map do |q|
@@ -49,23 +59,24 @@
@notifications[queries] = kaller
end
end
end
end
+ end
- @scan = false
- Prosopite.send_notifications if @notifications.present?
+ def fingerprint(query)
+ if ActiveRecord::Base.connection.adapter_name.downcase.include?('mysql')
+ mysql_fingerprint(query)
+ else
+ PgQuery.fingerprint(query)
+ end
end
# Many thanks to https://github.com/genkami/fluent-plugin-query-fingerprint/
- def fingerprint(query)
+ def mysql_fingerprint(query)
query = query.dup
- unless ActiveRecord::Base.connection.adapter_name.downcase.include?('mysql')
- return PgQuery.fingerprint(query)
- end
-
return "mysqldump" if query =~ %r#\ASELECT /\*!40001 SQL_NO_CACHE \*/ \* FROM `#
return "percona-toolkit" if query =~ %r#\*\w+\.\w+:[0-9]/[0-9]\*/#
if match = /\A\s*(call\s+\S+)\(/i.match(query)
return match.captures.first.downcase!
end
@@ -106,10 +117,15 @@
query
end
def send_notifications
+ @rails_logger ||= false
+ @stderr_logger ||= false
+ @prosopite_logger ||= false
+ @raise ||= false
+
notifications_str = ''
@notifications.each do |queries, kaller|
notifications_str << "N+1 queries detected:\n"
queries.each { |q| notifications_str << " #{q}\n" }
@@ -131,12 +147,12 @@
raise NPlusOneQueriesError.new(notifications_str) if @raise
end
def subscribe
+ @subscribed ||= false
return if @subscribed
- @subscribed = true
ActiveSupport::Notifications.subscribe 'sql.active_record' do |_, _, _, _, data|
sql = data[:sql]
if scan? && sql.include?('SELECT') && data[:cached].nil?
@@ -148,8 +164,10 @@
if @query_counter[location_key] > 1
@query_caller[location_key] = caller.dup
end
end
end
+
+ @subscribed = true
end
end
end