airbrake-ruby 4.1.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
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