airbrake-ruby 4.8.0 → 4.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/lib/airbrake-ruby.rb +101 -25
  3. data/lib/airbrake-ruby/async_sender.rb +3 -3
  4. data/lib/airbrake-ruby/backtrace.rb +2 -2
  5. data/lib/airbrake-ruby/benchmark.rb +1 -1
  6. data/lib/airbrake-ruby/code_hunk.rb +1 -1
  7. data/lib/airbrake-ruby/config.rb +1 -1
  8. data/lib/airbrake-ruby/config/validator.rb +3 -3
  9. data/lib/airbrake-ruby/deploy_notifier.rb +1 -1
  10. data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +2 -2
  11. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +2 -2
  12. data/lib/airbrake-ruby/filters/keys_filter.rb +1 -1
  13. data/lib/airbrake-ruby/filters/sql_filter.rb +3 -3
  14. data/lib/airbrake-ruby/filters/thread_filter.rb +1 -1
  15. data/lib/airbrake-ruby/grouppable.rb +12 -0
  16. data/lib/airbrake-ruby/inspectable.rb +2 -2
  17. data/lib/airbrake-ruby/mergeable.rb +12 -0
  18. data/lib/airbrake-ruby/notice.rb +7 -7
  19. data/lib/airbrake-ruby/notice_notifier.rb +3 -2
  20. data/lib/airbrake-ruby/performance_breakdown.rb +12 -6
  21. data/lib/airbrake-ruby/performance_notifier.rb +69 -22
  22. data/lib/airbrake-ruby/query.rb +15 -11
  23. data/lib/airbrake-ruby/queue.rb +56 -0
  24. data/lib/airbrake-ruby/request.rb +14 -12
  25. data/lib/airbrake-ruby/stat.rb +1 -1
  26. data/lib/airbrake-ruby/version.rb +1 -1
  27. data/spec/airbrake_spec.rb +135 -45
  28. data/spec/async_sender_spec.rb +4 -4
  29. data/spec/backtrace_spec.rb +18 -18
  30. data/spec/code_hunk_spec.rb +9 -9
  31. data/spec/config/validator_spec.rb +5 -5
  32. data/spec/config_spec.rb +5 -9
  33. data/spec/deploy_notifier_spec.rb +2 -2
  34. data/spec/filter_chain_spec.rb +1 -1
  35. data/spec/filters/dependency_filter_spec.rb +1 -1
  36. data/spec/filters/gem_root_filter_spec.rb +5 -5
  37. data/spec/filters/git_last_checkout_filter_spec.rb +1 -1
  38. data/spec/filters/git_repository_filter.rb +1 -1
  39. data/spec/filters/git_revision_filter_spec.rb +10 -10
  40. data/spec/filters/keys_blacklist_spec.rb +22 -22
  41. data/spec/filters/keys_whitelist_spec.rb +21 -21
  42. data/spec/filters/root_directory_filter_spec.rb +5 -5
  43. data/spec/filters/sql_filter_spec.rb +53 -55
  44. data/spec/filters/system_exit_filter_spec.rb +1 -1
  45. data/spec/filters/thread_filter_spec.rb +28 -28
  46. data/spec/fixtures/project_root/code.rb +9 -9
  47. data/spec/notice_notifier/options_spec.rb +12 -12
  48. data/spec/notice_notifier_spec.rb +18 -18
  49. data/spec/notice_spec.rb +5 -5
  50. data/spec/performance_breakdown_spec.rb +11 -0
  51. data/spec/performance_notifier_spec.rb +243 -72
  52. data/spec/query_spec.rb +11 -1
  53. data/spec/queue_spec.rb +21 -0
  54. data/spec/request_spec.rb +11 -1
  55. data/spec/response_spec.rb +8 -8
  56. data/spec/spec_helper.rb +2 -2
  57. data/spec/stat_spec.rb +2 -2
  58. data/spec/sync_sender_spec.rb +12 -12
  59. data/spec/tdigest_spec.rb +6 -6
  60. data/spec/thread_pool_spec.rb +5 -5
  61. data/spec/timed_trace_spec.rb +1 -1
  62. data/spec/truncator_spec.rb +12 -12
  63. metadata +7 -2
@@ -32,7 +32,7 @@ module Airbrake
32
32
  'count' => count,
33
33
  'sum' => sum,
34
34
  'sumsq' => sumsq,
35
- 'tdigest' => Base64.strict_encode64(tdigest.as_small_bytes)
35
+ 'tdigest' => Base64.strict_encode64(tdigest.as_small_bytes),
36
36
  }
37
37
  end
38
38
 
@@ -2,5 +2,5 @@
2
2
  # More information: http://semver.org/
3
3
  module Airbrake
4
4
  # @return [String] the library version
5
- AIRBRAKE_RUBY_VERSION = '4.8.0'.freeze
5
+ AIRBRAKE_RUBY_VERSION = '4.11.1'.freeze
6
6
  end
@@ -51,28 +51,6 @@ RSpec.describe Airbrake do
51
51
  expect(described_class).to be_configured
52
52
  end
53
53
 
54
- context "when a notifier was configured" do
55
- before do
56
- expect(described_class).to receive(:configured?).and_return(true)
57
- end
58
-
59
- it "closes previously configured notice notifier" do
60
- expect(described_class).to receive(:close)
61
- described_class.configure {}
62
- end
63
- end
64
-
65
- context "when a notifier wasn't configured" do
66
- before do
67
- expect(described_class).to receive(:configured?).and_return(false)
68
- end
69
-
70
- it "doesn't close previously configured notice notifier" do
71
- expect(described_class).not_to receive(:close)
72
- described_class.configure {}
73
- end
74
- end
75
-
76
54
  context "when called multiple times" do
77
55
  it "doesn't overwrite performance notifier" do
78
56
  described_class.configure {}
@@ -182,19 +160,6 @@ RSpec.describe Airbrake do
182
160
  end
183
161
  end
184
162
 
185
- describe "#reset" do
186
- context "when Airbrake was previously configured" do
187
- before do
188
- expect(described_class).to receive(:configured?).and_return(true)
189
- end
190
-
191
- it "closes notice notifier" do
192
- expect(described_class).to receive(:close)
193
- subject.reset
194
- end
195
- end
196
- end
197
-
198
163
  describe "#notify_request" do
199
164
  context "when :stash key is not provided" do
200
165
  it "doesn't add anything to the stash of the request" do
@@ -206,7 +171,7 @@ RSpec.describe Airbrake do
206
171
  method: 'GET',
207
172
  route: '/',
208
173
  status_code: 200,
209
- start_time: Time.now
174
+ timing: 1,
210
175
  )
211
176
  end
212
177
  end
@@ -222,14 +187,30 @@ RSpec.describe Airbrake do
222
187
  method: 'GET',
223
188
  route: '/',
224
189
  status_code: 200,
225
- start_time: Time.now
190
+ timing: 1,
226
191
  },
227
- request_id: 1
192
+ request_id: 1,
228
193
  )
229
194
  end
230
195
  end
231
196
  end
232
197
 
198
+ describe "#notify_request_sync" do
199
+ it "notifies request synchronously" do
200
+ expect(described_class.performance_notifier).to receive(:notify_sync)
201
+
202
+ described_class.notify_request_sync(
203
+ {
204
+ method: 'GET',
205
+ route: '/',
206
+ status_code: 200,
207
+ timing: 1,
208
+ },
209
+ request_id: 1,
210
+ )
211
+ end
212
+ end
213
+
233
214
  describe "#notify_query" do
234
215
  context "when :stash key is not provided" do
235
216
  it "doesn't add anything to the stash of the query" do
@@ -241,7 +222,7 @@ RSpec.describe Airbrake do
241
222
  method: 'GET',
242
223
  route: '/',
243
224
  query: '',
244
- start_time: Time.now
225
+ timing: 1,
245
226
  )
246
227
  end
247
228
  end
@@ -257,14 +238,30 @@ RSpec.describe Airbrake do
257
238
  method: 'GET',
258
239
  route: '/',
259
240
  query: '',
260
- start_time: Time.now
241
+ timing: 1,
261
242
  },
262
- request_id: 1
243
+ request_id: 1,
263
244
  )
264
245
  end
265
246
  end
266
247
  end
267
248
 
249
+ describe "#notify_query_sync" do
250
+ it "notifies query synchronously" do
251
+ expect(described_class.performance_notifier).to receive(:notify_sync)
252
+
253
+ described_class.notify_query_sync(
254
+ {
255
+ method: 'GET',
256
+ route: '/',
257
+ query: '',
258
+ timing: 1,
259
+ },
260
+ request_id: 1,
261
+ )
262
+ end
263
+ end
264
+
268
265
  describe "#notify_performance_breakdown" do
269
266
  context "when :stash key is not provided" do
270
267
  it "doesn't add anything to the stash of the performance breakdown" do
@@ -276,7 +273,7 @@ RSpec.describe Airbrake do
276
273
  method: 'GET',
277
274
  route: '/',
278
275
  query: '',
279
- start_time: Time.now
276
+ timing: 1,
280
277
  )
281
278
  end
282
279
  end
@@ -284,7 +281,7 @@ RSpec.describe Airbrake do
284
281
  context "when :stash key is provided" do
285
282
  it "adds the value as the stash of the performance breakdown" do
286
283
  expect(
287
- described_class.performance_notifier
284
+ described_class.performance_notifier,
288
285
  ).to receive(:notify) do |performance_breakdown|
289
286
  expect(performance_breakdown.stash).to eq(request_id: 1)
290
287
  end
@@ -295,14 +292,76 @@ RSpec.describe Airbrake do
295
292
  route: '/',
296
293
  response_type: :html,
297
294
  groups: {},
298
- start_time: Time.now
295
+ timing: 1,
296
+ },
297
+ request_id: 1,
298
+ )
299
+ end
300
+ end
301
+ end
302
+
303
+ describe "#notify_performance_breakdown_sync" do
304
+ it "notifies performance breakdown synchronously" do
305
+ expect(described_class.performance_notifier).to receive(:notify_sync)
306
+
307
+ described_class.notify_performance_breakdown_sync(
308
+ {
309
+ method: 'GET',
310
+ route: '/',
311
+ response_type: :html,
312
+ groups: {},
313
+ timing: 1,
314
+ },
315
+ request_id: 1,
316
+ )
317
+ end
318
+ end
319
+
320
+ describe "#notify_queue" do
321
+ context "when :stash key is not provided" do
322
+ it "doesn't add anything to the stash of the queue" do
323
+ expect(described_class.performance_notifier).to receive(:notify) do |queue|
324
+ expect(queue.stash).to be_empty
325
+ end
326
+
327
+ described_class.notify_queue(
328
+ queue: 'bananas',
329
+ error_count: 10,
330
+ )
331
+ end
332
+ end
333
+
334
+ context "when :stash key is provided" do
335
+ it "adds the value as the stash of the queue" do
336
+ expect(described_class.performance_notifier).to receive(:notify) do |queue|
337
+ expect(queue.stash).to eq(request_id: 1)
338
+ end
339
+
340
+ described_class.notify_queue(
341
+ {
342
+ queue: 'bananas',
343
+ error_count: 10,
299
344
  },
300
- request_id: 1
345
+ request_id: 1,
301
346
  )
302
347
  end
303
348
  end
304
349
  end
305
350
 
351
+ describe "#notify_queue_sync" do
352
+ it "notifies queue synchronously" do
353
+ expect(described_class.performance_notifier).to receive(:notify_sync)
354
+
355
+ described_class.notify_queue_sync(
356
+ {
357
+ queue: 'bananas',
358
+ error_count: 10,
359
+ },
360
+ request_id: 1,
361
+ )
362
+ end
363
+ end
364
+
306
365
  describe ".performance_notifier" do
307
366
  it "returns a performance notifier" do
308
367
  expect(described_class.performance_notifier)
@@ -321,4 +380,35 @@ RSpec.describe Airbrake do
321
380
  expect(described_class.deploy_notifier).to be_an(Airbrake::DeployNotifier)
322
381
  end
323
382
  end
383
+
384
+ describe ".close" do
385
+ after { Airbrake.reset }
386
+
387
+ context "when notice_notifier is defined" do
388
+ it "gets closed" do
389
+ expect(Airbrake.notice_notifier).to receive(:close)
390
+ end
391
+ end
392
+
393
+ context "when notice_notifier is undefined" do
394
+ it "doesn't get closed (because it wasn't initialized)" do
395
+ Airbrake.instance_variable_set(:@notice_notifier, nil)
396
+ expect_any_instance_of(Airbrake::NoticeNotifier).not_to receive(:close)
397
+ end
398
+ end
399
+
400
+ context "when performance_notifier is defined" do
401
+ it "gets closed" do
402
+ expect(Airbrake.performance_notifier).to receive(:close)
403
+ end
404
+ end
405
+
406
+ context "when perforance_notifier is undefined" do
407
+ it "doesn't get closed (because it wasn't initialized)" do
408
+ Airbrake.instance_variable_set(:@performance_notifier, nil)
409
+ expect_any_instance_of(Airbrake::PerformanceNotifier)
410
+ .not_to receive(:close)
411
+ end
412
+ end
413
+ end
324
414
  end
@@ -8,7 +8,7 @@ RSpec.describe Airbrake::AsyncSender do
8
8
  Airbrake::Config.instance = Airbrake::Config.new(
9
9
  project_id: '1',
10
10
  workers: 3,
11
- queue_size: 10
11
+ queue_size: 10,
12
12
  )
13
13
  end
14
14
 
@@ -35,7 +35,7 @@ RSpec.describe Airbrake::AsyncSender do
35
35
  Airbrake::Config.instance = Airbrake::Config.new(
36
36
  project_id: '1',
37
37
  workers: 0,
38
- queue_size: 1
38
+ queue_size: 1,
39
39
  )
40
40
  end
41
41
 
@@ -55,13 +55,13 @@ RSpec.describe Airbrake::AsyncSender do
55
55
 
56
56
  expect(promise).to be_rejected
57
57
  expect(promise.value).to eq(
58
- 'error' => "AsyncSender has reached its capacity of 1"
58
+ 'error' => "AsyncSender has reached its capacity of 1",
59
59
  )
60
60
  end
61
61
 
62
62
  it "logs discarded notice" do
63
63
  expect(Airbrake::Loggable.instance).to receive(:error).with(
64
- /reached its capacity/
64
+ /reached its capacity/,
65
65
  ).at_least(:once)
66
66
 
67
67
  15.times { subject.send(notice, Airbrake::Promise.new) }
@@ -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
@@ -280,18 +280,18 @@ RSpec.describe Airbrake::Backtrace do
280
280
  # rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
281
281
  96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
282
282
  # rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
283
- }
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
 
@@ -328,8 +328,8 @@ RSpec.describe Airbrake::Backtrace do
328
328
  # rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
329
329
  96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
330
330
  # rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
331
- }
332
- }
331
+ },
332
+ },
333
333
  ]
334
334
  end
335
335
 
@@ -360,7 +360,7 @@ RSpec.describe Airbrake::Backtrace do
360
360
  # rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
361
361
  96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
362
362
  # rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
363
- }
363
+ },
364
364
  },
365
365
  {
366
366
  file: project_root_path('code.rb'),
@@ -373,14 +373,14 @@ RSpec.describe Airbrake::Backtrace do
373
373
  # rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
374
374
  96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
375
375
  # rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
376
- 97 => ' else'
377
- }
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
 
@@ -37,7 +37,7 @@ RSpec.describe Airbrake::CodeHunk do
37
37
  # rubocop:disable Metrics/LineLength
38
38
  3 => ' # Represents a chunk of information that is meant to be either sent to',
39
39
  # rubocop:enable Metrics/LineLength
40
- )
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