rollbar 2.22.1 → 3.4.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 +34 -0
- data/.github/workflows/ci.yml +104 -0
- data/.rubocop.yml +185 -33
- data/Gemfile +26 -28
- data/README.md +32 -8
- data/data/rollbar.snippet.js +1 -1
- data/docs/configuration.md +8 -0
- data/gemfiles/rails30.gemfile +17 -35
- data/gemfiles/rails31.gemfile +20 -37
- data/gemfiles/rails32.gemfile +13 -31
- data/gemfiles/rails40.gemfile +12 -32
- data/gemfiles/rails41.gemfile +11 -31
- data/gemfiles/rails42.gemfile +12 -32
- data/gemfiles/rails50.gemfile +16 -30
- data/gemfiles/rails51.gemfile +16 -30
- data/gemfiles/rails52.gemfile +10 -19
- data/gemfiles/rails60.gemfile +10 -25
- data/gemfiles/rails61.gemfile +52 -0
- data/gemfiles/rails70.gemfile +52 -0
- data/lib/generators/rollbar/rollbar_generator.rb +18 -14
- data/lib/rails/rollbar_runner.rb +11 -20
- 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 +138 -84
- data/lib/rollbar/delay/girl_friday.rb +3 -7
- data/lib/rollbar/delay/resque.rb +2 -3
- data/lib/rollbar/delay/shoryuken.rb +4 -3
- data/lib/rollbar/delay/sidekiq.rb +5 -5
- data/lib/rollbar/delay/sucker_punch.rb +4 -6
- data/lib/rollbar/delay/thread.rb +17 -2
- data/lib/rollbar/deploy.rb +8 -7
- data/lib/rollbar/encoding/encoder.rb +17 -6
- data/lib/rollbar/encoding.rb +2 -7
- data/lib/rollbar/exception_reporter.rb +17 -8
- data/lib/rollbar/item/backtrace.rb +22 -10
- data/lib/rollbar/item/frame.rb +8 -5
- data/lib/rollbar/item/locals.rb +49 -2
- data/lib/rollbar/item.rb +80 -50
- 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/json_value.rb +15 -5
- data/lib/rollbar/middleware/js.rb +70 -38
- 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 +13 -3
- data/lib/rollbar/notifier.rb +309 -172
- data/lib/rollbar/plugin.rb +8 -8
- data/lib/rollbar/plugins/active_job.rb +20 -3
- data/lib/rollbar/plugins/delayed_job/plugin.rb +19 -2
- data/lib/rollbar/plugins/error_context.rb +11 -0
- 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 +39 -21
- 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 +53 -19
- 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 +2 -6
- data/lib/rollbar/truncation/frames_strategy.rb +1 -1
- data/lib/rollbar/truncation/mixin.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/truncation/strings_strategy.rb +4 -2
- data/lib/rollbar/util/hash.rb +14 -7
- data/lib/rollbar/util/ip_anonymizer.rb +1 -1
- data/lib/rollbar/util.rb +23 -13
- data/lib/rollbar/version.rb +1 -1
- data/lib/rollbar.rb +12 -7
- data/lib/tasks/benchmark.rake +2 -1
- data/rollbar.gemspec +6 -3
- data/spec/support/rollbar_api.rb +67 -0
- metadata +19 -12
- data/.travis.yml +0 -281
- data/lib/rollbar/encoding/legacy_encoder.rb +0 -20
- /data/lib/generators/rollbar/templates/{initializer.rb → initializer.erb} +0 -0
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,24 +204,23 @@ 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
|
214
|
-
|
219
|
+
log_error '[Rollbar] Error processing the item: ' \
|
220
|
+
"#{e.class}, #{e.message}. Item: #{item.payload.inspect}"
|
221
|
+
raise e unless via_failsafe?(item)
|
222
|
+
|
223
|
+
log_error('[Rollbar] Item has already failed. Not re-raising')
|
215
224
|
end
|
216
225
|
|
217
226
|
# We will reraise exceptions in this method so async queues
|
@@ -238,16 +247,16 @@ module Rollbar
|
|
238
247
|
# Using Rollbar.silenced we avoid the above behavior but Sidekiq
|
239
248
|
# will have a chance to retry the original job.
|
240
249
|
def process_from_async_handler(payload)
|
241
|
-
payload = Rollbar::JSON.load(payload) if payload.is_a?(String)
|
242
|
-
|
243
|
-
item = Item.build_with(payload,
|
244
|
-
:notifier => self,
|
245
|
-
:configuration => configuration,
|
246
|
-
:logger => logger)
|
247
|
-
|
248
250
|
Rollbar.silenced do
|
249
251
|
begin
|
250
|
-
|
252
|
+
if payload.is_a?(String)
|
253
|
+
# The final payload has already been built.
|
254
|
+
send_body(payload)
|
255
|
+
else
|
256
|
+
item = build_item_with_payload(payload)
|
257
|
+
|
258
|
+
process_item(item)
|
259
|
+
end
|
251
260
|
rescue StandardError => e
|
252
261
|
report_internal_error(e)
|
253
262
|
|
@@ -256,51 +265,108 @@ module Rollbar
|
|
256
265
|
end
|
257
266
|
end
|
258
267
|
|
259
|
-
def
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
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
|
265
273
|
|
266
|
-
|
274
|
+
def failsafe_initial_data(exception_reason)
|
275
|
+
{
|
267
276
|
:level => 'error',
|
268
277
|
:environment => configuration.environment.to_s,
|
269
278
|
:body => {
|
270
279
|
:message => {
|
271
|
-
:body =>
|
280
|
+
:body => failsafe_body(exception_reason)
|
272
281
|
}
|
273
282
|
},
|
274
283
|
:notifier => {
|
275
284
|
:name => 'rollbar-gem',
|
276
285
|
:version => VERSION
|
277
286
|
},
|
278
|
-
:custom => {
|
279
|
-
:orig_uuid => uuid,
|
280
|
-
:orig_host => host
|
281
|
-
},
|
282
287
|
:internal => true,
|
283
|
-
|
288
|
+
'failsafe' => true
|
284
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)
|
285
300
|
|
286
301
|
failsafe_payload = {
|
287
|
-
'access_token' => configuration.access_token,
|
288
302
|
'data' => failsafe_data
|
289
303
|
}
|
290
304
|
|
291
|
-
|
292
|
-
item = Item.build_with(failsafe_payload,
|
293
|
-
:notifier => self,
|
294
|
-
:configuration => configuration,
|
295
|
-
:logger => logger)
|
296
|
-
schedule_item(item)
|
297
|
-
rescue StandardError => e
|
298
|
-
log_error "[Rollbar] Error sending failsafe : #{e}"
|
299
|
-
end
|
305
|
+
process_failsafe_item(failsafe_payload)
|
300
306
|
|
301
307
|
failsafe_payload
|
302
308
|
end
|
303
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
|
+
|
304
370
|
## Logging
|
305
371
|
%w[debug info warn error].each do |level|
|
306
372
|
define_method(:"log_#{level}") do |message|
|
@@ -325,7 +391,8 @@ module Rollbar
|
|
325
391
|
end
|
326
392
|
|
327
393
|
def enable_locals?
|
328
|
-
configuration.locals[:enabled] &&
|
394
|
+
configuration.locals[:enabled] &&
|
395
|
+
[:app, :all].include?(configuration.send_extra_frame_data)
|
329
396
|
end
|
330
397
|
|
331
398
|
def enable_locals
|
@@ -347,13 +414,7 @@ module Rollbar
|
|
347
414
|
end
|
348
415
|
|
349
416
|
def call_before_process(options)
|
350
|
-
options =
|
351
|
-
:level => options[:level],
|
352
|
-
:scope => scope_object,
|
353
|
-
:exception => options[:exception],
|
354
|
-
:message => options[:message],
|
355
|
-
:extra => options[:extra]
|
356
|
-
}
|
417
|
+
options = options_for_handler(options)
|
357
418
|
handlers = configuration.before_process
|
358
419
|
|
359
420
|
handlers.each do |handler|
|
@@ -370,24 +431,30 @@ module Rollbar
|
|
370
431
|
end
|
371
432
|
end
|
372
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
|
+
|
373
444
|
def extract_arguments(args)
|
374
|
-
message = nil
|
375
|
-
exception = nil
|
376
|
-
extra = nil
|
377
|
-
context = nil
|
445
|
+
message = exception = extra = context = nil
|
378
446
|
|
379
447
|
args.each do |arg|
|
380
448
|
if arg.is_a?(String)
|
381
449
|
message = arg
|
382
450
|
elsif arg.is_a?(Exception)
|
383
451
|
exception = arg
|
384
|
-
elsif
|
452
|
+
elsif java_exception?(arg)
|
385
453
|
exception = arg
|
386
454
|
elsif arg.is_a?(Hash)
|
387
455
|
extra = arg
|
388
456
|
|
389
|
-
context = extra
|
390
|
-
extra.delete :custom_data_method_context
|
457
|
+
context = extra.delete :custom_data_method_context
|
391
458
|
|
392
459
|
extra = nil if extra.empty?
|
393
460
|
end
|
@@ -396,6 +463,10 @@ module Rollbar
|
|
396
463
|
[message, exception, extra, context]
|
397
464
|
end
|
398
465
|
|
466
|
+
def java_exception?(obj)
|
467
|
+
RUBY_PLATFORM == 'java' && obj.is_a?(java.lang.Throwable)
|
468
|
+
end
|
469
|
+
|
399
470
|
def lookup_exception_level(orig_level, exception, use_exception_level_filters)
|
400
471
|
return orig_level unless use_exception_level_filters
|
401
472
|
|
@@ -426,7 +497,9 @@ module Rollbar
|
|
426
497
|
|
427
498
|
def report(level, message, exception, extra, context)
|
428
499
|
unless message || exception || extra
|
429
|
-
log_error
|
500
|
+
log_error(
|
501
|
+
'[Rollbar] Tried to send a report with no message, exception or extra data.'
|
502
|
+
)
|
430
503
|
|
431
504
|
return 'error'
|
432
505
|
end
|
@@ -453,37 +526,48 @@ module Rollbar
|
|
453
526
|
log_info "[Rollbar] Data: #{data}"
|
454
527
|
end
|
455
528
|
|
456
|
-
# Reports an internal error in the Rollbar library. This will be reported
|
457
|
-
# Rollbar project. We'll first attempt to provide a
|
458
|
-
# If that fails, we'll fall back
|
459
|
-
|
460
|
-
|
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
|
+
)
|
461
540
|
|
462
541
|
configuration.execute_hook(:on_report_internal_error, exception)
|
463
542
|
|
464
|
-
|
465
|
-
|
466
|
-
rescue StandardError => e
|
467
|
-
send_failsafe('build_item in exception_data', e)
|
468
|
-
log_error "[Rollbar] Exception: #{exception}"
|
469
|
-
return
|
470
|
-
end
|
543
|
+
failsafe_message = 'build_item in exception_data'
|
544
|
+
item = build_item('error', nil, exception, { :internal => true }, nil)
|
471
545
|
|
472
|
-
|
473
|
-
|
474
|
-
rescue StandardError => e
|
475
|
-
send_failsafe('error in process_item', e)
|
476
|
-
log_error "[Rollbar] Item: #{item}"
|
477
|
-
return
|
478
|
-
end
|
546
|
+
failsafe_message = 'error in process_item'
|
547
|
+
process_item(item)
|
479
548
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
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
|
486
568
|
end
|
569
|
+
|
570
|
+
false
|
487
571
|
end
|
488
572
|
|
489
573
|
## Payload building functions
|
@@ -509,25 +593,35 @@ module Rollbar
|
|
509
593
|
|
510
594
|
## Delivery functions
|
511
595
|
|
512
|
-
def
|
513
|
-
|
514
|
-
return unless body
|
596
|
+
def send_using_eventmachine(body)
|
597
|
+
uri = URI.parse(configuration.endpoint)
|
515
598
|
|
516
|
-
headers = { 'X-Rollbar-Access-Token' =>
|
599
|
+
headers = { 'X-Rollbar-Access-Token' => configuration.access_token }
|
517
600
|
options = http_proxy_for_em(uri)
|
518
|
-
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)
|
603
|
+
|
604
|
+
eventmachine_callback(req)
|
605
|
+
eventmachine_errback(req)
|
606
|
+
end
|
519
607
|
|
608
|
+
def eventmachine_callback(req)
|
520
609
|
req.callback do
|
521
610
|
if req.response_header.status == 200
|
522
611
|
log_info '[Rollbar] Success'
|
523
612
|
else
|
524
|
-
log_warning
|
613
|
+
log_warning '[Rollbar] Got unexpected status code from Rollbar.io api: ' \
|
614
|
+
"#{req.response_header.status}"
|
525
615
|
log_info "[Rollbar] Response: #{req.response}"
|
526
616
|
end
|
527
617
|
end
|
618
|
+
end
|
528
619
|
|
620
|
+
def eventmachine_errback(req)
|
529
621
|
req.errback do
|
530
|
-
log_warning
|
622
|
+
log_warning(
|
623
|
+
"[Rollbar] Call to API failed, status code: #{req.response_header.status}"
|
624
|
+
)
|
531
625
|
log_info "[Rollbar] Error's response: #{req.response}"
|
532
626
|
end
|
533
627
|
end
|
@@ -538,40 +632,61 @@ module Rollbar
|
|
538
632
|
body = item.dump
|
539
633
|
return unless body
|
540
634
|
|
541
|
-
uri = URI.parse(configuration.endpoint)
|
542
|
-
|
543
635
|
if configuration.use_eventmachine
|
544
|
-
|
636
|
+
send_using_eventmachine(body)
|
545
637
|
return
|
546
638
|
end
|
547
639
|
|
548
|
-
|
640
|
+
send_body(body)
|
641
|
+
end
|
642
|
+
|
643
|
+
def send_body(body)
|
644
|
+
log_info '[Rollbar] Sending json'
|
645
|
+
|
646
|
+
uri = URI.parse(configuration.endpoint)
|
647
|
+
|
648
|
+
handle_response(do_post(uri, body, configuration.access_token))
|
549
649
|
end
|
550
650
|
|
551
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)
|
552
667
|
proxy = http_proxy(uri)
|
553
|
-
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)
|
554
670
|
|
555
|
-
http
|
556
|
-
http.read_timeout = configuration.request_timeout
|
671
|
+
init_http_timeouts(http)
|
557
672
|
|
558
673
|
if uri.scheme == 'https'
|
559
674
|
http.use_ssl = true
|
560
675
|
http.verify_mode = ssl_verify_mode
|
561
676
|
end
|
562
677
|
|
563
|
-
|
564
|
-
|
565
|
-
request.body = pack_ruby260_bytes(body)
|
566
|
-
request.add_field('X-Rollbar-Access-Token', access_token)
|
678
|
+
http
|
679
|
+
end
|
567
680
|
|
568
|
-
|
681
|
+
def init_http_timeouts(http)
|
682
|
+
http.open_timeout = configuration.open_timeout
|
683
|
+
http.read_timeout = configuration.request_timeout
|
569
684
|
end
|
570
685
|
|
571
686
|
def pack_ruby260_bytes(body)
|
572
687
|
# Ruby 2.6.0 shipped with a bug affecting multi-byte body for Net::HTTP.
|
573
688
|
# Fix (committed one day after 2.6.0p0 shipped) is here:
|
574
|
-
#
|
689
|
+
# ruby/ruby/commit/1680a13a926b17661329beec1ded6b32aad16c1b
|
575
690
|
#
|
576
691
|
# We work around this by repacking the body as single byte chars if needed.
|
577
692
|
if RUBY_VERSION == '2.6.0' && multibyte?(body)
|
@@ -621,8 +736,6 @@ module Rollbar
|
|
621
736
|
end
|
622
737
|
|
623
738
|
def handle_net_retries
|
624
|
-
return yield if skip_retries?
|
625
|
-
|
626
739
|
retries = configuration.net_retries - 1
|
627
740
|
|
628
741
|
begin
|
@@ -636,15 +749,13 @@ module Rollbar
|
|
636
749
|
end
|
637
750
|
end
|
638
751
|
|
639
|
-
def skip_retries?
|
640
|
-
Rollbar::LanguageSupport.ruby_19?
|
641
|
-
end
|
642
|
-
|
643
752
|
def handle_response(response)
|
644
753
|
if response.code == '200'
|
645
754
|
log_info '[Rollbar] Success'
|
646
755
|
else
|
647
|
-
log_warning
|
756
|
+
log_warning(
|
757
|
+
"[Rollbar] Got unexpected status code from Rollbar api: #{response.code}"
|
758
|
+
)
|
648
759
|
log_info "[Rollbar] Response: #{response.body}"
|
649
760
|
configuration.execute_hook(:on_error_response, response)
|
650
761
|
end
|
@@ -658,27 +769,20 @@ module Rollbar
|
|
658
769
|
end
|
659
770
|
end
|
660
771
|
|
661
|
-
def write_item(item)
|
662
|
-
if configuration.use_async
|
663
|
-
@file_semaphore.synchronize do
|
664
|
-
do_write_item(item)
|
665
|
-
end
|
666
|
-
else
|
667
|
-
do_write_item(item)
|
668
|
-
end
|
669
|
-
end
|
670
|
-
|
671
772
|
def do_write_item(item)
|
672
773
|
log_info '[Rollbar] Writing item to file'
|
673
774
|
|
674
775
|
body = item.dump
|
675
776
|
return unless body
|
676
777
|
|
778
|
+
file_name = file_name_with_pid(configuration)
|
779
|
+
|
677
780
|
begin
|
678
|
-
@file ||= File.open(
|
781
|
+
@file ||= File.open(file_name, 'a')
|
679
782
|
|
680
783
|
@file.puts(body)
|
681
784
|
@file.flush
|
785
|
+
update_file(@file, file_name)
|
682
786
|
|
683
787
|
log_info '[Rollbar] Success'
|
684
788
|
rescue IOError => e
|
@@ -686,32 +790,54 @@ module Rollbar
|
|
686
790
|
end
|
687
791
|
end
|
688
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
|
+
|
689
816
|
def failsafe_reason(message, exception)
|
690
|
-
|
817
|
+
return failsafe_exception_reason(message, exception) if exception
|
691
818
|
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
819
|
+
message.to_s
|
820
|
+
rescue StandardError
|
821
|
+
log_error('[Rollbar] Error building failsafe message')
|
822
|
+
''
|
823
|
+
end
|
696
824
|
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
exception_info += " in #{nearest_frame}" if nearest_frame
|
825
|
+
def failsafe_exception_reason(message, exception)
|
826
|
+
backtrace = exception.backtrace || []
|
827
|
+
nearest_frame = backtrace[0]
|
701
828
|
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
begin
|
708
|
-
body += message.to_s
|
709
|
-
rescue StandardError
|
710
|
-
log_error('[Rollbar] Error building failsafe message')
|
711
|
-
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}"]
|
712
834
|
end
|
835
|
+
exception_info += " in #{nearest_frame}" if nearest_frame
|
713
836
|
|
714
|
-
|
837
|
+
"#{exception_info}: #{message}"
|
838
|
+
rescue StandardError
|
839
|
+
log_error('[Rollbar] Error building failsafe exception message')
|
840
|
+
''
|
715
841
|
end
|
716
842
|
|
717
843
|
def failsafe_body(reason)
|
@@ -737,11 +863,15 @@ module Rollbar
|
|
737
863
|
end
|
738
864
|
|
739
865
|
def process_async_item(item)
|
866
|
+
# Send async payloads as JSON string when async_json_payload is set.
|
867
|
+
payload = configuration.async_json_payload ? item.dump : item.payload
|
868
|
+
|
740
869
|
configuration.async_handler ||= default_async_handler
|
741
|
-
configuration.async_handler.call(
|
870
|
+
configuration.async_handler.call(payload)
|
742
871
|
rescue StandardError
|
743
872
|
if configuration.failover_handlers.empty?
|
744
|
-
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"'
|
745
875
|
return
|
746
876
|
end
|
747
877
|
|
@@ -759,7 +889,8 @@ module Rollbar
|
|
759
889
|
rescue StandardError
|
760
890
|
next unless handler == failover_handlers.last
|
761
891
|
|
762
|
-
log_error
|
892
|
+
log_error '[Rollbar] All failover handlers failed while processing ' \
|
893
|
+
"item: #{Rollbar::JSON.dump(item.payload)}"
|
763
894
|
end
|
764
895
|
end
|
765
896
|
end
|
@@ -770,7 +901,13 @@ module Rollbar
|
|
770
901
|
return unless data[:uuid]
|
771
902
|
|
772
903
|
uuid_url = Util.uuid_rollbar_url(data, configuration)
|
773
|
-
log_info
|
904
|
+
log_info(
|
905
|
+
"[Rollbar] Details: #{uuid_url} (only available if report was successful)"
|
906
|
+
)
|
907
|
+
end
|
908
|
+
|
909
|
+
def via_failsafe?(item)
|
910
|
+
item.payload.fetch('data', {}).fetch('failsafe', false)
|
774
911
|
end
|
775
912
|
end
|
776
913
|
end
|