rollbar 2.19.1 → 2.27.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/pull_request_template.md +25 -0
- data/.rubocop.yml +168 -0
- data/.travis.yml +63 -34
- data/Appraisals +10 -10
- data/Gemfile +35 -14
- data/README.md +5 -2
- data/Rakefile +0 -0
- data/data/rollbar.snippet.js +1 -1
- data/docs/configuration.md +17 -0
- data/gemfiles/rails30.gemfile +10 -10
- data/gemfiles/rails31.gemfile +10 -9
- data/gemfiles/rails32.gemfile +10 -9
- data/gemfiles/rails40.gemfile +10 -9
- data/gemfiles/rails41.gemfile +10 -9
- data/gemfiles/rails42.gemfile +12 -9
- data/gemfiles/rails50.gemfile +21 -14
- data/gemfiles/rails51.gemfile +21 -14
- data/gemfiles/rails52.gemfile +15 -12
- data/gemfiles/rails60.gemfile +67 -0
- data/lib/generators/rollbar/rollbar_generator.rb +1 -1
- data/lib/rails/rollbar_runner.rb +4 -2
- data/lib/rollbar/capistrano.rb +1 -1
- data/lib/rollbar/capistrano3.rb +6 -3
- data/lib/rollbar/capistrano_tasks.rb +29 -21
- data/lib/rollbar/configuration.rb +86 -16
- data/lib/rollbar/delay/girl_friday.rb +4 -8
- data/lib/rollbar/delay/resque.rb +3 -6
- data/lib/rollbar/delay/sidekiq.rb +4 -10
- data/lib/rollbar/delay/sucker_punch.rb +16 -19
- data/lib/rollbar/delay/thread.rb +16 -2
- data/lib/rollbar/deploy.rb +52 -29
- data/lib/rollbar/encoding/encoder.rb +17 -10
- data/lib/rollbar/exception_reporter.rb +19 -5
- data/lib/rollbar/item/backtrace.rb +13 -3
- data/lib/rollbar/item/frame.rb +9 -1
- data/lib/rollbar/item/locals.rb +100 -0
- data/lib/rollbar/item.rb +56 -17
- data/lib/rollbar/json.rb +6 -51
- data/lib/rollbar/language_support.rb +4 -20
- data/lib/rollbar/lazy_store.rb +5 -5
- data/lib/rollbar/logger.rb +1 -0
- data/lib/rollbar/logger_proxy.rb +6 -2
- data/lib/rollbar/middleware/js.rb +28 -18
- data/lib/rollbar/middleware/rack.rb +4 -1
- data/lib/rollbar/middleware/rails/rollbar.rb +10 -1
- data/lib/rollbar/notifier/trace_with_bindings.rb +65 -0
- data/lib/rollbar/notifier.rb +225 -89
- data/lib/rollbar/plugin.rb +54 -6
- data/lib/rollbar/plugins/active_job.rb +6 -2
- data/lib/rollbar/plugins/basic_socket.rb +21 -6
- data/lib/rollbar/plugins/delayed_job/job_data.rb +3 -3
- data/lib/rollbar/plugins/delayed_job/plugin.rb +13 -3
- data/lib/rollbar/plugins/error_context.rb +11 -0
- data/lib/rollbar/plugins/goalie.rb +11 -3
- data/lib/rollbar/plugins/rails/controller_methods.rb +15 -3
- data/lib/rollbar/plugins/rake.rb +2 -2
- data/lib/rollbar/plugins/sidekiq/plugin.rb +5 -4
- data/lib/rollbar/plugins.rb +7 -1
- data/lib/rollbar/rake_tasks.rb +4 -148
- data/lib/rollbar/request_data_extractor.rb +31 -21
- data/lib/rollbar/rollbar_test.rb +36 -0
- data/lib/rollbar/scrubbers/params.rb +19 -18
- data/lib/rollbar/scrubbers/url.rb +18 -9
- data/lib/rollbar/scrubbers.rb +3 -3
- data/lib/rollbar/truncation/frames_strategy.rb +1 -1
- data/lib/rollbar/truncation/min_body_strategy.rb +2 -3
- data/lib/rollbar/truncation/mixin.rb +1 -1
- data/lib/rollbar/truncation/remove_any_key_strategy.rb +123 -0
- data/lib/rollbar/truncation/remove_extra_strategy.rb +35 -0
- data/lib/rollbar/truncation/remove_request_strategy.rb +21 -0
- data/lib/rollbar/truncation/strings_strategy.rb +6 -5
- data/lib/rollbar/truncation.rb +9 -2
- data/lib/rollbar/util/hash.rb +15 -0
- data/lib/rollbar/util/ip_anonymizer.rb +8 -7
- data/lib/rollbar/util/ip_obfuscator.rb +1 -1
- data/lib/rollbar/util.rb +6 -2
- data/lib/rollbar/version.rb +1 -1
- data/lib/rollbar.rb +2 -3
- data/lib/tasks/benchmark.rake +103 -0
- data/rollbar.gemspec +13 -5
- data/spec/support/rollbar_api.rb +67 -0
- metadata +21 -23
- data/gemfiles/ruby_1_8_and_1_9_2.gemfile +0 -49
- data/lib/rollbar/json/default.rb +0 -11
- data/lib/rollbar/json/oj.rb +0 -16
data/lib/rollbar/notifier.rb
CHANGED
@@ -8,6 +8,7 @@ require 'rollbar/delay/girl_friday'
|
|
8
8
|
require 'rollbar/delay/thread'
|
9
9
|
require 'rollbar/logger_proxy'
|
10
10
|
require 'rollbar/item'
|
11
|
+
require 'rollbar/notifier/trace_with_bindings'
|
11
12
|
require 'ostruct'
|
12
13
|
|
13
14
|
module Rollbar
|
@@ -18,7 +19,9 @@ module Rollbar
|
|
18
19
|
attr_accessor :last_report
|
19
20
|
attr_accessor :scope_object
|
20
21
|
|
21
|
-
|
22
|
+
MUTEX = Mutex.new
|
23
|
+
EXTENSION_REGEXP = /.rollbar\z/.freeze
|
24
|
+
FAILSAFE_STRING_LENGTH = 10_000
|
22
25
|
|
23
26
|
def initialize(parent_notifier = nil, payload_options = nil, scope = nil)
|
24
27
|
if parent_notifier
|
@@ -41,21 +44,21 @@ module Rollbar
|
|
41
44
|
# Similar to configure below, but used only internally within the gem
|
42
45
|
# to configure it without initializing any of the third party hooks
|
43
46
|
def preconfigure
|
44
|
-
yield(configuration)
|
47
|
+
yield(configuration.configured_options)
|
45
48
|
end
|
46
49
|
|
47
50
|
# Configures the notifier instance
|
48
51
|
def configure
|
49
52
|
configuration.enabled = true if configuration.enabled.nil?
|
50
53
|
|
51
|
-
yield(configuration)
|
54
|
+
yield(configuration.configured_options)
|
52
55
|
end
|
53
56
|
|
54
57
|
def reconfigure
|
55
58
|
self.configuration = Configuration.new
|
56
59
|
configuration.enabled = true
|
57
60
|
|
58
|
-
yield(configuration)
|
61
|
+
yield(configuration.configured_options)
|
59
62
|
end
|
60
63
|
|
61
64
|
def unconfigure
|
@@ -95,17 +98,17 @@ module Rollbar
|
|
95
98
|
# @yield Block which exceptions won't be reported.
|
96
99
|
def silenced
|
97
100
|
yield
|
98
|
-
rescue => e
|
101
|
+
rescue StandardError => e
|
99
102
|
e.instance_variable_set(:@_rollbar_do_not_report, true)
|
100
103
|
raise
|
101
104
|
end
|
102
105
|
|
103
106
|
# Sends a report to Rollbar.
|
104
107
|
#
|
105
|
-
# Accepts any number of arguments. The last String
|
106
|
-
# the message or description of the report. The last
|
107
|
-
# will become the associated exception for the report.
|
108
|
-
# 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.
|
109
112
|
#
|
110
113
|
# If the extra hash contains a symbol key :custom_data_method_context
|
111
114
|
# the value of the key will be used as the context for
|
@@ -116,17 +119,17 @@ module Rollbar
|
|
116
119
|
# begin
|
117
120
|
# foo = bar
|
118
121
|
# rescue => e
|
119
|
-
# Rollbar.log(e)
|
122
|
+
# Rollbar.log('error', e)
|
120
123
|
# end
|
121
124
|
#
|
122
125
|
# @example
|
123
|
-
# Rollbar.log('This is a simple log message')
|
126
|
+
# Rollbar.log('info', 'This is a simple log message')
|
124
127
|
#
|
125
128
|
# @example
|
126
|
-
# Rollbar.log(e, 'This is a description of the exception')
|
129
|
+
# Rollbar.log('error', e, 'This is a description of the exception')
|
127
130
|
#
|
128
131
|
def log(level, *args)
|
129
|
-
return 'disabled' unless
|
132
|
+
return 'disabled' unless enabled?
|
130
133
|
|
131
134
|
message, exception, extra, context = extract_arguments(args)
|
132
135
|
use_exception_level_filters = use_exception_level_filters?(extra)
|
@@ -146,13 +149,25 @@ module Rollbar
|
|
146
149
|
level = lookup_exception_level(level, exception,
|
147
150
|
use_exception_level_filters)
|
148
151
|
|
149
|
-
|
150
|
-
report(level, message, exception, extra, context)
|
151
|
-
rescue StandardError, SystemStackError => e
|
152
|
-
report_internal_error(e)
|
152
|
+
ret = report_with_rescue(level, message, exception, extra, context)
|
153
153
|
|
154
|
-
|
155
|
-
|
154
|
+
raise(exception) if configuration.raise_on_error && exception
|
155
|
+
|
156
|
+
ret
|
157
|
+
end
|
158
|
+
|
159
|
+
def report_with_rescue(level, message, exception, extra, context)
|
160
|
+
report(level, message, exception, extra, context)
|
161
|
+
rescue StandardError, SystemStackError => e
|
162
|
+
original_error = {
|
163
|
+
:message => message,
|
164
|
+
:exception => exception,
|
165
|
+
:configuration => configuration
|
166
|
+
}
|
167
|
+
|
168
|
+
report_internal_error(e, original_error)
|
169
|
+
|
170
|
+
'error'
|
156
171
|
end
|
157
172
|
|
158
173
|
# See log() above
|
@@ -185,21 +200,28 @@ module Rollbar
|
|
185
200
|
log('critical', *args)
|
186
201
|
end
|
187
202
|
|
203
|
+
def enabled?
|
204
|
+
# Require access_token so we don't try to send events when unconfigured.
|
205
|
+
configuration.enabled && configuration.access_token && !configuration.access_token.empty?
|
206
|
+
end
|
207
|
+
|
188
208
|
def process_item(item)
|
189
209
|
if configuration.write_to_file
|
190
210
|
if configuration.use_async
|
191
|
-
|
192
|
-
|
211
|
+
MUTEX.synchronize do
|
212
|
+
do_write_item(item)
|
193
213
|
end
|
194
214
|
else
|
195
|
-
|
215
|
+
do_write_item(item)
|
196
216
|
end
|
197
217
|
else
|
198
218
|
send_item(item)
|
199
219
|
end
|
200
|
-
rescue => e
|
220
|
+
rescue StandardError => e
|
201
221
|
log_error("[Rollbar] Error processing the item: #{e.class}, #{e.message}. Item: #{item.payload.inspect}")
|
202
|
-
raise e
|
222
|
+
raise e unless via_failsafe?(item)
|
223
|
+
|
224
|
+
log_error('[Rollbar] Item has already failed. Not re-raising')
|
203
225
|
end
|
204
226
|
|
205
227
|
# We will reraise exceptions in this method so async queues
|
@@ -226,17 +248,20 @@ module Rollbar
|
|
226
248
|
# Using Rollbar.silenced we avoid the above behavior but Sidekiq
|
227
249
|
# will have a chance to retry the original job.
|
228
250
|
def process_from_async_handler(payload)
|
229
|
-
payload = Rollbar::JSON.load(payload) if payload.is_a?(String)
|
230
|
-
|
231
|
-
item = Item.build_with(payload,
|
232
|
-
:notifier => self,
|
233
|
-
:configuration => configuration,
|
234
|
-
:logger => logger)
|
235
|
-
|
236
251
|
Rollbar.silenced do
|
237
252
|
begin
|
238
|
-
|
239
|
-
|
253
|
+
if payload.is_a?(String)
|
254
|
+
# The final payload has already been built.
|
255
|
+
send_body(payload)
|
256
|
+
else
|
257
|
+
item = Item.build_with(payload,
|
258
|
+
:notifier => self,
|
259
|
+
:configuration => configuration,
|
260
|
+
:logger => logger)
|
261
|
+
|
262
|
+
process_item(item)
|
263
|
+
end
|
264
|
+
rescue StandardError => e
|
240
265
|
report_internal_error(e)
|
241
266
|
|
242
267
|
raise
|
@@ -244,35 +269,34 @@ module Rollbar
|
|
244
269
|
end
|
245
270
|
end
|
246
271
|
|
247
|
-
def
|
248
|
-
|
249
|
-
|
250
|
-
log_error "[Rollbar] Sending failsafe response due to #{exception_reason}"
|
251
|
-
|
252
|
-
body = failsafe_body(exception_reason)
|
253
|
-
|
254
|
-
failsafe_data = {
|
272
|
+
def failsafe_initial_data(exception_reason)
|
273
|
+
{
|
255
274
|
:level => 'error',
|
256
275
|
:environment => configuration.environment.to_s,
|
257
276
|
:body => {
|
258
277
|
:message => {
|
259
|
-
:body =>
|
278
|
+
:body => failsafe_body(exception_reason)
|
260
279
|
}
|
261
280
|
},
|
262
281
|
:notifier => {
|
263
282
|
:name => 'rollbar-gem',
|
264
283
|
:version => VERSION
|
265
284
|
},
|
266
|
-
:custom => {
|
267
|
-
:orig_uuid => uuid,
|
268
|
-
:orig_host => host
|
269
|
-
},
|
270
285
|
:internal => true,
|
271
|
-
|
286
|
+
'failsafe' => true
|
272
287
|
}
|
288
|
+
end
|
289
|
+
|
290
|
+
def send_failsafe(message, exception, original_error = nil)
|
291
|
+
exception_reason = failsafe_reason(message, exception)
|
292
|
+
|
293
|
+
log_error "[Rollbar] Sending failsafe response due to #{exception_reason}"
|
294
|
+
|
295
|
+
failsafe_data = failsafe_initial_data(exception_reason)
|
296
|
+
|
297
|
+
failsafe_add_original_error_data(failsafe_data[:notifier], original_error)
|
273
298
|
|
274
299
|
failsafe_payload = {
|
275
|
-
'access_token' => configuration.access_token,
|
276
300
|
'data' => failsafe_data
|
277
301
|
}
|
278
302
|
|
@@ -281,16 +305,69 @@ module Rollbar
|
|
281
305
|
:notifier => self,
|
282
306
|
:configuration => configuration,
|
283
307
|
:logger => logger)
|
284
|
-
|
285
|
-
|
308
|
+
|
309
|
+
process_item(item)
|
310
|
+
log_and_return_item_data(item)
|
311
|
+
rescue StandardError => e
|
286
312
|
log_error "[Rollbar] Error sending failsafe : #{e}"
|
287
313
|
end
|
288
314
|
|
289
315
|
failsafe_payload
|
290
316
|
end
|
291
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
|
+
diagnostic[:original_message] = original_error[:message].truncate(FAILSAFE_STRING_LENGTH) if original_error[:message]
|
332
|
+
|
333
|
+
rescue StandardError => e
|
334
|
+
diagnostic[:original_message] = "Failed: #{e.message}"
|
335
|
+
end
|
336
|
+
|
337
|
+
def add_original_error(diagnostic, original_error)
|
338
|
+
if original_error[:exception]
|
339
|
+
backtrace = original_error[:exception].backtrace
|
340
|
+
message = original_error[:exception].message
|
341
|
+
diagnostic[:original_error] = {
|
342
|
+
:message => message && message.truncate(FAILSAFE_STRING_LENGTH),
|
343
|
+
:stack => backtrace && backtrace.join(', ').truncate(FAILSAFE_STRING_LENGTH)
|
344
|
+
}
|
345
|
+
end
|
346
|
+
|
347
|
+
rescue StandardError => e
|
348
|
+
diagnostic[:original_error] = "Failed: #{e.message}"
|
349
|
+
end
|
350
|
+
|
351
|
+
def add_configured_options(payload_notifier, original_error)
|
352
|
+
if original_error[:configuration]
|
353
|
+
configured = original_error[:configuration].configured_options.configured
|
354
|
+
payload_notifier[:configured_options] = ::JSON.generate(configured).truncate(FAILSAFE_STRING_LENGTH)
|
355
|
+
end
|
356
|
+
|
357
|
+
rescue StandardError => e
|
358
|
+
payload_notifier[:configured_options] = "Failed: #{e.message}"
|
359
|
+
end
|
360
|
+
|
361
|
+
def add_original_host(diagnostic, original_error)
|
362
|
+
diagnostic[:original_host] = original_error[:host] if original_error[:host]
|
363
|
+
end
|
364
|
+
|
365
|
+
def add_original_uuid(diagnostic, original_error)
|
366
|
+
diagnostic[:original_uuid] = original_error[:uuid] if original_error[:uuid]
|
367
|
+
end
|
368
|
+
|
292
369
|
## Logging
|
293
|
-
%w
|
370
|
+
%w[debug info warn error].each do |level|
|
294
371
|
define_method(:"log_#{level}") do |message|
|
295
372
|
logger.send(level, message)
|
296
373
|
end
|
@@ -300,6 +377,30 @@ module Rollbar
|
|
300
377
|
@logger ||= LoggerProxy.new(configuration.logger)
|
301
378
|
end
|
302
379
|
|
380
|
+
def trace_with_bindings
|
381
|
+
@trace_with_bindings ||= TraceWithBindings.new
|
382
|
+
end
|
383
|
+
|
384
|
+
def exception_bindings
|
385
|
+
trace_with_bindings.exception_frames
|
386
|
+
end
|
387
|
+
|
388
|
+
def current_bindings
|
389
|
+
trace_with_bindings.frames
|
390
|
+
end
|
391
|
+
|
392
|
+
def enable_locals?
|
393
|
+
configuration.locals[:enabled] && [:app, :all].include?(configuration.send_extra_frame_data)
|
394
|
+
end
|
395
|
+
|
396
|
+
def enable_locals
|
397
|
+
trace_with_bindings.enable if enable_locals?
|
398
|
+
end
|
399
|
+
|
400
|
+
def disable_locals
|
401
|
+
trace_with_bindings.disable if enable_locals?
|
402
|
+
end
|
403
|
+
|
303
404
|
private
|
304
405
|
|
305
406
|
def use_exception_level_filters?(options)
|
@@ -326,7 +427,7 @@ module Rollbar
|
|
326
427
|
return 'ignored' if status == 'ignored'
|
327
428
|
rescue Rollbar::Ignore
|
328
429
|
raise
|
329
|
-
rescue => e
|
430
|
+
rescue StandardError => e
|
330
431
|
log_error("[Rollbar] Error calling the `before_process` hook: #{e}")
|
331
432
|
|
332
433
|
break
|
@@ -399,43 +500,52 @@ module Rollbar
|
|
399
500
|
|
400
501
|
return 'ignored' if item.ignored?
|
401
502
|
|
402
|
-
schedule_item(item)
|
503
|
+
schedule_item(item) if configuration.transmit
|
504
|
+
|
505
|
+
log_and_return_item_data(item)
|
506
|
+
end
|
403
507
|
|
508
|
+
def log_and_return_item_data(item)
|
404
509
|
data = item['data']
|
405
510
|
log_instance_link(data)
|
406
511
|
Rollbar.last_report = data
|
512
|
+
log_data(data) if configuration.log_payload
|
407
513
|
|
408
514
|
data
|
409
515
|
end
|
410
516
|
|
517
|
+
def log_data(data)
|
518
|
+
log_info "[Rollbar] Data: #{data}"
|
519
|
+
end
|
520
|
+
|
411
521
|
# Reports an internal error in the Rollbar library. This will be reported within the configured
|
412
522
|
# Rollbar project. We'll first attempt to provide a report including the exception traceback.
|
413
523
|
# If that fails, we'll fall back to a more static failsafe response.
|
414
|
-
def report_internal_error(exception)
|
524
|
+
def report_internal_error(exception, original_error = nil)
|
415
525
|
log_error '[Rollbar] Reporting internal error encountered while sending data to Rollbar.'
|
416
526
|
|
417
527
|
configuration.execute_hook(:on_report_internal_error, exception)
|
418
528
|
|
419
529
|
begin
|
420
530
|
item = build_item('error', nil, exception, { :internal => true }, nil)
|
421
|
-
rescue => e
|
422
|
-
send_failsafe('build_item in exception_data', e)
|
531
|
+
rescue StandardError => e
|
532
|
+
send_failsafe('build_item in exception_data', e, original_error)
|
423
533
|
log_error "[Rollbar] Exception: #{exception}"
|
424
534
|
return
|
425
535
|
end
|
426
536
|
|
427
537
|
begin
|
428
538
|
process_item(item)
|
429
|
-
rescue => e
|
430
|
-
send_failsafe('error in process_item', e)
|
539
|
+
rescue StandardError => e
|
540
|
+
send_failsafe('error in process_item', e, original_error)
|
431
541
|
log_error "[Rollbar] Item: #{item}"
|
432
542
|
return
|
433
543
|
end
|
434
544
|
|
435
545
|
begin
|
436
546
|
log_instance_link(item['data'])
|
437
|
-
rescue => e
|
438
|
-
send_failsafe('error logging instance link', e)
|
547
|
+
rescue StandardError => e
|
548
|
+
send_failsafe('error logging instance link', e, original_error)
|
439
549
|
log_error "[Rollbar] Item: #{item}"
|
440
550
|
return
|
441
551
|
end
|
@@ -464,14 +574,18 @@ module Rollbar
|
|
464
574
|
|
465
575
|
## Delivery functions
|
466
576
|
|
467
|
-
def
|
468
|
-
|
469
|
-
return unless body
|
577
|
+
def send_using_eventmachine(body)
|
578
|
+
uri = URI.parse(configuration.endpoint)
|
470
579
|
|
471
|
-
headers = { 'X-Rollbar-Access-Token' =>
|
580
|
+
headers = { 'X-Rollbar-Access-Token' => configuration.access_token }
|
472
581
|
options = http_proxy_for_em(uri)
|
473
582
|
req = EventMachine::HttpRequest.new(uri.to_s, options).post(:body => body, :head => headers)
|
474
583
|
|
584
|
+
eventmachine_callback(req)
|
585
|
+
eventmachine_errback(req)
|
586
|
+
end
|
587
|
+
|
588
|
+
def eventmachine_callback(req)
|
475
589
|
req.callback do
|
476
590
|
if req.response_header.status == 200
|
477
591
|
log_info '[Rollbar] Success'
|
@@ -480,7 +594,9 @@ module Rollbar
|
|
480
594
|
log_info "[Rollbar] Response: #{req.response}"
|
481
595
|
end
|
482
596
|
end
|
597
|
+
end
|
483
598
|
|
599
|
+
def eventmachine_errback(req)
|
484
600
|
req.errback do
|
485
601
|
log_warning "[Rollbar] Call to API failed, status code: #{req.response_header.status}"
|
486
602
|
log_info "[Rollbar] Error's response: #{req.response}"
|
@@ -493,14 +609,20 @@ module Rollbar
|
|
493
609
|
body = item.dump
|
494
610
|
return unless body
|
495
611
|
|
496
|
-
uri = URI.parse(configuration.endpoint)
|
497
|
-
|
498
612
|
if configuration.use_eventmachine
|
499
|
-
|
613
|
+
send_using_eventmachine(body)
|
500
614
|
return
|
501
615
|
end
|
502
616
|
|
503
|
-
|
617
|
+
send_body(body)
|
618
|
+
end
|
619
|
+
|
620
|
+
def send_body(body)
|
621
|
+
log_info '[Rollbar] Sending json'
|
622
|
+
|
623
|
+
uri = URI.parse(configuration.endpoint)
|
624
|
+
|
625
|
+
handle_response(do_post(uri, body, configuration.access_token))
|
504
626
|
end
|
505
627
|
|
506
628
|
def do_post(uri, body, access_token)
|
@@ -512,8 +634,6 @@ module Rollbar
|
|
512
634
|
|
513
635
|
if uri.scheme == 'https'
|
514
636
|
http.use_ssl = true
|
515
|
-
# This is needed to have 1.8.7 passing tests
|
516
|
-
http.ca_file = ENV['ROLLBAR_SSL_CERT_FILE'] if ENV.key?('ROLLBAR_SSL_CERT_FILE')
|
517
637
|
http.verify_mode = ssl_verify_mode
|
518
638
|
end
|
519
639
|
|
@@ -594,7 +714,7 @@ module Rollbar
|
|
594
714
|
end
|
595
715
|
|
596
716
|
def skip_retries?
|
597
|
-
Rollbar::LanguageSupport.
|
717
|
+
Rollbar::LanguageSupport.ruby_19?
|
598
718
|
end
|
599
719
|
|
600
720
|
def handle_response(response)
|
@@ -615,27 +735,24 @@ module Rollbar
|
|
615
735
|
end
|
616
736
|
end
|
617
737
|
|
618
|
-
def write_item(item)
|
619
|
-
if configuration.use_async
|
620
|
-
@file_semaphore.synchronize do
|
621
|
-
do_write_item(item)
|
622
|
-
end
|
623
|
-
else
|
624
|
-
do_write_item(item)
|
625
|
-
end
|
626
|
-
end
|
627
|
-
|
628
738
|
def do_write_item(item)
|
629
739
|
log_info '[Rollbar] Writing item to file'
|
630
740
|
|
631
741
|
body = item.dump
|
632
742
|
return unless body
|
633
743
|
|
744
|
+
file_name = if configuration.files_with_pid_name_enabled
|
745
|
+
configuration.filepath.gsub(EXTENSION_REGEXP, "_#{Process.pid}\\0")
|
746
|
+
else
|
747
|
+
configuration.filepath
|
748
|
+
end
|
749
|
+
|
634
750
|
begin
|
635
|
-
@file ||= File.open(
|
751
|
+
@file ||= File.open(file_name, 'a')
|
636
752
|
|
637
753
|
@file.puts(body)
|
638
754
|
@file.flush
|
755
|
+
update_file(@file, file_name)
|
639
756
|
|
640
757
|
log_info '[Rollbar] Success'
|
641
758
|
rescue IOError => e
|
@@ -643,6 +760,18 @@ module Rollbar
|
|
643
760
|
end
|
644
761
|
end
|
645
762
|
|
763
|
+
def update_file(file, file_name)
|
764
|
+
return unless configuration.files_processed_enabled
|
765
|
+
|
766
|
+
time_now = Time.now
|
767
|
+
return if configuration.files_processed_duration > time_now - file.birthtime && file.size < configuration.files_processed_size
|
768
|
+
|
769
|
+
new_file_name = file_name.gsub(EXTENSION_REGEXP, "_processed_#{time_now.to_i}\\0")
|
770
|
+
File.rename(file, new_file_name)
|
771
|
+
file.close
|
772
|
+
@file = File.open(file_name, 'a')
|
773
|
+
end
|
774
|
+
|
646
775
|
def failsafe_reason(message, exception)
|
647
776
|
body = ''
|
648
777
|
|
@@ -653,17 +782,17 @@ module Rollbar
|
|
653
782
|
|
654
783
|
exception_info = exception.class.name
|
655
784
|
# #to_s and #message defaults to class.to_s. Add message only if add valuable info.
|
656
|
-
exception_info += %
|
785
|
+
exception_info += %[: "#{exception.message}"] if exception.message != exception.class.to_s
|
657
786
|
exception_info += " in #{nearest_frame}" if nearest_frame
|
658
787
|
|
659
788
|
body += "#{exception_info}: #{message}"
|
660
|
-
rescue
|
789
|
+
rescue StandardError
|
661
790
|
log_error('[Rollbar] Error building failsafe exception message')
|
662
791
|
end
|
663
792
|
else
|
664
793
|
begin
|
665
794
|
body += message.to_s
|
666
|
-
rescue
|
795
|
+
rescue StandardError
|
667
796
|
log_error('[Rollbar] Error building failsafe message')
|
668
797
|
end
|
669
798
|
end
|
@@ -694,9 +823,12 @@ module Rollbar
|
|
694
823
|
end
|
695
824
|
|
696
825
|
def process_async_item(item)
|
826
|
+
# Send async payloads as JSON string when async_json_payload is set.
|
827
|
+
payload = configuration.async_json_payload ? item.dump : item.payload
|
828
|
+
|
697
829
|
configuration.async_handler ||= default_async_handler
|
698
|
-
configuration.async_handler.call(
|
699
|
-
rescue
|
830
|
+
configuration.async_handler.call(payload)
|
831
|
+
rescue StandardError
|
700
832
|
if configuration.failover_handlers.empty?
|
701
833
|
log_error '[Rollbar] Async handler failed, and there are no failover handlers configured. See the docs for "failover_handlers"'
|
702
834
|
return
|
@@ -713,7 +845,7 @@ module Rollbar
|
|
713
845
|
failover_handlers.each do |handler|
|
714
846
|
begin
|
715
847
|
handler.call(item.payload)
|
716
|
-
rescue
|
848
|
+
rescue StandardError
|
717
849
|
next unless handler == failover_handlers.last
|
718
850
|
|
719
851
|
log_error "[Rollbar] All failover handlers failed while processing item: #{Rollbar::JSON.dump(item.payload)}"
|
@@ -721,7 +853,7 @@ module Rollbar
|
|
721
853
|
end
|
722
854
|
end
|
723
855
|
|
724
|
-
|
856
|
+
alias log_warning log_warn
|
725
857
|
|
726
858
|
def log_instance_link(data)
|
727
859
|
return unless data[:uuid]
|
@@ -729,5 +861,9 @@ module Rollbar
|
|
729
861
|
uuid_url = Util.uuid_rollbar_url(data, configuration)
|
730
862
|
log_info "[Rollbar] Details: #{uuid_url} (only available if report was successful)"
|
731
863
|
end
|
864
|
+
|
865
|
+
def via_failsafe?(item)
|
866
|
+
item.payload.fetch('data', {}).fetch('failsafe', false)
|
867
|
+
end
|
732
868
|
end
|
733
869
|
end
|
data/lib/rollbar/plugin.rb
CHANGED
@@ -7,6 +7,8 @@ module Rollbar
|
|
7
7
|
attr_reader :name
|
8
8
|
attr_reader :dependencies
|
9
9
|
attr_reader :callables
|
10
|
+
attr_reader :revert_callables
|
11
|
+
attr_accessor :on_demand
|
10
12
|
attr_accessor :loaded
|
11
13
|
|
12
14
|
private :loaded=
|
@@ -15,31 +17,73 @@ module Rollbar
|
|
15
17
|
@name = name
|
16
18
|
@dependencies = []
|
17
19
|
@callables = []
|
20
|
+
@revert_callables = []
|
18
21
|
@loaded = false
|
22
|
+
@on_demand = false
|
23
|
+
end
|
24
|
+
|
25
|
+
def load_on_demand
|
26
|
+
@on_demand = true
|
19
27
|
end
|
20
28
|
|
21
29
|
def configuration
|
22
30
|
Rollbar.configuration
|
23
31
|
end
|
24
32
|
|
33
|
+
def load_scoped!(transparent = false)
|
34
|
+
if transparent
|
35
|
+
load! if load?
|
36
|
+
|
37
|
+
result = yield
|
38
|
+
|
39
|
+
unload! if loaded
|
40
|
+
else
|
41
|
+
return unless load?
|
42
|
+
|
43
|
+
load!
|
44
|
+
|
45
|
+
result = yield
|
46
|
+
|
47
|
+
unload!
|
48
|
+
end
|
49
|
+
|
50
|
+
result
|
51
|
+
end
|
52
|
+
|
25
53
|
def load!
|
26
54
|
return unless load?
|
27
55
|
|
28
56
|
begin
|
29
57
|
callables.each(&:call)
|
30
|
-
rescue => e
|
58
|
+
rescue StandardError => e
|
31
59
|
log_loading_error(e)
|
32
60
|
ensure
|
33
61
|
self.loaded = true
|
34
62
|
end
|
35
63
|
end
|
36
64
|
|
65
|
+
def unload!
|
66
|
+
return unless loaded
|
67
|
+
|
68
|
+
begin
|
69
|
+
revert_callables.each(&:call)
|
70
|
+
rescue StandardError => e
|
71
|
+
log_unloading_error(e)
|
72
|
+
ensure
|
73
|
+
self.loaded = false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
37
77
|
def execute(&block)
|
38
78
|
callables << block
|
39
79
|
end
|
40
80
|
|
41
|
-
def execute!
|
42
|
-
|
81
|
+
def execute!
|
82
|
+
yield if load?
|
83
|
+
end
|
84
|
+
|
85
|
+
def revert(&block)
|
86
|
+
revert_callables << block
|
43
87
|
end
|
44
88
|
|
45
89
|
private
|
@@ -61,7 +105,7 @@ module Rollbar
|
|
61
105
|
|
62
106
|
def load?
|
63
107
|
!loaded && dependencies_satisfy?
|
64
|
-
rescue => e
|
108
|
+
rescue StandardError => e
|
65
109
|
log_loading_error(e)
|
66
110
|
|
67
111
|
false
|
@@ -71,8 +115,12 @@ module Rollbar
|
|
71
115
|
dependencies.all?(&:call)
|
72
116
|
end
|
73
117
|
|
74
|
-
def log_loading_error(
|
75
|
-
Rollbar.log_error("Error trying to load plugin '#{name}': #{
|
118
|
+
def log_loading_error(error)
|
119
|
+
Rollbar.log_error("Error trying to load plugin '#{name}': #{error.class}, #{error.message}")
|
120
|
+
end
|
121
|
+
|
122
|
+
def log_unloading_error(error)
|
123
|
+
Rollbar.log_error("Error trying to unload plugin '#{name}': #{error.class}, #{error.message}")
|
76
124
|
end
|
77
125
|
end
|
78
126
|
end
|