deprecation_collector 0.3.0 → 0.5.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/.rubocop.yml +2 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +4 -4
- data/Gemfile.lock +3 -2
- data/Rakefile +10 -6
- data/deprecation_collector.gemspec +2 -1
- data/gemfiles/rails_6.gemfile +3 -0
- data/gemfiles/rails_6.gemfile.lock +90 -86
- data/gemfiles/rails_7.gemfile +3 -0
- data/gemfiles/rails_7.gemfile.lock +85 -75
- data/gemfiles/rails_none.gemfile +3 -0
- data/gemfiles/rails_none.gemfile.lock +20 -7
- data/lib/deprecation_collector/deprecation.rb +2 -1
- data/lib/deprecation_collector/storage.rb +205 -0
- data/lib/deprecation_collector/version.rb +1 -1
- data/lib/deprecation_collector/web/application.rb +42 -20
- data/lib/deprecation_collector/web/helpers.rb +48 -4
- data/lib/deprecation_collector/web/router.rb +76 -49
- data/lib/deprecation_collector/web/utils.rb +10 -7
- data/lib/deprecation_collector/web/views/import.html.template.rb +13 -0
- data/lib/deprecation_collector/web/views/index.html.template.rb +57 -31
- data/lib/deprecation_collector/web/views/layout.html.template.rb +77 -4
- data/lib/deprecation_collector/web/views/show.html.template.rb +73 -4
- data/lib/deprecation_collector/web.rb +11 -2
- data/lib/deprecation_collector.rb +88 -116
- metadata +19 -3
@@ -1,73 +1,73 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
deprecation_collector (0.
|
4
|
+
deprecation_collector (0.5.0)
|
5
5
|
redis (>= 3.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
actioncable (7.0.4.
|
11
|
-
actionpack (= 7.0.4.
|
12
|
-
activesupport (= 7.0.4.
|
10
|
+
actioncable (7.0.4.3)
|
11
|
+
actionpack (= 7.0.4.3)
|
12
|
+
activesupport (= 7.0.4.3)
|
13
13
|
nio4r (~> 2.0)
|
14
14
|
websocket-driver (>= 0.6.1)
|
15
|
-
actionmailbox (7.0.4.
|
16
|
-
actionpack (= 7.0.4.
|
17
|
-
activejob (= 7.0.4.
|
18
|
-
activerecord (= 7.0.4.
|
19
|
-
activestorage (= 7.0.4.
|
20
|
-
activesupport (= 7.0.4.
|
15
|
+
actionmailbox (7.0.4.3)
|
16
|
+
actionpack (= 7.0.4.3)
|
17
|
+
activejob (= 7.0.4.3)
|
18
|
+
activerecord (= 7.0.4.3)
|
19
|
+
activestorage (= 7.0.4.3)
|
20
|
+
activesupport (= 7.0.4.3)
|
21
21
|
mail (>= 2.7.1)
|
22
22
|
net-imap
|
23
23
|
net-pop
|
24
24
|
net-smtp
|
25
|
-
actionmailer (7.0.4.
|
26
|
-
actionpack (= 7.0.4.
|
27
|
-
actionview (= 7.0.4.
|
28
|
-
activejob (= 7.0.4.
|
29
|
-
activesupport (= 7.0.4.
|
25
|
+
actionmailer (7.0.4.3)
|
26
|
+
actionpack (= 7.0.4.3)
|
27
|
+
actionview (= 7.0.4.3)
|
28
|
+
activejob (= 7.0.4.3)
|
29
|
+
activesupport (= 7.0.4.3)
|
30
30
|
mail (~> 2.5, >= 2.5.4)
|
31
31
|
net-imap
|
32
32
|
net-pop
|
33
33
|
net-smtp
|
34
34
|
rails-dom-testing (~> 2.0)
|
35
|
-
actionpack (7.0.4.
|
36
|
-
actionview (= 7.0.4.
|
37
|
-
activesupport (= 7.0.4.
|
35
|
+
actionpack (7.0.4.3)
|
36
|
+
actionview (= 7.0.4.3)
|
37
|
+
activesupport (= 7.0.4.3)
|
38
38
|
rack (~> 2.0, >= 2.2.0)
|
39
39
|
rack-test (>= 0.6.3)
|
40
40
|
rails-dom-testing (~> 2.0)
|
41
41
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
42
|
-
actiontext (7.0.4.
|
43
|
-
actionpack (= 7.0.4.
|
44
|
-
activerecord (= 7.0.4.
|
45
|
-
activestorage (= 7.0.4.
|
46
|
-
activesupport (= 7.0.4.
|
42
|
+
actiontext (7.0.4.3)
|
43
|
+
actionpack (= 7.0.4.3)
|
44
|
+
activerecord (= 7.0.4.3)
|
45
|
+
activestorage (= 7.0.4.3)
|
46
|
+
activesupport (= 7.0.4.3)
|
47
47
|
globalid (>= 0.6.0)
|
48
48
|
nokogiri (>= 1.8.5)
|
49
|
-
actionview (7.0.4.
|
50
|
-
activesupport (= 7.0.4.
|
49
|
+
actionview (7.0.4.3)
|
50
|
+
activesupport (= 7.0.4.3)
|
51
51
|
builder (~> 3.1)
|
52
52
|
erubi (~> 1.4)
|
53
53
|
rails-dom-testing (~> 2.0)
|
54
54
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
55
|
-
activejob (7.0.4.
|
56
|
-
activesupport (= 7.0.4.
|
55
|
+
activejob (7.0.4.3)
|
56
|
+
activesupport (= 7.0.4.3)
|
57
57
|
globalid (>= 0.3.6)
|
58
|
-
activemodel (7.0.4.
|
59
|
-
activesupport (= 7.0.4.
|
60
|
-
activerecord (7.0.4.
|
61
|
-
activemodel (= 7.0.4.
|
62
|
-
activesupport (= 7.0.4.
|
63
|
-
activestorage (7.0.4.
|
64
|
-
actionpack (= 7.0.4.
|
65
|
-
activejob (= 7.0.4.
|
66
|
-
activerecord (= 7.0.4.
|
67
|
-
activesupport (= 7.0.4.
|
58
|
+
activemodel (7.0.4.3)
|
59
|
+
activesupport (= 7.0.4.3)
|
60
|
+
activerecord (7.0.4.3)
|
61
|
+
activemodel (= 7.0.4.3)
|
62
|
+
activesupport (= 7.0.4.3)
|
63
|
+
activestorage (7.0.4.3)
|
64
|
+
actionpack (= 7.0.4.3)
|
65
|
+
activejob (= 7.0.4.3)
|
66
|
+
activerecord (= 7.0.4.3)
|
67
|
+
activesupport (= 7.0.4.3)
|
68
68
|
marcel (~> 1.0)
|
69
69
|
mini_mime (>= 1.1.0)
|
70
|
-
activesupport (7.0.4.
|
70
|
+
activesupport (7.0.4.3)
|
71
71
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
72
72
|
i18n (>= 1.6, < 2)
|
73
73
|
minitest (>= 5.1)
|
@@ -77,21 +77,21 @@ GEM
|
|
77
77
|
rake
|
78
78
|
thor (>= 0.14.0)
|
79
79
|
builder (3.2.4)
|
80
|
-
concurrent-ruby (1.
|
80
|
+
concurrent-ruby (1.2.2)
|
81
81
|
crass (1.0.6)
|
82
82
|
date (3.3.3)
|
83
83
|
diff-lcs (1.5.0)
|
84
84
|
erubi (1.12.0)
|
85
|
-
fakeredis (0.
|
86
|
-
redis (~> 4.
|
87
|
-
globalid (1.
|
85
|
+
fakeredis (0.9.1)
|
86
|
+
redis (~> 4.8)
|
87
|
+
globalid (1.1.0)
|
88
88
|
activesupport (>= 5.0)
|
89
|
-
i18n (1.
|
89
|
+
i18n (1.13.0)
|
90
90
|
concurrent-ruby (~> 1.0)
|
91
|
-
loofah (2.
|
91
|
+
loofah (2.20.0)
|
92
92
|
crass (~> 1.0.2)
|
93
93
|
nokogiri (>= 1.5.9)
|
94
|
-
mail (2.8.
|
94
|
+
mail (2.8.1)
|
95
95
|
mini_mime (>= 0.1.1)
|
96
96
|
net-imap
|
97
97
|
net-pop
|
@@ -99,7 +99,7 @@ GEM
|
|
99
99
|
marcel (1.0.2)
|
100
100
|
method_source (1.0.0)
|
101
101
|
mini_mime (1.1.2)
|
102
|
-
minitest (5.
|
102
|
+
minitest (5.18.0)
|
103
103
|
net-imap (0.3.4)
|
104
104
|
date
|
105
105
|
net-protocol
|
@@ -109,65 +109,71 @@ GEM
|
|
109
109
|
timeout
|
110
110
|
net-smtp (0.3.3)
|
111
111
|
net-protocol
|
112
|
-
nio4r (2.5.
|
113
|
-
nokogiri (1.14.
|
112
|
+
nio4r (2.5.9)
|
113
|
+
nokogiri (1.14.3-x86_64-darwin)
|
114
114
|
racc (~> 1.4)
|
115
|
-
nokogiri (1.14.
|
115
|
+
nokogiri (1.14.3-x86_64-linux)
|
116
116
|
racc (~> 1.4)
|
117
117
|
racc (1.6.2)
|
118
|
-
rack (2.2.
|
119
|
-
rack-test (2.0
|
118
|
+
rack (2.2.7)
|
119
|
+
rack-test (2.1.0)
|
120
120
|
rack (>= 1.3)
|
121
|
-
rails (7.0.4.
|
122
|
-
actioncable (= 7.0.4.
|
123
|
-
actionmailbox (= 7.0.4.
|
124
|
-
actionmailer (= 7.0.4.
|
125
|
-
actionpack (= 7.0.4.
|
126
|
-
actiontext (= 7.0.4.
|
127
|
-
actionview (= 7.0.4.
|
128
|
-
activejob (= 7.0.4.
|
129
|
-
activemodel (= 7.0.4.
|
130
|
-
activerecord (= 7.0.4.
|
131
|
-
activestorage (= 7.0.4.
|
132
|
-
activesupport (= 7.0.4.
|
121
|
+
rails (7.0.4.3)
|
122
|
+
actioncable (= 7.0.4.3)
|
123
|
+
actionmailbox (= 7.0.4.3)
|
124
|
+
actionmailer (= 7.0.4.3)
|
125
|
+
actionpack (= 7.0.4.3)
|
126
|
+
actiontext (= 7.0.4.3)
|
127
|
+
actionview (= 7.0.4.3)
|
128
|
+
activejob (= 7.0.4.3)
|
129
|
+
activemodel (= 7.0.4.3)
|
130
|
+
activerecord (= 7.0.4.3)
|
131
|
+
activestorage (= 7.0.4.3)
|
132
|
+
activesupport (= 7.0.4.3)
|
133
133
|
bundler (>= 1.15.0)
|
134
|
-
railties (= 7.0.4.
|
134
|
+
railties (= 7.0.4.3)
|
135
135
|
rails-dom-testing (2.0.3)
|
136
136
|
activesupport (>= 4.2.0)
|
137
137
|
nokogiri (>= 1.6)
|
138
|
-
rails-html-sanitizer (1.
|
138
|
+
rails-html-sanitizer (1.5.0)
|
139
139
|
loofah (~> 2.19, >= 2.19.1)
|
140
|
-
railties (7.0.4.
|
141
|
-
actionpack (= 7.0.4.
|
142
|
-
activesupport (= 7.0.4.
|
140
|
+
railties (7.0.4.3)
|
141
|
+
actionpack (= 7.0.4.3)
|
142
|
+
activesupport (= 7.0.4.3)
|
143
143
|
method_source
|
144
144
|
rake (>= 12.2)
|
145
145
|
thor (~> 1.0)
|
146
146
|
zeitwerk (~> 2.5)
|
147
147
|
rake (13.0.6)
|
148
|
-
redis (4.8.
|
148
|
+
redis (4.8.1)
|
149
149
|
rspec (3.12.0)
|
150
150
|
rspec-core (~> 3.12.0)
|
151
151
|
rspec-expectations (~> 3.12.0)
|
152
152
|
rspec-mocks (~> 3.12.0)
|
153
|
-
rspec-core (3.12.
|
153
|
+
rspec-core (3.12.2)
|
154
154
|
rspec-support (~> 3.12.0)
|
155
|
-
rspec-expectations (3.12.
|
155
|
+
rspec-expectations (3.12.3)
|
156
156
|
diff-lcs (>= 1.2.0, < 2.0)
|
157
157
|
rspec-support (~> 3.12.0)
|
158
|
-
rspec-mocks (3.12.
|
158
|
+
rspec-mocks (3.12.5)
|
159
159
|
diff-lcs (>= 1.2.0, < 2.0)
|
160
160
|
rspec-support (~> 3.12.0)
|
161
161
|
rspec-support (3.12.0)
|
162
|
+
slim (5.1.0)
|
163
|
+
temple (~> 0.10.0)
|
164
|
+
tilt (>= 2.0.6, < 2.2)
|
165
|
+
temple (0.10.0)
|
162
166
|
thor (1.2.1)
|
167
|
+
tilt (2.1.0)
|
163
168
|
timecop (0.9.6)
|
164
|
-
timeout (0.3.
|
165
|
-
tzinfo (2.0.
|
169
|
+
timeout (0.3.2)
|
170
|
+
tzinfo (2.0.6)
|
166
171
|
concurrent-ruby (~> 1.0)
|
172
|
+
webrick (1.8.1)
|
167
173
|
websocket-driver (0.7.5)
|
168
174
|
websocket-extensions (>= 0.1.0)
|
169
175
|
websocket-extensions (0.1.5)
|
170
|
-
zeitwerk (2.6.
|
176
|
+
zeitwerk (2.6.7)
|
171
177
|
|
172
178
|
PLATFORMS
|
173
179
|
x86_64-darwin-21
|
@@ -177,11 +183,15 @@ DEPENDENCIES
|
|
177
183
|
appraisal
|
178
184
|
deprecation_collector!
|
179
185
|
fakeredis
|
186
|
+
rack
|
187
|
+
rack-test
|
180
188
|
rails (~> 7.0)
|
181
189
|
rake (~> 13.0)
|
182
190
|
redis (~> 4.8)
|
183
191
|
rspec (~> 3.0)
|
192
|
+
slim
|
184
193
|
timecop
|
194
|
+
webrick
|
185
195
|
|
186
196
|
BUNDLED WITH
|
187
197
|
2.3.10
|
data/gemfiles/rails_none.gemfile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
deprecation_collector (0.
|
4
|
+
deprecation_collector (0.5.0)
|
5
5
|
redis (>= 3.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -12,25 +12,34 @@ GEM
|
|
12
12
|
rake
|
13
13
|
thor (>= 0.14.0)
|
14
14
|
diff-lcs (1.5.0)
|
15
|
-
fakeredis (0.
|
16
|
-
redis (~> 4.
|
15
|
+
fakeredis (0.9.1)
|
16
|
+
redis (~> 4.8)
|
17
|
+
rack (3.0.7)
|
18
|
+
rack-test (2.1.0)
|
19
|
+
rack (>= 1.3)
|
17
20
|
rake (13.0.6)
|
18
|
-
redis (4.8.
|
21
|
+
redis (4.8.1)
|
19
22
|
rspec (3.12.0)
|
20
23
|
rspec-core (~> 3.12.0)
|
21
24
|
rspec-expectations (~> 3.12.0)
|
22
25
|
rspec-mocks (~> 3.12.0)
|
23
|
-
rspec-core (3.12.
|
26
|
+
rspec-core (3.12.2)
|
24
27
|
rspec-support (~> 3.12.0)
|
25
|
-
rspec-expectations (3.12.
|
28
|
+
rspec-expectations (3.12.3)
|
26
29
|
diff-lcs (>= 1.2.0, < 2.0)
|
27
30
|
rspec-support (~> 3.12.0)
|
28
|
-
rspec-mocks (3.12.
|
31
|
+
rspec-mocks (3.12.5)
|
29
32
|
diff-lcs (>= 1.2.0, < 2.0)
|
30
33
|
rspec-support (~> 3.12.0)
|
31
34
|
rspec-support (3.12.0)
|
35
|
+
slim (5.1.0)
|
36
|
+
temple (~> 0.10.0)
|
37
|
+
tilt (>= 2.0.6, < 2.2)
|
38
|
+
temple (0.10.0)
|
32
39
|
thor (1.2.1)
|
40
|
+
tilt (2.1.0)
|
33
41
|
timecop (0.9.6)
|
42
|
+
webrick (1.8.1)
|
34
43
|
|
35
44
|
PLATFORMS
|
36
45
|
x86_64-darwin-21
|
@@ -40,10 +49,14 @@ DEPENDENCIES
|
|
40
49
|
appraisal
|
41
50
|
deprecation_collector!
|
42
51
|
fakeredis
|
52
|
+
rack
|
53
|
+
rack-test
|
43
54
|
rake (~> 13.0)
|
44
55
|
redis (~> 4.8)
|
45
56
|
rspec (~> 3.0)
|
57
|
+
slim
|
46
58
|
timecop
|
59
|
+
webrick
|
47
60
|
|
48
61
|
BUNDLED WITH
|
49
62
|
2.3.10
|
@@ -4,7 +4,7 @@ class DeprecationCollector
|
|
4
4
|
# :nodoc:
|
5
5
|
class Deprecation
|
6
6
|
attr_reader :message, :realm, :gem_traceline, :app_traceline, :occurences, :first_timestamp, :full_backtrace
|
7
|
-
attr_accessor :context, :custom_fingerprint
|
7
|
+
attr_accessor :context, :custom_fingerprint, :app_name
|
8
8
|
|
9
9
|
CLEANUP_REGEXES = {
|
10
10
|
# rails views generated methods names are unique per-worker
|
@@ -61,6 +61,7 @@ class DeprecationCollector
|
|
61
61
|
|
62
62
|
def as_json(_options = {})
|
63
63
|
{
|
64
|
+
app: app_name,
|
64
65
|
message: message,
|
65
66
|
realm: realm,
|
66
67
|
app_traceline: app_traceline,
|
@@ -0,0 +1,205 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "redis"
|
4
|
+
|
5
|
+
class DeprecationCollector
|
6
|
+
module Storage
|
7
|
+
# :nodoc:
|
8
|
+
class Base
|
9
|
+
# rubocop:disable Style/SingleLineMethods
|
10
|
+
def enabled?; true; end
|
11
|
+
def enable; end
|
12
|
+
def disable; end
|
13
|
+
|
14
|
+
def unsent_deprecations; []; end
|
15
|
+
def fetch_known_digests; end
|
16
|
+
|
17
|
+
def delete(digests); end
|
18
|
+
def clear(enable: false); end
|
19
|
+
|
20
|
+
def store(_deprecation); raise("Not implemented"); end
|
21
|
+
# rubocop:enable Style/SingleLineMethods
|
22
|
+
end
|
23
|
+
|
24
|
+
# dummy strategy that outputs every deprecation into stderr
|
25
|
+
class StdErr < Base
|
26
|
+
def store(deprecation)
|
27
|
+
DeprecationCollector.instance.send(:log_deprecation, deprecation)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# storing in redis with deduplication by fingerprint
|
32
|
+
class Redis < Base
|
33
|
+
attr_accessor :write_interval, :write_interval_jitter, :redis, :count
|
34
|
+
|
35
|
+
def initialize(redis, mutex: nil, count: false, write_interval: 900, write_interval_jitter: 60,
|
36
|
+
key_prefix: nil)
|
37
|
+
super()
|
38
|
+
@key_prefix = key_prefix || "deprecations"
|
39
|
+
@redis = redis
|
40
|
+
@last_write_time = current_time
|
41
|
+
@count = count
|
42
|
+
@write_interval = write_interval
|
43
|
+
@write_interval_jitter = write_interval_jitter
|
44
|
+
# on cruby hash itself is threadsafe, but we need to prevent races
|
45
|
+
@deprecations_mutex = mutex || Mutex.new
|
46
|
+
@deprecations = {}
|
47
|
+
@known_digests = Set.new
|
48
|
+
end
|
49
|
+
|
50
|
+
def unsent_deprecations
|
51
|
+
@deprecations
|
52
|
+
end
|
53
|
+
|
54
|
+
def enabled?
|
55
|
+
@redis.get(enabled_flag_key) != "false"
|
56
|
+
end
|
57
|
+
|
58
|
+
def enable
|
59
|
+
@redis.set(enabled_flag_key, "true")
|
60
|
+
end
|
61
|
+
|
62
|
+
def disable
|
63
|
+
@redis.set(enabled_flag_key, "false")
|
64
|
+
end
|
65
|
+
|
66
|
+
def delete(remove_digests)
|
67
|
+
return 0 unless remove_digests.any?
|
68
|
+
|
69
|
+
@redis.pipelined do |pipe|
|
70
|
+
pipe.hdel(data_hash_key, *remove_digests)
|
71
|
+
pipe.hdel(notes_hash_key, *remove_digests)
|
72
|
+
pipe.hdel(counter_hash_key, *remove_digests) if @count
|
73
|
+
end.first
|
74
|
+
end
|
75
|
+
|
76
|
+
def clear(enable: false)
|
77
|
+
@redis.del(data_hash_key, counter_hash_key, notes_hash_key)
|
78
|
+
@redis.del(enabled_flag_key) if enable
|
79
|
+
@known_digests.clear
|
80
|
+
@deprecations.clear
|
81
|
+
end
|
82
|
+
|
83
|
+
def fetch_known_digests
|
84
|
+
# FIXME: use `.merge!`?
|
85
|
+
@known_digests.merge(@redis.hkeys(data_hash_key))
|
86
|
+
end
|
87
|
+
|
88
|
+
def store(deprecation)
|
89
|
+
fresh = !@deprecations.key?(deprecation.digest)
|
90
|
+
@deprecations_mutex.synchronize do
|
91
|
+
(@deprecations[deprecation.digest] ||= deprecation).touch
|
92
|
+
end
|
93
|
+
|
94
|
+
flush if current_time - @last_write_time > (@write_interval + rand(@write_interval_jitter))
|
95
|
+
fresh
|
96
|
+
end
|
97
|
+
|
98
|
+
def flush(force: false)
|
99
|
+
return unless force || (current_time > @last_write_time + @write_interval)
|
100
|
+
|
101
|
+
deprecations_to_flush = nil
|
102
|
+
@deprecations_mutex.synchronize do
|
103
|
+
deprecations_to_flush = @deprecations
|
104
|
+
@deprecations = {}
|
105
|
+
@last_write_time = current_time
|
106
|
+
# checking in this section to prevent multiple parallel check requests
|
107
|
+
return DeprecationCollector.instance.instance_variable_set(:@enabled, false) unless enabled?
|
108
|
+
end
|
109
|
+
|
110
|
+
write_count_to_redis(deprecations_to_flush) if @count
|
111
|
+
|
112
|
+
# make as few writes as possible, other workers may already have reported our warning
|
113
|
+
fetch_known_digests
|
114
|
+
deprecations_to_flush.reject! { |digest, _val| @known_digests.include?(digest) }
|
115
|
+
return unless deprecations_to_flush.any?
|
116
|
+
|
117
|
+
@known_digests.merge(deprecations_to_flush.keys)
|
118
|
+
@redis.mapped_hmset(data_hash_key, deprecations_to_flush.transform_values(&:to_json))
|
119
|
+
end
|
120
|
+
|
121
|
+
def read_each
|
122
|
+
cursor = 0
|
123
|
+
loop do
|
124
|
+
cursor, data_pairs = @redis.hscan(data_hash_key, cursor)
|
125
|
+
|
126
|
+
if data_pairs.any?
|
127
|
+
data_pairs.zip(
|
128
|
+
@redis.hmget(counter_hash_key, data_pairs.map(&:first)),
|
129
|
+
@redis.hmget(notes_hash_key, data_pairs.map(&:first))
|
130
|
+
).each do |(digest, data), count, notes|
|
131
|
+
yield(digest, data, count, notes)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
break if cursor == "0"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def read_one(digest)
|
139
|
+
[
|
140
|
+
digest,
|
141
|
+
*@redis.pipelined do |pipe|
|
142
|
+
pipe.hget(data_hash_key, digest)
|
143
|
+
pipe.hget(counter_hash_key, digest)
|
144
|
+
pipe.hget(notes_hash_key, digest)
|
145
|
+
end
|
146
|
+
]
|
147
|
+
end
|
148
|
+
|
149
|
+
def import(dump_hash)
|
150
|
+
@redis.mapped_hmset(data_hash_key, dump_hash.transform_values(&:to_json))
|
151
|
+
end
|
152
|
+
|
153
|
+
def cleanup(&_block)
|
154
|
+
cursor = 0
|
155
|
+
removed = total = 0
|
156
|
+
loop do
|
157
|
+
cursor, data_pairs = @redis.hscan(data_hash_key, cursor) # NB: some pages may be empty
|
158
|
+
total += data_pairs.size
|
159
|
+
removed += delete(
|
160
|
+
data_pairs.to_h.select { |_digest, data| yield(JSON.parse(data, symbolize_names: true)) }.keys
|
161
|
+
)
|
162
|
+
break if cursor == "0"
|
163
|
+
end
|
164
|
+
"#{removed} removed, #{total - removed} left"
|
165
|
+
end
|
166
|
+
|
167
|
+
def key_prefix=(val)
|
168
|
+
@enabled_flag_key = @data_hash_key = @counter_hash_key = @notes_hash_key = nil
|
169
|
+
@key_prefix = val
|
170
|
+
end
|
171
|
+
|
172
|
+
protected
|
173
|
+
|
174
|
+
def enabled_flag_key
|
175
|
+
@enabled_flag_key ||= "#{@key_prefix}:enabled" # usually deprecations:enabled
|
176
|
+
end
|
177
|
+
|
178
|
+
def data_hash_key
|
179
|
+
@data_hash_key ||= "#{@key_prefix}:data" # usually deprecations:data
|
180
|
+
end
|
181
|
+
|
182
|
+
def counter_hash_key
|
183
|
+
@counter_hash_key ||= "#{@key_prefix}:counter" # usually deprecations:counter
|
184
|
+
end
|
185
|
+
|
186
|
+
def notes_hash_key
|
187
|
+
@notes_hash_key ||= "#{@key_prefix}:notes" # usually deprecations:notes
|
188
|
+
end
|
189
|
+
|
190
|
+
def current_time
|
191
|
+
return Time.zone.now if Time.respond_to?(:zone) && Time.zone
|
192
|
+
|
193
|
+
Time.now
|
194
|
+
end
|
195
|
+
|
196
|
+
def write_count_to_redis(deprecations_to_flush)
|
197
|
+
@redis.pipelined do |pipe|
|
198
|
+
deprecations_to_flush.each_pair do |digest, deprecation|
|
199
|
+
pipe.hincrby(counter_hash_key, digest, deprecation.occurences)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -1,29 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require 'pp'
|
3
|
+
require_relative "router"
|
4
|
+
require_relative "helpers"
|
6
5
|
|
7
6
|
class DeprecationCollector
|
8
7
|
class Web
|
8
|
+
# :nodoc:
|
9
9
|
class Application
|
10
10
|
extend Web::Router
|
11
11
|
helpers Helpers
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
attr_reader :web
|
14
|
+
|
15
|
+
def initialize(web)
|
16
|
+
@web = web
|
17
|
+
# used for escaping in compiled slim templates
|
18
|
+
require_relative "utils" unless defined?(Temple::Utils) || ENV["DEPRECATION_COLLECTOR_RELOAD_WEB_TEMPLATES"]
|
18
19
|
end
|
19
20
|
|
20
21
|
def call(env)
|
21
|
-
self.class.call(env)
|
22
|
+
self.class.call(env, self)
|
22
23
|
end
|
23
24
|
|
24
25
|
root do # index
|
25
|
-
@deprecations = collector_instance.read_each.to_a
|
26
|
-
@deprecations = @deprecations.sort_by { |dep| dep[:message] } unless params[:sort] ==
|
26
|
+
@deprecations = collector_instance.read_each.to_a.compact
|
27
|
+
@deprecations = @deprecations.sort_by { |dep| dep[:message] } unless params[:sort] == "0"
|
27
28
|
|
28
29
|
if params[:reject]
|
29
30
|
@deprecations = @deprecations.reject { |dep| dep[:message].match?(Regexp.union(Array(params[:reject]))) }
|
@@ -36,38 +37,59 @@ class DeprecationCollector
|
|
36
37
|
render slim: "index.html"
|
37
38
|
end
|
38
39
|
|
39
|
-
get
|
40
|
-
render json: collector_instance.
|
40
|
+
get "/dump.json" do
|
41
|
+
render json: collector_instance.dump
|
42
|
+
end
|
43
|
+
|
44
|
+
get "/import" do
|
45
|
+
return "Import not enabled" unless import_enabled?
|
46
|
+
|
47
|
+
render slim: "import.html"
|
48
|
+
end
|
49
|
+
|
50
|
+
post "/import" do
|
51
|
+
unless env["CONTENT_TYPE"]&.start_with?("multipart/form-data") && params.dig(:file, :tempfile)
|
52
|
+
halt 422, "need multipart json file"
|
53
|
+
end
|
54
|
+
collector_instance.import_dump(File.read(params[:file][:tempfile]))
|
55
|
+
redirect_to deprecations_path
|
56
|
+
end
|
57
|
+
|
58
|
+
get "/:id.json" do # show
|
59
|
+
@deprecation = collector_instance.read_one(params[:id])
|
60
|
+
halt 404 unless @deprecation
|
61
|
+
render json: JSON.pretty_generate(@deprecation)
|
41
62
|
end
|
42
63
|
|
43
|
-
get
|
64
|
+
get "/:id" do # show
|
44
65
|
@deprecation = collector_instance.read_one(params[:id])
|
66
|
+
halt 404 unless @deprecation
|
45
67
|
render slim: "show.html"
|
46
68
|
end
|
47
69
|
|
48
|
-
delete
|
70
|
+
delete "/all" do
|
49
71
|
collector_instance.flush_redis
|
50
72
|
redirect_to deprecations_path
|
51
73
|
end
|
52
74
|
|
53
|
-
post
|
75
|
+
post "/enable" do
|
54
76
|
collector_instance.enable
|
55
77
|
redirect_to deprecations_path
|
56
78
|
end
|
57
79
|
|
58
|
-
delete
|
80
|
+
delete "/disable" do
|
59
81
|
collector_instance.disable
|
60
82
|
redirect_to deprecations_path
|
61
83
|
end
|
62
84
|
|
63
85
|
# NB: order for wildcards is important
|
64
|
-
delete
|
86
|
+
delete "/:id" do # destroy
|
65
87
|
collector_instance.delete_deprecations([params[:id]])
|
66
88
|
redirect_to deprecations_path
|
67
89
|
end
|
68
90
|
|
69
|
-
post
|
70
|
-
trigger_kwargs_error_warning({ foo: nil }) if RUBY_VERSION.start_with?(
|
91
|
+
post "/trigger" do # trigger
|
92
|
+
trigger_kwargs_error_warning({ foo: nil }) if RUBY_VERSION.start_with?("2.7")
|
71
93
|
trigger_rails_deprecation
|
72
94
|
collector_instance.collect(
|
73
95
|
"TestFoo#assign_attributes called (test attr_spy) trigger_rails_deprecation", caller_locations, :attr_spy
|