rollbar 1.0.1 → 1.1.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/CHANGELOG.md +6 -0
- data/README.md +48 -4
- data/THANKS.md +2 -0
- data/lib/rollbar.rb +92 -52
- data/lib/rollbar/configuration.rb +17 -0
- data/lib/rollbar/delay/girl_friday.rb +26 -0
- data/lib/rollbar/delay/resque.rb +31 -0
- data/lib/rollbar/delay/thread.rb +13 -0
- data/lib/rollbar/middleware/sinatra.rb +27 -0
- data/lib/rollbar/request_data_extractor.rb +14 -14
- data/lib/rollbar/version.rb +1 -1
- data/rollbar.gemspec +2 -0
- data/spec/requests/home_spec.rb +7 -5
- data/spec/rollbar/configuration_spec.rb +24 -0
- data/spec/rollbar/delay/girl_friday_spec.rb +19 -0
- data/spec/rollbar/delay/resque_spec.rb +21 -0
- data/spec/rollbar/delay/thread_spec.rb +14 -0
- data/spec/rollbar/middleware/sinatra_spec.rb +88 -0
- data/spec/rollbar_spec.rb +135 -8
- data/spec/spec_helper.rb +1 -1
- data/spec/support/cause_exception.rb +1 -0
- metadata +46 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6ba9f625302b093e422f24c2c3a35a7e6388c099
|
|
4
|
+
data.tar.gz: ef53f6cd97ed94d5db499b77c496a81f6c6eb6f8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5752f3f6282c97ffce3142bd39089946eb79f0f7a9a864f9be56f74ec563ebc49b0839a92eb4388ef5d0445cc6f1fb80ae7ffc28860811e6884c5abf50257457
|
|
7
|
+
data.tar.gz: c00267db9b445b402c2a84b3b608a3b3c23c17371611467ed79a173a1b6eb45a02f2e6d496c2b8131da45750cccb14723c55d61810ed6c65a82f1fa97d41231b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
**1.1.0**
|
|
4
|
+
- New feature: `failover_handlers`. You can specify a list of async handlers, which will be tried in sequence upon failure. See [#135](https://github.com/rollbar/rollbar-gem/pull/135).
|
|
5
|
+
- Support nested exceptions for Ruby 2.1. See [#136](https://github.com/rollbar/rollbar-gem/pull/136)
|
|
6
|
+
- Fix handling of utf8 sequences in payload symbols. See [#131](https://github.com/rollbar/rollbar-gem/pull/131). Thanks [@kroky](https://github.com/kroky) for the fix and [@jondeandres](https://github.com/jondeandres) for reviewing.
|
|
7
|
+
- Fix logic bugs in assignments for `scrub_fields` and `scrub_headers`. See [#137](https://github.com/rollbar/rollbar-gem/pull/137)
|
|
8
|
+
|
|
3
9
|
**1.0.1**
|
|
4
10
|
- Use the payload's access token for the X-Rollbar-Access-Token header, instead of the configured access token. Fixes an issue where payloads would be reported into the wrong project when sent via Resque. See [#128](https://github.com/rollbar/rollbar-gem/pull/128). Thanks to [@jondeandres](https://github.com/jondeandres) for the fix.
|
|
5
11
|
|
data/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Ruby gem for reporting exceptions, errors, and log messages to [Rollbar](https:/
|
|
|
9
9
|
|
|
10
10
|
Add this line to your application's Gemfile:
|
|
11
11
|
|
|
12
|
-
gem 'rollbar', '~> 1.
|
|
12
|
+
gem 'rollbar', '~> 1.1.0'
|
|
13
13
|
|
|
14
14
|
And then execute:
|
|
15
15
|
|
|
@@ -239,7 +239,7 @@ config.delayed_job_enabled = false
|
|
|
239
239
|
|
|
240
240
|
## Asynchronous reporting
|
|
241
241
|
|
|
242
|
-
By default, all messages are reported synchronously. You can enable asynchronous reporting with [girl_friday](https://github.com/mperham/girl_friday)
|
|
242
|
+
By default, all messages are reported synchronously. You can enable asynchronous reporting with [girl_friday](https://github.com/mperham/girl_friday), [sucker_punch](https://github.com/brandonhilkert/sucker_punch), [Sidekiq](https://github.com/mperham/sidekiq), [Resque](https://github.com/resque/resque) or using threading.
|
|
243
243
|
|
|
244
244
|
### Using girl_friday
|
|
245
245
|
|
|
@@ -285,11 +285,40 @@ Start Sidekiq from the root directory of your Rails app and declare the name of
|
|
|
285
285
|
$ bundle exec sidekiq -q rollbar
|
|
286
286
|
```
|
|
287
287
|
|
|
288
|
+
### Using Resque
|
|
289
|
+
|
|
290
|
+
Add the following in ```config/initializers/rollbar.rb```:
|
|
291
|
+
|
|
292
|
+
```ruby
|
|
293
|
+
config.use_resque
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
You can also supply a custom Resque queue:
|
|
297
|
+
|
|
298
|
+
```ruby
|
|
299
|
+
config.use_resque :queue => 'my_queue'
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Now you can just start a new Resque worker processing jobs in that queue:
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
$ QUEUE=my_queue bundle exec resque:work
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Using threading
|
|
309
|
+
|
|
310
|
+
Add the following in ```config/initializers/rollbar.rb```:
|
|
311
|
+
|
|
312
|
+
```ruby
|
|
313
|
+
config.use_thread
|
|
314
|
+
```
|
|
315
|
+
|
|
288
316
|
### Using another handler
|
|
289
317
|
|
|
290
|
-
You can supply your own handler using ```config.async_handler```. The handler should schedule the payload for later processing (i.e. with a delayed_job, in a resque queue, etc.) and should itself return immediately. For example:
|
|
318
|
+
You can supply your own handler using ```config.async_handler```. The object to set for `async_handler` should respond to `#call` and receive the payload. The handler should schedule the payload for later processing (i.e. with a delayed_job, in a resque queue, etc.) and should itself return immediately. For example:
|
|
291
319
|
|
|
292
320
|
```ruby
|
|
321
|
+
config.use_async
|
|
293
322
|
config.async_handler = Proc.new { |payload|
|
|
294
323
|
Thread.new { Rollbar.process_payload(payload) }
|
|
295
324
|
}
|
|
@@ -297,6 +326,21 @@ config.async_handler = Proc.new { |payload|
|
|
|
297
326
|
|
|
298
327
|
Make sure you pass ```payload``` to ```Rollbar.process_payload``` in your own implementation.
|
|
299
328
|
|
|
329
|
+
## Failover handlers
|
|
330
|
+
|
|
331
|
+
If you are using `async_handler` to process asynchronous the error it's possible that the handler fails before it calls `Rollbar.process_payload`. For example, for the Resque handler, the Redis connection could fail so the job is finally not processed.
|
|
332
|
+
|
|
333
|
+
To ensure that the error is sent you can define a chain of failover handlers that Rollbar will use to send the payload in case that the primary handler fails. The failover handlers, as for `async_handler`, are just objects responding to `#call`.
|
|
334
|
+
|
|
335
|
+
To configure the failover handlers you can add the following:
|
|
336
|
+
|
|
337
|
+
```ruby
|
|
338
|
+
config.use_resque
|
|
339
|
+
config.failover_handlers = [Rollbar::Delay::GirlFriday, Rollbar::Delay::Thread]
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
With the configuration above Resque will be your primary asynchronous handler but if it fails queueing the job Rollbar will use GirlFriday at first, and just a thread in case that GirlFriday fails too.
|
|
343
|
+
|
|
300
344
|
## Using with rollbar-agent
|
|
301
345
|
|
|
302
346
|
For even more asynchrony, you can configure the gem to write to a file instead of sending the payload to Rollbar servers directly. [rollbar-agent](https://github.com/rollbar/rollbar-agent) can then be hooked up to this file to actually send the payload across. To enable, add the following in ```config/initializers/rollbar.rb```:
|
|
@@ -376,7 +420,7 @@ If you're using [Goalie](https://github.com/obvio171/goalie) for custom error pa
|
|
|
376
420
|
|
|
377
421
|
## Using with Resque
|
|
378
422
|
|
|
379
|
-
Check out [resque-rollbar](https://github.com/
|
|
423
|
+
Check out [resque-rollbar](https://github.com/dimko/resque-rollbar) for using Rollbar as a failure backend for Resque.
|
|
380
424
|
|
|
381
425
|
|
|
382
426
|
## Using with Zeus
|
data/THANKS.md
CHANGED
|
@@ -18,9 +18,11 @@ Huge thanks to the following contributors (by github username). For the most up-
|
|
|
18
18
|
- [ixti](https://github.com/ixti)
|
|
19
19
|
- [jeremyvdw](https://github.com/jeremyvdw)
|
|
20
20
|
- [johnknott](https://github.com/johnknott)
|
|
21
|
+
- [jondeandres](https://github.com/jondeandres)
|
|
21
22
|
- [JoshuaOSHickman](https://github.com/JoshuaOSHickman)
|
|
22
23
|
- [juggler](https://github.com/juggler)
|
|
23
24
|
- [kavu](https://github.com/kavu)
|
|
25
|
+
- [kroky](https://github.com/kroky)
|
|
24
26
|
- [lanej](https://github.com/lanej)
|
|
25
27
|
- [magnolia-fan](https://github.com/magnolia-fan)
|
|
26
28
|
- [mauricio](https://github.com/mauricio)
|
data/lib/rollbar.rb
CHANGED
|
@@ -16,6 +16,8 @@ require 'rollbar/exception_reporter'
|
|
|
16
16
|
require 'rollbar/active_record_extension' if defined?(ActiveRecord)
|
|
17
17
|
require 'rollbar/util'
|
|
18
18
|
require 'rollbar/railtie' if defined?(Rails)
|
|
19
|
+
require 'rollbar/delay/girl_friday'
|
|
20
|
+
require 'rollbar/delay/thread'
|
|
19
21
|
|
|
20
22
|
unless ''.respond_to? :encode
|
|
21
23
|
require 'iconv'
|
|
@@ -28,6 +30,8 @@ module Rollbar
|
|
|
28
30
|
attr_writer :configuration
|
|
29
31
|
attr_accessor :last_report
|
|
30
32
|
|
|
33
|
+
@file_semaphore = Mutex.new
|
|
34
|
+
|
|
31
35
|
# Similar to configure below, but used only internally within the gem
|
|
32
36
|
# to configure it without initializing any of the third party hooks
|
|
33
37
|
def preconfigure
|
|
@@ -46,9 +50,8 @@ module Rollbar
|
|
|
46
50
|
# end
|
|
47
51
|
def configure
|
|
48
52
|
# if configuration.enabled has not been set yet (is still 'nil'), set to true.
|
|
49
|
-
if configuration.enabled.nil?
|
|
50
|
-
|
|
51
|
-
end
|
|
53
|
+
configuration.enabled = true if configuration.enabled.nil?
|
|
54
|
+
|
|
52
55
|
yield(configuration)
|
|
53
56
|
|
|
54
57
|
require_hooks
|
|
@@ -225,6 +228,7 @@ module Rollbar
|
|
|
225
228
|
puts "[Rollbar] #{message}"
|
|
226
229
|
end
|
|
227
230
|
end
|
|
231
|
+
|
|
228
232
|
def log_debug(message)
|
|
229
233
|
begin
|
|
230
234
|
logger.debug message
|
|
@@ -234,6 +238,12 @@ module Rollbar
|
|
|
234
238
|
end
|
|
235
239
|
end
|
|
236
240
|
|
|
241
|
+
def default_async_handler
|
|
242
|
+
return Rollbar::Delay::GirlFriday if defined?(GirlFriday)
|
|
243
|
+
|
|
244
|
+
Rollbar::Delay::Thread
|
|
245
|
+
end
|
|
246
|
+
|
|
237
247
|
private
|
|
238
248
|
|
|
239
249
|
def attach_request_data(payload, request_data)
|
|
@@ -307,6 +317,37 @@ module Rollbar
|
|
|
307
317
|
|
|
308
318
|
data[:level] = force_level if force_level
|
|
309
319
|
|
|
320
|
+
traces = trace_chain(exception)
|
|
321
|
+
|
|
322
|
+
if traces.size > 1
|
|
323
|
+
body = {
|
|
324
|
+
:trace_chain => traces
|
|
325
|
+
}
|
|
326
|
+
elsif traces.size == 1
|
|
327
|
+
body = {
|
|
328
|
+
:trace => traces[0]
|
|
329
|
+
}
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
data[:body] = body
|
|
333
|
+
|
|
334
|
+
data[:server] = server_data
|
|
335
|
+
|
|
336
|
+
data
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def trace_chain(exception)
|
|
340
|
+
traces = [trace_data(exception)]
|
|
341
|
+
|
|
342
|
+
while exception.respond_to?(:cause) && (cause = exception.cause)
|
|
343
|
+
traces << trace_data(cause)
|
|
344
|
+
exception = cause
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
traces
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
def trace_data(exception)
|
|
310
351
|
# parse backtrace
|
|
311
352
|
if exception.backtrace.respond_to?( :map )
|
|
312
353
|
frames = exception.backtrace.map { |frame|
|
|
@@ -324,19 +365,13 @@ module Rollbar
|
|
|
324
365
|
frames = []
|
|
325
366
|
end
|
|
326
367
|
|
|
327
|
-
|
|
328
|
-
:
|
|
329
|
-
|
|
330
|
-
:
|
|
331
|
-
|
|
332
|
-
:message => exception.message
|
|
333
|
-
}
|
|
368
|
+
{
|
|
369
|
+
:frames => frames,
|
|
370
|
+
:exception => {
|
|
371
|
+
:class => exception.class.name,
|
|
372
|
+
:message => exception.message
|
|
334
373
|
}
|
|
335
374
|
}
|
|
336
|
-
|
|
337
|
-
data[:server] = server_data
|
|
338
|
-
|
|
339
|
-
data
|
|
340
375
|
end
|
|
341
376
|
|
|
342
377
|
def logger
|
|
@@ -425,29 +460,45 @@ module Rollbar
|
|
|
425
460
|
end
|
|
426
461
|
|
|
427
462
|
def schedule_payload(payload)
|
|
428
|
-
if payload.nil?
|
|
429
|
-
return
|
|
430
|
-
end
|
|
463
|
+
return if payload.nil?
|
|
431
464
|
|
|
432
465
|
log_info '[Rollbar] Scheduling payload'
|
|
433
466
|
|
|
434
467
|
if configuration.use_async
|
|
435
|
-
|
|
436
|
-
configuration.async_handler = method(:default_async_handler)
|
|
437
|
-
end
|
|
438
|
-
|
|
439
|
-
if configuration.write_to_file
|
|
440
|
-
unless @file_semaphore
|
|
441
|
-
@file_semaphore = Mutex.new
|
|
442
|
-
end
|
|
443
|
-
end
|
|
444
|
-
|
|
445
|
-
configuration.async_handler.call(payload)
|
|
468
|
+
process_async_payload(payload)
|
|
446
469
|
else
|
|
447
470
|
process_payload(payload)
|
|
448
471
|
end
|
|
449
472
|
end
|
|
450
473
|
|
|
474
|
+
def process_async_payload(payload)
|
|
475
|
+
configuration.async_handler ||= default_async_handler
|
|
476
|
+
configuration.async_handler.call(payload)
|
|
477
|
+
rescue
|
|
478
|
+
if configuration.failover_handlers.empty?
|
|
479
|
+
log_error '[Rollbar] Async handler failed, and there are no failover handlers configured. See the docs for "failover_handlers"'
|
|
480
|
+
return
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
async_failover(payload)
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
def async_failover(payload)
|
|
487
|
+
log_warning '[Rollbar] Primary async handler failed. Trying failovers...'
|
|
488
|
+
|
|
489
|
+
failover_handlers = configuration.failover_handlers
|
|
490
|
+
|
|
491
|
+
failover_handlers.each do |handler|
|
|
492
|
+
begin
|
|
493
|
+
handler.call(payload)
|
|
494
|
+
rescue
|
|
495
|
+
next unless handler == failover_handlers.last
|
|
496
|
+
|
|
497
|
+
log_error "[Rollbar] All failover handlers failed while processing payload: #{MultiJson.dump(payload)}"
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
|
|
451
502
|
def build_payload(data)
|
|
452
503
|
payload = {
|
|
453
504
|
'access_token' => configuration.access_token,
|
|
@@ -534,21 +585,6 @@ module Rollbar
|
|
|
534
585
|
data
|
|
535
586
|
end
|
|
536
587
|
|
|
537
|
-
def default_async_handler(payload)
|
|
538
|
-
if defined?(GirlFriday)
|
|
539
|
-
unless @queue
|
|
540
|
-
@queue = GirlFriday::WorkQueue.new(nil, :size => 5) do |payload|
|
|
541
|
-
process_payload(payload)
|
|
542
|
-
end
|
|
543
|
-
end
|
|
544
|
-
|
|
545
|
-
@queue.push(payload)
|
|
546
|
-
else
|
|
547
|
-
log_warning '[Rollbar] girl_friday not found to handle async call, falling back to Thread'
|
|
548
|
-
Thread.new { process_payload(payload) }
|
|
549
|
-
end
|
|
550
|
-
end
|
|
551
|
-
|
|
552
588
|
# Reports an internal error in the Rollbar library. This will be reported within the configured
|
|
553
589
|
# Rollbar project. We'll first attempt to provide a report including the exception traceback.
|
|
554
590
|
# If that fails, we'll fall back to a more static failsafe response.
|
|
@@ -617,19 +653,23 @@ module Rollbar
|
|
|
617
653
|
end
|
|
618
654
|
|
|
619
655
|
def enforce_valid_utf8(payload)
|
|
620
|
-
normalizer =
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
656
|
+
normalizer = lambda do |object|
|
|
657
|
+
is_symbol = object.is_a?(Symbol)
|
|
658
|
+
|
|
659
|
+
return object unless object == object.to_s || is_symbol
|
|
660
|
+
|
|
661
|
+
value = object.to_s
|
|
662
|
+
|
|
663
|
+
if value.respond_to? :encode
|
|
664
|
+
encoded_value = value.encode('UTF-8', 'binary', :invalid => :replace, :undef => :replace, :replace => '')
|
|
627
665
|
else
|
|
628
|
-
value
|
|
666
|
+
encoded_value = ::Iconv.conv('UTF-8//IGNORE', 'UTF-8', value)
|
|
629
667
|
end
|
|
668
|
+
|
|
669
|
+
is_symbol ? encoded_value.to_sym : encoded_value
|
|
630
670
|
end
|
|
631
671
|
|
|
632
|
-
Rollbar::Util
|
|
672
|
+
Rollbar::Util.iterate_and_update(payload, normalizer)
|
|
633
673
|
end
|
|
634
674
|
|
|
635
675
|
def truncate_payload(payload, byte_threshold)
|
|
@@ -15,6 +15,7 @@ module Rollbar
|
|
|
15
15
|
attr_accessor :endpoint
|
|
16
16
|
attr_accessor :environment
|
|
17
17
|
attr_accessor :exception_level_filters
|
|
18
|
+
attr_accessor :failover_handlers
|
|
18
19
|
attr_accessor :filepath
|
|
19
20
|
attr_accessor :framework
|
|
20
21
|
attr_accessor :ignored_person_ids
|
|
@@ -53,6 +54,7 @@ module Rollbar
|
|
|
53
54
|
'AbstractController::ActionNotFound' => 'warning',
|
|
54
55
|
'ActionController::RoutingError' => 'warning'
|
|
55
56
|
}
|
|
57
|
+
@failover_handlers = []
|
|
56
58
|
@framework = 'Plain'
|
|
57
59
|
@ignored_person_ids = []
|
|
58
60
|
@person_method = 'current_user'
|
|
@@ -77,6 +79,15 @@ module Rollbar
|
|
|
77
79
|
@async_handler = Rollbar::Delay::Sidekiq.new(options)
|
|
78
80
|
end
|
|
79
81
|
|
|
82
|
+
def use_resque(options = {})
|
|
83
|
+
require 'rollbar/delay/resque' if defined?(Resque)
|
|
84
|
+
|
|
85
|
+
Rollbar::Delay::Resque::Job.queue = options[:queue] if options[:queue]
|
|
86
|
+
|
|
87
|
+
@use_async = true
|
|
88
|
+
@async_handler = Rollbar::Delay::Resque
|
|
89
|
+
end
|
|
90
|
+
|
|
80
91
|
def use_sidekiq=(value)
|
|
81
92
|
deprecation_message = "#use_sidekiq=(value) has been deprecated in favor of #use_sidekiq(options = {}). Please update your rollbar configuration."
|
|
82
93
|
defined?(ActiveSupport) ? ActiveSupport::Deprecation.warn(deprecation_message) : puts(deprecation_message)
|
|
@@ -84,6 +95,12 @@ module Rollbar
|
|
|
84
95
|
value.is_a?(Hash) ? use_sidekiq(value) : use_sidekiq
|
|
85
96
|
end
|
|
86
97
|
|
|
98
|
+
def use_thread
|
|
99
|
+
require 'rollbar/delay/thread'
|
|
100
|
+
@use_async = true
|
|
101
|
+
@async_handler = Rollbar::Delay::Thread
|
|
102
|
+
end
|
|
103
|
+
|
|
87
104
|
def use_sucker_punch
|
|
88
105
|
require 'rollbar/delay/sucker_punch' if defined?(SuckerPunch)
|
|
89
106
|
@use_async = true
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Rollbar
|
|
2
|
+
module Delay
|
|
3
|
+
class GirlFriday
|
|
4
|
+
|
|
5
|
+
class << self
|
|
6
|
+
attr_accessor :queue
|
|
7
|
+
|
|
8
|
+
def call(payload)
|
|
9
|
+
new.call(payload)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def queue_class
|
|
14
|
+
::GirlFriday::WorkQueue
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def call(payload)
|
|
18
|
+
self.class.queue = queue_class.new(nil, :size => 5) do |payload|
|
|
19
|
+
Rollbar.process_payload(payload)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
self.class.queue.push(payload)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'resque'
|
|
2
|
+
|
|
3
|
+
module Rollbar
|
|
4
|
+
module Delay
|
|
5
|
+
class Resque
|
|
6
|
+
def self.call(payload)
|
|
7
|
+
new.call(payload)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call(payload)
|
|
11
|
+
::Resque.enqueue(Job, payload)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class Job
|
|
15
|
+
class << self
|
|
16
|
+
attr_accessor :queue
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
self.queue = :default
|
|
20
|
+
|
|
21
|
+
def self.perform(payload)
|
|
22
|
+
new.perform(payload)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def perform(payload)
|
|
26
|
+
Rollbar.process_payload(payload)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'rollbar'
|
|
2
|
+
require 'rollbar/exception_reporter'
|
|
3
|
+
|
|
4
|
+
module Rollbar
|
|
5
|
+
module Middleware
|
|
6
|
+
class Sinatra
|
|
7
|
+
include ::Rollbar::ExceptionReporter
|
|
8
|
+
|
|
9
|
+
def initialize(app)
|
|
10
|
+
@app = app
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def call(env)
|
|
14
|
+
response = @app.call(env)
|
|
15
|
+
report_exception_to_rollbar(env, framework_error(env)) if framework_error(env)
|
|
16
|
+
response
|
|
17
|
+
rescue ::Exception => exception
|
|
18
|
+
report_exception_to_rollbar(env, exception)
|
|
19
|
+
raise
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def framework_error(env)
|
|
23
|
+
env['sinatra.error']
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -12,13 +12,13 @@ module Rollbar
|
|
|
12
12
|
controller = env['action_controller.instance']
|
|
13
13
|
person_data = controller.rollbar_person_data rescue {}
|
|
14
14
|
end
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
person_data
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def extract_request_data_from_rack(env)
|
|
20
20
|
rack_req = Rack::Request.new(env)
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
sensitive_params = sensitive_params_list(env)
|
|
23
23
|
request_params = rollbar_filtered_params(sensitive_params, rollbar_request_params(env))
|
|
24
24
|
get_params = rollbar_filtered_params(sensitive_params, rollbar_get_params(rack_req))
|
|
@@ -26,9 +26,9 @@ module Rollbar
|
|
|
26
26
|
cookies = rollbar_filtered_params(sensitive_params, rollbar_request_cookies(rack_req))
|
|
27
27
|
session = rollbar_filtered_params(sensitive_params, env['rack.session.options'])
|
|
28
28
|
route_params = rollbar_filtered_params(sensitive_params, rollbar_route_params(env))
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
params = request_params.merge(get_params).merge(post_params)
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
data = {
|
|
33
33
|
:params => params,
|
|
34
34
|
:url => rollbar_url(env),
|
|
@@ -39,11 +39,11 @@ module Rollbar
|
|
|
39
39
|
:method => rollbar_request_method(env),
|
|
40
40
|
:route => route_params,
|
|
41
41
|
}
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
if env["action_dispatch.request_id"]
|
|
44
44
|
data[:request_id] = env["action_dispatch.request_id"]
|
|
45
45
|
end
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
data
|
|
48
48
|
end
|
|
49
49
|
|
|
@@ -68,13 +68,13 @@ module Rollbar
|
|
|
68
68
|
|
|
69
69
|
def rollbar_url(env)
|
|
70
70
|
scheme = env['HTTP_X_FORWARDED_PROTO'] || env['rack.url_scheme']
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
host = env['HTTP_X_FORWARDED_HOST'] || env['HTTP_HOST'] || env['SERVER_NAME']
|
|
73
73
|
path = env['ORIGINAL_FULLPATH'] || env['REQUEST_URI']
|
|
74
74
|
unless path.nil? || path.empty?
|
|
75
75
|
path = '/' + path.to_s if path.to_s.slice(0, 1) != '/'
|
|
76
76
|
end
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
port = env['HTTP_X_FORWARDED_PORT']
|
|
79
79
|
if port && !(scheme.downcase == 'http' && port.to_i == 80) && \
|
|
80
80
|
!(scheme.downcase == 'https' && port.to_i == 443) && \
|
|
@@ -88,7 +88,7 @@ module Rollbar
|
|
|
88
88
|
def rollbar_user_ip(env)
|
|
89
89
|
(env['action_dispatch.remote_ip'] || env['HTTP_X_REAL_IP'] || env['HTTP_X_FORWARDED_FOR'] || env['REMOTE_ADDR']).to_s
|
|
90
90
|
end
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
def rollbar_get_params(rack_req)
|
|
93
93
|
rack_req.GET
|
|
94
94
|
rescue
|
|
@@ -104,7 +104,7 @@ module Rollbar
|
|
|
104
104
|
def rollbar_request_params(env)
|
|
105
105
|
env['action_dispatch.request.parameters'] || {}
|
|
106
106
|
end
|
|
107
|
-
|
|
107
|
+
|
|
108
108
|
def rollbar_route_params(env)
|
|
109
109
|
begin
|
|
110
110
|
route = ::Rails.application.routes.recognize_path(env['PATH_INFO'])
|
|
@@ -117,7 +117,7 @@ module Rollbar
|
|
|
117
117
|
{}
|
|
118
118
|
end
|
|
119
119
|
end
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
def rollbar_request_cookies(rack_req)
|
|
122
122
|
rack_req.cookies
|
|
123
123
|
rescue
|
|
@@ -126,7 +126,7 @@ module Rollbar
|
|
|
126
126
|
|
|
127
127
|
def rollbar_filtered_params(sensitive_params, params)
|
|
128
128
|
@sensitive_params_regexp ||= Regexp.new(sensitive_params.map{ |val| Regexp.escape(val.to_s).to_s }.join('|'), true)
|
|
129
|
-
|
|
129
|
+
|
|
130
130
|
if params.nil?
|
|
131
131
|
{}
|
|
132
132
|
else
|
|
@@ -152,11 +152,11 @@ module Rollbar
|
|
|
152
152
|
end
|
|
153
153
|
|
|
154
154
|
def sensitive_params_list(env)
|
|
155
|
-
Rollbar.configuration.scrub_fields
|
|
155
|
+
Array(Rollbar.configuration.scrub_fields) | Array(env['action_dispatch.parameter_filter'])
|
|
156
156
|
end
|
|
157
157
|
|
|
158
158
|
def sensitive_headers_list
|
|
159
|
-
Rollbar.configuration.scrub_headers
|
|
159
|
+
Rollbar.configuration.scrub_headers || []
|
|
160
160
|
end
|
|
161
161
|
|
|
162
162
|
def rollbar_scrubbed(value)
|
data/lib/rollbar/version.rb
CHANGED
data/rollbar.gemspec
CHANGED
|
@@ -24,4 +24,6 @@ Gem::Specification.new do |gem|
|
|
|
24
24
|
gem.add_development_dependency 'sucker_punch', '>= 1.0.0' if RUBY_VERSION != '1.8.7'
|
|
25
25
|
gem.add_development_dependency 'sidekiq', '>= 2.13.0' if RUBY_VERSION != '1.8.7'
|
|
26
26
|
gem.add_development_dependency 'genspec', '>= 0.2.7'
|
|
27
|
+
gem.add_development_dependency 'sinatra'
|
|
28
|
+
gem.add_development_dependency 'resque'
|
|
27
29
|
end
|
data/spec/requests/home_spec.rb
CHANGED
|
@@ -22,7 +22,7 @@ describe HomeController do
|
|
|
22
22
|
expect{ get 'current_user', nil, :cookie => '8%B' }.to raise_exception
|
|
23
23
|
|
|
24
24
|
Rollbar.last_report.should_not be_nil
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
exception_info = Rollbar.last_report[:body][:trace][:exception]
|
|
27
27
|
exception_info[:class].should == 'ArgumentError'
|
|
28
28
|
exception_info[:message].should == 'invalid %-encoding (8%B)'
|
|
@@ -44,11 +44,13 @@ describe HomeController do
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
it "should report uncaught exceptions" do
|
|
47
|
-
expect{ get 'current_user' }.to raise_exception
|
|
47
|
+
expect { get 'current_user' }.to raise_exception
|
|
48
|
+
|
|
49
|
+
body = Rollbar.last_report[:body]
|
|
50
|
+
trace = body[:trace] && body[:trace] || body[:trace_chain][0]
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
# exception_info[:message].should == 'undefined method `-\' for "1":String'
|
|
52
|
+
trace[:exception][:class].should == 'NoMethodError'
|
|
53
|
+
trace[:exception][:message].should == 'undefined method `-\' for "1":String'
|
|
52
54
|
end
|
|
53
55
|
end
|
|
54
56
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'rollbar/configuration'
|
|
3
|
+
|
|
4
|
+
describe Rollbar::Configuration do
|
|
5
|
+
|
|
6
|
+
describe '#use_thread' do
|
|
7
|
+
it 'enables async and sets a Thread as handler' do
|
|
8
|
+
subject.use_thread
|
|
9
|
+
|
|
10
|
+
expect(subject.use_async).to be_eql(true)
|
|
11
|
+
expect(subject.async_handler).to be_eql(Rollbar::Delay::Thread)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe '#use_resque' do
|
|
16
|
+
it 'enables async and sets Resque as the handler' do
|
|
17
|
+
require 'resque'
|
|
18
|
+
subject.use_resque(:queue => 'errors')
|
|
19
|
+
|
|
20
|
+
expect(subject.use_async).to be_eql(true)
|
|
21
|
+
expect(subject.async_handler).to be_eql(Rollbar::Delay::Resque)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
# require girl_friday in the test instead in the implementation
|
|
4
|
+
# just to let the user decide to load it or not
|
|
5
|
+
require 'girl_friday'
|
|
6
|
+
require 'rollbar/delay/girl_friday'
|
|
7
|
+
|
|
8
|
+
describe Rollbar::Delay::GirlFriday do
|
|
9
|
+
describe '.call' do
|
|
10
|
+
let(:payload) do
|
|
11
|
+
{ :key => 'value' }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'push the payload into the queue' do
|
|
15
|
+
expect_any_instance_of(::GirlFriday::WorkQueue).to receive(:push).with(payload)
|
|
16
|
+
described_class.call(payload)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'rollbar/delay/resque'
|
|
3
|
+
|
|
4
|
+
describe Rollbar::Delay::Resque do
|
|
5
|
+
describe '.call' do
|
|
6
|
+
let(:payload) do
|
|
7
|
+
{ :key => 'value' }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
before do
|
|
11
|
+
allow(Resque).to receive(:inline?).and_return(true)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'process the payload' do
|
|
15
|
+
loaded_hash = MultiJson.load(MultiJson.dump(payload))
|
|
16
|
+
|
|
17
|
+
expect(Rollbar).to receive(:process_payload).with(loaded_hash)
|
|
18
|
+
described_class.call(payload)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Rollbar::Delay::Thread do
|
|
4
|
+
describe '.call' do
|
|
5
|
+
let(:payload) { { :key => 'value' } }
|
|
6
|
+
|
|
7
|
+
it 'process the payload in a new thread' do
|
|
8
|
+
expect(Rollbar).to receive(:process_payload).with(payload)
|
|
9
|
+
|
|
10
|
+
th = described_class.call(payload)
|
|
11
|
+
th.join
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'rollbar/middleware/sinatra'
|
|
3
|
+
require 'sinatra/base'
|
|
4
|
+
require 'rack/test'
|
|
5
|
+
|
|
6
|
+
class SinatraDummy < Sinatra::Base
|
|
7
|
+
class DummyError < StandardError; end
|
|
8
|
+
|
|
9
|
+
use Rollbar::Middleware::Sinatra
|
|
10
|
+
|
|
11
|
+
get '/foo' do
|
|
12
|
+
raise DummyError.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
get '/bar' do
|
|
16
|
+
'this will not crash'
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe Rollbar::Middleware::Sinatra do
|
|
21
|
+
include Rack::Test::Methods
|
|
22
|
+
|
|
23
|
+
def app
|
|
24
|
+
SinatraDummy
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
let(:expected_report_args) do
|
|
28
|
+
[exception, kind_of(Hash), kind_of(Hash)]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe '#call' do
|
|
32
|
+
context 'for a crashing endpoint' do
|
|
33
|
+
# this is the default for test mode in Sinatra
|
|
34
|
+
context 'with raise_errors? == true' do
|
|
35
|
+
let(:exception) { kind_of(SinatraDummy::DummyError) }
|
|
36
|
+
|
|
37
|
+
before do
|
|
38
|
+
allow(app.settings).to receive(:raise_errors?).and_return(true)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'reports the error to Rollbar API and raises error' do
|
|
42
|
+
expect(Rollbar).to receive(:report_exception).with(*expected_report_args)
|
|
43
|
+
|
|
44
|
+
expect do
|
|
45
|
+
get '/foo'
|
|
46
|
+
end.to raise_error(SinatraDummy::DummyError)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context 'with raise_errors? == false' do
|
|
51
|
+
let(:exception) { kind_of(SinatraDummy::DummyError) }
|
|
52
|
+
|
|
53
|
+
before do
|
|
54
|
+
allow(app.settings).to receive(:raise_errors?).and_return(false)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'reports the error to Rollbar, but nothing is raised' do
|
|
58
|
+
expect(Rollbar).to receive(:report_exception).with(*expected_report_args)
|
|
59
|
+
get '/foo'
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
context 'for a NOT crashing endpoint' do
|
|
65
|
+
it 'doesnt report any error to Rollbar API' do
|
|
66
|
+
expect(Rollbar).not_to receive(:report_exception)
|
|
67
|
+
get '/bar'
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context 'if the middleware itself fails' do
|
|
72
|
+
let(:exception) { Exception.new }
|
|
73
|
+
|
|
74
|
+
before do
|
|
75
|
+
allow_any_instance_of(described_class).to receive(:framework_error).and_raise(exception)
|
|
76
|
+
allow(app.settings).to receive(:raise_errors?).and_return(false)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'reports the report error' do
|
|
80
|
+
expect(Rollbar).to receive(:report_exception).with(*expected_report_args)
|
|
81
|
+
|
|
82
|
+
expect do
|
|
83
|
+
get '/foo'
|
|
84
|
+
end.to raise_error(exception)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
data/spec/rollbar_spec.rb
CHANGED
|
@@ -12,6 +12,7 @@ rescue LoadError
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
describe Rollbar do
|
|
15
|
+
let(:configuration) { Rollbar.configuration }
|
|
15
16
|
|
|
16
17
|
describe '.report_exception' do
|
|
17
18
|
before(:each) do
|
|
@@ -443,14 +444,14 @@ describe Rollbar do
|
|
|
443
444
|
|
|
444
445
|
Rollbar.configure do |config|
|
|
445
446
|
config.use_async = true
|
|
446
|
-
GirlFriday::WorkQueue
|
|
447
|
+
GirlFriday::WorkQueue.immediate!
|
|
447
448
|
end
|
|
448
449
|
|
|
449
450
|
Rollbar.report_exception(@exception)
|
|
450
451
|
|
|
451
452
|
Rollbar.configure do |config|
|
|
452
453
|
config.use_async = false
|
|
453
|
-
GirlFriday::WorkQueue
|
|
454
|
+
GirlFriday::WorkQueue.queue!
|
|
454
455
|
end
|
|
455
456
|
end
|
|
456
457
|
|
|
@@ -471,7 +472,7 @@ describe Rollbar do
|
|
|
471
472
|
|
|
472
473
|
Rollbar.configure do |config|
|
|
473
474
|
config.use_async = false
|
|
474
|
-
config.async_handler = Rollbar.
|
|
475
|
+
config.async_handler = Rollbar.default_async_handler
|
|
475
476
|
end
|
|
476
477
|
end
|
|
477
478
|
|
|
@@ -498,6 +499,84 @@ describe Rollbar do
|
|
|
498
499
|
|
|
499
500
|
Rollbar.report_exception(@exception)
|
|
500
501
|
end
|
|
502
|
+
|
|
503
|
+
context 'with async failover handlers' do
|
|
504
|
+
before do
|
|
505
|
+
Rollbar.reconfigure do |config|
|
|
506
|
+
config.use_async = true
|
|
507
|
+
config.async_handler = async_handler
|
|
508
|
+
config.failover_handlers = handlers
|
|
509
|
+
config.logger = logger_mock
|
|
510
|
+
end
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
let(:exception) { StandardError.new('the error') }
|
|
514
|
+
|
|
515
|
+
context 'if the async handler doesnt fail' do
|
|
516
|
+
let(:async_handler) { proc { |_| 'success' } }
|
|
517
|
+
let(:handler) { proc { |_| 'success' } }
|
|
518
|
+
let(:handlers) { [handler] }
|
|
519
|
+
|
|
520
|
+
it 'doesnt call any failover handler' do
|
|
521
|
+
expect(handler).not_to receive(:call)
|
|
522
|
+
|
|
523
|
+
Rollbar.report_exception(exception)
|
|
524
|
+
end
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
context 'if the async handler fails' do
|
|
528
|
+
let(:async_handler) { proc { |_| fail 'this handler will crash' } }
|
|
529
|
+
|
|
530
|
+
context 'if any failover handlers is configured' do
|
|
531
|
+
let(:handlers) { [] }
|
|
532
|
+
let(:log_message) do
|
|
533
|
+
'[Rollbar] Async handler failed, and there are no failover handlers configured. See the docs for "failover_handlers"'
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
it 'logs the error but doesnt try to report an internal error' do
|
|
537
|
+
expect(logger_mock).to receive(:error).with(log_message)
|
|
538
|
+
|
|
539
|
+
Rollbar.report_exception(exception)
|
|
540
|
+
end
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
context 'if the first failover handler success' do
|
|
544
|
+
let(:handler) { proc { |_| 'success' } }
|
|
545
|
+
let(:handlers) { [handler] }
|
|
546
|
+
|
|
547
|
+
it 'calls the failover handler and doesnt report internal error' do
|
|
548
|
+
expect(Rollbar).not_to receive(:report_internal_error)
|
|
549
|
+
expect(handler).to receive(:call)
|
|
550
|
+
|
|
551
|
+
Rollbar.report_exception(exception)
|
|
552
|
+
end
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
context 'with two handlers, the first failing' do
|
|
556
|
+
let(:handler1) { proc { |_| fail 'this handler fails' } }
|
|
557
|
+
let(:handler2) { proc { |_| 'success' } }
|
|
558
|
+
let(:handlers) { [handler1, handler2] }
|
|
559
|
+
|
|
560
|
+
it 'calls the second handler and doesnt report internal error' do
|
|
561
|
+
expect(handler2).to receive(:call)
|
|
562
|
+
|
|
563
|
+
Rollbar.report_exception(exception)
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
context 'with two handlers, both failing' do
|
|
568
|
+
let(:handler1) { proc { |_| fail 'this handler fails' } }
|
|
569
|
+
let(:handler2) { proc { |_| fail 'this will also fail' } }
|
|
570
|
+
let(:handlers) { [handler1, handler2] }
|
|
571
|
+
|
|
572
|
+
it 'reports internal error' do
|
|
573
|
+
expect(logger_mock).to receive(:error)
|
|
574
|
+
|
|
575
|
+
Rollbar.report_exception(exception)
|
|
576
|
+
end
|
|
577
|
+
end
|
|
578
|
+
end
|
|
579
|
+
end
|
|
501
580
|
end
|
|
502
581
|
|
|
503
582
|
describe "#use_sucker_punch", :if => defined?(SuckerPunch) do
|
|
@@ -514,7 +593,7 @@ describe Rollbar do
|
|
|
514
593
|
|
|
515
594
|
Rollbar.configure do |config|
|
|
516
595
|
config.use_async = false
|
|
517
|
-
config.async_handler = Rollbar.
|
|
596
|
+
config.async_handler = Rollbar.default_async_handler
|
|
518
597
|
end
|
|
519
598
|
end
|
|
520
599
|
end
|
|
@@ -539,7 +618,7 @@ describe Rollbar do
|
|
|
539
618
|
|
|
540
619
|
Rollbar.configure do |config|
|
|
541
620
|
config.use_async = false
|
|
542
|
-
config.async_handler = Rollbar.
|
|
621
|
+
config.async_handler = Rollbar.default_async_handler
|
|
543
622
|
end
|
|
544
623
|
end
|
|
545
624
|
end
|
|
@@ -592,7 +671,7 @@ describe Rollbar do
|
|
|
592
671
|
end
|
|
593
672
|
end
|
|
594
673
|
|
|
595
|
-
|
|
674
|
+
describe '.exception_data' do
|
|
596
675
|
before(:each) do
|
|
597
676
|
configure
|
|
598
677
|
begin
|
|
@@ -647,6 +726,51 @@ describe Rollbar do
|
|
|
647
726
|
end
|
|
648
727
|
end
|
|
649
728
|
|
|
729
|
+
context 'with nested exceptions' do
|
|
730
|
+
let(:crashing_code) do
|
|
731
|
+
proc do
|
|
732
|
+
begin
|
|
733
|
+
begin
|
|
734
|
+
fail CauseException.new('the cause')
|
|
735
|
+
rescue
|
|
736
|
+
fail StandardError.new('the error')
|
|
737
|
+
end
|
|
738
|
+
rescue => e
|
|
739
|
+
e
|
|
740
|
+
end
|
|
741
|
+
end
|
|
742
|
+
end
|
|
743
|
+
let(:rescued_exception) { crashing_code.call }
|
|
744
|
+
|
|
745
|
+
if Exception.instance_methods.include?(:cause)
|
|
746
|
+
it 'sends the two exceptions in the trace_chain attribute' do
|
|
747
|
+
data = Rollbar.send(:exception_data, rescued_exception)
|
|
748
|
+
body = data[:body]
|
|
749
|
+
|
|
750
|
+
body[:trace].should be_nil
|
|
751
|
+
body[:trace_chain].should be_kind_of(Array)
|
|
752
|
+
|
|
753
|
+
chain = body[:trace_chain]
|
|
754
|
+
chain[0][:exception][:class].should match(/StandardError/)
|
|
755
|
+
chain[0][:exception][:message].should match(/the error/)
|
|
756
|
+
|
|
757
|
+
chain[1][:exception][:class].should match(/CauseException/)
|
|
758
|
+
chain[1][:exception][:message].should match(/the cause/)
|
|
759
|
+
end
|
|
760
|
+
|
|
761
|
+
else
|
|
762
|
+
it 'sends only the last exception in the trace attribute' do
|
|
763
|
+
data = Rollbar.send(:exception_data, rescued_exception)
|
|
764
|
+
body = data[:body]
|
|
765
|
+
|
|
766
|
+
body[:trace].should be_kind_of(Hash)
|
|
767
|
+
body[:trace_chain].should be_nil
|
|
768
|
+
|
|
769
|
+
body[:trace][:exception][:class].should match(/StandardError/)
|
|
770
|
+
body[:trace][:exception][:message].should match(/the error/)
|
|
771
|
+
end
|
|
772
|
+
end
|
|
773
|
+
end
|
|
650
774
|
end
|
|
651
775
|
|
|
652
776
|
context 'logger' do
|
|
@@ -739,13 +863,16 @@ describe Rollbar do
|
|
|
739
863
|
|
|
740
864
|
context 'enforce_valid_utf8' do
|
|
741
865
|
it 'should replace invalid utf8 values' do
|
|
866
|
+
bad_key = "inner \x92bad key"
|
|
867
|
+
bad_key.force_encoding('ASCII-8BIT') if bad_key.respond_to?('force_encoding')
|
|
868
|
+
|
|
742
869
|
payload = {
|
|
743
870
|
:bad_value => "bad value 1\255",
|
|
744
871
|
:bad_value_2 => "bad\255 value 2",
|
|
745
872
|
"bad\255 key" => "good value",
|
|
746
873
|
:hash => {
|
|
747
874
|
:inner_bad_value => "\255\255bad value 3",
|
|
748
|
-
|
|
875
|
+
bad_key.to_sym => 'inner good value',
|
|
749
876
|
"bad array key\255" => [
|
|
750
877
|
'good array value 1',
|
|
751
878
|
"bad\255 array value 1\255",
|
|
@@ -764,7 +891,7 @@ describe Rollbar do
|
|
|
764
891
|
payload_copy["bad key"].should == "good value"
|
|
765
892
|
payload_copy.keys.should_not include("bad\456 key")
|
|
766
893
|
payload_copy[:hash][:inner_bad_value].should == "bad value 3"
|
|
767
|
-
payload_copy[:hash]["inner bad key"].should == 'inner good value'
|
|
894
|
+
payload_copy[:hash][:"inner bad key"].should == 'inner good value'
|
|
768
895
|
payload_copy[:hash]["bad array key"].should == [
|
|
769
896
|
'good array value 1',
|
|
770
897
|
'bad array value 1',
|
data/spec/spec_helper.rb
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class CauseException < StandardError; end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rollbar
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rollbar, Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2014-
|
|
11
|
+
date: 2014-10-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: multi_json
|
|
@@ -122,6 +122,34 @@ dependencies:
|
|
|
122
122
|
- - '>='
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
124
|
version: 0.2.7
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: sinatra
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - '>='
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '0'
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - '>='
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '0'
|
|
139
|
+
- !ruby/object:Gem::Dependency
|
|
140
|
+
name: resque
|
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
|
142
|
+
requirements:
|
|
143
|
+
- - '>='
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: '0'
|
|
146
|
+
type: :development
|
|
147
|
+
prerelease: false
|
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
+
requirements:
|
|
150
|
+
- - '>='
|
|
151
|
+
- !ruby/object:Gem::Version
|
|
152
|
+
version: '0'
|
|
125
153
|
description: Rails plugin to catch and send exceptions to Rollbar
|
|
126
154
|
email:
|
|
127
155
|
- support@rollbar.com
|
|
@@ -152,8 +180,11 @@ files:
|
|
|
152
180
|
- lib/rollbar/capistrano.rb
|
|
153
181
|
- lib/rollbar/capistrano3.rb
|
|
154
182
|
- lib/rollbar/configuration.rb
|
|
183
|
+
- lib/rollbar/delay/girl_friday.rb
|
|
184
|
+
- lib/rollbar/delay/resque.rb
|
|
155
185
|
- lib/rollbar/delay/sidekiq.rb
|
|
156
186
|
- lib/rollbar/delay/sucker_punch.rb
|
|
187
|
+
- lib/rollbar/delay/thread.rb
|
|
157
188
|
- lib/rollbar/delayed_job.rb
|
|
158
189
|
- lib/rollbar/exception_reporter.rb
|
|
159
190
|
- lib/rollbar/goalie.rb
|
|
@@ -161,6 +192,7 @@ files:
|
|
|
161
192
|
- lib/rollbar/middleware/rack/test_session.rb
|
|
162
193
|
- lib/rollbar/middleware/rails/rollbar_request_store.rb
|
|
163
194
|
- lib/rollbar/middleware/rails/show_exceptions.rb
|
|
195
|
+
- lib/rollbar/middleware/sinatra.rb
|
|
164
196
|
- lib/rollbar/rack.rb
|
|
165
197
|
- lib/rollbar/rails.rb
|
|
166
198
|
- lib/rollbar/rails/controller_methods.rb
|
|
@@ -228,8 +260,14 @@ files:
|
|
|
228
260
|
- spec/dummyapp/script/rails
|
|
229
261
|
- spec/generators/rollbar/rollbar_generator_spec.rb
|
|
230
262
|
- spec/requests/home_spec.rb
|
|
263
|
+
- spec/rollbar/configuration_spec.rb
|
|
264
|
+
- spec/rollbar/delay/girl_friday_spec.rb
|
|
265
|
+
- spec/rollbar/delay/resque_spec.rb
|
|
266
|
+
- spec/rollbar/delay/thread_spec.rb
|
|
267
|
+
- spec/rollbar/middleware/sinatra_spec.rb
|
|
231
268
|
- spec/rollbar_spec.rb
|
|
232
269
|
- spec/spec_helper.rb
|
|
270
|
+
- spec/support/cause_exception.rb
|
|
233
271
|
homepage: https://github.com/rollbar/rollbar-gem
|
|
234
272
|
licenses:
|
|
235
273
|
- MIT
|
|
@@ -310,5 +348,11 @@ test_files:
|
|
|
310
348
|
- spec/dummyapp/script/rails
|
|
311
349
|
- spec/generators/rollbar/rollbar_generator_spec.rb
|
|
312
350
|
- spec/requests/home_spec.rb
|
|
351
|
+
- spec/rollbar/configuration_spec.rb
|
|
352
|
+
- spec/rollbar/delay/girl_friday_spec.rb
|
|
353
|
+
- spec/rollbar/delay/resque_spec.rb
|
|
354
|
+
- spec/rollbar/delay/thread_spec.rb
|
|
355
|
+
- spec/rollbar/middleware/sinatra_spec.rb
|
|
313
356
|
- spec/rollbar_spec.rb
|
|
314
357
|
- spec/spec_helper.rb
|
|
358
|
+
- spec/support/cause_exception.rb
|