diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b5df7420..920b85fb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,9 @@ ### Features - Improve the accuracy of duration calculations in cron jobs monitoring ([#2471](https://github.com/getsentry/sentry-ruby/pull/2471)) +- Use attempt_threshold to skip reporting on first N attempts ([#2503](https://github.com/getsentry/sentry-ruby/pull/2503)) - Support `code.namespace` for Ruby 3.4+ stacktraces ([#2506](https://github.com/getsentry/sentry-ruby/pull/2506)) - ### Bug fixes - Default to `internal_error` error type for OpenTelemetry spans [#2473](https://github.com/getsentry/sentry-ruby/pull/2473) diff --git a/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb b/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb index 50c720929..64659df1e 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb @@ -31,6 +31,19 @@ def call(ex, context, sidekiq_config = nil) end end + # Check if the retry count is below the attempt_threshold + attempt_threshold = context.dig(:job, "attempt_threshold") + if attempt_threshold && retryable?(context) + attempt_threshold = attempt_threshold.to_i + retry_count = context.dig(:job, "retry_count") + # attempt 1 - retry_count is nil + # attempt 2 - this is your first retry so retry_count is 0 + # attempt 3 - you have retried once, retry_count is 1 + attempt = retry_count.nil? ? 1 : retry_count.to_i + 2 + + return if attempt < attempt_threshold + end + Sentry::Sidekiq.capture_exception( ex, contexts: { sidekiq: context_filter.filtered }, diff --git a/sentry-sidekiq/spec/sentry/sidekiq_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq_spec.rb index 4c788c9ce..110ea850a 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq_spec.rb @@ -109,18 +109,45 @@ expect(retry_set.count).to eq(1) end + def retry_last_failed_job + retry_set.first.add_to_queue + job = queue.first + work = Sidekiq::BasicFetch::UnitOfWork.new('queue:default', job.value) + process_work(processor, work) + end + + context "with attempt_threshold" do + it "doesn't report the error until attempts equal the threshold" do + worker = Class.new(SadWorker) + worker.sidekiq_options attempt_threshold: 3 + + execute_worker(processor, worker) + expect(transport.events.count).to eq(0) + + retry_last_failed_job + expect(transport.events.count).to eq(0) + + retry_last_failed_job + expect(transport.events.count).to eq(1) + end + + it "doesn't report the error when threshold is not reached" do + worker = Class.new(SadWorker) + worker.sidekiq_options attempt_threshold: 3 + + execute_worker(processor, worker) + expect(transport.events.count).to eq(0) + + retry_last_failed_job + expect(transport.events.count).to eq(0) + end + end + context "with config.report_after_job_retries = true" do before do Sentry.configuration.sidekiq.report_after_job_retries = true end - def retry_last_failed_job - retry_set.first.add_to_queue - job = queue.first - work = Sidekiq::BasicFetch::UnitOfWork.new('queue:default', job.value) - process_work(processor, work) - end - context "when retry: is specified" do it "doesn't report the error until retries are exhuasted" do worker = Class.new(SadWorker)