prosopite 1.0.2 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +29 -5
- data/lib/prosopite/version.rb +1 -1
- data/lib/prosopite.rb +31 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77276ce50263c0d9e2e4a9e0c525924ac5810367f036d783197222819f8fb312
|
4
|
+
data.tar.gz: b43868ebc87b40d97997db1c7a77fb3ee34cb032a76a0b290adb174c8d04c6d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5fc318b3becb5095f93244d8e23699c27e604c43ba7a3dc489ee3939d19b23e26a47eb4957d6355f28fdaa18fb6ecaa2caf27721a03fcadadefa73a5cbcfec7e
|
7
|
+
data.tar.gz: e5954aa6aec45c26722f807dcb2fde6aae4c1090d097cc7172a306cdde9639b734d226826fa1d6dcab59a9d22857dc7901978eb4297287ac49b81a63b23ae0e1
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -127,11 +127,12 @@ Prosopite auto-detection can be enabled on all controllers:
|
|
127
127
|
```ruby
|
128
128
|
class ApplicationController < ActionController::Base
|
129
129
|
unless Rails.env.production?
|
130
|
-
|
130
|
+
around_action :n_plus_one_detection
|
131
|
+
|
132
|
+
def n_plus_one_detection
|
131
133
|
Prosopite.scan
|
132
|
-
|
133
|
-
|
134
|
-
after_action do
|
134
|
+
yield
|
135
|
+
ensure
|
135
136
|
Prosopite.finish
|
136
137
|
end
|
137
138
|
end
|
@@ -181,7 +182,13 @@ WARNING: scan/finish should run before/after **each** test and NOT before/after
|
|
181
182
|
Ignore notifications for call stacks containing one or more substrings:
|
182
183
|
|
183
184
|
```ruby
|
184
|
-
Prosopite.
|
185
|
+
Prosopite.allow_stack_paths = ['substring_in_call_stack']
|
186
|
+
```
|
187
|
+
|
188
|
+
Ignore notifications matching a specific SQL query:
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
Prosopite.ignore_queries = [/regex_match/, "SELECT * from EXACT_STRING_MATCH"]
|
185
192
|
```
|
186
193
|
|
187
194
|
## Scanning code outside controllers or tests
|
@@ -202,6 +209,23 @@ Prosopite.scan do
|
|
202
209
|
end
|
203
210
|
```
|
204
211
|
|
212
|
+
## Pausing and resuming scans
|
213
|
+
|
214
|
+
Scans can be paused:
|
215
|
+
|
216
|
+
```ruby
|
217
|
+
Prosopite.scan
|
218
|
+
# <code to scan>
|
219
|
+
Prosopite.pause
|
220
|
+
# <code that has n+1s>
|
221
|
+
Prosopite.resume
|
222
|
+
# <code to scan>
|
223
|
+
Prosopite.finish
|
224
|
+
```
|
225
|
+
|
226
|
+
An example of when you might use this is if you are [testing Active Jobs inline](https://guides.rubyonrails.org/testing.html#testing-jobs),
|
227
|
+
and don't want to run Prosopite on background job code, just foreground app code. In that case you could write an [Active Job callback](https://edgeguides.rubyonrails.org/active_job_basics.html#callbacks) that pauses the scan while the job is running.
|
228
|
+
|
205
229
|
## Contributing
|
206
230
|
|
207
231
|
Bug reports and pull requests are welcome on GitHub at https://github.com/charkost/prosopite.
|
data/lib/prosopite/version.rb
CHANGED
data/lib/prosopite.rb
CHANGED
@@ -1,12 +1,21 @@
|
|
1
1
|
|
2
2
|
module Prosopite
|
3
|
+
DEFAULT_ALLOW_LIST = %w(active_record/associations/preloader active_record/validations/uniqueness)
|
4
|
+
|
3
5
|
class NPlusOneQueriesError < StandardError; end
|
4
6
|
class << self
|
5
7
|
attr_writer :raise,
|
6
8
|
:stderr_logger,
|
7
9
|
:rails_logger,
|
8
10
|
:prosopite_logger,
|
9
|
-
:
|
11
|
+
:allow_stack_paths,
|
12
|
+
:ignore_queries
|
13
|
+
|
14
|
+
def allow_list=(value)
|
15
|
+
puts "Prosopite.allow_list= is deprecated. Use Prosopite.allow_stack_paths= instead."
|
16
|
+
|
17
|
+
self.allow_stack_paths = value
|
18
|
+
end
|
10
19
|
|
11
20
|
def scan
|
12
21
|
tc[:prosopite_scan] ||= false
|
@@ -18,7 +27,7 @@ module Prosopite
|
|
18
27
|
tc[:prosopite_query_holder] = Hash.new { |h, k| h[k] = [] }
|
19
28
|
tc[:prosopite_query_caller] = {}
|
20
29
|
|
21
|
-
@
|
30
|
+
@allow_stack_paths ||= []
|
22
31
|
|
23
32
|
tc[:prosopite_scan] = true
|
24
33
|
|
@@ -36,6 +45,14 @@ module Prosopite
|
|
36
45
|
Thread.current
|
37
46
|
end
|
38
47
|
|
48
|
+
def pause
|
49
|
+
tc[:prosopite_scan] = false
|
50
|
+
end
|
51
|
+
|
52
|
+
def resume
|
53
|
+
tc[:prosopite_scan] = true
|
54
|
+
end
|
55
|
+
|
39
56
|
def scan?
|
40
57
|
tc[:prosopite_scan]
|
41
58
|
end
|
@@ -62,14 +79,15 @@ module Prosopite
|
|
62
79
|
end
|
63
80
|
end
|
64
81
|
|
82
|
+
next unless fingerprints.uniq.size == 1
|
83
|
+
|
65
84
|
kaller = tc[:prosopite_query_caller][location_key]
|
85
|
+
allow_list = (@allow_stack_paths + DEFAULT_ALLOW_LIST)
|
86
|
+
is_allowed = kaller.any? { |f| allow_list.any? { |s| f.include?(s) } }
|
66
87
|
|
67
|
-
|
88
|
+
unless is_allowed
|
68
89
|
queries = tc[:prosopite_query_holder][location_key]
|
69
|
-
|
70
|
-
unless kaller.any? { |f| f.include?('active_record/validations/uniqueness') }
|
71
|
-
tc[:prosopite_notifications][queries] = kaller
|
72
|
-
end
|
90
|
+
tc[:prosopite_notifications][queries] = kaller
|
73
91
|
end
|
74
92
|
end
|
75
93
|
end
|
@@ -170,6 +188,11 @@ module Prosopite
|
|
170
188
|
str.split("\n").map { |line| "\e[91m#{line}\e[0m" }.join("\n")
|
171
189
|
end
|
172
190
|
|
191
|
+
def ignore_query?(sql)
|
192
|
+
@ignore_queries ||= []
|
193
|
+
@ignore_queries.any? { |q| q === sql }
|
194
|
+
end
|
195
|
+
|
173
196
|
def subscribe
|
174
197
|
@subscribed ||= false
|
175
198
|
return if @subscribed
|
@@ -177,7 +200,7 @@ module Prosopite
|
|
177
200
|
ActiveSupport::Notifications.subscribe 'sql.active_record' do |_, _, _, _, data|
|
178
201
|
sql, name = data[:sql], data[:name]
|
179
202
|
|
180
|
-
if scan? && name != "SCHEMA" && sql.include?('SELECT') && data[:cached].nil?
|
203
|
+
if scan? && name != "SCHEMA" && sql.include?('SELECT') && data[:cached].nil? && !ignore_query?(sql)
|
181
204
|
location_key = Digest::SHA1.hexdigest(caller.join)
|
182
205
|
|
183
206
|
tc[:prosopite_query_counter][location_key] += 1
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prosopite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mpampis Kostas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry
|