airbrake-ruby 5.2.0-java → 5.2.1-java

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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/lib/airbrake-ruby.rb +3 -2
  3. data/lib/airbrake-ruby/async_sender.rb +3 -1
  4. data/lib/airbrake-ruby/context.rb +51 -0
  5. data/lib/airbrake-ruby/filter_chain.rb +2 -0
  6. data/lib/airbrake-ruby/filters/context_filter.rb +4 -5
  7. data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +1 -1
  8. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +1 -1
  9. data/lib/airbrake-ruby/filters/git_revision_filter.rb +1 -1
  10. data/lib/airbrake-ruby/filters/keys_filter.rb +2 -2
  11. data/lib/airbrake-ruby/filters/sql_filter.rb +2 -2
  12. data/lib/airbrake-ruby/filters/thread_filter.rb +1 -1
  13. data/lib/airbrake-ruby/ignorable.rb +0 -2
  14. data/lib/airbrake-ruby/notice_notifier.rb +3 -4
  15. data/lib/airbrake-ruby/performance_notifier.rb +1 -2
  16. data/lib/airbrake-ruby/remote_settings/settings_data.rb +1 -1
  17. data/lib/airbrake-ruby/tdigest.rb +7 -6
  18. data/lib/airbrake-ruby/thread_pool.rb +5 -3
  19. data/lib/airbrake-ruby/timed_trace.rb +1 -3
  20. data/lib/airbrake-ruby/version.rb +1 -1
  21. data/spec/airbrake_spec.rb +139 -76
  22. data/spec/async_sender_spec.rb +10 -8
  23. data/spec/backtrace_spec.rb +13 -10
  24. data/spec/benchmark_spec.rb +5 -3
  25. data/spec/code_hunk_spec.rb +24 -15
  26. data/spec/config/processor_spec.rb +12 -4
  27. data/spec/config/validator_spec.rb +5 -2
  28. data/spec/config_spec.rb +24 -16
  29. data/spec/context_spec.rb +54 -0
  30. data/spec/deploy_notifier_spec.rb +6 -4
  31. data/spec/file_cache_spec.rb +1 -0
  32. data/spec/filter_chain_spec.rb +29 -24
  33. data/spec/filters/context_filter_spec.rb +14 -5
  34. data/spec/filters/dependency_filter_spec.rb +3 -1
  35. data/spec/filters/exception_attributes_filter_spec.rb +5 -3
  36. data/spec/filters/gem_root_filter_spec.rb +5 -2
  37. data/spec/filters/git_last_checkout_filter_spec.rb +10 -12
  38. data/spec/filters/git_repository_filter.rb +9 -9
  39. data/spec/filters/git_revision_filter_spec.rb +19 -19
  40. data/spec/filters/keys_allowlist_spec.rb +25 -16
  41. data/spec/filters/keys_blocklist_spec.rb +25 -18
  42. data/spec/filters/root_directory_filter_spec.rb +3 -3
  43. data/spec/filters/sql_filter_spec.rb +26 -26
  44. data/spec/filters/system_exit_filter_spec.rb +4 -2
  45. data/spec/filters/thread_filter_spec.rb +15 -13
  46. data/spec/loggable_spec.rb +2 -2
  47. data/spec/monotonic_time_spec.rb +8 -6
  48. data/spec/nested_exception_spec.rb +46 -46
  49. data/spec/notice_notifier/options_spec.rb +23 -13
  50. data/spec/notice_notifier_spec.rb +52 -47
  51. data/spec/notice_spec.rb +6 -2
  52. data/spec/performance_notifier_spec.rb +67 -60
  53. data/spec/promise_spec.rb +38 -32
  54. data/spec/remote_settings/callback_spec.rb +27 -8
  55. data/spec/remote_settings/settings_data_spec.rb +4 -4
  56. data/spec/remote_settings_spec.rb +18 -8
  57. data/spec/response_spec.rb +34 -12
  58. data/spec/stashable_spec.rb +5 -5
  59. data/spec/stat_spec.rb +7 -5
  60. data/spec/sync_sender_spec.rb +49 -16
  61. data/spec/tdigest_spec.rb +60 -55
  62. data/spec/thread_pool_spec.rb +65 -55
  63. data/spec/time_truncate_spec.rb +4 -2
  64. data/spec/timed_trace_spec.rb +32 -30
  65. data/spec/truncator_spec.rb +72 -43
  66. metadata +51 -48
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f03821ae0b7ff2d1e1e0b7e1122e2fc8368c4cabd4fac5d623530dd7eafac33c
4
- data.tar.gz: cf2234bd6fc61e439796b0f664163a12fdd4c39c4256a1c469f06dd1f8132de3
3
+ metadata.gz: 3b991075f1de43dc06d88b8e0a7e674ae99fccfffc0dc5214aa823674fbc9d63
4
+ data.tar.gz: 714f8424b206e2842237c5417833118d2960e1eb0a1c4ff7d16ad75467b9bfc1
5
5
  SHA512:
6
- metadata.gz: 9980a80ea62fe7602ae7d689e3b35f439370d781b4d4001e4960b18705465fc3bed7f7a49b67eeb7249253c55c58a1ba9b87485979fd9cdb4c320c2a7e1aa67a
7
- data.tar.gz: d13b77d0f959ff3a5326f054b8df67c9402b216038afd25672df8b6803623ac135bb5366739687fc5c234ae2e127d075828f747bb945d9ba4d48f3f354775f17
6
+ metadata.gz: 6f796be1a4661cc7ad536f5fce6771c094ec2683b23f3474cfcea225c259f5adbb0943af6d04269c695abc745c0213699748be273284b101fd3410fc5d0bbb05
7
+ data.tar.gz: af89bef16ed1f0f64b1e65484d680cdd5204905d5981c7a1310d19c9d875cf4ce702b06d51b4c508985b5e1cc7d0a87b33c7cc8a002d673bad11dffa4fc0f248
data/lib/airbrake-ruby.rb CHANGED
@@ -58,6 +58,7 @@ require 'airbrake-ruby/benchmark'
58
58
  require 'airbrake-ruby/monotonic_time'
59
59
  require 'airbrake-ruby/timed_trace'
60
60
  require 'airbrake-ruby/queue'
61
+ require 'airbrake-ruby/context'
61
62
 
62
63
  # Airbrake is a thin wrapper around instances of the notifier classes (such as
63
64
  # notice, performance & deploy notifiers). It creates a way to access them via a
@@ -273,7 +274,7 @@ module Airbrake
273
274
  # Airbrake.notify('App crashed!') #=> raises Airbrake::Error
274
275
  #
275
276
  # @return [nil]
276
- # rubocop:disable Style/IfUnlessModifier, Metrics/CyclomaticComplexity
277
+ # rubocop:disable Style/IfUnlessModifier
277
278
  def close
278
279
  if defined?(@notice_notifier) && @notice_notifier
279
280
  @notice_notifier.close
@@ -289,7 +290,7 @@ module Airbrake
289
290
 
290
291
  nil
291
292
  end
292
- # rubocop:enable Style/IfUnlessModifier, Metrics/CyclomaticComplexity
293
+ # rubocop:enable Style/IfUnlessModifier
293
294
 
294
295
  # Pings the Airbrake Deploy API endpoint about the occurred deploy.
295
296
  #
@@ -7,9 +7,10 @@ module Airbrake
7
7
  class AsyncSender
8
8
  include Loggable
9
9
 
10
- def initialize(method = :post)
10
+ def initialize(method = :post, name = 'async-sender')
11
11
  @config = Airbrake::Config.instance
12
12
  @method = method
13
+ @name = name
13
14
  end
14
15
 
15
16
  # Asynchronously sends a notice to Airbrake.
@@ -47,6 +48,7 @@ module Airbrake
47
48
  @thread_pool ||= begin
48
49
  sender = SyncSender.new(@method)
49
50
  ThreadPool.new(
51
+ name: @name,
50
52
  worker_size: @config.workers,
51
53
  queue_size: @config.queue_size,
52
54
  block: proc { |args| sender.send(*args) },
@@ -0,0 +1,51 @@
1
+ module Airbrake
2
+ # Represents a thread-safe Airbrake context object, which carries arbitrary
3
+ # information added via {Airbrake.merge_context} calls.
4
+ #
5
+ # @example
6
+ # Airbrake::Context.current.merge!(foo: 'bar')
7
+ #
8
+ # @api private
9
+ # @since v5.2.1
10
+ class Context
11
+ # Returns current, thread-local, context.
12
+ # @return [self]
13
+ def self.current
14
+ Thread.current[:airbrake_context] ||= new
15
+ end
16
+
17
+ def initialize
18
+ @mutex = Mutex.new
19
+ @context = {}
20
+ end
21
+
22
+ # Merges the given context with the current one.
23
+ #
24
+ # @param [Hash{Object=>Object}] other
25
+ # @return [void]
26
+ def merge!(other)
27
+ @mutex.synchronize do
28
+ @context.merge!(other)
29
+ end
30
+ end
31
+
32
+ # @return [Hash] duplicated Hash context
33
+ def to_h
34
+ @mutex.synchronize do
35
+ @context.dup
36
+ end
37
+ end
38
+
39
+ # @return [Hash] clears (resets) the current context
40
+ def clear
41
+ @mutex.synchronize do
42
+ @context.clear
43
+ end
44
+ end
45
+
46
+ # @return [Boolean] checks whether the context has any data
47
+ def empty?
48
+ @context.empty?
49
+ end
50
+ end
51
+ end
@@ -57,7 +57,9 @@ module Airbrake
57
57
  # @return [void]
58
58
  # @since v3.1.0
59
59
  def delete_filter(filter_class)
60
+ # rubocop:disable Style/ClassEqualityComparison
60
61
  index = @filters.index { |f| f.class.name == filter_class.name }
62
+ # rubocop:enable Style/ClassEqualityComparison
61
63
  @filters.delete_at(index) if index
62
64
  end
63
65
 
@@ -9,8 +9,7 @@ module Airbrake
9
9
  # @return [Integer]
10
10
  attr_reader :weight
11
11
 
12
- def initialize(context)
13
- @context = context
12
+ def initialize
14
13
  @weight = 119
15
14
  @mutex = Mutex.new
16
15
  end
@@ -18,10 +17,10 @@ module Airbrake
18
17
  # @macro call_filter
19
18
  def call(notice)
20
19
  @mutex.synchronize do
21
- return if @context.empty?
20
+ return if Airbrake::Context.current.empty?
22
21
 
23
- notice[:params][:airbrake_context] = @context.dup
24
- @context.clear
22
+ notice[:params][:airbrake_context] = Airbrake::Context.current.to_h
23
+ Airbrake::Context.current.clear
25
24
  end
26
25
  end
27
26
  end
@@ -13,7 +13,7 @@ module Airbrake
13
13
  end
14
14
 
15
15
  # @macro call_filter
16
- def call(notice)
16
+ def call(notice) # rubocop:disable Metrics/AbcSize
17
17
  exception = notice.stash[:exception]
18
18
  return unless exception.respond_to?(:to_airbrake)
19
19
 
@@ -50,7 +50,7 @@ module Airbrake
50
50
  def last_checkout
51
51
  return unless (line = last_checkout_line)
52
52
 
53
- parts = line.chomp.split("\t").first.split(' ')
53
+ parts = line.chomp.split("\t").first.split
54
54
  if parts.size < MIN_HEAD_COLS
55
55
  logger.error(
56
56
  "#{LOG_LABEL} Airbrake::#{self.class.name}: can't parse line: #{line}",
@@ -57,7 +57,7 @@ module Airbrake
57
57
 
58
58
  File.readlines(packed_refs_path).each do |line|
59
59
  next if %w[# ^].include?(line[0])
60
- next unless (parts = line.split(' ')).size == 2
60
+ next unless (parts = line.split).size == 2
61
61
  return parts.first if parts.last == head
62
62
  end
63
63
 
@@ -82,7 +82,7 @@ module Airbrake
82
82
 
83
83
  private
84
84
 
85
- def filter_hash(hash)
85
+ def filter_hash(hash) # rubocop:disable Metrics/AbcSize
86
86
  return hash unless hash.is_a?(Hash)
87
87
 
88
88
  hash_copy = hash.dup
@@ -103,7 +103,7 @@ module Airbrake
103
103
  end
104
104
 
105
105
  def filter_url_params(url)
106
- url.query = Hash[URI.decode_www_form(url.query)].map do |key, val|
106
+ url.query = URI.decode_www_form(url.query).to_h.map do |key, val|
107
107
  should_filter?(key) ? "#{key}=[Filtered]" : "#{key}=#{val}"
108
108
  end.join('&')
109
109
 
@@ -27,13 +27,13 @@ module Airbrake
27
27
  single_quotes: /'(?:[^']|'')*?(?:\\'.*|'(?!'))/,
28
28
  double_quotes: /"(?:[^"]|"")*?(?:\\".*|"(?!"))/,
29
29
  dollar_quotes: /(\$(?!\d)[^$]*?\$).*?(?:\1|$)/,
30
- uuids: /\{?(?:[0-9a-fA-F]\-*){32}\}?/,
30
+ uuids: /\{?(?:[0-9a-fA-F]-*){32}\}?/,
31
31
  numeric_literals: /\b-?(?:[0-9]+\.)?[0-9]+([eE][+-]?[0-9]+)?\b/,
32
32
  boolean_literals: /\b(?:true|false|null)\b/i,
33
33
  hexadecimal_literals: /0x[0-9a-fA-F]+/,
34
34
  comments: /(?:#|--).*?(?=\r|\n|$)/i,
35
35
  multi_line_comments: %r{/\*(?:[^/]|/[^*])*?(?:\*/|/\*.*)},
36
- oracle_quoted_strings: /q'\[.*?(?:\]'|$)|q'\{.*?(?:\}'|$)|q'\<.*?(?:\>'|$)|q'\(.*?(?:\)'|$)/,
36
+ oracle_quoted_strings: /q'\[.*?(?:\]'|$)|q'\{.*?(?:\}'|$)|q'<.*?(?:>'|$)|q'\(.*?(?:\)'|$)/,
37
37
  # rubocop:enable Layout/LineLength
38
38
  }.freeze
39
39
 
@@ -83,7 +83,7 @@ module Airbrake
83
83
  when Array
84
84
  value = value.map { |elem| sanitize_value(elem) }
85
85
  when Hash
86
- Hash[value.map { |k, v| [k, sanitize_value(v)] }]
86
+ value.transform_values { |v| sanitize_value(v) }
87
87
  else
88
88
  value.to_s
89
89
  end
@@ -18,11 +18,9 @@ module Airbrake
18
18
  # Checks whether the instance was ignored.
19
19
  # @return [Boolean]
20
20
  # @see #ignore!
21
- # rubocop:disable Style/DoubleNegation
22
21
  def ignored?
23
22
  !!ignored
24
23
  end
25
- # rubocop:enable Style/DoubleNegation
26
24
 
27
25
  # Ignores an instance. Ignored instances must never reach the Airbrake
28
26
  # dashboard.
@@ -20,14 +20,13 @@ module Airbrake
20
20
 
21
21
  def initialize
22
22
  @config = Airbrake::Config.instance
23
- @context = {}
24
23
  @filter_chain = FilterChain.new
25
- @async_sender = AsyncSender.new
24
+ @async_sender = AsyncSender.new(:post, self.class.name)
26
25
  @sync_sender = SyncSender.new
27
26
 
28
27
  DEFAULT_FILTERS.each { |filter| add_filter(filter.new) }
29
28
 
30
- add_filter(Airbrake::Filters::ContextFilter.new(@context))
29
+ add_filter(Airbrake::Filters::ContextFilter.new)
31
30
  add_filter(Airbrake::Filters::ExceptionAttributesFilter.new)
32
31
  end
33
32
 
@@ -79,7 +78,7 @@ module Airbrake
79
78
 
80
79
  # @see Airbrake.merge_context
81
80
  def merge_context(context)
82
- @context.merge!(context)
81
+ Airbrake::Context.current.merge!(context)
83
82
  end
84
83
 
85
84
  # @return [Boolean]
@@ -12,7 +12,7 @@ module Airbrake
12
12
  def initialize
13
13
  @config = Airbrake::Config.instance
14
14
  @flush_period = Airbrake::Config.instance.performance_stats_flush_period
15
- @async_sender = AsyncSender.new(:put)
15
+ @async_sender = AsyncSender.new(:put, self.class.name)
16
16
  @sync_sender = SyncSender.new(:put)
17
17
  @schedule_flush = nil
18
18
  @filter_chain = FilterChain.new
@@ -51,7 +51,6 @@ module Airbrake
51
51
  @payload.synchronize do
52
52
  @schedule_flush.kill if @schedule_flush
53
53
  @async_sender.close
54
- logger.debug("#{LOG_LABEL} performance notifier closed")
55
54
  end
56
55
  end
57
56
 
@@ -59,7 +59,7 @@ module Airbrake
59
59
  # @return [String] where the config is stored on S3.
60
60
  def config_route(remote_config_host)
61
61
  if @data['config_route'] && !@data['config_route'].empty?
62
- return remote_config_host.chomp('/') + '/' + @data['config_route']
62
+ return "#{remote_config_host.chomp('/')}/#{@data['config_route']}"
63
63
  end
64
64
 
65
65
  format(
@@ -24,6 +24,7 @@ module Airbrake
24
24
  # @since v3.2.0
25
25
  class Centroid
26
26
  attr_accessor :mean, :n, :cumn, :mean_cumn
27
+
27
28
  def initialize(mean, n, cumn, mean_cumn = nil)
28
29
  @mean = mean
29
30
  @n = n
@@ -130,7 +131,7 @@ module Airbrake
130
131
  points = to_a
131
132
  reset!
132
133
  push_centroid(points.shuffle)
133
- _cumulate(true, true)
134
+ _cumulate(exact: true, force: true)
134
135
  nil
135
136
  end
136
137
 
@@ -175,7 +176,7 @@ module Airbrake
175
176
  elsif item > max[1].mean
176
177
  1.0
177
178
  else
178
- _cumulate(true)
179
+ _cumulate(exact: true)
179
180
  bound = bound_mean(item)
180
181
  lower, upper = bound
181
182
  mean_cumn = lower.mean_cumn
@@ -204,7 +205,7 @@ module Airbrake
204
205
  if size == 0
205
206
  nil
206
207
  else
207
- _cumulate(true)
208
+ _cumulate(exact: true)
208
209
  h = @size * item
209
210
  lower, upper = bound_mean_cumn(h)
210
211
  if lower.nil? && upper.nil?
@@ -306,7 +307,7 @@ module Airbrake
306
307
  centroid.mean += n * (x - centroid.mean) / (centroid.n + n)
307
308
  end
308
309
 
309
- _cumulate(false, true) if centroid.mean_cumn.nil?
310
+ _cumulate(exact: false, force: true) if centroid.mean_cumn.nil?
310
311
 
311
312
  centroid.cumn += n
312
313
  centroid.mean_cumn += n / 2.0
@@ -314,7 +315,7 @@ module Airbrake
314
315
  end
315
316
 
316
317
  # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
317
- def _cumulate(exact = false, force = false)
318
+ def _cumulate(exact: false, force: false)
318
319
  unless force
319
320
  factor = if @last_cumulate == 0
320
321
  Float::INFINITY
@@ -361,7 +362,7 @@ module Airbrake
361
362
  end
362
363
  end
363
364
 
364
- _cumulate(false)
365
+ _cumulate(exact: false)
365
366
 
366
367
  # If the number of centroids has grown to a very large size,
367
368
  # it may be due to values being inserted in sorted order.
@@ -6,6 +6,7 @@ module Airbrake
6
6
  # # Initialize a new thread pool with 5 workers and a queue size of 100. Set
7
7
  # # the block to be run concurrently.
8
8
  # thread_pool = ThreadPool.new(
9
+ # name: 'performance-notifier',
9
10
  # worker_size: 5,
10
11
  # queue_size: 100,
11
12
  # block: proc { |message| print "ECHO: #{message}..."}
@@ -24,7 +25,8 @@ module Airbrake
24
25
  # @note This is exposed for eaiser unit testing
25
26
  attr_reader :workers
26
27
 
27
- def initialize(worker_size:, queue_size:, block:)
28
+ def initialize(worker_size:, queue_size:, block:, name: nil)
29
+ @name = name
28
30
  @worker_size = worker_size
29
31
  @queue_size = queue_size
30
32
  @block = block
@@ -102,7 +104,7 @@ module Airbrake
102
104
 
103
105
  unless @queue.empty?
104
106
  msg = "#{LOG_LABEL} waiting to process #{@queue.size} task(s)..."
105
- logger.debug(msg + ' (Ctrl-C to abort)')
107
+ logger.debug("#{msg} (Ctrl-C to abort)")
106
108
  end
107
109
 
108
110
  @worker_size.times { @queue << :stop }
@@ -111,7 +113,7 @@ module Airbrake
111
113
  end
112
114
 
113
115
  threads.each(&:join)
114
- logger.debug("#{LOG_LABEL} thread pool closed")
116
+ logger.debug("#{LOG_LABEL} #{@name} thread pool closed")
115
117
  end
116
118
 
117
119
  def closed?
@@ -50,9 +50,7 @@ module Airbrake
50
50
 
51
51
  # @return [Hash<String=>Float>]
52
52
  def spans
53
- @spans.each_with_object({}) do |(label, benchmark), new_spans|
54
- new_spans[label] = benchmark.duration
55
- end
53
+ @spans.transform_values(&:duration)
56
54
  end
57
55
  end
58
56
  end
@@ -3,7 +3,7 @@
3
3
  module Airbrake
4
4
  # @return [String] the library version
5
5
  # @api public
6
- AIRBRAKE_RUBY_VERSION = '5.2.0'.freeze
6
+ AIRBRAKE_RUBY_VERSION = '5.2.1'.freeze
7
7
 
8
8
  # @return [Hash{Symbol=>String}] the information about the notifier library
9
9
  # @since v5.0.0
@@ -30,11 +30,9 @@ RSpec.describe Airbrake do
30
30
 
31
31
  it "yields the config" do
32
32
  expect do |b|
33
- begin
34
- described_class.configure(&b)
35
- rescue Airbrake::Error
36
- nil
37
- end
33
+ described_class.configure(&b)
34
+ rescue Airbrake::Error
35
+ nil
38
36
  end.to yield_with_args(Airbrake::Config)
39
37
  end
40
38
 
@@ -62,26 +60,26 @@ RSpec.describe Airbrake do
62
60
 
63
61
  context "when called multiple times" do
64
62
  it "doesn't overwrite performance notifier" do
65
- described_class.configure {}
63
+ described_class.configure { anything }
66
64
  performance_notifier = described_class.performance_notifier
67
65
 
68
- described_class.configure {}
66
+ described_class.configure { anything }
69
67
  expect(described_class.performance_notifier).to eql(performance_notifier)
70
68
  end
71
69
 
72
70
  it "doesn't overwrite notice notifier" do
73
- described_class.configure {}
71
+ described_class.configure { anything }
74
72
  notice_notifier = described_class.notice_notifier
75
73
 
76
- described_class.configure {}
74
+ described_class.configure { anything }
77
75
  expect(described_class.notice_notifier).to eql(notice_notifier)
78
76
  end
79
77
 
80
78
  it "doesn't overwrite deploy notifier" do
81
- described_class.configure {}
79
+ described_class.configure { anything }
82
80
  deploy_notifier = described_class.deploy_notifier
83
81
 
84
- described_class.configure {}
82
+ described_class.configure { anything }
85
83
  expect(described_class.deploy_notifier).to eql(deploy_notifier)
86
84
  end
87
85
 
@@ -91,20 +89,24 @@ RSpec.describe Airbrake do
91
89
  c.project_key = '2'
92
90
  end
93
91
 
94
- expect(described_class.notice_notifier).not_to receive(:add_filter)
95
- 10.times { described_class.configure {} }
92
+ allow(described_class.notice_notifier).to receive(:add_filter)
93
+
94
+ 10.times { described_class.configure { anything } }
95
+
96
+ expect(described_class.notice_notifier).not_to have_received(:add_filter)
96
97
  end
97
98
 
98
99
  it "appends some default filters" do
99
100
  allow(described_class.notice_notifier).to receive(:add_filter)
100
- expect(described_class.notice_notifier).to receive(:add_filter).with(
101
- an_instance_of(Airbrake::Filters::RootDirectoryFilter),
102
- )
103
101
 
104
102
  described_class.configure do |c|
105
103
  c.project_id = 1
106
104
  c.project_key = '2'
107
105
  end
106
+
107
+ expect(described_class.notice_notifier).to have_received(:add_filter).with(
108
+ an_instance_of(Airbrake::Filters::RootDirectoryFilter),
109
+ )
108
110
  end
109
111
  end
110
112
 
@@ -112,14 +114,21 @@ RSpec.describe Airbrake do
112
114
  before { allow(described_class.notice_notifier).to receive(:add_filter) }
113
115
 
114
116
  it "adds blocklist filter" do
115
- expect(described_class.notice_notifier).to receive(:add_filter)
116
- .with(an_instance_of(Airbrake::Filters::KeysBlocklist))
117
+ allow(described_class.notice_notifier).to receive(:add_filter)
118
+
117
119
  described_class.configure { |c| c.blocklist_keys = %w[password] }
120
+
121
+ expect(described_class.notice_notifier).to have_received(:add_filter)
122
+ .with(an_instance_of(Airbrake::Filters::KeysBlocklist))
118
123
  end
119
124
 
120
125
  it "initializes blocklist with specified parameters" do
121
- expect(Airbrake::Filters::KeysBlocklist).to receive(:new).with(%w[password])
126
+ allow(Airbrake::Filters::KeysBlocklist).to receive(:new)
127
+
122
128
  described_class.configure { |c| c.blocklist_keys = %w[password] }
129
+
130
+ expect(Airbrake::Filters::KeysBlocklist)
131
+ .to have_received(:new).with(%w[password])
123
132
  end
124
133
  end
125
134
 
@@ -127,14 +136,17 @@ RSpec.describe Airbrake do
127
136
  before { allow(described_class.notice_notifier).to receive(:add_filter) }
128
137
 
129
138
  it "adds allowlist filter" do
130
- expect(described_class.notice_notifier).to receive(:add_filter)
131
- .with(an_instance_of(Airbrake::Filters::KeysAllowlist))
132
139
  described_class.configure { |c| c.allowlist_keys = %w[banana] }
140
+ expect(described_class.notice_notifier).to have_received(:add_filter)
141
+ .with(an_instance_of(Airbrake::Filters::KeysAllowlist))
133
142
  end
134
143
 
135
144
  it "initializes allowlist with specified parameters" do
136
- expect(Airbrake::Filters::KeysAllowlist).to receive(:new).with(%w[banana])
145
+ allow(Airbrake::Filters::KeysAllowlist).to receive(:new)
146
+
137
147
  described_class.configure { |c| c.allowlist_keys = %w[banana] }
148
+ expect(Airbrake::Filters::KeysAllowlist)
149
+ .to have_received(:new).with(%w[banana])
138
150
  end
139
151
  end
140
152
 
@@ -142,77 +154,90 @@ RSpec.describe Airbrake do
142
154
  before { allow(described_class.notice_notifier).to receive(:add_filter) }
143
155
 
144
156
  it "adds root directory filter" do
145
- expect(described_class.notice_notifier).to receive(:add_filter)
146
- .with(an_instance_of(Airbrake::Filters::RootDirectoryFilter))
147
157
  described_class.configure { |c| c.root_directory = '/my/path' }
158
+
159
+ expect(described_class.notice_notifier).to have_received(:add_filter)
160
+ .with(an_instance_of(Airbrake::Filters::RootDirectoryFilter))
148
161
  end
149
162
 
150
163
  it "initializes root directory filter with specified path" do
151
- expect(Airbrake::Filters::RootDirectoryFilter)
152
- .to receive(:new).with('/my/path')
164
+ allow(Airbrake::Filters::RootDirectoryFilter).to receive(:new)
153
165
  described_class.configure { |c| c.root_directory = '/my/path' }
166
+
167
+ expect(Airbrake::Filters::RootDirectoryFilter)
168
+ .to have_received(:new).with('/my/path')
154
169
  end
155
170
 
156
171
  it "adds git revision filter" do
157
- expect(described_class.notice_notifier).to receive(:add_filter)
158
- .with(an_instance_of(Airbrake::Filters::GitRevisionFilter))
159
172
  described_class.configure { |c| c.root_directory = '/my/path' }
173
+ expect(described_class.notice_notifier).to have_received(:add_filter)
174
+ .with(an_instance_of(Airbrake::Filters::GitRevisionFilter))
160
175
  end
161
176
 
162
177
  it "initializes git revision filter with correct root directory" do
163
- expect(Airbrake::Filters::GitRevisionFilter)
164
- .to receive(:new).with('/my/path')
178
+ allow(Airbrake::Filters::GitRevisionFilter).to receive(:new)
165
179
  described_class.configure { |c| c.root_directory = '/my/path' }
180
+
181
+ expect(Airbrake::Filters::GitRevisionFilter)
182
+ .to have_received(:new).with('/my/path')
166
183
  end
167
184
 
168
185
  it "adds git repository filter" do
169
- expect(described_class.notice_notifier).to receive(:add_filter)
170
- .with(an_instance_of(Airbrake::Filters::GitRepositoryFilter))
171
186
  described_class.configure { |c| c.root_directory = '/my/path' }
187
+
188
+ expect(described_class.notice_notifier).to have_received(:add_filter)
189
+ .with(an_instance_of(Airbrake::Filters::GitRepositoryFilter))
172
190
  end
173
191
 
174
192
  it "initializes git repository filter with correct root directory" do
175
- expect(Airbrake::Filters::GitRepositoryFilter)
176
- .to receive(:new).with('/my/path')
193
+ allow(Airbrake::Filters::GitRepositoryFilter).to receive(:new)
194
+
177
195
  described_class.configure { |c| c.root_directory = '/my/path' }
196
+
197
+ expect(Airbrake::Filters::GitRepositoryFilter)
198
+ .to have_received(:new).with('/my/path')
178
199
  end
179
200
 
180
201
  it "adds git last checkout filter" do
181
- expect(described_class.notice_notifier).to receive(:add_filter)
182
- .with(an_instance_of(Airbrake::Filters::GitLastCheckoutFilter))
183
202
  described_class.configure { |c| c.root_directory = '/my/path' }
203
+ expect(described_class.notice_notifier).to have_received(:add_filter)
204
+ .with(an_instance_of(Airbrake::Filters::GitLastCheckoutFilter))
184
205
  end
185
206
 
186
207
  it "initializes git last checkout filter with correct root directory" do
187
- expect(Airbrake::Filters::GitLastCheckoutFilter)
188
- .to receive(:new).with('/my/path')
208
+ allow(Airbrake::Filters::GitLastCheckoutFilter).to receive(:new)
189
209
  described_class.configure { |c| c.root_directory = '/my/path' }
210
+
211
+ expect(Airbrake::Filters::GitLastCheckoutFilter)
212
+ .to have_received(:new).with('/my/path')
190
213
  end
191
214
  end
192
215
  end
193
216
 
194
217
  describe ".notify_request" do
218
+ before do
219
+ allow(described_class.performance_notifier).to receive(:notify)
220
+ end
221
+
195
222
  context "when :stash key is not provided" do
196
223
  it "doesn't add anything to the stash of the request" do
197
- expect(described_class.performance_notifier).to receive(:notify) do |request|
198
- expect(request.stash).to be_empty
199
- end
200
-
201
224
  described_class.notify_request(
202
225
  method: 'GET',
203
226
  route: '/',
204
227
  status_code: 200,
205
228
  timing: 1,
206
229
  )
230
+
231
+ expect(
232
+ described_class.performance_notifier,
233
+ ).to have_received(:notify) do |request|
234
+ expect(request.stash).to be_empty
235
+ end
207
236
  end
208
237
  end
209
238
 
210
239
  context "when :stash key is provided" do
211
240
  it "adds the value as the stash of the request" do
212
- expect(described_class.performance_notifier).to receive(:notify) do |request|
213
- expect(request.stash).to eq(request_id: 1)
214
- end
215
-
216
241
  described_class.notify_request(
217
242
  {
218
243
  method: 'GET',
@@ -222,13 +247,19 @@ RSpec.describe Airbrake do
222
247
  },
223
248
  request_id: 1,
224
249
  )
250
+
251
+ expect(
252
+ described_class.performance_notifier,
253
+ ).to have_received(:notify) do |request|
254
+ expect(request.stash).to eq(request_id: 1)
255
+ end
225
256
  end
226
257
  end
227
258
  end
228
259
 
229
260
  describe ".notify_request_sync" do
230
261
  it "notifies request synchronously" do
231
- expect(described_class.performance_notifier).to receive(:notify_sync)
262
+ allow(described_class.performance_notifier).to receive(:notify_sync)
232
263
 
233
264
  described_class.notify_request_sync(
234
265
  {
@@ -239,31 +270,35 @@ RSpec.describe Airbrake do
239
270
  },
240
271
  request_id: 1,
241
272
  )
273
+
274
+ expect(described_class.performance_notifier).to have_received(:notify_sync)
242
275
  end
243
276
  end
244
277
 
245
278
  describe ".notify_query" do
279
+ before do
280
+ allow(described_class.performance_notifier).to receive(:notify)
281
+ end
282
+
246
283
  context "when :stash key is not provided" do
247
284
  it "doesn't add anything to the stash of the query" do
248
- expect(described_class.performance_notifier).to receive(:notify) do |query|
249
- expect(query.stash).to be_empty
250
- end
251
-
252
285
  described_class.notify_query(
253
286
  method: 'GET',
254
287
  route: '/',
255
288
  query: '',
256
289
  timing: 1,
257
290
  )
291
+
292
+ expect(
293
+ described_class.performance_notifier,
294
+ ).to have_received(:notify) do |query|
295
+ expect(query.stash).to be_empty
296
+ end
258
297
  end
259
298
  end
260
299
 
261
300
  context "when :stash key is provided" do
262
301
  it "adds the value as the stash of the query" do
263
- expect(described_class.performance_notifier).to receive(:notify) do |query|
264
- expect(query.stash).to eq(request_id: 1)
265
- end
266
-
267
302
  described_class.notify_query(
268
303
  {
269
304
  method: 'GET',
@@ -273,13 +308,19 @@ RSpec.describe Airbrake do
273
308
  },
274
309
  request_id: 1,
275
310
  )
311
+
312
+ expect(
313
+ described_class.performance_notifier,
314
+ ).to have_received(:notify) do |query|
315
+ expect(query.stash).to eq(request_id: 1)
316
+ end
276
317
  end
277
318
  end
278
319
  end
279
320
 
280
321
  describe ".notify_query_sync" do
281
322
  it "notifies query synchronously" do
282
- expect(described_class.performance_notifier).to receive(:notify_sync)
323
+ allow(described_class.performance_notifier).to receive(:notify_sync)
283
324
 
284
325
  described_class.notify_query_sync(
285
326
  {
@@ -290,33 +331,35 @@ RSpec.describe Airbrake do
290
331
  },
291
332
  request_id: 1,
292
333
  )
334
+
335
+ expect(described_class.performance_notifier).to have_received(:notify_sync)
293
336
  end
294
337
  end
295
338
 
296
339
  describe ".notify_performance_breakdown" do
340
+ before do
341
+ allow(described_class.performance_notifier).to receive(:notify)
342
+ end
343
+
297
344
  context "when :stash key is not provided" do
298
345
  it "doesn't add anything to the stash of the performance breakdown" do
299
- expect(described_class.performance_notifier).to receive(:notify) do |query|
300
- expect(query.stash).to be_empty
301
- end
302
-
303
346
  described_class.notify_query(
304
347
  method: 'GET',
305
348
  route: '/',
306
349
  query: '',
307
350
  timing: 1,
308
351
  )
309
- end
310
- end
311
352
 
312
- context "when :stash key is provided" do
313
- it "adds the value as the stash of the performance breakdown" do
314
353
  expect(
315
354
  described_class.performance_notifier,
316
- ).to receive(:notify) do |performance_breakdown|
317
- expect(performance_breakdown.stash).to eq(request_id: 1)
355
+ ).to have_received(:notify) do |query|
356
+ expect(query.stash).to be_empty
318
357
  end
358
+ end
359
+ end
319
360
 
361
+ context "when :stash key is provided" do
362
+ it "adds the value as the stash of the performance breakdown" do
320
363
  described_class.notify_performance_breakdown(
321
364
  {
322
365
  method: 'GET',
@@ -327,13 +370,19 @@ RSpec.describe Airbrake do
327
370
  },
328
371
  request_id: 1,
329
372
  )
373
+
374
+ expect(
375
+ described_class.performance_notifier,
376
+ ).to have_received(:notify) do |performance_breakdown|
377
+ expect(performance_breakdown.stash).to eq(request_id: 1)
378
+ end
330
379
  end
331
380
  end
332
381
  end
333
382
 
334
383
  describe ".notify_performance_breakdown_sync" do
335
384
  it "notifies performance breakdown synchronously" do
336
- expect(described_class.performance_notifier).to receive(:notify_sync)
385
+ allow(described_class.performance_notifier).to receive(:notify_sync)
337
386
 
338
387
  described_class.notify_performance_breakdown_sync(
339
388
  {
@@ -345,29 +394,33 @@ RSpec.describe Airbrake do
345
394
  },
346
395
  request_id: 1,
347
396
  )
397
+
398
+ expect(described_class.performance_notifier).to have_received(:notify_sync)
348
399
  end
349
400
  end
350
401
 
351
402
  describe ".notify_queue" do
403
+ before do
404
+ allow(described_class.performance_notifier).to receive(:notify)
405
+ end
406
+
352
407
  context "when :stash key is not provided" do
353
408
  it "doesn't add anything to the stash of the queue" do
354
- expect(described_class.performance_notifier).to receive(:notify) do |queue|
355
- expect(queue.stash).to be_empty
356
- end
357
-
358
409
  described_class.notify_queue(
359
410
  queue: 'bananas',
360
411
  error_count: 10,
361
412
  )
413
+
414
+ expect(
415
+ described_class.performance_notifier,
416
+ ).to have_received(:notify) do |queue|
417
+ expect(queue.stash).to be_empty
418
+ end
362
419
  end
363
420
  end
364
421
 
365
422
  context "when :stash key is provided" do
366
423
  it "adds the value as the stash of the queue" do
367
- expect(described_class.performance_notifier).to receive(:notify) do |queue|
368
- expect(queue.stash).to eq(request_id: 1)
369
- end
370
-
371
424
  described_class.notify_queue(
372
425
  {
373
426
  queue: 'bananas',
@@ -375,13 +428,19 @@ RSpec.describe Airbrake do
375
428
  },
376
429
  request_id: 1,
377
430
  )
431
+
432
+ expect(
433
+ described_class.performance_notifier,
434
+ ).to have_received(:notify) do |queue|
435
+ expect(queue.stash).to eq(request_id: 1)
436
+ end
378
437
  end
379
438
  end
380
439
  end
381
440
 
382
441
  describe ".notify_queue_sync" do
383
442
  it "notifies queue synchronously" do
384
- expect(described_class.performance_notifier).to receive(:notify_sync)
443
+ allow(described_class.performance_notifier).to receive(:notify_sync)
385
444
 
386
445
  described_class.notify_queue_sync(
387
446
  {
@@ -390,6 +449,8 @@ RSpec.describe Airbrake do
390
449
  },
391
450
  request_id: 1,
392
451
  )
452
+
453
+ expect(described_class.performance_notifier).to have_received(:notify_sync)
393
454
  end
394
455
  end
395
456
 
@@ -412,6 +473,7 @@ RSpec.describe Airbrake do
412
473
  end
413
474
  end
414
475
 
476
+ # rubocop:disable RSpec/MessageSpies
415
477
  describe ".close" do
416
478
  after { described_class.reset }
417
479
 
@@ -456,4 +518,5 @@ RSpec.describe Airbrake do
456
518
  end
457
519
  end
458
520
  end
521
+ # rubocop:enable RSpec/MessageSpies
459
522
  end