Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add query counts and maximum queries to log configuration #74

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ Or install it yourself as:

The preferred type of notifications can be configured with:

* `Prosopite.min_n_queries`: Minimum number of N queries to report per N+1 case. Defaults to 2.
* `Prosopite.min_n_queries`: Minimum number of N queries required to report per N+1 case. Defaults to 2.
* `Prosopite.display_max_n_queries`: Maximum number of queries to log per N+1 case. Defaults to all queries. Note that this does not change whether an N+1 is reported or not, only how many queries are logged.
* `Prosopite.display_query_count = true`: Include the count of queries for each N+1 case logged.
* `Prosopite.raise = true`: Raise warnings as exceptions
* `Prosopite.rails_logger = true`: Send warnings to the Rails log
* `Prosopite.prosopite_logger = true`: Send warnings to `log/prosopite.log`
Expand Down
20 changes: 17 additions & 3 deletions lib/prosopite.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ class << self

attr_accessor :allow_stack_paths,
:ignore_queries,
:min_n_queries
:min_n_queries,
:display_max_n_queries,
:display_query_count

def allow_list=(value)
puts "Prosopite.allow_list= is deprecated. Use Prosopite.allow_stack_paths= instead."
Expand Down Expand Up @@ -217,9 +219,21 @@ def send_notifications
notifications_str = ''

tc[:prosopite_notifications].each do |queries, kaller|
notifications_str << "N+1 queries detected:\n"
notifications_str <<
if @display_query_count
"N+1 queries detected (#{queries.count}):\n"
else
"N+1 queries detected:\n"
end

queries_to_display =
if @display_max_n_queries
queries.take(@display_max_n_queries)
else
queries
end

queries.each { |q| notifications_str << " #{q}\n" }
queries_to_display.each { |q| notifications_str << " #{q}\n" }

notifications_str << "Call stack:\n"
kaller = backtrace_cleaner.clean(kaller)
Expand Down
48 changes: 48 additions & 0 deletions test/test_queries.rb
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,54 @@ def test_min_n_queries
Prosopite.min_n_queries = 2
end

def test_display_max_n_queries
log_output = StringIO.new
Prosopite.custom_logger = Logger.new(log_output)
Prosopite.display_max_n_queries = 3

# 20 chairs, 4 legs each
chairs = create_list(:chair, 20)
chairs.each { |c| create_list(:leg, 4, chair: c) }

Prosopite.scan
Chair.last(20).each do |c|
c.legs.first
end

assert_n_plus_one

log_lines = log_output.string.split("\n").map(&:strip)
repeated_query =
%(SELECT "legs".* FROM "legs" WHERE "legs"."chair_id" = ? ORDER BY "legs"."id" ASC LIMIT ?)

assert_equal log_lines.count(repeated_query), 3
ensure
Prosopite.custom_logger = nil
Prosopite.display_max_n_queries = nil
end

def test_display_query_count
log_output = StringIO.new
Prosopite.custom_logger = Logger.new(log_output)
Prosopite.display_query_count = true

# 20 chairs, 4 legs each
chairs = create_list(:chair, 20)
chairs.each { |c| create_list(:leg, 4, chair: c) }

Prosopite.scan
Chair.last(20).each do |c|
c.legs.first
end

assert_n_plus_one

assert_includes log_output.string, 'N+1 queries detected (20)'
ensure
Prosopite.custom_logger = nil
Prosopite.display_query_count = false
end

private
def assert_n_plus_one
assert_raises(Prosopite::NPlusOneQueriesError) do
Expand Down