Skip to content

Commit

Permalink
Record the original exception info when job can be retried (#29)
Browse files Browse the repository at this point in the history
If a failed job is able to be retried, Sidekiq will

1. catch the original exception
2. append the exception message to the job and push it into retry queue
3. raise a new exception `Sidekiq::JobRetry::Skip`

when `Sidekiq::LogstashJobLogger` tries to parse the failed job by #log_job_exception,
the received exception is `Sidekiq::JobRetry::Skip` and
the recorded `error_message`, `error` and `error_backtrace` are wrong.
  • Loading branch information
yiichou authored May 6, 2022
1 parent bd78a5c commit f59fa08
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 1 deletion.
2 changes: 2 additions & 0 deletions lib/sidekiq/logging/shared.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ def log_job_exception(job, started_at, exc)

payload['message'] += ": fail: #{payload['duration']} sec"
payload['job_status'] = 'fail'

exc = exc.cause || exc if exc.is_a? Sidekiq::JobRetry::Handled
payload['error_message'] = exc.message
payload['error'] = exc.class
payload['error_backtrace'] = %('#{exc.backtrace.join("\n")}')
Expand Down
24 changes: 24 additions & 0 deletions spec/sidekiq/logstash_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,30 @@ def process(worker, params = [], encrypt: false)
end
end

context 'when job raises a error' do
it 'logs the exception with job retry' do
mock_redis = double(:Redis)
allow(Sidekiq).to receive(:redis).and_yield(mock_redis)

expect(mock_redis).to receive(:zadd).with('retry', any_args).once
expect { process(SpecWorker, [true]) }.to raise_error(RuntimeError)

expect(log_messages.last['error_message']).to eq('You know nothing, Jon Snow.')
expect(log_messages.last['error']).to eq('RuntimeError')
expect(log_messages.last['error_backtrace'].split("\n").first).to include('workers/spec_worker.rb:7')
end

it 'logs the exception without job retry' do
allow(SpecWorker).to receive(:get_sidekiq_options).and_return({ 'retry' => false, 'queue' => 'default' })

expect { process(SpecWorker, [true]) }.to raise_error(RuntimeError)

expect(log_messages.last['error_message']).to eq('You know nothing, Jon Snow.')
expect(log_messages.last['error']).to eq('RuntimeError')
expect(log_messages.last['error_backtrace'].split("\n").first).to include('workers/spec_worker.rb:7')
end
end

context 'with job_start_log enabled' do
before do
Sidekiq::Logstash.configure do |config|
Expand Down
2 changes: 1 addition & 1 deletion spec/workers/spec_worker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ class SpecWorker
include Sidekiq::Worker

def perform(fail = false, _params = {})
raise RuntimeError if fail
raise 'You know nothing, Jon Snow.' if fail
end
end

0 comments on commit f59fa08

Please sign in to comment.