prosopite 1.4.2 → 2.1.0
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/.github/workflows/ci.yml +1 -1
- data/Gemfile.lock +97 -48
- data/README.md +80 -29
- data/lib/prosopite/version.rb +1 -1
- data/lib/prosopite.rb +24 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79f272a757baeae3f05f7721b7204130588532ac09fb28d163d09737512f8edd
|
4
|
+
data.tar.gz: d45ecc27ba09f2b55447eb82f9fc35773846cf44d924b710a83eaa5ada5260a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60cd8f6dc74fc8a51e7ada04ae53212c8965309ffbe67ad83f6e2537a289bb205a4e626e44fda4b14673aed407cf2bb706306ba0f47051d22da7a16c78f73fcb
|
7
|
+
data.tar.gz: 66c392a288ddbdf44bacc433740c9b6c2e7213c714e80c77992581460736300451a0f7add73196d81203a0533900424128754960ffbce6914d20c9e01cfdb8c5
|
data/.github/workflows/ci.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,87 +1,136 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
prosopite (1.
|
4
|
+
prosopite (2.1.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
actionpack (
|
10
|
-
actionview (=
|
11
|
-
activesupport (=
|
12
|
-
|
9
|
+
actionpack (8.0.1)
|
10
|
+
actionview (= 8.0.1)
|
11
|
+
activesupport (= 8.0.1)
|
12
|
+
nokogiri (>= 1.8.5)
|
13
|
+
rack (>= 2.2.4)
|
14
|
+
rack-session (>= 1.0.1)
|
13
15
|
rack-test (>= 0.6.3)
|
14
|
-
rails-dom-testing (~> 2.
|
15
|
-
rails-html-sanitizer (~> 1.
|
16
|
-
|
17
|
-
|
16
|
+
rails-dom-testing (~> 2.2)
|
17
|
+
rails-html-sanitizer (~> 1.6)
|
18
|
+
useragent (~> 0.16)
|
19
|
+
actionview (8.0.1)
|
20
|
+
activesupport (= 8.0.1)
|
18
21
|
builder (~> 3.1)
|
19
|
-
erubi (~> 1.
|
20
|
-
rails-dom-testing (~> 2.
|
21
|
-
rails-html-sanitizer (~> 1.
|
22
|
-
activemodel (
|
23
|
-
activesupport (=
|
24
|
-
activerecord (
|
25
|
-
activemodel (=
|
26
|
-
activesupport (=
|
27
|
-
|
28
|
-
|
22
|
+
erubi (~> 1.11)
|
23
|
+
rails-dom-testing (~> 2.2)
|
24
|
+
rails-html-sanitizer (~> 1.6)
|
25
|
+
activemodel (8.0.1)
|
26
|
+
activesupport (= 8.0.1)
|
27
|
+
activerecord (8.0.1)
|
28
|
+
activemodel (= 8.0.1)
|
29
|
+
activesupport (= 8.0.1)
|
30
|
+
timeout (>= 0.4.0)
|
31
|
+
activesupport (8.0.1)
|
32
|
+
base64
|
33
|
+
benchmark (>= 0.3)
|
34
|
+
bigdecimal
|
35
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
36
|
+
connection_pool (>= 2.2.5)
|
37
|
+
drb
|
29
38
|
i18n (>= 1.6, < 2)
|
39
|
+
logger (>= 1.4.2)
|
30
40
|
minitest (>= 5.1)
|
31
|
-
|
32
|
-
|
41
|
+
securerandom (>= 0.3)
|
42
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
43
|
+
uri (>= 0.13.1)
|
33
44
|
ansi (1.5.0)
|
45
|
+
base64 (0.2.0)
|
46
|
+
benchmark (0.4.0)
|
47
|
+
bigdecimal (3.1.9)
|
34
48
|
builder (3.2.4)
|
35
49
|
coderay (1.1.3)
|
36
|
-
concurrent-ruby (1.
|
50
|
+
concurrent-ruby (1.3.5)
|
51
|
+
connection_pool (2.5.0)
|
37
52
|
crass (1.0.6)
|
53
|
+
date (3.4.1)
|
54
|
+
drb (2.2.1)
|
38
55
|
erubi (1.12.0)
|
39
|
-
factory_bot (6.1
|
40
|
-
activesupport (>=
|
56
|
+
factory_bot (6.5.1)
|
57
|
+
activesupport (>= 6.1.0)
|
41
58
|
i18n (1.8.9)
|
42
59
|
concurrent-ruby (~> 1.0)
|
43
|
-
|
60
|
+
io-console (0.8.0)
|
61
|
+
irb (1.15.1)
|
62
|
+
pp (>= 0.6.0)
|
63
|
+
rdoc (>= 4.0.0)
|
64
|
+
reline (>= 0.4.2)
|
65
|
+
logger (1.6.6)
|
66
|
+
loofah (2.24.0)
|
44
67
|
crass (~> 1.0.2)
|
45
|
-
nokogiri (>= 1.
|
68
|
+
nokogiri (>= 1.12.0)
|
46
69
|
method_source (1.0.0)
|
47
|
-
mini_portile2 (2.8.
|
48
|
-
minitest (5.
|
70
|
+
mini_portile2 (2.8.8)
|
71
|
+
minitest (5.25.4)
|
49
72
|
minitest-reporters (1.5.0)
|
50
73
|
ansi
|
51
74
|
builder
|
52
75
|
minitest (>= 5.0)
|
53
76
|
ruby-progressbar
|
54
|
-
nokogiri (1.
|
55
|
-
mini_portile2 (~> 2.8.
|
77
|
+
nokogiri (1.18.3)
|
78
|
+
mini_portile2 (~> 2.8.2)
|
56
79
|
racc (~> 1.4)
|
57
|
-
nokogiri (1.
|
80
|
+
nokogiri (1.18.3-x86_64-linux-gnu)
|
58
81
|
racc (~> 1.4)
|
59
82
|
pg_query (1.3.0)
|
83
|
+
pp (0.6.2)
|
84
|
+
prettyprint
|
85
|
+
prettyprint (0.2.0)
|
60
86
|
pry (0.14.0)
|
61
87
|
coderay (~> 1.1)
|
62
88
|
method_source (~> 1.0)
|
63
|
-
|
64
|
-
|
89
|
+
psych (5.2.3)
|
90
|
+
date
|
91
|
+
stringio
|
92
|
+
racc (1.8.1)
|
93
|
+
rack (3.1.10)
|
94
|
+
rack-session (2.1.0)
|
95
|
+
base64 (>= 0.1.0)
|
96
|
+
rack (>= 3.0.0)
|
65
97
|
rack-test (2.0.2)
|
66
98
|
rack (>= 1.3)
|
67
|
-
|
68
|
-
|
99
|
+
rackup (2.2.1)
|
100
|
+
rack (>= 3)
|
101
|
+
rails-dom-testing (2.2.0)
|
102
|
+
activesupport (>= 5.0.0)
|
103
|
+
minitest
|
69
104
|
nokogiri (>= 1.6)
|
70
|
-
rails-html-sanitizer (1.
|
71
|
-
loofah (~> 2.
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
105
|
+
rails-html-sanitizer (1.6.2)
|
106
|
+
loofah (~> 2.21)
|
107
|
+
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
108
|
+
railties (8.0.1)
|
109
|
+
actionpack (= 8.0.1)
|
110
|
+
activesupport (= 8.0.1)
|
111
|
+
irb (~> 1.13)
|
112
|
+
rackup (>= 1.0.0)
|
113
|
+
rake (>= 12.2)
|
114
|
+
thor (~> 1.0, >= 1.2.2)
|
115
|
+
zeitwerk (~> 2.6)
|
78
116
|
rake (13.0.6)
|
117
|
+
rdoc (6.12.0)
|
118
|
+
psych (>= 4.0.0)
|
119
|
+
reline (0.6.0)
|
120
|
+
io-console (~> 0.5)
|
79
121
|
ruby-progressbar (1.11.0)
|
80
|
-
|
81
|
-
|
82
|
-
|
122
|
+
securerandom (0.4.1)
|
123
|
+
sqlite3 (2.5.0)
|
124
|
+
mini_portile2 (~> 2.8.0)
|
125
|
+
sqlite3 (2.5.0-x86_64-linux-gnu)
|
126
|
+
stringio (3.1.4)
|
127
|
+
thor (1.3.2)
|
128
|
+
timeout (0.4.3)
|
129
|
+
tzinfo (2.0.6)
|
83
130
|
concurrent-ruby (~> 1.0)
|
84
|
-
|
131
|
+
uri (1.0.2)
|
132
|
+
useragent (0.16.11)
|
133
|
+
zeitwerk (2.7.2)
|
85
134
|
|
86
135
|
PLATFORMS
|
87
136
|
ruby
|
@@ -100,4 +149,4 @@ DEPENDENCIES
|
|
100
149
|
sqlite3
|
101
150
|
|
102
151
|
BUNDLED WITH
|
103
|
-
2.
|
152
|
+
2.6.5
|
data/README.md
CHANGED
@@ -116,37 +116,17 @@ Or install it yourself as:
|
|
116
116
|
The preferred type of notifications can be configured with:
|
117
117
|
|
118
118
|
* `Prosopite.min_n_queries`: Minimum number of N queries to report per N+1 case. Defaults to 2.
|
119
|
-
* `Prosopite.raise = true`: Raise warnings as exceptions
|
120
|
-
* `Prosopite.
|
121
|
-
* `
|
122
|
-
* `Prosopite.
|
119
|
+
* `Prosopite.raise = true`: Raise warnings as exceptions. Defaults to `false`.
|
120
|
+
* `Prosopite.start_raise`: Raises warnings as exceptions from when this is called. Overrides `Proposite.raise`.
|
121
|
+
* `Propsoite.stop_raise`: Disables raising warnings as exceptions if previously enabled with `Proposite.start_raise`.
|
122
|
+
* `Prosopite.local_raise?`: Returns `true` if `Prosopite.start_raise` has been called previously.
|
123
|
+
* `Prosopite.rails_logger = true`: Send warnings to the Rails log. Defaults to `false`.
|
124
|
+
* `Prosopite.prosopite_logger = true`: Send warnings to `log/prosopite.log`. Defaults to `false`.
|
125
|
+
* `Prosopite.stderr_logger = true`: Send warnings to STDERR. Defaults to `false`.
|
123
126
|
* `Prosopite.backtrace_cleaner = my_custom_backtrace_cleaner`: use a different [ActiveSupport::BacktraceCleaner](https://api.rubyonrails.org/classes/ActiveSupport/BacktraceCleaner.html). Defaults to `Rails.backtrace_cleaner`.
|
124
|
-
* `Prosopite.custom_logger = my_custom_logger`:
|
127
|
+
* `Prosopite.custom_logger = my_custom_logger`: Set a custom logger. See the following section for the details. Defaults to `false`.
|
125
128
|
* `Prosopite.enabled = true`: Enables or disables the gem. Defaults to `true`.
|
126
129
|
|
127
|
-
### Custom Logging Configuration
|
128
|
-
|
129
|
-
You can supply a custom logger with the `Prosopite.custom_logger` setting.
|
130
|
-
|
131
|
-
This is useful for circumstances where you don't want your logs to be
|
132
|
-
highlighted with red, or you want logs sent to a custom location.
|
133
|
-
|
134
|
-
One common scenario is that you may be generating json logs and sending them to
|
135
|
-
Datadog, ELK stack, or similar, and don't want to have to remove the default red
|
136
|
-
escaping data from messages sent to the Rails logger, or want to tag them
|
137
|
-
differently with your own custom logger.
|
138
|
-
|
139
|
-
```ruby
|
140
|
-
# Turns off logging with red highlights, but still sends them to the Rails logger
|
141
|
-
Prosopite.custom_logger = Rails.logger
|
142
|
-
```
|
143
|
-
|
144
|
-
```ruby
|
145
|
-
# Use a completely custom logging instance
|
146
|
-
Prosopite.custom_logger = MyLoggerClass.new
|
147
|
-
|
148
|
-
```
|
149
|
-
|
150
130
|
## Development Environment Usage
|
151
131
|
|
152
132
|
Prosopite auto-detection can be enabled on all controllers:
|
@@ -174,7 +154,7 @@ config.after_initialize do
|
|
174
154
|
Prosopite.rails_logger = true
|
175
155
|
end
|
176
156
|
```
|
177
|
-
|
157
|
+
```
|
178
158
|
## Test Environment Usage
|
179
159
|
|
180
160
|
Tests with N+1 queries can be configured to fail with:
|
@@ -315,6 +295,77 @@ Pauses can be ignored with `Prosopite.ignore_pauses = true` in case you want to
|
|
315
295
|
An example of when you might use this is if you are [testing Active Jobs inline](https://guides.rubyonrails.org/testing.html#testing-jobs),
|
316
296
|
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.
|
317
297
|
|
298
|
+
## Local Raise
|
299
|
+
|
300
|
+
In some cases you may want to configure prosopite to not raise by default and only raise in certain scenarios.
|
301
|
+
In this example we scan on all controllers but also provide an API to only raise on specific actions.
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
Proposite.raise = false
|
305
|
+
```
|
306
|
+
|
307
|
+
```ruby
|
308
|
+
# app/controllers/application_controller.rb
|
309
|
+
class ApplicationController < ActionController::Base
|
310
|
+
def raise_on_n_plus_ones!(**options)
|
311
|
+
return if Rails.env.production?
|
312
|
+
|
313
|
+
prepend_around_action(:_raise_on_n_plus_ones, **options)
|
314
|
+
end
|
315
|
+
|
316
|
+
unless Rails.env.production?
|
317
|
+
around_action :n_plus_one_detection
|
318
|
+
|
319
|
+
def n_plus_one_detection
|
320
|
+
...
|
321
|
+
end
|
322
|
+
|
323
|
+
def _raise_on_n_plus_ones
|
324
|
+
Proposite.start_raise
|
325
|
+
yield
|
326
|
+
ensure
|
327
|
+
Prosopite.stop_raise
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
```
|
332
|
+
```ruby
|
333
|
+
# app/controllers/books_controller.rb
|
334
|
+
class BooksController < ApplicationController
|
335
|
+
raise_on_n_plus_ones!(only: [:index])
|
336
|
+
|
337
|
+
def index
|
338
|
+
@books = Book.all.map(&:author) # This will raise N+1 errors
|
339
|
+
end
|
340
|
+
|
341
|
+
def show
|
342
|
+
@book = Book.find(params[:id])
|
343
|
+
@book.reviews.map(&:author) # This will not raise N+1 errors
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
## Custom Logging Configuration
|
348
|
+
|
349
|
+
You can supply a custom logger with the `Prosopite.custom_logger` setting.
|
350
|
+
|
351
|
+
This is useful for circumstances where you don't want your logs to be
|
352
|
+
highlighted with red, or you want logs sent to a custom location.
|
353
|
+
|
354
|
+
One common scenario is that you may be generating json logs and sending them to
|
355
|
+
Datadog, ELK stack, or similar, and don't want to have to remove the default red
|
356
|
+
escaping data from messages sent to the Rails logger, or want to tag them
|
357
|
+
differently with your own custom logger.
|
358
|
+
|
359
|
+
```ruby
|
360
|
+
# Turns off logging with red highlights, but still sends them to the Rails logger
|
361
|
+
Prosopite.custom_logger = Rails.logger
|
362
|
+
```
|
363
|
+
|
364
|
+
```ruby
|
365
|
+
# Use a completely custom logging instance
|
366
|
+
Prosopite.custom_logger = MyLoggerClass.new
|
367
|
+
```
|
368
|
+
|
318
369
|
## Contributing
|
319
370
|
|
320
371
|
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
@@ -113,6 +113,22 @@ module Prosopite
|
|
113
113
|
tc[:prosopite_query_caller] = nil
|
114
114
|
end
|
115
115
|
|
116
|
+
def start_raise
|
117
|
+
tc[:prosopite_local_raise] = true
|
118
|
+
end
|
119
|
+
|
120
|
+
def stop_raise
|
121
|
+
tc[:prosopite_local_raise] = false
|
122
|
+
end
|
123
|
+
|
124
|
+
def local_raise?
|
125
|
+
tc[:prosopite_local_raise] == true
|
126
|
+
end
|
127
|
+
|
128
|
+
def raise?
|
129
|
+
local_raise? || !!@raise
|
130
|
+
end
|
131
|
+
|
116
132
|
def create_notifications
|
117
133
|
tc[:prosopite_notifications] = {}
|
118
134
|
|
@@ -144,7 +160,12 @@ module Prosopite
|
|
144
160
|
end
|
145
161
|
|
146
162
|
def fingerprint(query)
|
147
|
-
|
163
|
+
conn = if ActiveRecord::Base.respond_to?(:lease_connection)
|
164
|
+
ActiveRecord::Base.lease_connection
|
165
|
+
else
|
166
|
+
ActiveRecord::Base.connection
|
167
|
+
end
|
168
|
+
db_adapter = conn.adapter_name.downcase
|
148
169
|
if db_adapter.include?('mysql') || db_adapter.include?('trilogy')
|
149
170
|
mysql_fingerprint(query)
|
150
171
|
else
|
@@ -212,9 +233,8 @@ module Prosopite
|
|
212
233
|
@rails_logger ||= false
|
213
234
|
@stderr_logger ||= false
|
214
235
|
@prosopite_logger ||= false
|
215
|
-
@raise ||= false
|
216
236
|
|
217
|
-
notifications_str = ''
|
237
|
+
notifications_str = String.new('')
|
218
238
|
|
219
239
|
tc[:prosopite_notifications].each do |queries, kaller|
|
220
240
|
notifications_str << "N+1 queries detected:\n"
|
@@ -241,7 +261,7 @@ module Prosopite
|
|
241
261
|
end
|
242
262
|
end
|
243
263
|
|
244
|
-
raise NPlusOneQueriesError.new(notifications_str) if
|
264
|
+
raise NPlusOneQueriesError.new(notifications_str) if raise?
|
245
265
|
end
|
246
266
|
|
247
267
|
def red(str)
|
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.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mpampis Kostas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry
|
@@ -148,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
148
|
- !ruby/object:Gem::Version
|
149
149
|
version: '0'
|
150
150
|
requirements: []
|
151
|
-
rubygems_version: 3.
|
151
|
+
rubygems_version: 3.5.3
|
152
152
|
signing_key:
|
153
153
|
specification_version: 4
|
154
154
|
summary: N+1 auto-detection for Rails with zero false positives / false negatives
|