prosopite 1.4.2 → 2.2.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/.gitignore +1 -0
- data/Gemfile.lock +97 -48
- data/README.md +82 -29
- data/lib/prosopite/version.rb +1 -1
- data/lib/prosopite.rb +41 -12
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3ba705386994a5f73eb64b024eadd45fd4c29db669ccc408283746d03d58bdf8
|
|
4
|
+
data.tar.gz: b3d52ea151dd88b9da262286df321fcdafd2245ce3b09c9539fd54e9ae54ee8d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e6f74f6cd59e7537429f32300072394c428837e3ec0dd8aed971d601f447c0f3b28e2bdd68f240f98906be205d23958c3cdd8cbf181821cc26f4f435de5f17c8
|
|
7
|
+
data.tar.gz: 570b9ed4965908b45b5f1f5d6dc1b41d84e0b00759c93e1ff875aa181f143c445ec910ad96dfb4c52ba2020e4948660fc203d3ff8cd8c7496bc870acf0df8180
|
data/.github/workflows/ci.yml
CHANGED
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,87 +1,136 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
prosopite (
|
|
4
|
+
prosopite (2.2.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,79 @@ 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
|
+
|
|
333
|
+
```ruby
|
|
334
|
+
# app/controllers/books_controller.rb
|
|
335
|
+
class BooksController < ApplicationController
|
|
336
|
+
raise_on_n_plus_ones!(only: [:index])
|
|
337
|
+
|
|
338
|
+
def index
|
|
339
|
+
@books = Book.all.map(&:author) # This will raise N+1 errors
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def show
|
|
343
|
+
@book = Book.find(params[:id])
|
|
344
|
+
@book.reviews.map(&:author) # This will not raise N+1 errors
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Custom Logging Configuration
|
|
350
|
+
|
|
351
|
+
You can supply a custom logger with the `Prosopite.custom_logger` setting.
|
|
352
|
+
|
|
353
|
+
This is useful for circumstances where you don't want your logs to be
|
|
354
|
+
highlighted with red, or you want logs sent to a custom location.
|
|
355
|
+
|
|
356
|
+
One common scenario is that you may be generating json logs and sending them to
|
|
357
|
+
Datadog, ELK stack, or similar, and don't want to have to remove the default red
|
|
358
|
+
escaping data from messages sent to the Rails logger, or want to tag them
|
|
359
|
+
differently with your own custom logger.
|
|
360
|
+
|
|
361
|
+
```ruby
|
|
362
|
+
# Turns off logging with red highlights, but still sends them to the Rails logger
|
|
363
|
+
Prosopite.custom_logger = Rails.logger
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
```ruby
|
|
367
|
+
# Use a completely custom logging instance
|
|
368
|
+
Prosopite.custom_logger = MyLoggerClass.new
|
|
369
|
+
```
|
|
370
|
+
|
|
318
371
|
## Contributing
|
|
319
372
|
|
|
320
373
|
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
|
@@ -51,6 +51,7 @@ module Prosopite
|
|
|
51
51
|
tc[:prosopite_query_counter] = Hash.new(0)
|
|
52
52
|
tc[:prosopite_query_holder] = Hash.new { |h, k| h[k] = [] }
|
|
53
53
|
tc[:prosopite_query_caller] = {}
|
|
54
|
+
tc[:prosopite_query_duration] = Hash.new(0.0)
|
|
54
55
|
|
|
55
56
|
@allow_stack_paths ||= []
|
|
56
57
|
@ignore_pauses ||= false
|
|
@@ -111,6 +112,23 @@ module Prosopite
|
|
|
111
112
|
tc[:prosopite_query_counter] = nil
|
|
112
113
|
tc[:prosopite_query_holder] = nil
|
|
113
114
|
tc[:prosopite_query_caller] = nil
|
|
115
|
+
tc[:prosopite_query_duration] = nil
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def start_raise
|
|
119
|
+
tc[:prosopite_local_raise] = true
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def stop_raise
|
|
123
|
+
tc[:prosopite_local_raise] = false
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def local_raise?
|
|
127
|
+
tc[:prosopite_local_raise] == true
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def raise?
|
|
131
|
+
local_raise? || !!@raise
|
|
114
132
|
end
|
|
115
133
|
|
|
116
134
|
def create_notifications
|
|
@@ -130,13 +148,14 @@ module Prosopite
|
|
|
130
148
|
|
|
131
149
|
next unless queries.any?
|
|
132
150
|
|
|
133
|
-
kaller = tc[:prosopite_query_caller][location_key]
|
|
151
|
+
kaller = tc[:prosopite_query_caller][location_key].map(&:to_s)
|
|
134
152
|
allow_list = (@allow_stack_paths + DEFAULT_ALLOW_LIST)
|
|
135
153
|
is_allowed = kaller.any? { |f| allow_list.any? { |s| f.match?(s) } }
|
|
136
154
|
|
|
137
155
|
unless is_allowed
|
|
156
|
+
duration_ms = tc[:prosopite_query_duration][location_key]
|
|
138
157
|
queries.each do |q|
|
|
139
|
-
tc[:prosopite_notifications][q] = kaller
|
|
158
|
+
tc[:prosopite_notifications][q] = { kaller: kaller, duration_ms: duration_ms }
|
|
140
159
|
end
|
|
141
160
|
end
|
|
142
161
|
end
|
|
@@ -144,7 +163,7 @@ module Prosopite
|
|
|
144
163
|
end
|
|
145
164
|
|
|
146
165
|
def fingerprint(query)
|
|
147
|
-
db_adapter = ActiveRecord::Base.
|
|
166
|
+
db_adapter = ActiveRecord::Base.connection_db_config.adapter
|
|
148
167
|
if db_adapter.include?('mysql') || db_adapter.include?('trilogy')
|
|
149
168
|
mysql_fingerprint(query)
|
|
150
169
|
else
|
|
@@ -212,12 +231,15 @@ module Prosopite
|
|
|
212
231
|
@rails_logger ||= false
|
|
213
232
|
@stderr_logger ||= false
|
|
214
233
|
@prosopite_logger ||= false
|
|
215
|
-
@raise ||= false
|
|
216
234
|
|
|
217
|
-
notifications_str = ''
|
|
235
|
+
notifications_str = String.new('')
|
|
218
236
|
|
|
219
|
-
tc[:prosopite_notifications].each do |queries,
|
|
220
|
-
|
|
237
|
+
tc[:prosopite_notifications].each do |queries, info|
|
|
238
|
+
kaller = info[:kaller]
|
|
239
|
+
duration_ms = info[:duration_ms]
|
|
240
|
+
time_str = duration_ms ? " (#{duration_ms.round(1)}ms)" : ''
|
|
241
|
+
|
|
242
|
+
notifications_str << "N+1 queries detected#{time_str}:\n"
|
|
221
243
|
|
|
222
244
|
queries.each { |q| notifications_str << " #{q}\n" }
|
|
223
245
|
|
|
@@ -241,7 +263,7 @@ module Prosopite
|
|
|
241
263
|
end
|
|
242
264
|
end
|
|
243
265
|
|
|
244
|
-
raise NPlusOneQueriesError.new(notifications_str) if
|
|
266
|
+
raise NPlusOneQueriesError.new(notifications_str) if raise?
|
|
245
267
|
end
|
|
246
268
|
|
|
247
269
|
def red(str)
|
|
@@ -257,18 +279,25 @@ module Prosopite
|
|
|
257
279
|
@subscribed ||= false
|
|
258
280
|
return if @subscribed
|
|
259
281
|
|
|
260
|
-
ActiveSupport::Notifications.subscribe 'sql.active_record' do |_,
|
|
282
|
+
ActiveSupport::Notifications.subscribe 'sql.active_record' do |_, start, finish, _, data|
|
|
261
283
|
sql, name = data[:sql], data[:name]
|
|
262
284
|
|
|
263
285
|
if scan? && name != "SCHEMA" && sql.include?('SELECT') && data[:cached].nil? && !ignore_query?(sql)
|
|
264
|
-
query_caller =
|
|
265
|
-
|
|
286
|
+
query_caller = caller_locations
|
|
287
|
+
# Calculate the location key with as few allocations as possible
|
|
288
|
+
location_key = [].tap do |array|
|
|
289
|
+
query_caller.each do |loc|
|
|
290
|
+
array << loc.path
|
|
291
|
+
array << loc.lineno
|
|
292
|
+
end
|
|
293
|
+
end.hash
|
|
266
294
|
|
|
267
295
|
tc[:prosopite_query_counter][location_key] += 1
|
|
268
296
|
tc[:prosopite_query_holder][location_key] << sql
|
|
297
|
+
tc[:prosopite_query_duration][location_key] += (finish - start) * 1000 if tc[:prosopite_query_duration]
|
|
269
298
|
|
|
270
299
|
if tc[:prosopite_query_counter][location_key] > 1
|
|
271
|
-
tc[:prosopite_query_caller][location_key] = query_caller
|
|
300
|
+
tc[:prosopite_query_caller][location_key] = query_caller
|
|
272
301
|
end
|
|
273
302
|
end
|
|
274
303
|
end
|
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:
|
|
4
|
+
version: 2.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mpampis Kostas
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-04-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: pry
|
|
@@ -133,7 +133,7 @@ licenses:
|
|
|
133
133
|
metadata:
|
|
134
134
|
homepage_uri: https://github.com/charkost/prosopite
|
|
135
135
|
source_code_uri: https://github.com/charkost/prosopite
|
|
136
|
-
post_install_message:
|
|
136
|
+
post_install_message:
|
|
137
137
|
rdoc_options: []
|
|
138
138
|
require_paths:
|
|
139
139
|
- lib
|
|
@@ -148,8 +148,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
148
148
|
- !ruby/object:Gem::Version
|
|
149
149
|
version: '0'
|
|
150
150
|
requirements: []
|
|
151
|
-
rubygems_version: 3.
|
|
152
|
-
signing_key:
|
|
151
|
+
rubygems_version: 3.5.3
|
|
152
|
+
signing_key:
|
|
153
153
|
specification_version: 4
|
|
154
154
|
summary: N+1 auto-detection for Rails with zero false positives / false negatives
|
|
155
155
|
test_files: []
|