n_one 1.0.1 → 1.0.2
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 +5 -5
- data/README.md +35 -6
- data/lib/n_one/runner.rb +9 -4
- data/lib/n_one/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: 6ed8520fefb3a0e04185dc4a7f234ec3f9d65d110223dfd52b568d9f1f8d9080
|
4
|
+
data.tar.gz: 1164c40f76713cab191569ff896d4309c8938194737ed31cd21897bcc10027d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98c9dedda0ec0540d55443c678c399dd1bb5bf5b3ee007769b85b6d276aa13bcf14096aa0a8ab310ddedb824df7cd0289a88f0bd952e3f6dd4e707ca0da0ce97
|
7
|
+
data.tar.gz: 19da0020d67ef61418399ecfe266c063822d63fcb3912832bc57c135b5df6739aea5d4583927f90e89ecbc557d352cc1bfa99777efdc1cd4ecf6d9983c6a4715
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
n_one (1.0.
|
4
|
+
n_one (1.0.2)
|
5
5
|
pg_query
|
6
6
|
|
7
7
|
GEM
|
@@ -23,8 +23,8 @@ GEM
|
|
23
23
|
concurrent-ruby (1.1.8)
|
24
24
|
factory_bot (6.1.0)
|
25
25
|
activesupport (>= 5.0.0)
|
26
|
-
google-protobuf (3.19.
|
27
|
-
google-protobuf (3.19.
|
26
|
+
google-protobuf (3.19.4)
|
27
|
+
google-protobuf (3.19.4-x86_64-linux)
|
28
28
|
i18n (1.8.9)
|
29
29
|
concurrent-ruby (~> 1.0)
|
30
30
|
method_source (1.0.0)
|
@@ -32,8 +32,8 @@ GEM
|
|
32
32
|
parallel (1.20.1)
|
33
33
|
parser (3.0.1.0)
|
34
34
|
ast (~> 2.4.1)
|
35
|
-
pg_query (2.1.
|
36
|
-
google-protobuf (>= 3.
|
35
|
+
pg_query (2.1.3)
|
36
|
+
google-protobuf (>= 3.19.2)
|
37
37
|
pry (0.14.0)
|
38
38
|
coderay (~> 1.1)
|
39
39
|
method_source (~> 1.0)
|
data/README.md
CHANGED
@@ -74,9 +74,9 @@ end
|
|
74
74
|
Ignore notifications for call stacks containing one or more substrings:
|
75
75
|
|
76
76
|
```ruby
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
NOne.scan!(whitelist: ['myapp/lib/known_n_plus_ones/']) do
|
78
|
+
example.run
|
79
|
+
end
|
80
80
|
```
|
81
81
|
|
82
82
|
## Ignore names
|
@@ -84,13 +84,42 @@ Ignore notifications for call stacks containing one or more substrings:
|
|
84
84
|
Ignore queries with names:
|
85
85
|
|
86
86
|
```ruby
|
87
|
-
|
88
|
-
|
89
|
-
|
87
|
+
NOne.scan!(ignore_names: ['SCHEMA']) do
|
88
|
+
example.run
|
89
|
+
end
|
90
90
|
```
|
91
91
|
|
92
92
|
It will skip schema queries(e.g. for column names of a given table)
|
93
93
|
|
94
|
+
## Stack trace sanitizing
|
95
|
+
|
96
|
+
Sanitize the call stack trace that is used to calculate the query fingerprint:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
sanitizer = lambda do |stacktrace|
|
100
|
+
stacktrace.reject { |s| s.include?('/active_record/relation/delegation.rb') }
|
101
|
+
end
|
102
|
+
|
103
|
+
NOne.scan!(stacktrace_sanitizer: sanitizer) do
|
104
|
+
example.run
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
Consider the following example:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
class Foo < ActiveRecord::Base
|
112
|
+
def self.bar
|
113
|
+
first(5)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
2.times { Foo.all.bar }
|
118
|
+
```
|
119
|
+
|
120
|
+
The subsequent `Foo.all.bar` call here will not be recognized as an N+1 query since it will have a different call stack trace (see the reason [here](https://github.com/rails/rails/blob/9a400d808bdbebd5ea50cebc79bde591d2669017/activerecord/lib/active_record/relation/delegation.rb#L82-L85)).
|
121
|
+
This can be fixed with the `stacktrace_sanitizer` option as described above.
|
122
|
+
|
94
123
|
## Contributing
|
95
124
|
|
96
125
|
Bug reports and pull requests are welcome on GitHub at https://github.com/prikha/n_one.
|
data/lib/n_one/runner.rb
CHANGED
@@ -6,10 +6,13 @@ module NOne
|
|
6
6
|
#
|
7
7
|
# @param whitelist [<String>] frame substrings to be ignored
|
8
8
|
# @param ignore_names [<String>] query names to be ignored
|
9
|
+
# @param stacktrace_sanitizer [Proc<Array<String>>] if given, used to filter the stack trace
|
10
|
+
# that is used to calculate the location key
|
9
11
|
#
|
10
|
-
def initialize(whitelist: [], ignore_names: [])
|
12
|
+
def initialize(whitelist: [], ignore_names: [], stacktrace_sanitizer: nil)
|
11
13
|
@whitelist = ['active_record/validations/uniqueness'] + whitelist
|
12
14
|
@ignore_names = ignore_names
|
15
|
+
@stacktrace_sanitizer = stacktrace_sanitizer
|
13
16
|
end
|
14
17
|
|
15
18
|
def scan(&block)
|
@@ -51,7 +54,7 @@ module NOne
|
|
51
54
|
end.compact
|
52
55
|
end
|
53
56
|
|
54
|
-
def record_sql(&block) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
57
|
+
def record_sql(&block) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
|
55
58
|
subscriber = ActiveSupport::Notifications.subscribe 'sql.active_record' do |_, _, _, _, data|
|
56
59
|
sql = data[:sql]
|
57
60
|
cached = data[:cached]
|
@@ -62,7 +65,9 @@ module NOne
|
|
62
65
|
sql_fingerprint = Query.fingerprint(sql)
|
63
66
|
next unless sql_fingerprint
|
64
67
|
|
65
|
-
|
68
|
+
stacktrace = caller
|
69
|
+
stacktrace = @stacktrace_sanitizer.call(stacktrace) if @stacktrace_sanitizer
|
70
|
+
location_key = Digest::SHA1.hexdigest(stacktrace.join)
|
66
71
|
|
67
72
|
store["#{sql_fingerprint}_#{location_key}"] ||= {
|
68
73
|
count: 0,
|
@@ -73,7 +78,7 @@ module NOne
|
|
73
78
|
store["#{sql_fingerprint}_#{location_key}"][:count] += 1
|
74
79
|
store["#{sql_fingerprint}_#{location_key}"][:sql] << sql
|
75
80
|
store["#{sql_fingerprint}_#{location_key}"][:sql].uniq!
|
76
|
-
store["#{sql_fingerprint}_#{location_key}"][:caller] ||=
|
81
|
+
store["#{sql_fingerprint}_#{location_key}"][:caller] ||= stacktrace
|
77
82
|
end
|
78
83
|
|
79
84
|
block.call
|
data/lib/n_one/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: n_one
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergey Prikhodko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg_query
|