Skip to content

Commit 0f418b0

Browse files
authored
Merge pull request #185 from nikz/unwrap-sidekiq-handled-error
Unwraps `Sidekiq::JobRetry::Handled` errors
2 parents 0da2d2f + 46bfb2a commit 0f418b0

File tree

5 files changed

+93
-2
lines changed

5 files changed

+93
-2
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,10 @@ class FailingWorker
402402
end
403403
```
404404

405+
##### Sidekiq Retries
406+
407+
By default, Raygun4Ruby will unwrap `Sidekiq::JobRetry::Handled` exceptions and report the original error via `Exception#cause`. If you would prefer not to hear about retries, you can set `config.track_retried_sidekiq_jobs` to `false` in your Raygun configuration.
408+
405409
### Other Configuration options
406410

407411
For a complete list of configuration options see the [configuration.rb](https://github.com/MindscapeHQ/raygun4ruby/blob/master/lib/raygun/configuration.rb) file

lib/raygun/configuration.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ def self.proc_config_option(name)
8989
# Should we register an error handler with [Rails' built in API](https://edgeguides.rubyonrails.org/error_reporting.html)
9090
config_option :register_rails_error_handler
9191

92+
# Should we track jobs that are retried in Sidekiq (ones that raise Sidekiq::JobRetry::Handled). Set to "false" to ignore.
93+
config_option :track_retried_sidekiq_jobs
94+
9295
# Exception classes to ignore by default
9396
IGNORE_DEFAULT = ['ActiveRecord::RecordNotFound',
9497
'ActionController::RoutingError',
@@ -143,7 +146,8 @@ def initialize
143146
breadcrumb_level: :info,
144147
record_raw_data: false,
145148
send_in_background: false,
146-
error_report_send_timeout: 10
149+
error_report_send_timeout: 10,
150+
track_retried_sidekiq_jobs: true
147151
)
148152
end
149153

lib/raygun/error_subscriber.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ def report(error, handled:, severity:, context:, source: nil)
1616
tags: ["rails_error_reporter", *tags].compact
1717
}
1818

19-
Raygun.track_exception(error, data)
19+
if source == "job.sidekiq" && defined?(Sidekiq)
20+
Raygun::SidekiqReporter.call(error, data)
21+
else
22+
Raygun.track_exception(error, data)
23+
end
2024
end
2125
end

lib/raygun/sidekiq.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@ def self.call(exception, context_hash = {}, config = nil)
1414
},
1515
tags: ['sidekiq']
1616
}
17+
18+
if exception.is_a?(Sidekiq::JobRetry::Handled) && exception.cause
19+
if Raygun.configuration.track_retried_sidekiq_jobs
20+
data.merge!(sidekiq_retried: true)
21+
exception = exception.cause
22+
else
23+
return false
24+
end
25+
end
26+
1727
if exception.instance_variable_defined?(:@__raygun_correlation_id) && correlation_id = exception.instance_variable_get(:@__raygun_correlation_id)
1828
data.merge!(correlation_id: correlation_id)
1929
end

test/unit/sidekiq_failure_test.rb

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
require_relative "../test_helper.rb"
22

33
require "sidekiq"
4+
45
# Convince Sidekiq it's on a server :)
56
module Sidekiq
67
class << self
@@ -15,6 +16,8 @@ def server?
1516
class SidekiqFailureTest < Raygun::UnitTest
1617

1718
def setup
19+
require "sidekiq/job_retry"
20+
1821
super
1922
Raygun.configuration.send_in_background = false
2023

@@ -32,6 +35,50 @@ def test_failure_backend_appears_to_work
3235
assert response && response.success?, "Expected success, got #{response.class}: #{response.inspect}"
3336
end
3437

38+
def test_failure_backend_unwraps_retries
39+
WebMock.reset!
40+
41+
unwrapped_stub = stub_request(:post, 'https://api.raygun.com/entries').
42+
with(body: /StandardError/).
43+
to_return(status: 202)
44+
45+
begin
46+
raise StandardError.new("Some job in Sidekiq failed, oh dear!")
47+
rescue
48+
raise Sidekiq::JobRetry::Handled
49+
end
50+
51+
rescue Sidekiq::JobRetry::Handled => e
52+
53+
response = Raygun::SidekiqReporter.call(
54+
e,
55+
{ sidekick_name: "robin" },
56+
{} # config
57+
)
58+
59+
assert_requested unwrapped_stub
60+
assert response && response.success?, "Expected success, got #{response.class}: #{response.inspect}"
61+
end
62+
63+
def test_failured_backend_ignores_retries_if_configured
64+
Raygun.configuration.track_retried_sidekiq_jobs = false
65+
66+
begin
67+
raise StandardError.new("Some job in Sidekiq failed, oh dear!")
68+
rescue
69+
raise Sidekiq::JobRetry::Handled
70+
end
71+
72+
rescue Sidekiq::JobRetry::Handled => e
73+
74+
refute Raygun::SidekiqReporter.call(e,
75+
{ sidekick_name: "robin" },
76+
{} # config
77+
)
78+
ensure
79+
Raygun.configuration.track_retried_sidekiq_jobs = true
80+
end
81+
3582
# See https://github.com/MindscapeHQ/raygun4ruby/issues/183
3683
# (This is how Sidekiq pre 7.1.5 calls error handlers: https://github.com/sidekiq/sidekiq/blob/1ba89bbb22d2fd574b11702d8b6ed63ae59e2256/lib/sidekiq/config.rb#L269)
3784
def test_failure_backend_appears_to_work_without_config_argument
@@ -50,4 +97,26 @@ def test_we_are_in_sidekiqs_list_of_error_handlers
5097
assert error_handlers.include?(Raygun::SidekiqReporter)
5198
end
5299

100+
def test_rails_error_reporter_uses_sidekiq_reporter
101+
WebMock.reset!
102+
103+
tagged_request = stub_request(:post, 'https://api.raygun.com/entries').
104+
with(body: /"sidekiq"/). # should have a sidekiq tag!
105+
to_return(status: 202)
106+
107+
error = StandardError.new("Oh no! Your Sidekiq has failed!")
108+
109+
response = Raygun::ErrorSubscriber.new.report(
110+
error,
111+
handled: true,
112+
severity: "error",
113+
context: { sidekick_name: "robin" },
114+
source: "job.sidekiq"
115+
)
116+
117+
assert response && response.success?, "Expected success, got #{response.class}: #{response.inspect}"
118+
119+
assert_requested tagged_request
120+
end
121+
53122
end

0 commit comments

Comments
 (0)