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.
- checksums.yaml +4 -4
- data/.github/pull_request_template.md +25 -0
- data/.github/workflows/ci.yml +118 -0
- data/.rubocop.yml +85 -34
- data/Gemfile +22 -22
- data/README.md +11 -9
- data/data/rollbar.snippet.js +1 -1
- data/docs/configuration.md +8 -0
- data/gemfiles/rails30.gemfile +18 -35
- data/gemfiles/rails31.gemfile +21 -37
- data/gemfiles/rails32.gemfile +14 -31
- data/gemfiles/rails40.gemfile +13 -32
- data/gemfiles/rails41.gemfile +12 -31
- data/gemfiles/rails42.gemfile +12 -35
- data/gemfiles/rails50.gemfile +17 -29
- data/gemfiles/rails51.gemfile +17 -29
- data/gemfiles/rails52.gemfile +7 -14
- data/gemfiles/rails60.gemfile +7 -20
- data/gemfiles/rails61.gemfile +54 -0
- data/lib/generators/rollbar/rollbar_generator.rb +18 -14
- data/lib/generators/rollbar/templates/{initializer.rb → initializer.erb} +0 -0
- data/lib/rails/rollbar_runner.rb +15 -6
- data/lib/rollbar/capistrano.rb +17 -9
- data/lib/rollbar/capistrano3.rb +8 -2
- data/lib/rollbar/capistrano_tasks.rb +44 -8
- data/lib/rollbar/configuration.rb +128 -84
- data/lib/rollbar/delay/shoryuken.rb +4 -3
- data/lib/rollbar/delay/sidekiq.rb +3 -1
- data/lib/rollbar/delay/sucker_punch.rb +1 -2
- data/lib/rollbar/delay/thread.rb +3 -2
- data/lib/rollbar/deploy.rb +8 -7
- data/lib/rollbar/encoding/encoder.rb +10 -3
- data/lib/rollbar/exception_reporter.rb +17 -8
- data/lib/rollbar/item/backtrace.rb +11 -9
- data/lib/rollbar/item/frame.rb +6 -5
- data/lib/rollbar/item/locals.rb +3 -2
- data/lib/rollbar/item.rb +68 -40
- data/lib/rollbar/json.rb +2 -1
- data/lib/rollbar/language_support.rb +0 -6
- data/lib/rollbar/lazy_store.rb +3 -7
- data/lib/rollbar/logger.rb +2 -0
- data/lib/rollbar/logger_proxy.rb +3 -1
- data/lib/rollbar/middleware/js.rb +64 -37
- data/lib/rollbar/middleware/rack/builder.rb +3 -3
- data/lib/rollbar/middleware/rack/test_session.rb +3 -3
- data/lib/rollbar/middleware/rack.rb +4 -4
- data/lib/rollbar/middleware/rails/rollbar.rb +9 -6
- data/lib/rollbar/middleware/rails/show_exceptions.rb +8 -4
- data/lib/rollbar/notifier/trace_with_bindings.rb +4 -2
- data/lib/rollbar/notifier.rb +272 -159
- data/lib/rollbar/plugin.rb +8 -8
- data/lib/rollbar/plugins/active_job.rb +11 -2
- data/lib/rollbar/plugins/delayed_job/plugin.rb +19 -2
- data/lib/rollbar/plugins/goalie.rb +27 -16
- data/lib/rollbar/plugins/rails/controller_methods.rb +18 -14
- data/lib/rollbar/plugins/rails/railtie30.rb +2 -1
- data/lib/rollbar/plugins/rails/railtie32.rb +2 -1
- data/lib/rollbar/plugins/rails/railtie_mixin.rb +2 -2
- data/lib/rollbar/plugins/rails.rb +5 -2
- data/lib/rollbar/plugins/rake.rb +2 -1
- data/lib/rollbar/plugins/sidekiq/plugin.rb +37 -20
- data/lib/rollbar/plugins/sidekiq.rb +1 -1
- data/lib/rollbar/plugins/thread.rb +8 -7
- data/lib/rollbar/plugins/validations.rb +3 -1
- data/lib/rollbar/rake_tasks.rb +1 -2
- data/lib/rollbar/request_data_extractor.rb +43 -16
- data/lib/rollbar/rollbar_test.rb +9 -118
- data/lib/rollbar/scrubbers/params.rb +13 -7
- data/lib/rollbar/scrubbers/url.rb +56 -17
- data/lib/rollbar/scrubbers.rb +1 -1
- data/lib/rollbar/truncation/remove_any_key_strategy.rb +4 -1
- data/lib/rollbar/truncation/remove_extra_strategy.rb +3 -1
- data/lib/rollbar/util/hash.rb +14 -7
- data/lib/rollbar/util/ip_anonymizer.rb +1 -1
- data/lib/rollbar/util.rb +19 -13
- data/lib/rollbar/version.rb +1 -1
- data/lib/rollbar.rb +12 -7
- data/lib/tasks/benchmark.rake +2 -1
- data/rollbar.gemspec +5 -2
- data/spec/support/rollbar_api.rb +67 -0
- metadata +9 -6
- data/.travis.yml +0 -284
data/lib/rollbar/notifier.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
107
|
-
# the message or description of the report. The last
|
108
|
-
# will become the associated exception for the report.
|
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
|
-
|
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 &&
|
207
|
+
configuration.enabled &&
|
208
|
+
configuration.access_token &&
|
209
|
+
!configuration.access_token.empty?
|
198
210
|
end
|
199
211
|
|
200
212
|
def process_item(item)
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
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
|
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 =
|
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
|
265
|
-
|
266
|
-
|
267
|
-
|
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
|
-
|
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 =>
|
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
|
-
|
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
|
-
|
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] &&
|
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
|
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
|
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
|
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
|
462
|
-
# Rollbar project. We'll first attempt to provide a
|
463
|
-
# If that fails, we'll fall back
|
464
|
-
|
465
|
-
|
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
|
-
|
470
|
-
|
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
|
-
|
478
|
-
|
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
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
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,
|
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
|
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
|
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,
|
668
|
+
http = Net::HTTP.new(uri.host, uri.port, proxy.host, proxy.port, proxy.user,
|
669
|
+
proxy.password)
|
571
670
|
|
572
|
-
http
|
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
|
-
|
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
|
-
|
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
|
-
#
|
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
|
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(
|
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
|
-
|
817
|
+
return failsafe_exception_reason(message, exception) if exception
|
708
818
|
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
819
|
+
message.to_s
|
820
|
+
rescue StandardError
|
821
|
+
log_error('[Rollbar] Error building failsafe message')
|
822
|
+
''
|
823
|
+
end
|
713
824
|
|
714
|
-
|
715
|
-
|
716
|
-
|
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
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
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
|
-
|
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
|
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
|
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
|
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(
|
910
|
+
item.payload.fetch('data', {}).fetch('failsafe', false)
|
798
911
|
end
|
799
912
|
end
|
800
913
|
end
|