rollbar 2.1.2 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 553381499b916556da8272eadf551847254ffcaa
4
- data.tar.gz: c80b393ccaa1cb9e2c2d46646703510852965ecf
3
+ metadata.gz: 245d598a698d57310a524065495b585450e183d8
4
+ data.tar.gz: ae4841097d594e0b58528806f3b151163e9b432a
5
5
  SHA512:
6
- metadata.gz: d31b2d8d6d71c30c5888c3dacd631cda2f584d2de6a8b4cb238ca8c484a7037745904cfa5925ea5eca5e2100a93afa8c56681deab6292ffeefd97d4a764b078d
7
- data.tar.gz: eedb32f0cc342297fbb7c48f989b8568bb6856ee385bc8f5d65c7d95334f58ed0a3121511d5824c870ddb1545e94fe8f2c265435a1afeb458730f2a2d927d581
6
+ metadata.gz: 43011a9710f91e3640dc5542d099b112ea4b2424842d2db8045a5f14444027ec225b15380539d7f38ecde2258744db6e74df31855b1a293c36d106c7ee2ac0dd
7
+ data.tar.gz: 47bfe86f356e5efa27fea9ef15c5150541d4c065c9d8c72f0def6c1ad2813d8ff0be5bc1381b0b9bea38f7df49f3fc3dfb03a3b23a362510da196a1391596668
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Change Log
2
2
 
3
+ ## 2.2.0
4
+
5
+ New features:
6
+
7
+ - Raise internal exceptions when processing reports from async handlers, instead of swallowing them. This allows queue systems (e.g. Sidekiq, Resque) to track and retry errored jobs. See [#282](https://github.com/rollbar/rollbar-gem/pull/282)
8
+ - Send the error class name when reporting internal errors. See [#283](https://github.com/rollbar/rollbar-gem/pull/283)
9
+
3
10
  ## 2.1.2
4
11
 
5
12
  Bug fix:
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Rollbar notifier for Ruby [![Build Status](https://api.travis-ci.org/rollbar/rollbar-gem.svg?branch=v2.1.2)](https://travis-ci.org/rollbar/rollbar-gem/branches)
1
+ # Rollbar notifier for Ruby [![Build Status](https://api.travis-ci.org/rollbar/rollbar-gem.svg?branch=v2.2.0)](https://travis-ci.org/rollbar/rollbar-gem/branches)
2
2
 
3
3
  <!-- RemoveNext -->
4
4
  [Rollbar](https://rollbar.com) is an error tracking service for Ruby and other languages. The Rollbar service will alert you of problems with your code and help you understand them in a ways never possible before. We love it and we hope you will too.
@@ -12,7 +12,7 @@ This is the Ruby library for Rollbar. It will instrument many kinds of Ruby appl
12
12
  Add this line to your application's Gemfile:
13
13
 
14
14
  ```ruby
15
- gem 'rollbar', '~> 2.1.2'
15
+ gem 'rollbar', '~> 2.2.0'
16
16
  ```
17
17
 
18
18
  And then execute:
@@ -518,11 +518,11 @@ You can supply your own handler using ```config.async_handler```. The object to
518
518
  ```ruby
519
519
  config.use_async = true
520
520
  config.async_handler = Proc.new { |payload|
521
- Thread.new { Rollbar.process_payload_safely(payload) }
521
+ Thread.new { Rollbar.process_from_async_handler(payload) }
522
522
  }
523
523
  ```
524
524
 
525
- Make sure you pass ```payload``` to ```Rollbar.process_payload_safely``` in your own implementation.
525
+ Make sure you pass ```payload``` to ```Rollbar.process_from_async_handler``` in your own implementation.
526
526
 
527
527
  ## Failover handlers
528
528
 
@@ -666,19 +666,6 @@ You can find upgrading notes in [UPGRADING.md](UPGRADING.md).
666
666
 
667
667
  ## Known Issues
668
668
 
669
- We've received some issues from users having problems when they use [Oj](https://github.com/ohler55/oj) as the JSON serialization library with [MultiJson](https://github.com/intridea/multi_json). To avoid these problems, we recommend upgrading to Oj version 2.11.0:
670
-
671
- ```ruby
672
- gem 'oj', '~> 2.11.0'
673
- ```
674
-
675
- If you are using Oj but cannot upgrade, you can work around this with:
676
-
677
- ```ruby
678
- require 'json'
679
- MultiJson.use(:json_common)
680
- ```
681
-
682
669
  If you are using jRuby with Oracle and JDK7, you may be expecting some errors sending reports to our API. This is caused by a bug in that JDK and the primer number used in the SSL algorithm. In order to fix this you can set the next configuration:
683
670
 
684
671
  ```ruby
@@ -47,7 +47,7 @@ Rollbar.configure do |config|
47
47
  # config.use_async = true
48
48
  # Supply your own async handler:
49
49
  # config.async_handler = Proc.new { |payload|
50
- # Thread.new { Rollbar.process_payload_safely(payload) }
50
+ # Thread.new { Rollbar.process_from_async_handler(payload) }
51
51
  # }
52
52
 
53
53
  # Enable asynchronous reporting (using sucker_punch)
data/lib/rollbar.rb CHANGED
@@ -17,7 +17,7 @@ require 'rollbar/logger_proxy'
17
17
  require 'rollbar/exception_reporter'
18
18
  require 'rollbar/util'
19
19
  require 'rollbar/railtie' if defined?(Rails::VERSION)
20
- require 'rollbar/delay/girl_friday'
20
+ require 'rollbar/delay/girl_friday' if defined?(GirlFriday)
21
21
  require 'rollbar/delay/thread'
22
22
  require 'rollbar/truncation'
23
23
 
@@ -27,7 +27,7 @@ module Rollbar
27
27
  Rack::Multipart::UploadedFile
28
28
  ].freeze
29
29
  PUBLIC_NOTIFIER_METHODS = %w(debug info warn warning error critical log logger
30
- process_payload process_payload_safely scope send_failsafe log_info log_debug
30
+ process_payload process_from_async_handler scope send_failsafe log_info log_debug
31
31
  log_warning log_error silenced)
32
32
 
33
33
  class Notifier
@@ -195,10 +195,39 @@ module Rollbar
195
195
  raise e
196
196
  end
197
197
 
198
- def process_payload_safely(payload)
199
- process_payload(payload)
200
- rescue => e
201
- report_internal_error(e)
198
+ # We will reraise exceptions in this method so async queues
199
+ # can retry the job or, in general, handle an error report some way.
200
+ #
201
+ # At same time that exception is silenced so we don't generate
202
+ # infinite reports. This example is what we want to avoid:
203
+ #
204
+ # 1. New exception in a the project is raised
205
+ # 2. That report enqueued to Sidekiq queue.
206
+ # 3. The Sidekiq job tries to send the report to our API
207
+ # 4. The report fails, for example cause a network failure,
208
+ # and a exception is raised
209
+ # 5. We report an internal error for that exception
210
+ # 6. We reraise the exception so Sidekiq job fails and
211
+ # Sidekiq can retry the job reporting the original exception
212
+ # 7. Because the job failed and Sidekiq can be managed by rollbar we'll
213
+ # report a new exception.
214
+ # 8. Go to point 2.
215
+ #
216
+ # We'll then push to Sidekiq queue indefinitely until the network failure
217
+ # is fixed.
218
+ #
219
+ # Using Rollbar.silenced we avoid the above behavior but Sidekiq
220
+ # will have a chance to retry the original job.
221
+ def process_from_async_handler(payload)
222
+ Rollbar.silenced do
223
+ begin
224
+ process_payload(payload)
225
+ rescue => e
226
+ report_internal_error(e)
227
+
228
+ raise
229
+ end
230
+ end
202
231
  end
203
232
 
204
233
  def custom_data
@@ -544,23 +573,28 @@ module Rollbar
544
573
  end
545
574
 
546
575
  def send_failsafe(message, exception)
576
+ body = 'Failsafe from rollbar-gem: '
547
577
  log_error "[Rollbar] Sending failsafe response due to #{message}."
578
+
548
579
  if exception
549
580
  begin
581
+ body += "#{exception.class.name}: #{message}"
550
582
  log_error "[Rollbar] #{exception.class.name}: #{exception}"
551
- rescue => e
583
+ rescue
584
+ end
585
+ else
586
+ begin
587
+ body += message.to_s
588
+ rescue
552
589
  end
553
590
  end
554
591
 
555
- config = configuration
556
- environment = config.environment
557
-
558
592
  failsafe_data = {
559
593
  :level => 'error',
560
- :environment => environment.to_s,
594
+ :environment => configuration.environment.to_s,
561
595
  :body => {
562
596
  :message => {
563
- :body => "Failsafe from rollbar-gem: #{message}"
597
+ :body => body
564
598
  }
565
599
  },
566
600
  :notifier => {
@@ -581,6 +615,8 @@ module Rollbar
581
615
  rescue => e
582
616
  log_error "[Rollbar] Error sending failsafe : #{e}"
583
617
  end
618
+
619
+ failsafe_payload
584
620
  end
585
621
 
586
622
  def schedule_payload(payload)
@@ -3,22 +3,28 @@ module Rollbar
3
3
  class GirlFriday
4
4
 
5
5
  class << self
6
- attr_accessor :queue
6
+ def queue_class
7
+ ::GirlFriday::WorkQueue
8
+ end
7
9
 
8
10
  def call(payload)
9
11
  new.call(payload)
10
12
  end
11
- end
12
13
 
13
- def queue_class
14
- ::GirlFriday::WorkQueue
14
+ def queue
15
+ @queue ||= self.queue_class.new(nil, :size => 5) do |payload|
16
+ begin
17
+ Rollbar.process_from_async_handler(payload)
18
+ rescue
19
+ # According to https://github.com/mperham/girl_friday/wiki#error-handling
20
+ # we reraise the exception so it can be handled some way
21
+ raise
22
+ end
23
+ end
24
+ end
15
25
  end
16
26
 
17
27
  def call(payload)
18
- self.class.queue = queue_class.new(nil, :size => 5) do |payload|
19
- Rollbar.process_payload_safely(payload)
20
- end
21
-
22
28
  self.class.queue.push(payload)
23
29
  end
24
30
  end
@@ -23,7 +23,12 @@ module Rollbar
23
23
  end
24
24
 
25
25
  def perform(payload)
26
- Rollbar.process_payload_safely(payload)
26
+ begin
27
+ Rollbar.process_from_async_handler(payload)
28
+ rescue
29
+ # Raise the exception so Resque can track the errored job
30
+ raise
31
+ end
27
32
  end
28
33
  end
29
34
  end
@@ -16,7 +16,13 @@ module Rollbar
16
16
  include ::Sidekiq::Worker
17
17
 
18
18
  def perform(*args)
19
- Rollbar.process_payload_safely(*args)
19
+ begin
20
+ Rollbar.process_from_async_handler(*args)
21
+ rescue
22
+ # Raise the exception so Sidekiq can track the errored job
23
+ # and retry it
24
+ raise
25
+ end
20
26
  end
21
27
  end
22
28
  end
@@ -11,7 +11,20 @@ module Rollbar
11
11
  end
12
12
 
13
13
  def perform(*args)
14
- Rollbar.process_payload_safely(*args)
14
+ begin
15
+ Rollbar.process_from_async_handler(*args)
16
+ rescue
17
+ # SuckerPunch can configure an exception handler with:
18
+ #
19
+ # SuckerPunch.exception_handler { # do something here }
20
+ #
21
+ # This is just passed to Celluloid.exception_handler which will
22
+ # push the reiceved block to an array of handlers, by default empty, [].
23
+ #
24
+ # We reraise the exception here casue it's safe and users could have defined
25
+ # their own exception handler for SuckerPunch
26
+ raise
27
+ end
15
28
  end
16
29
  end
17
30
  end
@@ -6,7 +6,18 @@ module Rollbar
6
6
  end
7
7
 
8
8
  def call(payload)
9
- ::Thread.new { Rollbar.process_payload_safely(payload) }
9
+ ::Thread.new do
10
+ begin
11
+ Rollbar.process_from_async_handler(payload)
12
+ rescue
13
+ # Here we swallow the exception:
14
+ # 1. The original report wasn't sent.
15
+ # 2. An internal error was sent and logged
16
+ #
17
+ # If users want to handle this in some way they
18
+ # can provide a more custom Thread based implementation
19
+ end
20
+ end
10
21
  end
11
22
  end
12
23
  end
@@ -1,3 +1,3 @@
1
1
  module Rollbar
2
- VERSION = "2.1.2"
2
+ VERSION = "2.2.0"
3
3
  end
data/rollbar.gemspec CHANGED
@@ -4,7 +4,7 @@ require File.expand_path('../lib/rollbar/version', __FILE__)
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ["Rollbar, Inc."]
6
6
  gem.email = ["support@rollbar.com"]
7
- gem.description = %q{Rails plugin to catch and send exceptions to Rollbar}
7
+ gem.description = %q{Easy and powerful exception tracking for Ruby}
8
8
  gem.executables = ['rollbar-rails-runner']
9
9
  gem.summary = %q{Reports exceptions to Rollbar}
10
10
  gem.homepage = "https://rollbar.com"
@@ -17,7 +17,7 @@ describe Rollbar::Delay::Sidekiq, :if => RUBY_VERSION != '1.8.7' do
17
17
 
18
18
  describe "#perform" do
19
19
  it "performs payload" do
20
- Rollbar.should_receive(:process_payload_safely).with(payload)
20
+ Rollbar.should_receive(:process_from_async_handler).with(payload)
21
21
  subject.perform payload
22
22
  end
23
23
  end
@@ -26,7 +26,7 @@ describe Rollbar::Delay::Sidekiq, :if => RUBY_VERSION != '1.8.7' do
26
26
  shared_examples "a Rollbar processor" do
27
27
 
28
28
  it "processes payload" do
29
- Rollbar.should_receive(:process_payload_safely).with(payload)
29
+ Rollbar.should_receive(:process_from_async_handler).with(payload)
30
30
 
31
31
  subject.call payload
32
32
  described_class.drain
@@ -17,7 +17,7 @@ describe Rollbar::Delay::SuckerPunch, :if => RUBY_VERSION != '1.8.7' do
17
17
  let(:payload) { "anything" }
18
18
 
19
19
  it "performs the task asynchronously" do
20
- Rollbar.should_receive(:process_payload_safely)
20
+ Rollbar.should_receive(:process_from_async_handler)
21
21
 
22
22
  Rollbar::Delay::SuckerPunch.call payload
23
23
  end
@@ -6,14 +6,36 @@ require 'girl_friday'
6
6
  require 'rollbar/delay/girl_friday'
7
7
 
8
8
  describe Rollbar::Delay::GirlFriday do
9
+ before do
10
+ queue_class = ::GirlFriday::WorkQueue.immediate!
11
+ allow(::Rollbar::Delay::GirlFriday).to receive(:queue_class).and_return(queue_class)
12
+ end
13
+
9
14
  describe '.call' do
10
15
  let(:payload) do
11
16
  { :key => 'value' }
12
17
  end
13
18
 
14
19
  it 'push the payload into the queue' do
15
- expect_any_instance_of(::GirlFriday::WorkQueue).to receive(:push).with(payload)
20
+ expect(Rollbar).to receive(:process_from_async_handler).with(payload)
21
+
16
22
  described_class.call(payload)
17
23
  end
24
+
25
+ context 'with exceptions processing payload' do
26
+ let(:exception) { Exception.new }
27
+
28
+ before do
29
+ expect(Rollbar).to receive(:process_from_async_handler).with(payload).and_raise(exception)
30
+ end
31
+
32
+ it 'raises an exception cause we are using immediate queue' do
33
+ # This will not happen with a norma work queue cause this:
34
+ # https://github.com/mperham/girl_friday/blob/master/lib/girl_friday/work_queue.rb#L90-L106
35
+ expect do
36
+ described_class.call(payload)
37
+ end.to raise_error(exception)
38
+ end
39
+ end
18
40
  end
19
41
  end
@@ -7,15 +7,31 @@ describe Rollbar::Delay::Resque do
7
7
  { :key => 'value' }
8
8
  end
9
9
 
10
+ let(:loaded_hash) do
11
+ Rollbar::JSON.load(Rollbar::JSON.dump(payload))
12
+ end
13
+
10
14
  before do
11
15
  allow(Resque).to receive(:inline?).and_return(true)
12
16
  end
13
17
 
14
18
  it 'process the payload' do
15
- loaded_hash = Rollbar::JSON.load(Rollbar::JSON.dump(payload))
16
-
17
- expect(Rollbar).to receive(:process_payload_safely).with(loaded_hash)
19
+ expect(Rollbar).to receive(:process_from_async_handler).with(loaded_hash)
18
20
  described_class.call(payload)
19
21
  end
22
+
23
+ context 'with exceptions processing payload' do
24
+ let(:exception) { Exception.new }
25
+
26
+ before do
27
+ expect(Rollbar).to receive(:process_from_async_handler).with(loaded_hash).and_raise(exception)
28
+ end
29
+
30
+ it 'raises an exception' do
31
+ expect do
32
+ described_class.call(payload)
33
+ end.to raise_error(exception)
34
+ end
35
+ end
20
36
  end
21
37
  end
@@ -5,10 +5,23 @@ describe Rollbar::Delay::Thread do
5
5
  let(:payload) { { :key => 'value' } }
6
6
 
7
7
  it 'process the payload in a new thread' do
8
- expect(Rollbar).to receive(:process_payload_safely).with(payload)
8
+ expect(Rollbar).to receive(:process_from_async_handler).with(payload)
9
9
 
10
- th = described_class.call(payload)
11
- th.join
10
+ described_class.call(payload).join
11
+ end
12
+
13
+ context 'with exceptions processing payload' do
14
+ let(:exception) { StandardError.new }
15
+
16
+ before do
17
+ expect(Rollbar).to receive(:process_from_async_handler).with(payload).and_raise(exception)
18
+ end
19
+
20
+ it 'doesnt raise any exception' do
21
+ expect do
22
+ described_class.call(payload).join
23
+ end.not_to raise_error(exception)
24
+ end
12
25
  end
13
26
  end
14
27
  end
data/spec/rollbar_spec.rb CHANGED
@@ -1562,17 +1562,27 @@ describe Rollbar do
1562
1562
  end
1563
1563
 
1564
1564
  context "send_failsafe" do
1565
+ let(:exception) { StandardError.new }
1566
+
1565
1567
  it "should not crash when given a message and exception" do
1566
- begin
1567
- 1 / 0
1568
- rescue => e
1569
- notifier.send(:send_failsafe, "test failsafe", e)
1570
- end
1568
+ sent_payload = notifier.send(:send_failsafe, "test failsafe", exception)
1569
+
1570
+ expected_message = 'Failsafe from rollbar-gem: StandardError: test failsafe'
1571
+ expect(sent_payload['data'][:body][:message][:body]).to be_eql(expected_message)
1571
1572
  end
1572
1573
 
1573
1574
  it "should not crash when given all nils" do
1574
1575
  notifier.send(:send_failsafe, nil, nil)
1575
1576
  end
1577
+
1578
+ context 'without exception object' do
1579
+ it 'just sends the given message' do
1580
+ sent_payload = notifier.send(:send_failsafe, "test failsafe", nil)
1581
+
1582
+ expected_message = 'Failsafe from rollbar-gem: test failsafe'
1583
+ expect(sent_payload['data'][:body][:message][:body]).to be_eql(expected_message)
1584
+ end
1585
+ end
1576
1586
  end
1577
1587
 
1578
1588
  context 'when reporting internal error with nil context' do
@@ -1704,15 +1714,20 @@ describe Rollbar do
1704
1714
  end
1705
1715
  end
1706
1716
 
1707
- describe '.process_payload_safely' do
1717
+ describe '.process_from_async_handler' do
1708
1718
  context 'with errors' do
1709
1719
  let(:exception) { StandardError.new('the error') }
1710
1720
 
1711
- it 'doesnt raise anything and sends internal error' do
1721
+ it 'raises anything and sends internal error' do
1712
1722
  allow(Rollbar.notifier).to receive(:process_payload).and_raise(exception)
1713
1723
  expect(Rollbar.notifier).to receive(:report_internal_error).with(exception)
1714
1724
 
1715
- Rollbar.notifier.process_payload_safely({})
1725
+ expect do
1726
+ Rollbar.notifier.process_from_async_handler({})
1727
+ end.to raise_error(exception)
1728
+
1729
+ rollbar_do_not_report = exception.instance_variable_get(:@_rollbar_do_not_report)
1730
+ expect(rollbar_do_not_report).to be_eql(true)
1716
1731
  end
1717
1732
  end
1718
1733
  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: 2.1.2
4
+ version: 2.2.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: 2015-08-14 00:00:00.000000000 Z
11
+ date: 2015-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -178,7 +178,7 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
- description: Rails plugin to catch and send exceptions to Rollbar
181
+ description: Easy and powerful exception tracking for Ruby
182
182
  email:
183
183
  - support@rollbar.com
184
184
  executables: