prosopite 0.1.5 → 0.1.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/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/lib/prosopite.rb +29 -25
- data/lib/prosopite/version.rb +1 -1
- 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: 77a2d861398e1f7a76cc71705f68d1f7287ca1343b3bd8fcf7e909f941682125
|
4
|
+
data.tar.gz: 586d0e356edfb83152c538bc4b017d9e8009d6fcd1ba746ec2cf677a97ea7f23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c4e9d238b5f10d8f57531d84024758d3a6e05b4b3cefb49317c1576a0cbcf71287bcd77050ddfc073b1f03cdb3a601bb6f33a49f4488f7ab4483f51f19e7af0
|
7
|
+
data.tar.gz: 3f22640ed22014cd38f47e770de44253314e134192745fc3abf43d14374d815d249929f4e1dd754c46318e579ee40cf1b76ba90aa7009dd18c15f42a642aa39c
|
data/LICENSE.txt
CHANGED
@@ -187,7 +187,7 @@
|
|
187
187
|
same "printed page" as the copyright notice for easier
|
188
188
|
identification within third-party archives.
|
189
189
|
|
190
|
-
Copyright
|
190
|
+
Copyright 2021 Mpampis Kostas
|
191
191
|
|
192
192
|
Licensed under the Apache License, Version 2.0 (the "License");
|
193
193
|
you may not use this file except in compliance with the License.
|
data/README.md
CHANGED
@@ -168,12 +168,12 @@ end
|
|
168
168
|
|
169
169
|
WARNING: scan/finish should run before/after **each** test and NOT before/after the whole suite.
|
170
170
|
|
171
|
-
##
|
171
|
+
## Allow list
|
172
172
|
|
173
173
|
Ignore notifications for call stacks containing one or more substrings:
|
174
174
|
|
175
175
|
```ruby
|
176
|
-
Prosopite.
|
176
|
+
Prosopite.allow_list = ['substring_in_call_stack']
|
177
177
|
```
|
178
178
|
|
179
179
|
## Scanning code outside controllers or tests
|
data/lib/prosopite.rb
CHANGED
@@ -7,42 +7,46 @@ module Prosopite
|
|
7
7
|
:stderr_logger,
|
8
8
|
:rails_logger,
|
9
9
|
:prosopite_logger,
|
10
|
-
:
|
10
|
+
:allow_list
|
11
11
|
|
12
12
|
def scan
|
13
|
-
|
13
|
+
tc[:prosopite_scan] ||= false
|
14
14
|
return if scan?
|
15
15
|
|
16
16
|
subscribe
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
tc[:prosopite_query_counter] = Hash.new(0)
|
19
|
+
tc[:prosopite_query_holder] = Hash.new { |h, k| h[k] = [] }
|
20
|
+
tc[:prosopite_query_caller] = {}
|
21
21
|
|
22
|
-
@
|
22
|
+
@allow_list ||= []
|
23
23
|
|
24
|
-
|
24
|
+
tc[:prosopite_scan] = true
|
25
|
+
end
|
26
|
+
|
27
|
+
def tc
|
28
|
+
Thread.current
|
25
29
|
end
|
26
30
|
|
27
31
|
def scan?
|
28
|
-
|
32
|
+
tc[:prosopite_scan]
|
29
33
|
end
|
30
34
|
|
31
35
|
def finish
|
32
36
|
return unless scan?
|
33
37
|
|
34
|
-
|
38
|
+
tc[:prosopite_scan] = false
|
35
39
|
|
36
40
|
create_notifications
|
37
|
-
send_notifications if
|
41
|
+
send_notifications if tc[:prosopite_notifications].present?
|
38
42
|
end
|
39
43
|
|
40
44
|
def create_notifications
|
41
|
-
|
45
|
+
tc[:prosopite_notifications] = {}
|
42
46
|
|
43
|
-
|
47
|
+
tc[:prosopite_query_counter].each do |location_key, count|
|
44
48
|
if count > 1
|
45
|
-
fingerprints =
|
49
|
+
fingerprints = tc[:prosopite_query_holder][location_key].map do |q|
|
46
50
|
begin
|
47
51
|
fingerprint(q)
|
48
52
|
rescue
|
@@ -50,13 +54,13 @@ module Prosopite
|
|
50
54
|
end
|
51
55
|
end
|
52
56
|
|
53
|
-
kaller =
|
57
|
+
kaller = tc[:prosopite_query_caller][location_key]
|
54
58
|
|
55
|
-
if fingerprints.uniq.size == 1 && !kaller.any? { |f| @
|
56
|
-
queries =
|
59
|
+
if fingerprints.uniq.size == 1 && !kaller.any? { |f| @allow_list.any? { |s| f.include?(s) } }
|
60
|
+
queries = tc[:prosopite_query_holder][location_key]
|
57
61
|
|
58
62
|
unless kaller.any? { |f| f.include?('active_record/validations/uniqueness') }
|
59
|
-
|
63
|
+
tc[:prosopite_notifications][queries] = kaller
|
60
64
|
end
|
61
65
|
end
|
62
66
|
end
|
@@ -126,7 +130,7 @@ module Prosopite
|
|
126
130
|
|
127
131
|
notifications_str = ''
|
128
132
|
|
129
|
-
|
133
|
+
tc[:prosopite_notifications].each do |queries, kaller|
|
130
134
|
notifications_str << "N+1 queries detected:\n"
|
131
135
|
queries.each { |q| notifications_str << " #{q}\n" }
|
132
136
|
notifications_str << "Call stack:\n"
|
@@ -149,8 +153,8 @@ module Prosopite
|
|
149
153
|
end
|
150
154
|
|
151
155
|
def subscribe
|
152
|
-
|
153
|
-
return if
|
156
|
+
tc[:prosopite_subscribed] ||= false
|
157
|
+
return if tc[:prosopite_subscribed]
|
154
158
|
|
155
159
|
ActiveSupport::Notifications.subscribe 'sql.active_record' do |_, _, _, _, data|
|
156
160
|
sql = data[:sql]
|
@@ -158,16 +162,16 @@ module Prosopite
|
|
158
162
|
if scan? && sql.include?('SELECT') && data[:cached].nil?
|
159
163
|
location_key = Digest::SHA1.hexdigest(caller.join)
|
160
164
|
|
161
|
-
|
162
|
-
|
165
|
+
tc[:prosopite_query_counter][location_key] += 1
|
166
|
+
tc[:prosopite_query_holder][location_key] << sql
|
163
167
|
|
164
|
-
if
|
165
|
-
|
168
|
+
if tc[:prosopite_query_counter][location_key] > 1
|
169
|
+
tc[:prosopite_query_caller][location_key] = caller.dup
|
166
170
|
end
|
167
171
|
end
|
168
172
|
end
|
169
173
|
|
170
|
-
|
174
|
+
tc[:prosopite_subscribed] = true
|
171
175
|
end
|
172
176
|
end
|
173
177
|
end
|
data/lib/prosopite/version.rb
CHANGED
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: 0.1.
|
4
|
+
version: 0.1.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-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg_query
|