deprecation_collector 0.0.2 → 0.0.5
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/CHANGELOG.md +8 -1
- data/Gemfile +2 -0
- data/Gemfile.lock +9 -3
- data/README.md +6 -2
- data/deprecation_collector.gemspec +1 -1
- data/lib/deprecation_collector/deprecation.rb +4 -2
- data/lib/deprecation_collector/version.rb +1 -1
- data/lib/deprecation_collector.rb +33 -18
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f45c8742c0a83f697b04d7a99af54749b354c25cfcffb78f152a680f8224584
|
4
|
+
data.tar.gz: ab25a06b38f3ebfe82a48136c8a58da8d61e4db93614af0c66e283771f0b61b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d395dc4cedb786ab398911e5de19568f44317040352f1b85a6fc45a45fce465d6c82b8092c2f74e0a6b1d18e4dedfbc3284d59767dad2f3a2202143acd969b81
|
7
|
+
data.tar.gz: 0f9a6cd6f02b9b674710db839fcce21f69a2af31a41cc552ad3266b7cd1c3eaa21dac1ac7f94f0208833536e29c20d70e0261e6b087bc548597035c45bc47799
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
|
-
== unreleased
|
1
|
+
== 0.0.5 (unreleased)
|
2
|
+
- options `print_to_stderr`, `print_recurring`
|
3
|
+
- fix redis deprecated `pipelined` block arity (support for redis 5)
|
2
4
|
|
5
|
+
== 0.0.4
|
6
|
+
- added first_timestamp to deprecations (unix timestamp of first occurrence, not accurate because a worker with later timestamp may dump its deprecations earlier)
|
7
|
+
|
8
|
+
== 0.0.3
|
9
|
+
- Fixed selective deprecation cleanup (`DeprecationCollector.instance.cleanup { |d| d[:message].include?('foo') }`)
|
3
10
|
|
4
11
|
== 0.0.2
|
5
12
|
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
deprecation_collector (0.0.
|
5
|
-
redis (>=
|
4
|
+
deprecation_collector (0.0.5)
|
5
|
+
redis (>= 3.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
@@ -84,8 +84,12 @@ GEM
|
|
84
84
|
nokogiri (~> 1)
|
85
85
|
rake
|
86
86
|
mini_mime (1.1.2)
|
87
|
+
mini_portile2 (2.8.0)
|
87
88
|
minitest (5.15.0)
|
88
89
|
nio4r (2.5.8)
|
90
|
+
nokogiri (1.13.6)
|
91
|
+
mini_portile2 (~> 2.8.0)
|
92
|
+
racc (~> 1.4)
|
89
93
|
nokogiri (1.13.6-x86_64-darwin)
|
90
94
|
racc (~> 1.4)
|
91
95
|
parallel (1.22.1)
|
@@ -123,7 +127,7 @@ GEM
|
|
123
127
|
thor (>= 0.20.3, < 2.0)
|
124
128
|
rainbow (3.1.1)
|
125
129
|
rake (13.0.6)
|
126
|
-
redis (4.
|
130
|
+
redis (4.8.0)
|
127
131
|
regexp_parser (2.5.0)
|
128
132
|
rexml (3.2.5)
|
129
133
|
rspec (3.11.0)
|
@@ -181,12 +185,14 @@ GEM
|
|
181
185
|
zeitwerk (2.5.4)
|
182
186
|
|
183
187
|
PLATFORMS
|
188
|
+
ruby
|
184
189
|
x86_64-darwin-21
|
185
190
|
|
186
191
|
DEPENDENCIES
|
187
192
|
deprecation_collector!
|
188
193
|
rails (= 6.0)
|
189
194
|
rake (~> 13.0)
|
195
|
+
redis (~> 4.8)
|
190
196
|
rspec (~> 3.0)
|
191
197
|
rubocop (~> 1.21)
|
192
198
|
rubocop-performance
|
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
[](https://badge.fury.io/rb/deprecation_collector)
|
3
3
|
|
4
4
|
Collects ruby and rails deprecation warnings.
|
5
|
+
Designed to be suitable for use in production under load.
|
6
|
+
|
5
7
|
(gem is a work-in-process, documentation will come later)
|
6
8
|
|
7
9
|
## Installation
|
@@ -17,15 +19,17 @@ bundle add deprecation_collector
|
|
17
19
|
Add an initializer with configuration, like
|
18
20
|
|
19
21
|
```ruby
|
20
|
-
DeprecationCollector.create_instance(redis: your_redis_connection)
|
21
22
|
Rails.application.config.to_prepare do
|
22
23
|
DeprecationCollector.install do |instance|
|
24
|
+
instance.redis = Redis.new # default is $redis
|
23
25
|
instance.app_revision = ::GIT_REVISION
|
24
26
|
instance.count = false
|
25
27
|
instance.save_full_backtrace = true
|
26
28
|
instance.raise_on_deprecation = false
|
27
29
|
instance.write_interval = (::Rails.env.production? && 15.minutes) || 1.minute
|
28
30
|
instance.exclude_realms = %i[kernel] if Rails.env.production?
|
31
|
+
instance.print_to_stderr = true if Rails.env.development?
|
32
|
+
instance.print_recurring = false
|
29
33
|
instance.ignored_messages = [
|
30
34
|
"Ignoring db/schema_cache.yml because it has expired"
|
31
35
|
]
|
@@ -41,7 +45,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
41
45
|
|
42
46
|
## Contributing
|
43
47
|
|
44
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
48
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/Vasfed/deprecation_collector.
|
45
49
|
|
46
50
|
## License
|
47
51
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
class DeprecationCollector
|
4
4
|
# :nodoc:
|
5
5
|
class Deprecation
|
6
|
-
attr_reader :message, :realm, :gem_traceline, :app_traceline, :occurences, :full_backtrace
|
6
|
+
attr_reader :message, :realm, :gem_traceline, :app_traceline, :occurences, :first_timestamp, :full_backtrace
|
7
7
|
|
8
8
|
CLEANUP_REGEXES = {
|
9
9
|
# rails views generated methods names are unique per-worker
|
@@ -20,6 +20,7 @@ class DeprecationCollector
|
|
20
20
|
@occurences = 0
|
21
21
|
@gem_traceline = find_gem_traceline(backtrace)
|
22
22
|
@app_traceline = find_app_traceline(backtrace)
|
23
|
+
@first_timestamp = Time.now.to_i
|
23
24
|
|
24
25
|
cleanup_prefixes.each do |path|
|
25
26
|
@gem_traceline.delete_prefix!(path)
|
@@ -53,7 +54,7 @@ class DeprecationCollector
|
|
53
54
|
end
|
54
55
|
|
55
56
|
def digest_base
|
56
|
-
"1:#{RUBY_VERSION}:#{Rails.version}:#{message_for_digest}:#{gem_traceline}:#{app_traceline}"
|
57
|
+
"1:#{RUBY_VERSION}:#{defined?(Rails) && Rails.version}:#{message_for_digest}:#{gem_traceline}:#{app_traceline}"
|
57
58
|
end
|
58
59
|
|
59
60
|
def as_json(_options = {})
|
@@ -68,6 +69,7 @@ class DeprecationCollector
|
|
68
69
|
hostname: Socket.gethostname,
|
69
70
|
revision: DeprecationCollector.instance.app_revision,
|
70
71
|
count: @occurences, # output anyway for frequency estimation (during write_interval inside single process)
|
72
|
+
first_timestamp: first_timestamp, # this may not be accurate, a worker with later timestamp may dump earlier
|
71
73
|
digest_base: digest_base # for debug purposes
|
72
74
|
}.compact
|
73
75
|
end
|
@@ -5,6 +5,7 @@ require_relative "deprecation_collector/deprecation"
|
|
5
5
|
require_relative "deprecation_collector/collectors"
|
6
6
|
require "time"
|
7
7
|
require "redis"
|
8
|
+
require "json"
|
8
9
|
|
9
10
|
# singleton class for collector
|
10
11
|
class DeprecationCollector
|
@@ -53,7 +54,8 @@ class DeprecationCollector
|
|
53
54
|
attr_accessor :count, :raise_on_deprecation, :save_full_backtrace,
|
54
55
|
:exclude_realms,
|
55
56
|
:write_interval, :write_interval_jitter,
|
56
|
-
:app_revision, :app_root
|
57
|
+
:app_revision, :app_root,
|
58
|
+
:print_to_stderr, :print_recurring
|
57
59
|
attr_writer :redis
|
58
60
|
|
59
61
|
def initialize(mutex: nil)
|
@@ -96,8 +98,8 @@ class DeprecationCollector
|
|
96
98
|
raise "Deprecation: #{message}" if @raise_on_deprecation
|
97
99
|
|
98
100
|
deprecation = Deprecation.new(message, realm, backtrace, cleanup_prefixes)
|
99
|
-
store_deprecation(deprecation)
|
100
|
-
log_deprecation_if_needed(deprecation)
|
101
|
+
fresh = store_deprecation(deprecation)
|
102
|
+
log_deprecation_if_needed(deprecation, fresh)
|
101
103
|
end
|
102
104
|
|
103
105
|
def unsent_data?
|
@@ -163,6 +165,10 @@ class DeprecationCollector
|
|
163
165
|
@redis.set("deprecations:enabled", "false")
|
164
166
|
end
|
165
167
|
|
168
|
+
def dump
|
169
|
+
read_each.to_a.to_json
|
170
|
+
end
|
171
|
+
|
166
172
|
def read_each
|
167
173
|
return to_enum(:read_each) unless block_given?
|
168
174
|
|
@@ -185,10 +191,10 @@ class DeprecationCollector
|
|
185
191
|
def read_one(digest)
|
186
192
|
decode_deprecation(
|
187
193
|
digest,
|
188
|
-
*@redis.pipelined do
|
189
|
-
|
190
|
-
|
191
|
-
|
194
|
+
*@redis.pipelined do |pipe|
|
195
|
+
pipe.hget("deprecations:data", digest)
|
196
|
+
pipe.hget("deprecations:counter", digest)
|
197
|
+
pipe.hget("deprecations:notes", digest)
|
192
198
|
end
|
193
199
|
)
|
194
200
|
end
|
@@ -196,10 +202,10 @@ class DeprecationCollector
|
|
196
202
|
def delete_deprecations(remove_digests)
|
197
203
|
return 0 unless remove_digests.any?
|
198
204
|
|
199
|
-
@redis.pipelined do
|
200
|
-
|
201
|
-
|
202
|
-
|
205
|
+
@redis.pipelined do |pipe|
|
206
|
+
pipe.hdel("deprecations:data", *remove_digests)
|
207
|
+
pipe.hdel("deprecations:notes", *remove_digests)
|
208
|
+
pipe.hdel("deprecations:counter", *remove_digests) if @count
|
203
209
|
end.first
|
204
210
|
end
|
205
211
|
|
@@ -210,7 +216,7 @@ class DeprecationCollector
|
|
210
216
|
cursor, data_pairs = @redis.hscan("deprecations:data", cursor) # NB: some pages may be empty
|
211
217
|
total += data_pairs.size
|
212
218
|
removed += delete_deprecations(
|
213
|
-
data_pairs.select { |_digest, data| !block_given? || yield(JSON.parse(data, symbolize_names: true)) }.keys
|
219
|
+
data_pairs.to_h.select { |_digest, data| !block_given? || yield(JSON.parse(data, symbolize_names: true)) }.keys
|
214
220
|
)
|
215
221
|
break if cursor == "0"
|
216
222
|
end
|
@@ -221,18 +227,22 @@ class DeprecationCollector
|
|
221
227
|
|
222
228
|
def store_deprecation(deprecation)
|
223
229
|
return if deprecation.ignored?
|
230
|
+
fresh = !@deprecations.key?(deprecation.digest)
|
224
231
|
|
225
232
|
@deprecations_mutex.synchronize do
|
226
233
|
(@deprecations[deprecation.digest] ||= deprecation).touch
|
227
234
|
end
|
228
235
|
|
229
236
|
write_to_redis if current_time - @last_write_time > (@write_interval + rand(@write_interval_jitter))
|
237
|
+
fresh
|
230
238
|
end
|
231
239
|
|
232
|
-
def log_deprecation_if_needed(deprecation)
|
233
|
-
return unless
|
234
|
-
|
235
|
-
|
240
|
+
def log_deprecation_if_needed(deprecation, fresh)
|
241
|
+
return unless print_to_stderr && !deprecation.ignored?
|
242
|
+
return unless fresh || print_recurring
|
243
|
+
msg = deprecation.message
|
244
|
+
msg = "DEPRECATION: #{msg}" unless msg.start_with?('DEPRECAT')
|
245
|
+
$stderr.puts(msg) # rubocop:disable Style/StderrPuts
|
236
246
|
end
|
237
247
|
|
238
248
|
def current_time
|
@@ -242,7 +252,12 @@ class DeprecationCollector
|
|
242
252
|
end
|
243
253
|
|
244
254
|
def decode_deprecation(digest, data, count, notes)
|
255
|
+
return nil unless data
|
245
256
|
data = JSON.parse(data, symbolize_names: true)
|
257
|
+
unless data.is_a?(Hash)
|
258
|
+
binding.irb
|
259
|
+
return nil
|
260
|
+
end
|
246
261
|
data[:digest] = digest
|
247
262
|
data[:notes] = JSON.parse(notes, symbolize_names: true) if notes
|
248
263
|
data[:count] = count.to_i if count
|
@@ -250,9 +265,9 @@ class DeprecationCollector
|
|
250
265
|
end
|
251
266
|
|
252
267
|
def write_count_to_redis(deprecations_to_flush)
|
253
|
-
@redis.pipelined do
|
268
|
+
@redis.pipelined do |pipe|
|
254
269
|
deprecations_to_flush.each_pair do |digest, deprecation|
|
255
|
-
|
270
|
+
pipe.hincrby("deprecations:counter", digest, deprecation.occurences)
|
256
271
|
end
|
257
272
|
end
|
258
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.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vasily Fedoseyev
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '3.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '3.0'
|
27
27
|
description: Collects and aggregates warnings and deprecations. Optimized for production
|
28
28
|
environment.
|
29
29
|
email:
|
@@ -54,7 +54,7 @@ metadata:
|
|
54
54
|
homepage_uri: https://github.com/Vasfed/deprecation_collector
|
55
55
|
source_code_uri: https://github.com/Vasfed/deprecation_collector
|
56
56
|
changelog_uri: https://github.com/Vasfed/deprecation_collector/blob/main/CHANGELOG.md
|
57
|
-
post_install_message:
|
57
|
+
post_install_message:
|
58
58
|
rdoc_options: []
|
59
59
|
require_paths:
|
60
60
|
- lib
|
@@ -70,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
70
|
version: '0'
|
71
71
|
requirements: []
|
72
72
|
rubygems_version: 3.1.6
|
73
|
-
signing_key:
|
73
|
+
signing_key:
|
74
74
|
specification_version: 4
|
75
75
|
summary: Collector for ruby/rails deprecations and warnings, suitable for production
|
76
76
|
test_files: []
|