airbrake-ruby 4.1.0 → 5.0.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.
Files changed (94) hide show
  1. checksums.yaml +5 -5
  2. data/lib/airbrake-ruby/async_sender.rb +22 -96
  3. data/lib/airbrake-ruby/backtrace.rb +8 -7
  4. data/lib/airbrake-ruby/benchmark.rb +39 -0
  5. data/lib/airbrake-ruby/code_hunk.rb +1 -1
  6. data/lib/airbrake-ruby/config/processor.rb +84 -0
  7. data/lib/airbrake-ruby/config/validator.rb +9 -3
  8. data/lib/airbrake-ruby/config.rb +76 -20
  9. data/lib/airbrake-ruby/deploy_notifier.rb +1 -1
  10. data/lib/airbrake-ruby/file_cache.rb +6 -0
  11. data/lib/airbrake-ruby/filter_chain.rb +16 -1
  12. data/lib/airbrake-ruby/filters/dependency_filter.rb +1 -0
  13. data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +2 -2
  14. data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
  15. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +5 -5
  16. data/lib/airbrake-ruby/filters/git_repository_filter.rb +3 -0
  17. data/lib/airbrake-ruby/filters/git_revision_filter.rb +2 -0
  18. data/lib/airbrake-ruby/filters/{keys_whitelist.rb → keys_allowlist.rb} +3 -3
  19. data/lib/airbrake-ruby/filters/{keys_blacklist.rb → keys_blocklist.rb} +3 -3
  20. data/lib/airbrake-ruby/filters/keys_filter.rb +39 -20
  21. data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
  22. data/lib/airbrake-ruby/filters/sql_filter.rb +30 -6
  23. data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
  24. data/lib/airbrake-ruby/filters/thread_filter.rb +4 -2
  25. data/lib/airbrake-ruby/grouppable.rb +12 -0
  26. data/lib/airbrake-ruby/ignorable.rb +1 -0
  27. data/lib/airbrake-ruby/inspectable.rb +2 -2
  28. data/lib/airbrake-ruby/loggable.rb +2 -2
  29. data/lib/airbrake-ruby/mergeable.rb +12 -0
  30. data/lib/airbrake-ruby/monotonic_time.rb +48 -0
  31. data/lib/airbrake-ruby/notice.rb +10 -20
  32. data/lib/airbrake-ruby/notice_notifier.rb +23 -42
  33. data/lib/airbrake-ruby/performance_breakdown.rb +52 -0
  34. data/lib/airbrake-ruby/performance_notifier.rb +126 -49
  35. data/lib/airbrake-ruby/promise.rb +1 -0
  36. data/lib/airbrake-ruby/query.rb +26 -11
  37. data/lib/airbrake-ruby/queue.rb +65 -0
  38. data/lib/airbrake-ruby/remote_settings/settings_data.rb +120 -0
  39. data/lib/airbrake-ruby/remote_settings.rb +145 -0
  40. data/lib/airbrake-ruby/request.rb +20 -6
  41. data/lib/airbrake-ruby/stashable.rb +15 -0
  42. data/lib/airbrake-ruby/stat.rb +34 -24
  43. data/lib/airbrake-ruby/sync_sender.rb +3 -2
  44. data/lib/airbrake-ruby/tdigest.rb +43 -58
  45. data/lib/airbrake-ruby/thread_pool.rb +138 -0
  46. data/lib/airbrake-ruby/timed_trace.rb +58 -0
  47. data/lib/airbrake-ruby/truncator.rb +10 -4
  48. data/lib/airbrake-ruby/version.rb +11 -1
  49. data/lib/airbrake-ruby.rb +219 -53
  50. data/spec/airbrake_spec.rb +428 -9
  51. data/spec/async_sender_spec.rb +26 -110
  52. data/spec/backtrace_spec.rb +44 -44
  53. data/spec/benchmark_spec.rb +33 -0
  54. data/spec/code_hunk_spec.rb +11 -11
  55. data/spec/config/processor_spec.rb +209 -0
  56. data/spec/config/validator_spec.rb +23 -6
  57. data/spec/config_spec.rb +77 -7
  58. data/spec/deploy_notifier_spec.rb +2 -2
  59. data/spec/{file_cache.rb → file_cache_spec.rb} +2 -4
  60. data/spec/filter_chain_spec.rb +28 -1
  61. data/spec/filters/dependency_filter_spec.rb +1 -1
  62. data/spec/filters/gem_root_filter_spec.rb +9 -9
  63. data/spec/filters/git_last_checkout_filter_spec.rb +21 -4
  64. data/spec/filters/git_repository_filter.rb +1 -1
  65. data/spec/filters/git_revision_filter_spec.rb +13 -11
  66. data/spec/filters/{keys_whitelist_spec.rb → keys_allowlist_spec.rb} +29 -28
  67. data/spec/filters/{keys_blacklist_spec.rb → keys_blocklist_spec.rb} +39 -29
  68. data/spec/filters/root_directory_filter_spec.rb +9 -9
  69. data/spec/filters/sql_filter_spec.rb +110 -55
  70. data/spec/filters/system_exit_filter_spec.rb +1 -1
  71. data/spec/filters/thread_filter_spec.rb +33 -31
  72. data/spec/fixtures/project_root/code.rb +9 -9
  73. data/spec/loggable_spec.rb +17 -0
  74. data/spec/monotonic_time_spec.rb +23 -0
  75. data/spec/{notice_notifier_spec → notice_notifier}/options_spec.rb +19 -21
  76. data/spec/notice_notifier_spec.rb +20 -80
  77. data/spec/notice_spec.rb +9 -11
  78. data/spec/performance_breakdown_spec.rb +11 -0
  79. data/spec/performance_notifier_spec.rb +360 -85
  80. data/spec/query_spec.rb +11 -0
  81. data/spec/queue_spec.rb +18 -0
  82. data/spec/remote_settings/settings_data_spec.rb +365 -0
  83. data/spec/remote_settings_spec.rb +230 -0
  84. data/spec/request_spec.rb +9 -0
  85. data/spec/response_spec.rb +8 -8
  86. data/spec/spec_helper.rb +9 -13
  87. data/spec/stashable_spec.rb +23 -0
  88. data/spec/stat_spec.rb +17 -15
  89. data/spec/sync_sender_spec.rb +14 -12
  90. data/spec/tdigest_spec.rb +6 -6
  91. data/spec/thread_pool_spec.rb +187 -0
  92. data/spec/timed_trace_spec.rb +125 -0
  93. data/spec/truncator_spec.rb +12 -12
  94. metadata +55 -18
@@ -2,7 +2,7 @@ RSpec.describe Airbrake::Backtrace do
2
2
  describe ".parse" do
3
3
  context "UNIX backtrace" do
4
4
  let(:parsed_backtrace) do
5
- # rubocop:disable Metrics/LineLength, Style/HashSyntax, Layout/SpaceAroundOperators, Layout/SpaceInsideHashLiteralBraces
5
+ # rubocop:disable Layout/LineLength, Style/HashSyntax, Layout/SpaceAroundOperators, Layout/SpaceInsideHashLiteralBraces
6
6
  [{:file=>"/home/kyrylo/code/airbrake/ruby/spec/spec_helper.rb", :line=>23, :function=>"<top (required)>"},
7
7
  {:file=>"/opt/rubies/ruby-2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb", :line=>54, :function=>"require"},
8
8
  {:file=>"/opt/rubies/ruby-2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb", :line=>54, :function=>"require"},
@@ -16,7 +16,7 @@ RSpec.describe Airbrake::Backtrace do
16
16
  {:file=>"/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb", :line=>73, :function=>"run"},
17
17
  {:file=>"/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb", :line=>41, :function=>"invoke"},
18
18
  {:file=>"/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/exe/rspec", :line=>4, :function=>"<main>"}]
19
- # rubocop:enable Metrics/LineLength, Style/HashSyntax, Layout/SpaceAroundOperators, Layout/SpaceInsideHashLiteralBraces
19
+ # rubocop:enable Layout/LineLength, Style/HashSyntax, Layout/SpaceAroundOperators, Layout/SpaceInsideHashLiteralBraces
20
20
  end
21
21
 
22
22
  it "returns a properly formatted array of hashes" do
@@ -34,10 +34,10 @@ RSpec.describe Airbrake::Backtrace do
34
34
  let(:ex) { AirbrakeTestError.new.tap { |e| e.set_backtrace(windows_bt) } }
35
35
 
36
36
  let(:parsed_backtrace) do
37
- # rubocop:disable Metrics/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
37
+ # rubocop:disable Layout/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
38
38
  [{:file=>"C:/Program Files/Server/app/models/user.rb", :line=>13, :function=>"magic"},
39
39
  {:file=>"C:/Program Files/Server/app/controllers/users_controller.rb", :line=>8, :function=>"index"}]
40
- # rubocop:enable Metrics/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
40
+ # rubocop:enable Layout/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
41
41
  end
42
42
 
43
43
  it "returns a properly formatted array of hashes" do
@@ -47,7 +47,7 @@ RSpec.describe Airbrake::Backtrace do
47
47
 
48
48
  context "JRuby Java exceptions" do
49
49
  let(:backtrace_array) do
50
- # rubocop:disable Metrics/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
50
+ # rubocop:disable Layout/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
51
51
  [{:file=>"InstanceMethodInvoker.java", :line=>26, :function=>"org.jruby.java.invokers.InstanceMethodInvoker.call"},
52
52
  {:file=>"Interpreter.java", :line=>126, :function=>"org.jruby.ir.interpreter.Interpreter.INTERPRET_EVAL"},
53
53
  {:file=>"RubyKernel$INVOKER$s$0$3$eval19.gen", :line=>nil, :function=>"org.jruby.RubyKernel$INVOKER$s$0$3$eval19.call"},
@@ -59,7 +59,7 @@ RSpec.describe Airbrake::Backtrace do
59
59
  {:file=>"Compiler.java", :line=>111, :function=>"org.jruby.ir.Compiler$1.load"},
60
60
  {:file=>"Main.java", :line=>225, :function=>"org.jruby.Main.run"},
61
61
  {:file=>"Main.java", :line=>197, :function=>"org.jruby.Main.main"}]
62
- # rubocop:enable Metrics/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
62
+ # rubocop:enable Layout/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
63
63
  end
64
64
 
65
65
  it "returns a properly formatted array of hashes" do
@@ -72,21 +72,21 @@ RSpec.describe Airbrake::Backtrace do
72
72
 
73
73
  context "JRuby classloader exceptions" do
74
74
  let(:backtrace) do
75
- # rubocop:disable Metrics/LineLength
75
+ # rubocop:disable Layout/LineLength
76
76
  ['uri_3a_classloader_3a_.META_minus_INF.jruby_dot_home.lib.ruby.stdlib.net.protocol.rbuf_fill(uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/net/protocol.rb:158)',
77
77
  'bin.processors.image_uploader.block in make_streams(bin/processors/image_uploader.rb:21)',
78
78
  'uri_3a_classloader_3a_.gems.faye_minus_websocket_minus_0_dot_10_dot_5.lib.faye.websocket.api.invokeOther13:dispatch_event(uri_3a_classloader_3a_/gems/faye_minus_websocket_minus_0_dot_10_dot_5/lib/faye/websocket/uri:classloader:/gems/faye-websocket-0.10.5/lib/faye/websocket/api.rb:109)',
79
79
  'tmp.jruby9022301782566983632extract.$dot.META_minus_INF.rails.file(/tmp/jruby9022301782566983632extract/./META-INF/rails.rb:13)']
80
- # rubocop:enable Metrics/LineLength
80
+ # rubocop:enable Layout/LineLength
81
81
  end
82
82
 
83
83
  let(:parsed_backtrace) do
84
- # rubocop:disable Metrics/LineLength
84
+ # rubocop:disable Layout/LineLength
85
85
  [{ file: 'uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/net/protocol.rb', line: 158, function: 'uri_3a_classloader_3a_.META_minus_INF.jruby_dot_home.lib.ruby.stdlib.net.protocol.rbuf_fill' },
86
86
  { file: 'bin/processors/image_uploader.rb', line: 21, function: 'bin.processors.image_uploader.block in make_streams' },
87
87
  { file: 'uri_3a_classloader_3a_/gems/faye_minus_websocket_minus_0_dot_10_dot_5/lib/faye/websocket/uri:classloader:/gems/faye-websocket-0.10.5/lib/faye/websocket/api.rb', line: 109, function: 'uri_3a_classloader_3a_.gems.faye_minus_websocket_minus_0_dot_10_dot_5.lib.faye.websocket.api.invokeOther13:dispatch_event' },
88
88
  { file: '/tmp/jruby9022301782566983632extract/./META-INF/rails.rb', line: 13, function: 'tmp.jruby9022301782566983632extract.$dot.META_minus_INF.rails.file' }]
89
- # rubocop:enable Metrics/LineLength
89
+ # rubocop:enable Layout/LineLength
90
90
  end
91
91
 
92
92
  let(:ex) { JavaAirbrakeTestError.new.tap { |e| e.set_backtrace(backtrace) } }
@@ -99,19 +99,19 @@ RSpec.describe Airbrake::Backtrace do
99
99
 
100
100
  context "JRuby non-throwable exceptions" do
101
101
  let(:backtrace) do
102
- # rubocop:disable Metrics/LineLength
102
+ # rubocop:disable Layout/LineLength
103
103
  ['org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(org/postgresql/core/v3/ConnectionFactoryImpl.java:257)',
104
104
  'org.postgresql.core.ConnectionFactory.openConnection(org/postgresql/core/ConnectionFactory.java:65)',
105
105
  'org.postgresql.jdbc2.AbstractJdbc2Connection.<init>(org/postgresql/jdbc2/AbstractJdbc2Connection.java:149)']
106
- # rubocop:enable Metrics/LineLength
106
+ # rubocop:enable Layout/LineLength
107
107
  end
108
108
 
109
109
  let(:parsed_backtrace) do
110
- # rubocop:disable Metrics/LineLength
110
+ # rubocop:disable Layout/LineLength
111
111
  [{ file: 'org/postgresql/core/v3/ConnectionFactoryImpl.java', line: 257, function: 'org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl' },
112
112
  { file: 'org/postgresql/core/ConnectionFactory.java', line: 65, function: 'org.postgresql.core.ConnectionFactory.openConnection' },
113
113
  { file: 'org/postgresql/jdbc2/AbstractJdbc2Connection.java', line: 149, function: 'org.postgresql.jdbc2.AbstractJdbc2Connection.<init>' }]
114
- # rubocop:enable Metrics/LineLength
114
+ # rubocop:enable Layout/LineLength
115
115
  end
116
116
 
117
117
  let(:ex) { AirbrakeTestError.new.tap { |e| e.set_backtrace(backtrace) } }
@@ -123,22 +123,22 @@ RSpec.describe Airbrake::Backtrace do
123
123
 
124
124
  context "generic backtrace" do
125
125
  context "when function is absent" do
126
- # rubocop:disable Metrics/LineLength
126
+ # rubocop:disable Layout/LineLength
127
127
  let(:generic_bt) do
128
128
  ["/home/bingo/bango/assets/stylesheets/error_pages.scss:139:in `animation'",
129
129
  "/home/bingo/bango/assets/stylesheets/error_pages.scss:139",
130
130
  "/home/bingo/.gem/ruby/2.2.2/gems/sass-3.4.20/lib/sass/tree/visitors/perform.rb:349:in `block in visit_mixin'"]
131
131
  end
132
- # rubocop:enable Metrics/LineLength
132
+ # rubocop:enable Layout/LineLength
133
133
 
134
134
  let(:ex) { AirbrakeTestError.new.tap { |e| e.set_backtrace(generic_bt) } }
135
135
 
136
136
  let(:parsed_backtrace) do
137
- # rubocop:disable Metrics/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
137
+ # rubocop:disable Layout/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
138
138
  [{:file=>"/home/bingo/bango/assets/stylesheets/error_pages.scss", :line=>139, :function=>"animation"},
139
139
  {:file=>"/home/bingo/bango/assets/stylesheets/error_pages.scss", :line=>139, :function=>nil},
140
140
  {:file=>"/home/bingo/.gem/ruby/2.2.2/gems/sass-3.4.20/lib/sass/tree/visitors/perform.rb", :line=>349, :function=>"block in visit_mixin"}]
141
- # rubocop:enable Metrics/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
141
+ # rubocop:enable Layout/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
142
142
  end
143
143
 
144
144
  it "returns a properly formatted array of hashes" do
@@ -172,13 +172,13 @@ RSpec.describe Airbrake::Backtrace do
172
172
 
173
173
  it "returns array of hashes where each unknown frame is marked as 'function'" do
174
174
  expect(
175
- described_class.parse(ex)
175
+ described_class.parse(ex),
176
176
  ).to eq([file: nil, line: nil, function: 'a b c 1 23 321 .rb'])
177
177
  end
178
178
 
179
179
  it "logs frames that cannot be parsed" do
180
180
  expect(Airbrake::Loggable.instance).to receive(:error).with(
181
- /can't parse 'a b c 1 23 321 .rb'/
181
+ /can't parse 'a b c 1 23 321 .rb'/,
182
182
  )
183
183
  described_class.parse(ex)
184
184
  end
@@ -277,21 +277,21 @@ RSpec.describe Airbrake::Backtrace do
277
277
  93 => ' begin',
278
278
  94 => ' json = @payload.to_json',
279
279
  95 => ' rescue *JSON_EXCEPTIONS => ex',
280
- # rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
280
+ # rubocop:disable Layout/LineLength,Lint/InterpolationCheck
281
281
  96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
282
- # rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
283
- }
282
+ # rubocop:enable Layout/LineLength,Lint/InterpolationCheck
283
+ },
284
284
  },
285
285
  {
286
286
  file: fixture_path('notroot.txt'),
287
287
  line: 3,
288
- function: 'pineapple'
288
+ function: 'pineapple',
289
289
  },
290
290
  {
291
291
  file: project_root_path('vendor/bundle/ignored_file.rb'),
292
292
  line: 2,
293
- function: 'ignore_me'
294
- }
293
+ function: 'ignore_me',
294
+ },
295
295
  ]
296
296
  end
297
297
 
@@ -300,7 +300,7 @@ RSpec.describe Airbrake::Backtrace do
300
300
  backtrace = [
301
301
  project_root_path('code.rb') + ":94:in `to_json'",
302
302
  fixture_path('notroot.txt' + ":3:in `pineapple'"),
303
- project_root_path('vendor/bundle/ignored_file.rb') + ":2:in `ignore_me'"
303
+ project_root_path('vendor/bundle/ignored_file.rb') + ":2:in `ignore_me'",
304
304
  ]
305
305
  ex.set_backtrace(backtrace)
306
306
  expect(described_class.parse(ex)).to eq(parsed_backtrace)
@@ -310,7 +310,7 @@ RSpec.describe Airbrake::Backtrace do
310
310
  context "and when root_directory is a Pathname" do
311
311
  before do
312
312
  Airbrake::Config.instance.merge(
313
- root_directory: Pathname.new(project_root_path(''))
313
+ root_directory: Pathname.new(project_root_path('')),
314
314
  )
315
315
  end
316
316
 
@@ -325,11 +325,11 @@ RSpec.describe Airbrake::Backtrace do
325
325
  93 => ' begin',
326
326
  94 => ' json = @payload.to_json',
327
327
  95 => ' rescue *JSON_EXCEPTIONS => ex',
328
- # rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
328
+ # rubocop:disable Layout/LineLength,Lint/InterpolationCheck
329
329
  96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
330
- # rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
331
- }
332
- }
330
+ # rubocop:enable Layout/LineLength,Lint/InterpolationCheck
331
+ },
332
+ },
333
333
  ]
334
334
  end
335
335
 
@@ -357,10 +357,10 @@ RSpec.describe Airbrake::Backtrace do
357
357
  93 => ' begin',
358
358
  94 => ' json = @payload.to_json',
359
359
  95 => ' rescue *JSON_EXCEPTIONS => ex',
360
- # rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
360
+ # rubocop:disable Layout/LineLength,Lint/InterpolationCheck
361
361
  96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
362
- # rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
363
- }
362
+ # rubocop:enable Layout/LineLength,Lint/InterpolationCheck
363
+ },
364
364
  },
365
365
  {
366
366
  file: project_root_path('code.rb'),
@@ -370,17 +370,17 @@ RSpec.describe Airbrake::Backtrace do
370
370
  93 => ' begin',
371
371
  94 => ' json = @payload.to_json',
372
372
  95 => ' rescue *JSON_EXCEPTIONS => ex',
373
- # rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
373
+ # rubocop:disable Layout/LineLength,Lint/InterpolationCheck
374
374
  96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
375
- # rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
376
- 97 => ' else'
377
- }
375
+ # rubocop:enable Layout/LineLength,Lint/InterpolationCheck
376
+ 97 => ' else',
377
+ },
378
378
  },
379
379
  {
380
380
  file: project_root_path('code.rb'),
381
381
  line: 96,
382
- function: 'to_json'
383
- }
382
+ function: 'to_json',
383
+ },
384
384
  ]
385
385
  end
386
386
 
@@ -389,7 +389,7 @@ RSpec.describe Airbrake::Backtrace do
389
389
  backtrace = [
390
390
  project_root_path('code.rb') + ":94:in `to_json'",
391
391
  project_root_path('code.rb') + ":95:in `to_json'",
392
- project_root_path('code.rb') + ":96:in `to_json'"
392
+ project_root_path('code.rb') + ":96:in `to_json'",
393
393
  ]
394
394
  ex.set_backtrace(backtrace)
395
395
  expect(described_class.parse(ex)).to eq(parsed_backtrace)
@@ -410,8 +410,8 @@ RSpec.describe Airbrake::Backtrace do
410
410
  {
411
411
  file: project_root_path('code.rb'),
412
412
  line: 94,
413
- function: 'to_json'
414
- }
413
+ function: 'to_json',
414
+ },
415
415
  ]
416
416
  end
417
417
 
@@ -0,0 +1,33 @@
1
+ RSpec.describe Airbrake::Benchmark do
2
+ describe ".measure" do
3
+ it "returns measured performance time" do
4
+ expect(described_class.measure { '10' * 10 }).to be_kind_of(Numeric)
5
+ end
6
+ end
7
+
8
+ describe "#stop" do
9
+ before { subject }
10
+
11
+ context "when called one time" do
12
+ its(:stop) { is_expected.to eq(true) }
13
+ end
14
+
15
+ context "when called twice or more" do
16
+ before { subject.stop }
17
+
18
+ its(:stop) { is_expected.to eq(false) }
19
+ end
20
+ end
21
+
22
+ describe "#duration" do
23
+ context "when #stop wasn't called yet" do
24
+ its(:duration) { is_expected.to be_zero }
25
+ end
26
+
27
+ context "when #stop was called" do
28
+ before { subject.stop }
29
+
30
+ its(:duration) { is_expected.to be > 0 }
31
+ end
32
+ end
33
+ end
@@ -34,10 +34,10 @@ RSpec.describe Airbrake::CodeHunk do
34
34
  eq(
35
35
  1 => 'module Airbrake',
36
36
  2 => ' ##',
37
- # rubocop:disable Metrics/LineLength
37
+ # rubocop:disable Layout/LineLength
38
38
  3 => ' # Represents a chunk of information that is meant to be either sent to',
39
- # rubocop:enable Metrics/LineLength
40
- )
39
+ # rubocop:enable Layout/LineLength
40
+ ),
41
41
  )
42
42
  end
43
43
  end
@@ -49,8 +49,8 @@ RSpec.describe Airbrake::CodeHunk do
49
49
  is_expected.to(
50
50
  eq(
51
51
  220 => ' end',
52
- 221 => 'end'
53
- )
52
+ 221 => 'end',
53
+ ),
54
54
  )
55
55
  end
56
56
  end
@@ -65,8 +65,8 @@ RSpec.describe Airbrake::CodeHunk do
65
65
  eq(
66
66
  1 => 'module Banana',
67
67
  2 => ' attr_reader :bingo',
68
- 3 => 'end'
69
- )
68
+ 3 => 'end',
69
+ ),
70
70
  )
71
71
  end
72
72
  end
@@ -81,8 +81,8 @@ RSpec.describe Airbrake::CodeHunk do
81
81
  99 => ' end',
82
82
  100 => '',
83
83
  101 => ' break if truncate == 0',
84
- 102 => ' end'
85
- )
84
+ 102 => ' end',
85
+ ),
86
86
  )
87
87
  end
88
88
  end
@@ -104,10 +104,10 @@ RSpec.describe Airbrake::CodeHunk do
104
104
 
105
105
  it "logs error and returns nil" do
106
106
  expect(Airbrake::Loggable.instance).to receive(:error).with(
107
- /can't read code hunk.+Permission denied/
107
+ /can't read code hunk.+Permission denied/,
108
108
  )
109
109
  expect(subject.get(project_root_path('code.rb'), 1)).to(
110
- eq(1 => '')
110
+ eq(1 => ''),
111
111
  )
112
112
  end
113
113
  end
@@ -0,0 +1,209 @@
1
+ RSpec.describe Airbrake::Config::Processor do
2
+ let(:notifier) { Airbrake::NoticeNotifier.new }
3
+
4
+ describe "#process_blocklist" do
5
+ let(:config) { Airbrake::Config.new(blocklist_keys: %w[a b c]) }
6
+
7
+ context "when there ARE blocklist keys" do
8
+ it "adds the blocklist filter" do
9
+ described_class.new(config).process_blocklist(notifier)
10
+ expect(notifier.has_filter?(Airbrake::Filters::KeysBlocklist)).to eq(true)
11
+ end
12
+ end
13
+
14
+ context "when there are NO blocklist keys" do
15
+ let(:config) { Airbrake::Config.new(blocklist_keys: %w[]) }
16
+
17
+ it "doesn't add the blocklist filter" do
18
+ described_class.new(config).process_blocklist(notifier)
19
+ expect(notifier.has_filter?(Airbrake::Filters::KeysBlocklist))
20
+ .to eq(false)
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "#process_allowlist" do
26
+ let(:config) { Airbrake::Config.new(allowlist_keys: %w[a b c]) }
27
+
28
+ context "when there ARE allowlist keys" do
29
+ it "adds the allowlist filter" do
30
+ described_class.new(config).process_allowlist(notifier)
31
+ expect(notifier.has_filter?(Airbrake::Filters::KeysAllowlist)).to eq(true)
32
+ end
33
+ end
34
+
35
+ context "when there are NO allowlist keys" do
36
+ let(:config) { Airbrake::Config.new(allowlist_keys: %w[]) }
37
+
38
+ it "doesn't add the allowlist filter" do
39
+ described_class.new(config).process_allowlist(notifier)
40
+ expect(notifier.has_filter?(Airbrake::Filters::KeysAllowlist))
41
+ .to eq(false)
42
+ end
43
+ end
44
+ end
45
+
46
+ describe "#process_remote_configuration" do
47
+ context "when the config doesn't define a project_id" do
48
+ let(:config) { Airbrake::Config.new(project_id: nil) }
49
+
50
+ it "doesn't set remote settings" do
51
+ expect(Airbrake::RemoteSettings).not_to receive(:poll)
52
+ described_class.new(config).process_remote_configuration
53
+ end
54
+ end
55
+
56
+ context "when the config defines a project_id" do
57
+ let(:config) do
58
+ Airbrake::Config.new(project_id: 123)
59
+ end
60
+
61
+ it "sets remote settings" do
62
+ expect(Airbrake::RemoteSettings).to receive(:poll)
63
+ described_class.new(config).process_remote_configuration
64
+ end
65
+ end
66
+ end
67
+
68
+ describe "#add_filters" do
69
+ context "when there's a root directory" do
70
+ let(:config) { Airbrake::Config.new(root_directory: '/abc') }
71
+
72
+ it "adds RootDirectoryFilter" do
73
+ described_class.new(config).add_filters(notifier)
74
+ expect(notifier.has_filter?(Airbrake::Filters::RootDirectoryFilter))
75
+ .to eq(true)
76
+ end
77
+
78
+ it "adds GitRevisionFilter" do
79
+ described_class.new(config).add_filters(notifier)
80
+ expect(notifier.has_filter?(Airbrake::Filters::GitRevisionFilter))
81
+ .to eq(true)
82
+ end
83
+
84
+ it "adds GitRepositoryFilter" do
85
+ described_class.new(config).add_filters(notifier)
86
+ expect(notifier.has_filter?(Airbrake::Filters::GitRepositoryFilter))
87
+ .to eq(true)
88
+ end
89
+
90
+ it "adds GitLastCheckoutFilter" do
91
+ described_class.new(config).add_filters(notifier)
92
+ expect(notifier.has_filter?(Airbrake::Filters::GitLastCheckoutFilter))
93
+ .to eq(true)
94
+ end
95
+ end
96
+
97
+ context "when there's NO root directory" do
98
+ let(:config) { Airbrake::Config.new(root_directory: nil) }
99
+
100
+ it "doesn't add RootDirectoryFilter" do
101
+ described_class.new(config).add_filters(notifier)
102
+ expect(notifier.has_filter?(Airbrake::Filters::RootDirectoryFilter))
103
+ .to eq(false)
104
+ end
105
+
106
+ it "doesn't add GitRevisionFilter" do
107
+ described_class.new(config).add_filters(notifier)
108
+ expect(notifier.has_filter?(Airbrake::Filters::GitRevisionFilter))
109
+ .to eq(false)
110
+ end
111
+
112
+ it "doesn't add GitRepositoryFilter" do
113
+ described_class.new(config).add_filters(notifier)
114
+ expect(notifier.has_filter?(Airbrake::Filters::GitRepositoryFilter))
115
+ .to eq(false)
116
+ end
117
+
118
+ it "doesn't add GitLastCheckoutFilter" do
119
+ described_class.new(config).add_filters(notifier)
120
+ expect(notifier.has_filter?(Airbrake::Filters::GitLastCheckoutFilter))
121
+ .to eq(false)
122
+ end
123
+ end
124
+ end
125
+
126
+ describe "#poll_callback" do
127
+ let(:logger) { Logger.new(File::NULL) }
128
+
129
+ let(:config) do
130
+ Airbrake::Config.new(
131
+ project_id: 123,
132
+ logger: logger,
133
+ )
134
+ end
135
+
136
+ let(:data) do
137
+ instance_double(Airbrake::RemoteSettings::SettingsData)
138
+ end
139
+
140
+ before do
141
+ allow(data).to receive(:to_h)
142
+ allow(data).to receive(:error_host)
143
+ allow(data).to receive(:apm_host)
144
+ allow(data).to receive(:error_notifications?)
145
+ allow(data).to receive(:performance_stats?)
146
+ end
147
+
148
+ it "logs given data" do
149
+ expect(logger).to receive(:debug).with(/applying remote settings/)
150
+ described_class.new(config).poll_callback(data)
151
+ end
152
+
153
+ it "sets the error_notifications option" do
154
+ config.error_notifications = false
155
+ expect(data).to receive(:error_notifications?).and_return(true)
156
+
157
+ described_class.new(config).poll_callback(data)
158
+ expect(config.error_notifications).to eq(true)
159
+ end
160
+
161
+ it "sets the performance_stats option" do
162
+ config.performance_stats = false
163
+ expect(data).to receive(:performance_stats?).and_return(true)
164
+
165
+ described_class.new(config).poll_callback(data)
166
+ expect(config.performance_stats).to eq(true)
167
+ end
168
+
169
+ context "when error_host returns a value" do
170
+ it "sets the error_host option" do
171
+ config.error_host = 'http://api.airbrake.io'
172
+ allow(data).to receive(:error_host).and_return('https://api.example.com')
173
+
174
+ described_class.new(config).poll_callback(data)
175
+ expect(config.error_host).to eq('https://api.example.com')
176
+ end
177
+ end
178
+
179
+ context "when error_host returns nil" do
180
+ it "doesn't modify the error_host option" do
181
+ config.error_host = 'http://api.airbrake.io'
182
+ allow(data).to receive(:error_host).and_return(nil)
183
+
184
+ described_class.new(config).poll_callback(data)
185
+ expect(config.error_host).to eq('http://api.airbrake.io')
186
+ end
187
+ end
188
+
189
+ context "when apm_host returns a value" do
190
+ it "sets the apm_host option" do
191
+ config.apm_host = 'http://api.airbrake.io'
192
+ allow(data).to receive(:apm_host).and_return('https://api.example.com')
193
+
194
+ described_class.new(config).poll_callback(data)
195
+ expect(config.apm_host).to eq('https://api.example.com')
196
+ end
197
+ end
198
+
199
+ context "when apm_host returns nil" do
200
+ it "doesn't modify the apm_host option" do
201
+ config.apm_host = 'http://api.airbrake.io'
202
+ allow(data).to receive(:apm_host).and_return(nil)
203
+
204
+ described_class.new(config).poll_callback(data)
205
+ expect(config.apm_host).to eq('http://api.airbrake.io')
206
+ end
207
+ end
208
+ end
209
+ end
@@ -118,7 +118,7 @@ RSpec.describe Airbrake::Config::Validator do
118
118
  promise = described_class.validate(config)
119
119
  expect(promise.value).to eq(
120
120
  'error' => "the 'environment' option must be configured with a " \
121
- "Symbol (or String), but 'Float' was provided: 1.0"
121
+ "Symbol (or String), but 'Float' was provided: 1.0",
122
122
  )
123
123
  end
124
124
  end
@@ -130,7 +130,7 @@ RSpec.describe Airbrake::Config::Validator do
130
130
  {
131
131
  project_id: valid_id,
132
132
  project_key: valid_key,
133
- environment: string_inquirer.new('test')
133
+ environment: string_inquirer.new('test'),
134
134
  }
135
135
  end
136
136
 
@@ -148,14 +148,14 @@ RSpec.describe Airbrake::Config::Validator do
148
148
  project_id: valid_id,
149
149
  project_key: valid_key,
150
150
  environment: 'test',
151
- ignore_environments: ['test']
151
+ ignore_environments: ['test'],
152
152
  }
153
153
  end
154
154
 
155
155
  it "returns a rejected promise" do
156
156
  promise = described_class.check_notify_ability(config)
157
157
  expect(promise.value).to eq(
158
- 'error' => "current environment 'test' is ignored"
158
+ 'error' => "current environment 'test' is ignored",
159
159
  )
160
160
  end
161
161
  end
@@ -165,11 +165,11 @@ RSpec.describe Airbrake::Config::Validator do
165
165
  {
166
166
  project_id: valid_id,
167
167
  project_key: valid_key,
168
- ignore_environments: ['test']
168
+ ignore_environments: ['test'],
169
169
  }
170
170
  end
171
171
 
172
- it "returns a rejected promise" do
172
+ it "returns a resolved promise" do
173
173
  promise = described_class.check_notify_ability(config)
174
174
  expect(promise).to be_resolved
175
175
  end
@@ -180,5 +180,22 @@ RSpec.describe Airbrake::Config::Validator do
180
180
  described_class.check_notify_ability(config)
181
181
  end
182
182
  end
183
+
184
+ context "when the error_notifications option is false" do
185
+ let(:config_params) do
186
+ {
187
+ project_id: valid_id,
188
+ project_key: valid_key,
189
+ error_notifications: false,
190
+ }
191
+ end
192
+
193
+ it "returns a rejected promise" do
194
+ promise = described_class.check_notify_ability(config)
195
+ expect(promise.value).to eq(
196
+ 'error' => "error notifications are disabled",
197
+ )
198
+ end
199
+ end
183
200
  end
184
201
  end