deprecation_collector 0.3.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,13 +1,82 @@
|
|
1
1
|
_buf = ''; _buf << ("<header class=\"mb-3\"><h1>Deprecation</h1><a class=\"btn btn-secondary\"".freeze);
|
2
2
|
;
|
3
3
|
;
|
4
|
-
; _slim_codeattributes1 = deprecations_path; if _slim_codeattributes1; if _slim_codeattributes1 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes1))).to_s); _buf << ("\"".freeze); end; end; _buf << (">Back</a
|
5
|
-
; _slim_codeattributes2 = deprecation_path(@deprecation[:digest]); if _slim_codeattributes2; if _slim_codeattributes2 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes2))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\" title=\"Delete\"><span class=\"glyphicon glyphicon-trash insalesicon-trash\"></span>Delete</a
|
4
|
+
; _slim_codeattributes1 = deprecations_path; if _slim_codeattributes1; if _slim_codeattributes1 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes1))).to_s); _buf << ("\"".freeze); end; end; _buf << (">Back</a> <a class=\"btn btn-danger\" data-confirm=\"Delete?\" data-method=\"delete\"".freeze);
|
5
|
+
; _slim_codeattributes2 = deprecation_path(@deprecation[:digest]); if _slim_codeattributes2; if _slim_codeattributes2 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes2))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\" title=\"Delete\"><span class=\"glyphicon glyphicon-trash insalesicon-trash\"></span>Delete</a> </header><main><dl class=\"row\"><dt>Message</dt><dd><code>".freeze);
|
6
6
|
;
|
7
7
|
;
|
8
8
|
;
|
9
9
|
;
|
10
10
|
;
|
11
11
|
;
|
12
|
-
;
|
13
|
-
; _buf << (
|
12
|
+
;
|
13
|
+
; _buf << ((::Temple::Utils.escape_html((@deprecation[:message]))).to_s);
|
14
|
+
; _buf << ("</code></dd><dt>First time</dt><dd>".freeze);
|
15
|
+
;
|
16
|
+
;
|
17
|
+
; _buf << ((::Temple::Utils.escape_html((@deprecation[:first_timestamp]&.yield_self { |time| Time.at(time) }))).to_s);
|
18
|
+
;
|
19
|
+
; _buf << ("</dd>".freeze); if @deprecation[:count] > 1;
|
20
|
+
; _buf << ("<dt>Count</dt><dd>".freeze);
|
21
|
+
; _buf << ((::Temple::Utils.escape_html((@deprecation[:count]))).to_s);
|
22
|
+
;
|
23
|
+
; _buf << ("</dd>".freeze); end; _buf << ("<dt>Realm</dt><dd>".freeze);
|
24
|
+
; _buf << ((::Temple::Utils.escape_html((@deprecation[:realm]))).to_s);
|
25
|
+
;
|
26
|
+
; _buf << ("</dd>".freeze); if @deprecation[:ruby_version];
|
27
|
+
; _buf << ("<dt>Ruby</dt><dd>".freeze);
|
28
|
+
; _buf << ((::Temple::Utils.escape_html((@deprecation[:ruby_version]))).to_s);
|
29
|
+
; _buf << ("</dd>".freeze); end; if @deprecation[:rails_version];
|
30
|
+
; _buf << ("<dt>Rails</dt><dd>".freeze);
|
31
|
+
; _buf << ((::Temple::Utils.escape_html((@deprecation[:rails_version]))).to_s);
|
32
|
+
;
|
33
|
+
; _buf << ("</dd>".freeze); end; if @deprecation[:revision];
|
34
|
+
; _buf << ("<dt>Revision</dt><dd>".freeze);
|
35
|
+
; _buf << ((::Temple::Utils.escape_html((@deprecation[:revision]))).to_s);
|
36
|
+
; _buf << ("</dd>".freeze); end; if @deprecation[:hostname];
|
37
|
+
; _buf << ("<dt>Hostname</dt><dd>".freeze);
|
38
|
+
; _buf << ((::Temple::Utils.escape_html((@deprecation[:hostname]))).to_s);
|
39
|
+
;
|
40
|
+
; _buf << ("</dd>".freeze); end; if @deprecation[:context];
|
41
|
+
; _buf << ("<dt>Context</dt><dd><div class=\"card p-3\"><pre><code>".freeze);
|
42
|
+
;
|
43
|
+
;
|
44
|
+
;
|
45
|
+
; _buf << ((::Temple::Utils.escape_html((JSON.pretty_generate(@deprecation[:context])))).to_s);
|
46
|
+
;
|
47
|
+
; _buf << ("</code></pre></div></dd>".freeze); end; if @deprecation[:app_traceline];
|
48
|
+
; _buf << ("<dt>App traceline</dt><dd>".freeze);
|
49
|
+
;
|
50
|
+
; location, function = @deprecation[:app_traceline].split(':in `', 2);
|
51
|
+
; _buf << ("<code class=\"code_location\">".freeze); _buf << ((::Temple::Utils.escape_html((location))).to_s);
|
52
|
+
; _buf << ("</code> <i>".freeze); _buf << ((::Temple::Utils.escape_html((function.delete_suffix("'")))).to_s);
|
53
|
+
;
|
54
|
+
; _buf << ("</i></dd>".freeze); end; if @deprecation[:gem_traceline];
|
55
|
+
; _buf << ("<dt>Gem traceline</dt><dd>".freeze);
|
56
|
+
;
|
57
|
+
; location, function = @deprecation[:gem_traceline].split(':in `', 2);
|
58
|
+
; full_gemname = location.delete_prefix('/gems/').gsub(%r{/.*}, '');
|
59
|
+
; location_in_gem = location.delete_prefix("/gems/#{full_gemname}/");
|
60
|
+
; _buf << ("<i>".freeze); _buf << ((::Temple::Utils.escape_html((full_gemname))).to_s);
|
61
|
+
; _buf << ("</i> <code class=\"code_location\"".freeze); _slim_codeattributes3 = location_in_gem; if _slim_codeattributes3; if _slim_codeattributes3 == true; _buf << (" data-copy-value=\"\"".freeze); else; _buf << (" data-copy-value=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes3))).to_s); _buf << ("\"".freeze); end; end; _buf << (">".freeze); _buf << ((::Temple::Utils.escape_html((location_in_gem.delete_prefix('lib/')))).to_s);
|
62
|
+
; _buf << ("</code> <i>".freeze); _buf << ((::Temple::Utils.escape_html((function.delete_suffix("'")))).to_s);
|
63
|
+
;
|
64
|
+
; _buf << ("</i></dd>".freeze); end; if @deprecation[:full_backtrace];
|
65
|
+
; _buf << ("<dt>Backtrace</dt><dd>".freeze);
|
66
|
+
;
|
67
|
+
; @deprecation[:full_backtrace].each do |trace_line|;
|
68
|
+
; _buf << ("<div class=\"trace-line\">".freeze);
|
69
|
+
; location, function = trace_line.split(':in `', 2);
|
70
|
+
; _buf << ("<code class=\"code_location\">".freeze); _buf << ((::Temple::Utils.escape_html((location))).to_s);
|
71
|
+
; _buf << ("</code> <i>".freeze); _buf << ((::Temple::Utils.escape_html((function.delete_suffix("'")))).to_s);
|
72
|
+
;
|
73
|
+
; _buf << ("</i></div>".freeze); end; _buf << ("</dd>".freeze); end; fields_to_reject = %i[message first_timestamp count realm app_traceline gem_traceline full_backtrace ruby_version rails_version context revision hostname digest_base digest].to_set;
|
74
|
+
; additional_data = @deprecation.reject { |key,_val| fields_to_reject.include?(key) };
|
75
|
+
; if additional_data.size > 0;
|
76
|
+
; _buf << ("<dt>Additional data <div class=\"card p-3\"><pre><code>".freeze);
|
77
|
+
;
|
78
|
+
;
|
79
|
+
;
|
80
|
+
; _buf << ((::Temple::Utils.escape_html((JSON.pretty_generate additional_data))).to_s);
|
81
|
+
; _buf << ("</code></pre></div></dt>".freeze); end; _buf << ("</dl><a".freeze); _slim_codeattributes4 = deprecation_path(params[:id], format: 'json'); if _slim_codeattributes4; if _slim_codeattributes4 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes4))).to_s); _buf << ("\"".freeze); end; end; _buf << (">Raw json</a></main>".freeze);
|
82
|
+
; _buf
|
@@ -4,10 +4,17 @@ require "erb"
|
|
4
4
|
require "rack/content_length"
|
5
5
|
require "rack/builder"
|
6
6
|
|
7
|
-
require_relative
|
7
|
+
require_relative "web/application"
|
8
8
|
|
9
9
|
class DeprecationCollector
|
10
|
+
# rack app with a html interface to deprecation collector with a persistent storage like redis
|
10
11
|
class Web
|
12
|
+
attr_accessor :import_enabled
|
13
|
+
|
14
|
+
def initialize(import_enabled: nil)
|
15
|
+
@import_enabled = import_enabled
|
16
|
+
end
|
17
|
+
|
11
18
|
def self.call(env)
|
12
19
|
@app ||= new
|
13
20
|
@app.call(env)
|
@@ -22,11 +29,13 @@ class DeprecationCollector
|
|
22
29
|
end
|
23
30
|
|
24
31
|
private
|
32
|
+
|
25
33
|
def build
|
34
|
+
web = self
|
26
35
|
::Rack::Builder.new do
|
27
36
|
# use Rack::Static etc goes here
|
28
37
|
|
29
|
-
run Web::Application.new
|
38
|
+
run Web::Application.new(web)
|
30
39
|
end
|
31
40
|
end
|
32
41
|
end
|
@@ -3,8 +3,8 @@
|
|
3
3
|
require_relative "deprecation_collector/version"
|
4
4
|
require_relative "deprecation_collector/deprecation"
|
5
5
|
require_relative "deprecation_collector/collectors"
|
6
|
+
require_relative "deprecation_collector/storage"
|
6
7
|
require "time"
|
7
|
-
require "redis"
|
8
8
|
require "json"
|
9
9
|
require "set"
|
10
10
|
|
@@ -52,37 +52,68 @@ class DeprecationCollector
|
|
52
52
|
end
|
53
53
|
|
54
54
|
# NB: count is expensive in production env (but possible if needed) - produces a lot of redis writes
|
55
|
-
attr_accessor :
|
55
|
+
attr_accessor :raise_on_deprecation, :save_full_backtrace,
|
56
56
|
:exclude_realms,
|
57
|
-
:
|
58
|
-
:app_revision, :app_root,
|
57
|
+
:app_name, :app_revision, :app_root,
|
59
58
|
:print_to_stderr, :print_recurring
|
60
|
-
|
59
|
+
attr_reader :count, :write_interval, :write_interval_jitter, :key_prefix
|
60
|
+
attr_writer :context_saver, :fingerprinter
|
61
61
|
|
62
62
|
def initialize(mutex: nil)
|
63
|
-
# on cruby hash itself is threadsafe, but we need to prevent races
|
64
|
-
@deprecations_mutex = mutex || Mutex.new
|
65
|
-
@deprecations = {}
|
66
|
-
@known_digests = Set.new
|
67
|
-
@last_write_time = current_time
|
68
63
|
@enabled = true
|
64
|
+
@instance_mutex = mutex
|
69
65
|
|
70
66
|
load_default_config
|
71
67
|
end
|
72
68
|
|
73
69
|
def load_default_config
|
74
|
-
|
75
|
-
|
70
|
+
if (redis = defined?($redis) && $redis) # rubocop:disable Style/GlobalVars
|
71
|
+
self.redis = redis
|
72
|
+
end
|
76
73
|
@raise_on_deprecation = false
|
77
74
|
@exclude_realms = []
|
78
75
|
@ignore_message_regexp = nil
|
79
76
|
@app_root = (defined?(Rails) && Rails.root.present? && Rails.root) || Dir.pwd
|
80
77
|
# NB: in production with hugreds of workers may easily overload redis with writes, so more delay needed:
|
81
|
-
|
82
|
-
|
78
|
+
self.count = false
|
79
|
+
self.write_interval = 900 # 15.minutes
|
80
|
+
self.write_interval_jitter = 60
|
83
81
|
@context_saver = nil
|
84
82
|
end
|
85
83
|
|
84
|
+
def redis=(val)
|
85
|
+
raise ArgumentError, "redis should not be nil" unless val
|
86
|
+
|
87
|
+
@storage ||= DeprecationCollector::Storage::Redis.new(val, mutex: @instance_mutex, count: count, # rubocop:disable Naming/MemoizedInstanceVariableName
|
88
|
+
write_interval: write_interval,
|
89
|
+
write_interval_jitter: write_interval_jitter,
|
90
|
+
key_prefix: key_prefix)
|
91
|
+
end
|
92
|
+
|
93
|
+
def count=(val)
|
94
|
+
storage.count = val if storage.respond_to?(:count)
|
95
|
+
@count = val
|
96
|
+
end
|
97
|
+
|
98
|
+
def write_interval=(val)
|
99
|
+
storage.write_interval = val if storage.respond_to?(:write_interval)
|
100
|
+
@write_interval = val
|
101
|
+
end
|
102
|
+
|
103
|
+
def write_interval_jitter=(val)
|
104
|
+
storage.write_interval_jitter = val if storage.respond_to?(:write_interval_jitter)
|
105
|
+
@write_interval_jitter = val
|
106
|
+
end
|
107
|
+
|
108
|
+
def key_prefix=(val)
|
109
|
+
storage.key_prefix = val
|
110
|
+
@key_prefix = val
|
111
|
+
end
|
112
|
+
|
113
|
+
def storage
|
114
|
+
@storage ||= DeprecationCollector::Storage::StdErr.new
|
115
|
+
end
|
116
|
+
|
86
117
|
def ignored_messages=(val)
|
87
118
|
@ignore_message_regexp = (val && Regexp.union(val)) || nil
|
88
119
|
end
|
@@ -127,123 +158,81 @@ class DeprecationCollector
|
|
127
158
|
@count
|
128
159
|
end
|
129
160
|
|
130
|
-
def redis
|
131
|
-
raise "DeprecationCollector#redis is not set" unless @redis
|
132
|
-
|
133
|
-
@redis
|
134
|
-
end
|
135
|
-
|
136
161
|
def write_to_redis(force: false)
|
137
|
-
return unless force ||
|
138
|
-
|
139
|
-
deprecations_to_flush = nil
|
140
|
-
@deprecations_mutex.synchronize do
|
141
|
-
deprecations_to_flush = @deprecations
|
142
|
-
@deprecations = {}
|
143
|
-
@last_write_time = current_time
|
144
|
-
# checking in this section to prevent multiple parallel check requests
|
145
|
-
return (@enabled = false) unless enabled_in_redis?
|
146
|
-
end
|
162
|
+
return unless force || @enabled
|
147
163
|
|
148
|
-
|
149
|
-
|
150
|
-
# make as few writes as possible, other workers may already have reported our warning
|
151
|
-
fetch_known_digests
|
152
|
-
deprecations_to_flush.reject! { |digest, _val| @known_digests.include?(digest) }
|
153
|
-
return unless deprecations_to_flush.any?
|
154
|
-
|
155
|
-
@known_digests.merge(deprecations_to_flush.keys)
|
156
|
-
@redis.mapped_hmset("deprecations:data", deprecations_to_flush.transform_values(&:to_json))
|
164
|
+
storage.flush(force: force)
|
157
165
|
end
|
158
166
|
|
159
167
|
# prevent fresh process from wiring frequent already known messages
|
160
168
|
def fetch_known_digests
|
161
|
-
|
169
|
+
storage.fetch_known_digests
|
162
170
|
end
|
163
171
|
|
164
172
|
def flush_redis(enable: false)
|
165
|
-
|
166
|
-
@redis.del("deprecations:enabled") if enable
|
167
|
-
@deprecations.clear
|
168
|
-
@known_digests.clear
|
173
|
+
storage.clear(enable: enable)
|
169
174
|
end
|
170
175
|
|
171
176
|
def enabled_in_redis?
|
172
|
-
|
177
|
+
storage.enabled?
|
178
|
+
end
|
179
|
+
|
180
|
+
def enabled?
|
181
|
+
@enabled
|
173
182
|
end
|
174
183
|
|
175
184
|
def enable
|
185
|
+
storage.enable
|
176
186
|
@enabled = true
|
177
|
-
@redis.set("deprecations:enabled", "true")
|
178
187
|
end
|
179
188
|
|
180
189
|
def disable
|
181
190
|
@enabled = false
|
182
|
-
|
191
|
+
storage.disable
|
183
192
|
end
|
184
193
|
|
185
194
|
def dump
|
186
|
-
read_each.to_a.to_json
|
195
|
+
read_each.to_a.compact.to_json
|
196
|
+
end
|
197
|
+
|
198
|
+
def import_dump(json)
|
199
|
+
dump = JSON.parse(json)
|
200
|
+
# TODO: some checks
|
201
|
+
|
202
|
+
digests = dump.map { |dep| dep["digest"] }
|
203
|
+
raise "need digests" unless digests.none?(&:nil?)
|
204
|
+
|
205
|
+
dump_hash = dump.map { |dep| [dep.delete("digest"), dep] }.to_h
|
206
|
+
|
207
|
+
storage.import(dump_hash)
|
187
208
|
end
|
188
209
|
|
189
210
|
def read_each
|
190
211
|
return to_enum(:read_each) unless block_given?
|
191
212
|
|
192
|
-
|
193
|
-
|
194
|
-
cursor, data_pairs = @redis.hscan("deprecations:data", cursor)
|
195
|
-
|
196
|
-
if data_pairs.any?
|
197
|
-
data_pairs.zip(
|
198
|
-
@redis.hmget("deprecations:counter", data_pairs.map(&:first)),
|
199
|
-
@redis.hmget("deprecations:notes", data_pairs.map(&:first))
|
200
|
-
).each do |(digest, data), count, notes|
|
201
|
-
yield decode_deprecation(digest, data, count, notes)
|
202
|
-
end
|
203
|
-
end
|
204
|
-
break if cursor == "0"
|
213
|
+
storage.read_each do |digest, data, count, notes|
|
214
|
+
yield decode_deprecation(digest, data, count, notes)
|
205
215
|
end
|
206
216
|
end
|
207
217
|
|
208
218
|
def read_one(digest)
|
209
|
-
decode_deprecation(
|
210
|
-
digest,
|
211
|
-
*@redis.pipelined do |pipe|
|
212
|
-
pipe.hget("deprecations:data", digest)
|
213
|
-
pipe.hget("deprecations:counter", digest)
|
214
|
-
pipe.hget("deprecations:notes", digest)
|
215
|
-
end
|
216
|
-
)
|
219
|
+
decode_deprecation(*storage.read_one(digest))
|
217
220
|
end
|
218
221
|
|
219
222
|
def delete_deprecations(remove_digests)
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
end
|
228
|
-
|
229
|
-
def cleanup
|
230
|
-
cursor = 0
|
231
|
-
removed = total = 0
|
232
|
-
loop do
|
233
|
-
cursor, data_pairs = @redis.hscan("deprecations:data", cursor) # NB: some pages may be empty
|
234
|
-
total += data_pairs.size
|
235
|
-
removed += delete_deprecations(
|
236
|
-
data_pairs.to_h.select { |_digest, data| !block_given? || yield(JSON.parse(data, symbolize_names: true)) }.keys
|
237
|
-
)
|
238
|
-
break if cursor == "0"
|
239
|
-
end
|
240
|
-
"#{removed} removed, #{total - removed} left"
|
223
|
+
storage.delete(remove_digests)
|
224
|
+
end
|
225
|
+
|
226
|
+
def cleanup(&block)
|
227
|
+
raise ArgumentError, "provide a block to filter deprecations" unless block
|
228
|
+
|
229
|
+
storage.cleanup(&block)
|
241
230
|
end
|
242
231
|
|
243
232
|
protected
|
244
233
|
|
245
234
|
def unsent_deprecations
|
246
|
-
|
235
|
+
storage.unsent_deprecations
|
247
236
|
end
|
248
237
|
|
249
238
|
def store_deprecation(deprecation, allow_context: true)
|
@@ -251,51 +240,34 @@ class DeprecationCollector
|
|
251
240
|
|
252
241
|
deprecation.context = context_saver.call if context_saver && allow_context
|
253
242
|
deprecation.custom_fingerprint = fingerprinter.call(deprecation) if fingerprinter && allow_context
|
243
|
+
deprecation.app_name = app_name if app_name
|
254
244
|
|
255
|
-
|
256
|
-
@deprecations_mutex.synchronize do
|
257
|
-
(@deprecations[deprecation.digest] ||= deprecation).touch
|
258
|
-
end
|
259
|
-
|
260
|
-
write_to_redis if current_time - @last_write_time > (@write_interval + rand(@write_interval_jitter))
|
261
|
-
fresh
|
245
|
+
storage.store(deprecation)
|
262
246
|
end
|
263
247
|
|
264
248
|
def log_deprecation_if_needed(deprecation, fresh)
|
265
249
|
return unless print_to_stderr && !deprecation.ignored?
|
266
250
|
return unless fresh || print_recurring
|
267
251
|
|
252
|
+
log_deprecation(deprecation)
|
253
|
+
end
|
254
|
+
|
255
|
+
def log_deprecation(deprecation)
|
268
256
|
msg = deprecation.message
|
269
257
|
msg = "DEPRECATION: #{msg}" unless msg.start_with?("DEPRECAT")
|
270
258
|
$stderr.puts(msg) # rubocop:disable Style/StderrPuts
|
271
259
|
end
|
272
260
|
|
273
|
-
def current_time
|
274
|
-
return Time.zone.now if Time.respond_to?(:zone) && Time.zone
|
275
|
-
|
276
|
-
Time.now
|
277
|
-
end
|
278
|
-
|
279
261
|
def decode_deprecation(digest, data, count, notes)
|
280
262
|
return nil unless data
|
281
263
|
|
282
264
|
data = JSON.parse(data, symbolize_names: true)
|
283
|
-
|
284
|
-
|
285
|
-
return nil
|
286
|
-
end
|
265
|
+
# this should not happen (this means broken Deprecation#to_json or some data curruption)
|
266
|
+
return nil unless data.is_a?(Hash)
|
287
267
|
|
288
268
|
data[:digest] = digest
|
289
269
|
data[:notes] = JSON.parse(notes, symbolize_names: true) if notes
|
290
270
|
data[:count] = count.to_i if count
|
291
271
|
data
|
292
272
|
end
|
293
|
-
|
294
|
-
def write_count_to_redis(deprecations_to_flush)
|
295
|
-
@redis.pipelined do |pipe|
|
296
|
-
deprecations_to_flush.each_pair do |digest, deprecation|
|
297
|
-
pipe.hincrby("deprecations:counter", digest, deprecation.occurences)
|
298
|
-
end
|
299
|
-
end
|
300
|
-
end
|
301
273
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deprecation_collector
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vasily Fedoseyev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-04
|
11
|
+
date: 2023-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rack-test
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
description: Collects and aggregates warnings and deprecations. Optimized for production
|
42
56
|
environment.
|
43
57
|
email:
|
@@ -66,12 +80,14 @@ files:
|
|
66
80
|
- lib/deprecation_collector.rb
|
67
81
|
- lib/deprecation_collector/collectors.rb
|
68
82
|
- lib/deprecation_collector/deprecation.rb
|
83
|
+
- lib/deprecation_collector/storage.rb
|
69
84
|
- lib/deprecation_collector/version.rb
|
70
85
|
- lib/deprecation_collector/web.rb
|
71
86
|
- lib/deprecation_collector/web/application.rb
|
72
87
|
- lib/deprecation_collector/web/helpers.rb
|
73
88
|
- lib/deprecation_collector/web/router.rb
|
74
89
|
- lib/deprecation_collector/web/utils.rb
|
90
|
+
- lib/deprecation_collector/web/views/import.html.template.rb
|
75
91
|
- lib/deprecation_collector/web/views/index.html.template.rb
|
76
92
|
- lib/deprecation_collector/web/views/layout.html.template.rb
|
77
93
|
- lib/deprecation_collector/web/views/show.html.template.rb
|
@@ -98,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
114
|
- !ruby/object:Gem::Version
|
99
115
|
version: '0'
|
100
116
|
requirements: []
|
101
|
-
rubygems_version: 3.4.
|
117
|
+
rubygems_version: 3.4.10
|
102
118
|
signing_key:
|
103
119
|
specification_version: 4
|
104
120
|
summary: Collector for ruby/rails deprecations and warnings, suitable for production
|