rollbar 2.23.2 → 3.3.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/.github/pull_request_template.md +25 -0
  3. data/.github/workflows/ci.yml +118 -0
  4. data/.rubocop.yml +85 -34
  5. data/Gemfile +22 -22
  6. data/README.md +11 -9
  7. data/data/rollbar.snippet.js +1 -1
  8. data/docs/configuration.md +8 -0
  9. data/gemfiles/rails30.gemfile +18 -35
  10. data/gemfiles/rails31.gemfile +21 -37
  11. data/gemfiles/rails32.gemfile +14 -31
  12. data/gemfiles/rails40.gemfile +13 -32
  13. data/gemfiles/rails41.gemfile +12 -31
  14. data/gemfiles/rails42.gemfile +12 -35
  15. data/gemfiles/rails50.gemfile +17 -29
  16. data/gemfiles/rails51.gemfile +17 -29
  17. data/gemfiles/rails52.gemfile +7 -14
  18. data/gemfiles/rails60.gemfile +7 -20
  19. data/gemfiles/rails61.gemfile +54 -0
  20. data/lib/generators/rollbar/rollbar_generator.rb +18 -14
  21. data/lib/generators/rollbar/templates/{initializer.rb → initializer.erb} +0 -0
  22. data/lib/rails/rollbar_runner.rb +15 -6
  23. data/lib/rollbar/capistrano.rb +17 -9
  24. data/lib/rollbar/capistrano3.rb +8 -2
  25. data/lib/rollbar/capistrano_tasks.rb +44 -8
  26. data/lib/rollbar/configuration.rb +128 -84
  27. data/lib/rollbar/delay/shoryuken.rb +4 -3
  28. data/lib/rollbar/delay/sidekiq.rb +3 -1
  29. data/lib/rollbar/delay/sucker_punch.rb +1 -2
  30. data/lib/rollbar/delay/thread.rb +3 -2
  31. data/lib/rollbar/deploy.rb +8 -7
  32. data/lib/rollbar/encoding/encoder.rb +10 -3
  33. data/lib/rollbar/exception_reporter.rb +17 -8
  34. data/lib/rollbar/item/backtrace.rb +11 -9
  35. data/lib/rollbar/item/frame.rb +6 -5
  36. data/lib/rollbar/item/locals.rb +3 -2
  37. data/lib/rollbar/item.rb +68 -40
  38. data/lib/rollbar/json.rb +2 -1
  39. data/lib/rollbar/language_support.rb +0 -6
  40. data/lib/rollbar/lazy_store.rb +3 -7
  41. data/lib/rollbar/logger.rb +2 -0
  42. data/lib/rollbar/logger_proxy.rb +3 -1
  43. data/lib/rollbar/middleware/js.rb +64 -37
  44. data/lib/rollbar/middleware/rack/builder.rb +3 -3
  45. data/lib/rollbar/middleware/rack/test_session.rb +3 -3
  46. data/lib/rollbar/middleware/rack.rb +4 -4
  47. data/lib/rollbar/middleware/rails/rollbar.rb +9 -6
  48. data/lib/rollbar/middleware/rails/show_exceptions.rb +8 -4
  49. data/lib/rollbar/notifier/trace_with_bindings.rb +4 -2
  50. data/lib/rollbar/notifier.rb +272 -159
  51. data/lib/rollbar/plugin.rb +8 -8
  52. data/lib/rollbar/plugins/active_job.rb +11 -2
  53. data/lib/rollbar/plugins/delayed_job/plugin.rb +19 -2
  54. data/lib/rollbar/plugins/goalie.rb +27 -16
  55. data/lib/rollbar/plugins/rails/controller_methods.rb +18 -14
  56. data/lib/rollbar/plugins/rails/railtie30.rb +2 -1
  57. data/lib/rollbar/plugins/rails/railtie32.rb +2 -1
  58. data/lib/rollbar/plugins/rails/railtie_mixin.rb +2 -2
  59. data/lib/rollbar/plugins/rails.rb +5 -2
  60. data/lib/rollbar/plugins/rake.rb +2 -1
  61. data/lib/rollbar/plugins/sidekiq/plugin.rb +37 -20
  62. data/lib/rollbar/plugins/sidekiq.rb +1 -1
  63. data/lib/rollbar/plugins/thread.rb +8 -7
  64. data/lib/rollbar/plugins/validations.rb +3 -1
  65. data/lib/rollbar/rake_tasks.rb +1 -2
  66. data/lib/rollbar/request_data_extractor.rb +43 -16
  67. data/lib/rollbar/rollbar_test.rb +9 -118
  68. data/lib/rollbar/scrubbers/params.rb +13 -7
  69. data/lib/rollbar/scrubbers/url.rb +56 -17
  70. data/lib/rollbar/scrubbers.rb +1 -1
  71. data/lib/rollbar/truncation/remove_any_key_strategy.rb +4 -1
  72. data/lib/rollbar/truncation/remove_extra_strategy.rb +3 -1
  73. data/lib/rollbar/util/hash.rb +14 -7
  74. data/lib/rollbar/util/ip_anonymizer.rb +1 -1
  75. data/lib/rollbar/util.rb +19 -13
  76. data/lib/rollbar/version.rb +1 -1
  77. data/lib/rollbar.rb +12 -7
  78. data/lib/tasks/benchmark.rake +2 -1
  79. data/rollbar.gemspec +5 -2
  80. data/spec/support/rollbar_api.rb +67 -0
  81. metadata +9 -6
  82. data/.travis.yml +0 -284
@@ -15,11 +15,11 @@ module Rollbar
15
15
  # The notifier class. It has the core functionality
16
16
  # for sending reports to the API.
17
17
  class Notifier
18
- attr_accessor :configuration
19
- attr_accessor :last_report
20
- attr_accessor :scope_object
18
+ attr_accessor :configuration, :last_report, :scope_object
21
19
 
22
- @file_semaphore = Mutex.new
20
+ MUTEX = Mutex.new
21
+ EXTENSION_REGEXP = /.rollbar\z/.freeze
22
+ FAILSAFE_STRING_LENGTH = 10_000
23
23
 
24
24
  def initialize(parent_notifier = nil, payload_options = nil, scope = nil)
25
25
  if parent_notifier
@@ -32,7 +32,9 @@ module Rollbar
32
32
  self.scope_object = ::Rollbar::LazyStore.new(scope)
33
33
  end
34
34
 
35
- Rollbar::Util.deep_merge(configuration.payload_options, payload_options) if payload_options
35
+ return unless payload_options
36
+
37
+ Rollbar::Util.deep_merge(configuration.payload_options, payload_options)
36
38
  end
37
39
 
38
40
  def reset!
@@ -103,10 +105,10 @@ module Rollbar
103
105
 
104
106
  # Sends a report to Rollbar.
105
107
  #
106
- # Accepts any number of arguments. The last String argument will become
107
- # the message or description of the report. The last Exception argument
108
- # will become the associated exception for the report. The last hash
109
- # argument will be used as the extra data for the report.
108
+ # Accepts a level string plus any number of arguments. The last String
109
+ # argument will become the message or description of the report. The last
110
+ # Exception argument will become the associated exception for the report.
111
+ # The last hash argument will be used as the extra data for the report.
110
112
  #
111
113
  # If the extra hash contains a symbol key :custom_data_method_context
112
114
  # the value of the key will be used as the context for
@@ -117,14 +119,14 @@ module Rollbar
117
119
  # begin
118
120
  # foo = bar
119
121
  # rescue => e
120
- # Rollbar.log(e)
122
+ # Rollbar.log('error', e)
121
123
  # end
122
124
  #
123
125
  # @example
124
- # Rollbar.log('This is a simple log message')
126
+ # Rollbar.log('info', 'This is a simple log message')
125
127
  #
126
128
  # @example
127
- # Rollbar.log(e, 'This is a description of the exception')
129
+ # Rollbar.log('error', e, 'This is a description of the exception')
128
130
  #
129
131
  def log(level, *args)
130
132
  return 'disabled' unless enabled?
@@ -132,17 +134,8 @@ module Rollbar
132
134
  message, exception, extra, context = extract_arguments(args)
133
135
  use_exception_level_filters = use_exception_level_filters?(extra)
134
136
 
135
- return 'ignored' if ignored?(exception, use_exception_level_filters)
136
-
137
- begin
138
- status = call_before_process(:level => level,
139
- :exception => exception,
140
- :message => message,
141
- :extra => extra)
142
- return 'ignored' if status == 'ignored'
143
- rescue Rollbar::Ignore
144
- return 'ignored'
145
- end
137
+ return 'ignored' if ignored?(exception, use_exception_level_filters) ||
138
+ ignore_before_process?(level, exception, message, extra)
146
139
 
147
140
  level = lookup_exception_level(level, exception,
148
141
  use_exception_level_filters)
@@ -154,10 +147,27 @@ module Rollbar
154
147
  ret
155
148
  end
156
149
 
150
+ def ignore_before_process?(level, exception, message, extra)
151
+ status = call_before_process(:level => level,
152
+ :exception => exception,
153
+ :message => message,
154
+ :extra => extra)
155
+
156
+ status == 'ignored'
157
+ rescue Rollbar::Ignore
158
+ true
159
+ end
160
+
157
161
  def report_with_rescue(level, message, exception, extra, context)
158
162
  report(level, message, exception, extra, context)
159
163
  rescue StandardError, SystemStackError => e
160
- report_internal_error(e)
164
+ original_error = {
165
+ :message => message,
166
+ :exception => exception,
167
+ :configuration => configuration
168
+ }
169
+
170
+ report_internal_error(e, original_error)
161
171
 
162
172
  'error'
163
173
  end
@@ -194,23 +204,20 @@ module Rollbar
194
204
 
195
205
  def enabled?
196
206
  # Require access_token so we don't try to send events when unconfigured.
197
- configuration.enabled && configuration.access_token && !configuration.access_token.empty?
207
+ configuration.enabled &&
208
+ configuration.access_token &&
209
+ !configuration.access_token.empty?
198
210
  end
199
211
 
200
212
  def process_item(item)
201
- if configuration.write_to_file
202
- if configuration.use_async
203
- @file_semaphore.synchronize do
204
- write_item(item)
205
- end
206
- else
207
- write_item(item)
208
- end
209
- else
210
- send_item(item)
211
- end
213
+ return send_item(item) unless configuration.write_to_file
214
+
215
+ return do_write_item(item) unless configuration.use_async
216
+
217
+ MUTEX.synchronize { do_write_item(item) }
212
218
  rescue StandardError => e
213
- log_error("[Rollbar] Error processing the item: #{e.class}, #{e.message}. Item: #{item.payload.inspect}")
219
+ log_error '[Rollbar] Error processing the item: ' \
220
+ "#{e.class}, #{e.message}. Item: #{item.payload.inspect}"
214
221
  raise e unless via_failsafe?(item)
215
222
 
216
223
  log_error('[Rollbar] Item has already failed. Not re-raising')
@@ -246,10 +253,7 @@ module Rollbar
246
253
  # The final payload has already been built.
247
254
  send_body(payload)
248
255
  else
249
- item = Item.build_with(payload,
250
- :notifier => self,
251
- :configuration => configuration,
252
- :logger => logger)
256
+ item = build_item_with_payload(payload)
253
257
 
254
258
  process_item(item)
255
259
  end
@@ -261,51 +265,108 @@ module Rollbar
261
265
  end
262
266
  end
263
267
 
264
- def send_failsafe(message, exception, uuid = nil, host = nil)
265
- exception_reason = failsafe_reason(message, exception)
266
-
267
- log_error "[Rollbar] Sending failsafe response due to #{exception_reason}"
268
-
269
- body = failsafe_body(exception_reason)
268
+ def build_item_with_payload(payload)
269
+ Item.build_with(payload, :notifier => self,
270
+ :configuration => configuration,
271
+ :logger => logger)
272
+ end
270
273
 
271
- failsafe_data = {
274
+ def failsafe_initial_data(exception_reason)
275
+ {
272
276
  :level => 'error',
273
277
  :environment => configuration.environment.to_s,
274
278
  :body => {
275
279
  :message => {
276
- :body => body
280
+ :body => failsafe_body(exception_reason)
277
281
  }
278
282
  },
279
283
  :notifier => {
280
284
  :name => 'rollbar-gem',
281
285
  :version => VERSION
282
286
  },
283
- :custom => {
284
- :orig_uuid => uuid,
285
- :orig_host => host
286
- },
287
287
  :internal => true,
288
- :failsafe => true
288
+ 'failsafe' => true
289
289
  }
290
+ end
291
+
292
+ def send_failsafe(message, exception, original_error = nil)
293
+ exception_reason = failsafe_reason(message, exception)
294
+
295
+ log_error "[Rollbar] Sending failsafe response due to #{exception_reason}"
296
+
297
+ failsafe_data = failsafe_initial_data(exception_reason)
298
+
299
+ failsafe_add_original_error_data(failsafe_data[:notifier], original_error)
290
300
 
291
301
  failsafe_payload = {
292
- 'access_token' => configuration.access_token,
293
302
  'data' => failsafe_data
294
303
  }
295
304
 
296
- begin
297
- item = Item.build_with(failsafe_payload,
298
- :notifier => self,
299
- :configuration => configuration,
300
- :logger => logger)
301
- schedule_item(item)
302
- rescue StandardError => e
303
- log_error "[Rollbar] Error sending failsafe : #{e}"
304
- end
305
+ process_failsafe_item(failsafe_payload)
305
306
 
306
307
  failsafe_payload
307
308
  end
308
309
 
310
+ def process_failsafe_item(failsafe_payload)
311
+ item = build_item_with_payload(failsafe_payload)
312
+ process_item(item)
313
+ log_and_return_item_data(item)
314
+ rescue StandardError => e
315
+ log_error "[Rollbar] Error sending failsafe : #{e}"
316
+ end
317
+
318
+ def failsafe_add_original_error_data(payload_notifier, original_error)
319
+ return unless original_error
320
+
321
+ payload_notifier[:diagnostic] ||= {}
322
+
323
+ add_original_host(payload_notifier[:diagnostic], original_error)
324
+ add_original_uuid(payload_notifier[:diagnostic], original_error)
325
+ add_original_message(payload_notifier[:diagnostic], original_error)
326
+ add_original_error(payload_notifier[:diagnostic], original_error)
327
+ add_configured_options(payload_notifier, original_error)
328
+ end
329
+
330
+ def add_original_message(diagnostic, original_error)
331
+ if original_error[:message]
332
+ diagnostic[:original_message] =
333
+ original_error[:message].truncate(FAILSAFE_STRING_LENGTH)
334
+ end
335
+ rescue StandardError => e
336
+ diagnostic[:original_message] = "Failed: #{e.message}"
337
+ end
338
+
339
+ def add_original_error(diagnostic, original_error)
340
+ if original_error[:exception]
341
+ backtrace = original_error[:exception].backtrace
342
+ message = original_error[:exception].message
343
+ diagnostic[:original_error] = {
344
+ :message => message && message.truncate(FAILSAFE_STRING_LENGTH),
345
+ :stack => backtrace && backtrace.join(', ').truncate(FAILSAFE_STRING_LENGTH)
346
+ }
347
+ end
348
+ rescue StandardError => e
349
+ diagnostic[:original_error] = "Failed: #{e.message}"
350
+ end
351
+
352
+ def add_configured_options(payload_notifier, original_error)
353
+ if original_error[:configuration]
354
+ configured = original_error[:configuration].configured_options.configured
355
+ payload_notifier[:configured_options] =
356
+ ::JSON.generate(configured).truncate(FAILSAFE_STRING_LENGTH)
357
+ end
358
+ rescue StandardError => e
359
+ payload_notifier[:configured_options] = "Failed: #{e.message}"
360
+ end
361
+
362
+ def add_original_host(diagnostic, original_error)
363
+ diagnostic[:original_host] = original_error[:host] if original_error[:host]
364
+ end
365
+
366
+ def add_original_uuid(diagnostic, original_error)
367
+ diagnostic[:original_uuid] = original_error[:uuid] if original_error[:uuid]
368
+ end
369
+
309
370
  ## Logging
310
371
  %w[debug info warn error].each do |level|
311
372
  define_method(:"log_#{level}") do |message|
@@ -330,7 +391,8 @@ module Rollbar
330
391
  end
331
392
 
332
393
  def enable_locals?
333
- configuration.locals[:enabled] && [:app, :all].include?(configuration.send_extra_frame_data)
394
+ configuration.locals[:enabled] &&
395
+ [:app, :all].include?(configuration.send_extra_frame_data)
334
396
  end
335
397
 
336
398
  def enable_locals
@@ -352,13 +414,7 @@ module Rollbar
352
414
  end
353
415
 
354
416
  def call_before_process(options)
355
- options = {
356
- :level => options[:level],
357
- :scope => scope_object,
358
- :exception => options[:exception],
359
- :message => options[:message],
360
- :extra => options[:extra]
361
- }
417
+ options = options_for_handler(options)
362
418
  handlers = configuration.before_process
363
419
 
364
420
  handlers.each do |handler|
@@ -375,24 +431,30 @@ module Rollbar
375
431
  end
376
432
  end
377
433
 
434
+ def options_for_handler(options)
435
+ {
436
+ :level => options[:level],
437
+ :scope => scope_object,
438
+ :exception => options[:exception],
439
+ :message => options[:message],
440
+ :extra => options[:extra]
441
+ }
442
+ end
443
+
378
444
  def extract_arguments(args)
379
- message = nil
380
- exception = nil
381
- extra = nil
382
- context = nil
445
+ message = exception = extra = context = nil
383
446
 
384
447
  args.each do |arg|
385
448
  if arg.is_a?(String)
386
449
  message = arg
387
450
  elsif arg.is_a?(Exception)
388
451
  exception = arg
389
- elsif RUBY_PLATFORM == 'java' && arg.is_a?(java.lang.Throwable)
452
+ elsif java_exception?(arg)
390
453
  exception = arg
391
454
  elsif arg.is_a?(Hash)
392
455
  extra = arg
393
456
 
394
- context = extra[:custom_data_method_context]
395
- extra.delete :custom_data_method_context
457
+ context = extra.delete :custom_data_method_context
396
458
 
397
459
  extra = nil if extra.empty?
398
460
  end
@@ -401,6 +463,10 @@ module Rollbar
401
463
  [message, exception, extra, context]
402
464
  end
403
465
 
466
+ def java_exception?(obj)
467
+ RUBY_PLATFORM == 'java' && obj.is_a?(java.lang.Throwable)
468
+ end
469
+
404
470
  def lookup_exception_level(orig_level, exception, use_exception_level_filters)
405
471
  return orig_level unless use_exception_level_filters
406
472
 
@@ -431,7 +497,9 @@ module Rollbar
431
497
 
432
498
  def report(level, message, exception, extra, context)
433
499
  unless message || exception || extra
434
- log_error '[Rollbar] Tried to send a report with no message, exception or extra data.'
500
+ log_error(
501
+ '[Rollbar] Tried to send a report with no message, exception or extra data.'
502
+ )
435
503
 
436
504
  return 'error'
437
505
  end
@@ -458,37 +526,48 @@ module Rollbar
458
526
  log_info "[Rollbar] Data: #{data}"
459
527
  end
460
528
 
461
- # Reports an internal error in the Rollbar library. This will be reported within the configured
462
- # Rollbar project. We'll first attempt to provide a report including the exception traceback.
463
- # If that fails, we'll fall back to a more static failsafe response.
464
- def report_internal_error(exception)
465
- log_error '[Rollbar] Reporting internal error encountered while sending data to Rollbar.'
529
+ # Reports an internal error in the Rollbar library. This will be reported
530
+ # within the configured Rollbar project. We'll first attempt to provide a
531
+ # report including the exception traceback. If that fails, we'll fall back
532
+ # to a more static failsafe response.
533
+ def report_internal_error(exception, original_error = nil)
534
+ return if skip_reporting_internal_error(exception)
535
+
536
+ failsafe_message = ''
537
+ log_error(
538
+ '[Rollbar] Reporting internal error encountered while sending data to Rollbar.'
539
+ )
466
540
 
467
541
  configuration.execute_hook(:on_report_internal_error, exception)
468
542
 
469
- begin
470
- item = build_item('error', nil, exception, { :internal => true }, nil)
471
- rescue StandardError => e
472
- send_failsafe('build_item in exception_data', e)
473
- log_error "[Rollbar] Exception: #{exception}"
474
- return
475
- end
543
+ failsafe_message = 'build_item in exception_data'
544
+ item = build_item('error', nil, exception, { :internal => true }, nil)
476
545
 
477
- begin
478
- process_item(item)
479
- rescue StandardError => e
480
- send_failsafe('error in process_item', e)
481
- log_error "[Rollbar] Item: #{item}"
482
- return
483
- end
546
+ failsafe_message = 'error in process_item'
547
+ process_item(item)
484
548
 
485
- begin
486
- log_instance_link(item['data'])
487
- rescue StandardError => e
488
- send_failsafe('error logging instance link', e)
489
- log_error "[Rollbar] Item: #{item}"
490
- return
549
+ failsafe_message = 'error logging instance link'
550
+ log_instance_link(item['data'])
551
+ rescue StandardError => e
552
+ send_failsafe(failsafe_message, e, original_error)
553
+ log_error(item ? "[Rollbar] Item: #{item}" : "[Rollbar] Exception: #{exception}")
554
+ end
555
+
556
+ def skip_reporting_internal_error(exception)
557
+ return true if configuration.ignore_internal_errors == true
558
+
559
+ configuration.ignore_internal_errors.each do |error_name|
560
+ begin
561
+ error_cls = error_name.split('::').reduce(Module, :const_get)
562
+ return true if exception.class <= error_cls
563
+ rescue NameError
564
+ # Ignore errors and continue matching.
565
+ # It's possible for a class name in the list to not be resolvable,
566
+ # and this is ok.
567
+ end
491
568
  end
569
+
570
+ false
492
571
  end
493
572
 
494
573
  ## Payload building functions
@@ -519,7 +598,8 @@ module Rollbar
519
598
 
520
599
  headers = { 'X-Rollbar-Access-Token' => configuration.access_token }
521
600
  options = http_proxy_for_em(uri)
522
- req = EventMachine::HttpRequest.new(uri.to_s, options).post(:body => body, :head => headers)
601
+ req = EventMachine::HttpRequest.new(uri.to_s, options).post(:body => body,
602
+ :head => headers)
523
603
 
524
604
  eventmachine_callback(req)
525
605
  eventmachine_errback(req)
@@ -530,7 +610,8 @@ module Rollbar
530
610
  if req.response_header.status == 200
531
611
  log_info '[Rollbar] Success'
532
612
  else
533
- log_warning "[Rollbar] Got unexpected status code from Rollbar.io api: #{req.response_header.status}"
613
+ log_warning '[Rollbar] Got unexpected status code from Rollbar.io api: ' \
614
+ "#{req.response_header.status}"
534
615
  log_info "[Rollbar] Response: #{req.response}"
535
616
  end
536
617
  end
@@ -538,7 +619,9 @@ module Rollbar
538
619
 
539
620
  def eventmachine_errback(req)
540
621
  req.errback do
541
- log_warning "[Rollbar] Call to API failed, status code: #{req.response_header.status}"
622
+ log_warning(
623
+ "[Rollbar] Call to API failed, status code: #{req.response_header.status}"
624
+ )
542
625
  log_info "[Rollbar] Error's response: #{req.response}"
543
626
  end
544
627
  end
@@ -566,29 +649,44 @@ module Rollbar
566
649
  end
567
650
 
568
651
  def do_post(uri, body, access_token)
652
+ http = init_http(uri)
653
+
654
+ request = Net::HTTP::Post.new(uri.request_uri)
655
+
656
+ request.body = pack_ruby260_bytes(body)
657
+
658
+ # Ensure the payload token will be used if the option is set.
659
+ unless configuration.use_payload_access_token
660
+ request.add_field('X-Rollbar-Access-Token', access_token)
661
+ end
662
+
663
+ handle_net_retries { http.request(request) }
664
+ end
665
+
666
+ def init_http(uri)
569
667
  proxy = http_proxy(uri)
570
- http = Net::HTTP.new(uri.host, uri.port, proxy.host, proxy.port, proxy.user, proxy.password)
668
+ http = Net::HTTP.new(uri.host, uri.port, proxy.host, proxy.port, proxy.user,
669
+ proxy.password)
571
670
 
572
- http.open_timeout = configuration.open_timeout
573
- http.read_timeout = configuration.request_timeout
671
+ init_http_timeouts(http)
574
672
 
575
673
  if uri.scheme == 'https'
576
674
  http.use_ssl = true
577
675
  http.verify_mode = ssl_verify_mode
578
676
  end
579
677
 
580
- request = Net::HTTP::Post.new(uri.request_uri)
581
-
582
- request.body = pack_ruby260_bytes(body)
583
- request.add_field('X-Rollbar-Access-Token', access_token)
678
+ http
679
+ end
584
680
 
585
- handle_net_retries { http.request(request) }
681
+ def init_http_timeouts(http)
682
+ http.open_timeout = configuration.open_timeout
683
+ http.read_timeout = configuration.request_timeout
586
684
  end
587
685
 
588
686
  def pack_ruby260_bytes(body)
589
687
  # Ruby 2.6.0 shipped with a bug affecting multi-byte body for Net::HTTP.
590
688
  # Fix (committed one day after 2.6.0p0 shipped) is here:
591
- # https://github.com/ruby/ruby/commit/1680a13a926b17661329beec1ded6b32aad16c1b#diff-00a99d8c71daaf5fc60a050da41f7261
689
+ # ruby/ruby/commit/1680a13a926b17661329beec1ded6b32aad16c1b
592
690
  #
593
691
  # We work around this by repacking the body as single byte chars if needed.
594
692
  if RUBY_VERSION == '2.6.0' && multibyte?(body)
@@ -638,8 +736,6 @@ module Rollbar
638
736
  end
639
737
 
640
738
  def handle_net_retries
641
- return yield if skip_retries?
642
-
643
739
  retries = configuration.net_retries - 1
644
740
 
645
741
  begin
@@ -653,15 +749,13 @@ module Rollbar
653
749
  end
654
750
  end
655
751
 
656
- def skip_retries?
657
- Rollbar::LanguageSupport.ruby_19?
658
- end
659
-
660
752
  def handle_response(response)
661
753
  if response.code == '200'
662
754
  log_info '[Rollbar] Success'
663
755
  else
664
- log_warning "[Rollbar] Got unexpected status code from Rollbar api: #{response.code}"
756
+ log_warning(
757
+ "[Rollbar] Got unexpected status code from Rollbar api: #{response.code}"
758
+ )
665
759
  log_info "[Rollbar] Response: #{response.body}"
666
760
  configuration.execute_hook(:on_error_response, response)
667
761
  end
@@ -675,27 +769,20 @@ module Rollbar
675
769
  end
676
770
  end
677
771
 
678
- def write_item(item)
679
- if configuration.use_async
680
- @file_semaphore.synchronize do
681
- do_write_item(item)
682
- end
683
- else
684
- do_write_item(item)
685
- end
686
- end
687
-
688
772
  def do_write_item(item)
689
773
  log_info '[Rollbar] Writing item to file'
690
774
 
691
775
  body = item.dump
692
776
  return unless body
693
777
 
778
+ file_name = file_name_with_pid(configuration)
779
+
694
780
  begin
695
- @file ||= File.open(configuration.filepath, 'a')
781
+ @file ||= File.open(file_name, 'a')
696
782
 
697
783
  @file.puts(body)
698
784
  @file.flush
785
+ update_file(@file, file_name)
699
786
 
700
787
  log_info '[Rollbar] Success'
701
788
  rescue IOError => e
@@ -703,32 +790,54 @@ module Rollbar
703
790
  end
704
791
  end
705
792
 
793
+ def file_name_with_pid(configuration)
794
+ if configuration.files_with_pid_name_enabled
795
+ configuration.filepath.gsub(EXTENSION_REGEXP, "_#{Process.pid}\\0")
796
+ else
797
+ configuration.filepath
798
+ end
799
+ end
800
+
801
+ def update_file(file, file_name)
802
+ return unless configuration.files_processed_enabled
803
+
804
+ time_now = Time.now
805
+ if configuration.files_processed_duration > time_now - file.birthtime &&
806
+ file.size < configuration.files_processed_size
807
+ return
808
+ end
809
+
810
+ new_file_name = file_name.gsub(EXTENSION_REGEXP, "_processed_#{time_now.to_i}\\0")
811
+ File.rename(file, new_file_name)
812
+ file.close
813
+ @file = File.open(file_name, 'a')
814
+ end
815
+
706
816
  def failsafe_reason(message, exception)
707
- body = ''
817
+ return failsafe_exception_reason(message, exception) if exception
708
818
 
709
- if exception
710
- begin
711
- backtrace = exception.backtrace || []
712
- nearest_frame = backtrace[0]
819
+ message.to_s
820
+ rescue StandardError
821
+ log_error('[Rollbar] Error building failsafe message')
822
+ ''
823
+ end
713
824
 
714
- exception_info = exception.class.name
715
- # #to_s and #message defaults to class.to_s. Add message only if add valuable info.
716
- exception_info += %[: "#{exception.message}"] if exception.message != exception.class.to_s
717
- exception_info += " in #{nearest_frame}" if nearest_frame
825
+ def failsafe_exception_reason(message, exception)
826
+ backtrace = exception.backtrace || []
827
+ nearest_frame = backtrace[0]
718
828
 
719
- body += "#{exception_info}: #{message}"
720
- rescue StandardError
721
- log_error('[Rollbar] Error building failsafe exception message')
722
- end
723
- else
724
- begin
725
- body += message.to_s
726
- rescue StandardError
727
- log_error('[Rollbar] Error building failsafe message')
728
- end
829
+ exception_info = exception.class.name
830
+ # #to_s and #message defaults to class.to_s.
831
+ # Add message only if add valuable info.
832
+ if exception.message != exception.class.to_s
833
+ exception_info += %[: "#{exception.message}"]
729
834
  end
835
+ exception_info += " in #{nearest_frame}" if nearest_frame
730
836
 
731
- body
837
+ "#{exception_info}: #{message}"
838
+ rescue StandardError
839
+ log_error('[Rollbar] Error building failsafe exception message')
840
+ ''
732
841
  end
733
842
 
734
843
  def failsafe_body(reason)
@@ -761,7 +870,8 @@ module Rollbar
761
870
  configuration.async_handler.call(payload)
762
871
  rescue StandardError
763
872
  if configuration.failover_handlers.empty?
764
- log_error '[Rollbar] Async handler failed, and there are no failover handlers configured. See the docs for "failover_handlers"'
873
+ log_error '[Rollbar] Async handler failed, and there are no failover ' \
874
+ 'handlers configured. See the docs for "failover_handlers"'
765
875
  return
766
876
  end
767
877
 
@@ -779,7 +889,8 @@ module Rollbar
779
889
  rescue StandardError
780
890
  next unless handler == failover_handlers.last
781
891
 
782
- log_error "[Rollbar] All failover handlers failed while processing item: #{Rollbar::JSON.dump(item.payload)}"
892
+ log_error '[Rollbar] All failover handlers failed while processing ' \
893
+ "item: #{Rollbar::JSON.dump(item.payload)}"
783
894
  end
784
895
  end
785
896
  end
@@ -790,11 +901,13 @@ module Rollbar
790
901
  return unless data[:uuid]
791
902
 
792
903
  uuid_url = Util.uuid_rollbar_url(data, configuration)
793
- log_info "[Rollbar] Details: #{uuid_url} (only available if report was successful)"
904
+ log_info(
905
+ "[Rollbar] Details: #{uuid_url} (only available if report was successful)"
906
+ )
794
907
  end
795
908
 
796
909
  def via_failsafe?(item)
797
- item.payload.fetch('data', {}).fetch(:failsafe, false)
910
+ item.payload.fetch('data', {}).fetch('failsafe', false)
798
911
  end
799
912
  end
800
913
  end