deprecation_collector 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2342f445e6c89ba4ea74094dd39894d99ad6e546781405fe43a6ecba71396264
4
- data.tar.gz: d5d6edaa942f57a726f9336a06541dabc3eadae2731d01953443a88d84fc7c2e
3
+ metadata.gz: edc00d8d4dd22e076dd0c331bd65ee2a6caad48e28ee0f2a79253f94d6d5a1b3
4
+ data.tar.gz: a8d0a71ada4d0eae355f853f685ea4548124e5090bcac361bb4363ef69b8faaa
5
5
  SHA512:
6
- metadata.gz: 9ac2e881d1687dc3756904840f21f98cc62dc497cac31804fcfeac8e4e01c780b5370497ed52da2d1ec22ca14a68ee3be4dc163c5d48cd47c38b775ef0df7b1c
7
- data.tar.gz: 5725ea9137d79a83ea8d1df1ae9b458fe0f94479d5e7c9643ac15368ef853f75fac38cce3b7e8543fd4d03df884fa3999019d08902ba437a196f6b5b3c78dd06
6
+ metadata.gz: b7f467b251d4e04f9d23f5524f1c0e36d6ab363090664178ef82d78d261e118d7f30511f6711ebde8205cde3fe46e871f870752c8be867f4f0bd743344589e5b
7
+ data.tar.gz: 2c3b8f59fc2adb43a04a39f3fb39f02bcd752ebbc9d7a1974a77a8441dfeb1daaf65ec87704d7159a1b31a443c20df5a202ff1872e08a28e709baccd84657998
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ == 0.0.6
2
+ - added custom context saving ability
3
+
4
+ == 0.0.5
5
+ - options `print_to_stderr`, `print_recurring`
6
+ - fix redis deprecated `pipelined` block arity (support for redis 5)
7
+
1
8
  == 0.0.4
2
9
  - added first_timestamp to deprecations (unix timestamp of first occurrence, not accurate because a worker with later timestamp may dump its deprecations earlier)
3
10
 
data/Gemfile CHANGED
@@ -18,3 +18,5 @@ gem "rubocop-rspec"
18
18
 
19
19
  # TODO: appraisals
20
20
  gem "rails", "6.0"
21
+
22
+ gem 'redis', '~>4.8'
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- deprecation_collector (0.0.4)
5
- redis (>= 2.0)
4
+ deprecation_collector (0.0.6)
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.7.1)
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
@@ -28,9 +28,15 @@ Add an initializer with configuration, like
28
28
  instance.raise_on_deprecation = false
29
29
  instance.write_interval = (::Rails.env.production? && 15.minutes) || 1.minute
30
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
31
33
  instance.ignored_messages = [
32
34
  "Ignoring db/schema_cache.yml because it has expired"
33
35
  ]
36
+ instance.context_saver do
37
+ # this will only be called for new deprecations, return value must be json-compatible
38
+ { some: "custom", context: "for example request.id" }
39
+ end
34
40
  end
35
41
  end
36
42
  ```
@@ -27,5 +27,5 @@ Gem::Specification.new do |spec|
27
27
  end
28
28
  spec.require_paths = ["lib"]
29
29
 
30
- spec.add_dependency "redis", ">= 2.0" # TODO: check exact minimum version
30
+ spec.add_dependency "redis", ">= 3.0"
31
31
  end
@@ -4,6 +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
7
8
 
8
9
  CLEANUP_REGEXES = {
9
10
  # rails views generated methods names are unique per-worker
@@ -54,7 +55,7 @@ class DeprecationCollector
54
55
  end
55
56
 
56
57
  def digest_base
57
- "1:#{RUBY_VERSION}:#{Rails.version}:#{message_for_digest}:#{gem_traceline}:#{app_traceline}"
58
+ "1:#{RUBY_VERSION}:#{defined?(Rails) && Rails.version}:#{message_for_digest}:#{gem_traceline}:#{app_traceline}"
58
59
  end
59
60
 
60
61
  def as_json(_options = {})
@@ -70,7 +71,8 @@ class DeprecationCollector
70
71
  revision: DeprecationCollector.instance.app_revision,
71
72
  count: @occurences, # output anyway for frequency estimation (during write_interval inside single process)
72
73
  first_timestamp: first_timestamp, # this may not be accurate, a worker with later timestamp may dump earlier
73
- digest_base: digest_base # for debug purposes
74
+ digest_base: digest_base, # for debug purposes
75
+ context: context
74
76
  }.compact
75
77
  end
76
78
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class DeprecationCollector
4
- VERSION = "0.0.4"
4
+ VERSION = "0.0.6"
5
5
  end
@@ -54,8 +54,9 @@ class DeprecationCollector
54
54
  attr_accessor :count, :raise_on_deprecation, :save_full_backtrace,
55
55
  :exclude_realms,
56
56
  :write_interval, :write_interval_jitter,
57
- :app_revision, :app_root
58
- attr_writer :redis
57
+ :app_revision, :app_root,
58
+ :print_to_stderr, :print_recurring
59
+ attr_writer :redis, :context_saver
59
60
 
60
61
  def initialize(mutex: nil)
61
62
  # on cruby hash itself is threadsafe, but we need to prevent races
@@ -78,12 +79,19 @@ class DeprecationCollector
78
79
  # NB: in production with hugreds of workers may easily overload redis with writes, so more delay needed:
79
80
  @write_interval = 900 # 15.minutes
80
81
  @write_interval_jitter = 60
82
+ @context_saver = nil
81
83
  end
82
84
 
83
85
  def ignored_messages=(val)
84
86
  @ignore_message_regexp = (val && Regexp.union(val)) || nil
85
87
  end
86
88
 
89
+ def context_saver(&block)
90
+ return @context_saver unless block_given?
91
+
92
+ @context_saver = block
93
+ end
94
+
87
95
  def app_root_prefix
88
96
  "#{app_root}/"
89
97
  end
@@ -97,8 +105,8 @@ class DeprecationCollector
97
105
  raise "Deprecation: #{message}" if @raise_on_deprecation
98
106
 
99
107
  deprecation = Deprecation.new(message, realm, backtrace, cleanup_prefixes)
100
- store_deprecation(deprecation)
101
- log_deprecation_if_needed(deprecation)
108
+ fresh = store_deprecation(deprecation)
109
+ log_deprecation_if_needed(deprecation, fresh)
102
110
  end
103
111
 
104
112
  def unsent_data?
@@ -190,10 +198,10 @@ class DeprecationCollector
190
198
  def read_one(digest)
191
199
  decode_deprecation(
192
200
  digest,
193
- *@redis.pipelined do
194
- @redis.hget("deprecations:data", digest)
195
- @redis.hget("deprecations:counter", digest)
196
- @redis.hget("deprecations:notes", digest)
201
+ *@redis.pipelined do |pipe|
202
+ pipe.hget("deprecations:data", digest)
203
+ pipe.hget("deprecations:counter", digest)
204
+ pipe.hget("deprecations:notes", digest)
197
205
  end
198
206
  )
199
207
  end
@@ -201,10 +209,10 @@ class DeprecationCollector
201
209
  def delete_deprecations(remove_digests)
202
210
  return 0 unless remove_digests.any?
203
211
 
204
- @redis.pipelined do
205
- @redis.hdel("deprecations:data", *remove_digests)
206
- @redis.hdel("deprecations:notes", *remove_digests)
207
- @redis.hdel("deprecations:counter", *remove_digests) if @count
212
+ @redis.pipelined do |pipe|
213
+ pipe.hdel("deprecations:data", *remove_digests)
214
+ pipe.hdel("deprecations:notes", *remove_digests)
215
+ pipe.hdel("deprecations:counter", *remove_digests) if @count
208
216
  end.first
209
217
  end
210
218
 
@@ -226,18 +234,23 @@ class DeprecationCollector
226
234
 
227
235
  def store_deprecation(deprecation)
228
236
  return if deprecation.ignored?
237
+ fresh = !@deprecations.key?(deprecation.digest)
238
+ deprecation.context = context_saver.call if context_saver
229
239
 
230
240
  @deprecations_mutex.synchronize do
231
241
  (@deprecations[deprecation.digest] ||= deprecation).touch
232
242
  end
233
243
 
234
244
  write_to_redis if current_time - @last_write_time > (@write_interval + rand(@write_interval_jitter))
245
+ fresh
235
246
  end
236
247
 
237
- def log_deprecation_if_needed(deprecation)
238
- return unless defined?(Rails) && Rails.env.development? && !deprecation.ignored?
239
-
240
- $stderr.puts(deprecation.message) # rubocop:disable Style/StderrPuts
248
+ def log_deprecation_if_needed(deprecation, fresh)
249
+ return unless print_to_stderr && !deprecation.ignored?
250
+ return unless fresh || print_recurring
251
+ msg = deprecation.message
252
+ msg = "DEPRECATION: #{msg}" unless msg.start_with?('DEPRECAT')
253
+ $stderr.puts(msg) # rubocop:disable Style/StderrPuts
241
254
  end
242
255
 
243
256
  def current_time
@@ -247,7 +260,12 @@ class DeprecationCollector
247
260
  end
248
261
 
249
262
  def decode_deprecation(digest, data, count, notes)
263
+ return nil unless data
250
264
  data = JSON.parse(data, symbolize_names: true)
265
+ unless data.is_a?(Hash)
266
+ binding.irb
267
+ return nil
268
+ end
251
269
  data[:digest] = digest
252
270
  data[:notes] = JSON.parse(notes, symbolize_names: true) if notes
253
271
  data[:count] = count.to_i if count
@@ -255,9 +273,9 @@ class DeprecationCollector
255
273
  end
256
274
 
257
275
  def write_count_to_redis(deprecations_to_flush)
258
- @redis.pipelined do
276
+ @redis.pipelined do |pipe|
259
277
  deprecations_to_flush.each_pair do |digest, deprecation|
260
- @redis.hincrby("deprecations:counter", digest, deprecation.occurences)
278
+ pipe.hincrby("deprecations:counter", digest, deprecation.occurences)
261
279
  end
262
280
  end
263
281
  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
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vasily Fedoseyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-29 00:00:00.000000000 Z
11
+ date: 2022-10-04 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: '2.0'
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: '2.0'
26
+ version: '3.0'
27
27
  description: Collects and aggregates warnings and deprecations. Optimized for production
28
28
  environment.
29
29
  email:
@@ -69,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
69
  - !ruby/object:Gem::Version
70
70
  version: '0'
71
71
  requirements: []
72
- rubygems_version: 3.1.6
72
+ rubygems_version: 3.3.7
73
73
  signing_key:
74
74
  specification_version: 4
75
75
  summary: Collector for ruby/rails deprecations and warnings, suitable for production