Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

RSpec.shared_examples "an ActiveJob backend that respects skippable_job_adapters" do
it "captures no events when the adapter is in skippable_job_adapters" do
it "leaves error reporting to the backend when the adapter is in skippable_job_adapters" do
Sentry.configuration.rails.skippable_job_adapters = [
failing_job.queue_adapter.class.to_s
]
Expand All @@ -11,6 +11,6 @@
drain
end.to raise_error(RuntimeError, /boom from failing_job spec/)

expect(sentry_events).to be_empty
expect(sentry_events.size).to eq(skipped_adapter_error_events)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ def perform
Sentry.configuration.rails.active_job_report_on_retry_error = true
end

it "captures one error event per attempt", skip: RAILS_VERSION < 6.0 do
it "captures one error event per attempt unless the backend reports only exhausted retries", skip: RAILS_VERSION < 6.0 do
expect do
retryable_job.perform_later
3.times { drain }
end.to raise_error(RuntimeError, /boom from retryable_job spec/)

expect(sentry_events.size).to eq(3)
expect(sentry_events.size).to eq(reports_retried_exceptions ? 3 : 1)
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
expect(transaction.transaction).to eq(successful_job.name)
expect(transaction.transaction_info).to eq(source: :task)
expect(transaction.contexts.dig(:trace, :op)).to eq("queue.process")
expect(transaction.contexts.dig(:trace, :origin)).to eq("auto.queue.active_job")
expect(transaction.contexts.dig(:trace, :origin)).to eq(job_span_origin)
expect(transaction.contexts.dig(:trace, :status)).to eq("ok")
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def perform(_greeting); end
drain

data = consumer_transaction.contexts.dig(:trace, :data)
expect(data["messaging.message.body.size"]).to eq(JSON.generate(delivered_job_data.last).bytesize)
expect(data["messaging.message.body.size"]).to eq(expected_message_body_size(delivered_job_data.last))
end

it "records messaging.message.retry.count = 0 for non-retryable jobs" do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
publish_span = parent.spans.find { |s| s[:op] == "queue.publish" }
expect(publish_span).not_to be_nil
expect(publish_span[:description]).to eq(successful_job.name)
expect(publish_span[:origin]).to eq("auto.queue.active_job")
expect(publish_span[:origin]).to eq(job_span_origin)
expect(publish_span[:data]["messaging.system"]).to be_a(String).and(satisfy { |v| !v.empty? })
expect(publish_span[:data]["messaging.system"]).to eq(successful_job.queue_adapter_name)
expect(publish_span[:data]["messaging.message.id"]).to be_a(String).and(satisfy { |v| !v.empty? })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def perform
publish_span = parent.spans.find { |s| s[:op] == "queue.publish" }
expect(publish_span).not_to be_nil
expect(publish_span[:description]).to eq(successful_job.name)
expect(publish_span[:origin]).to eq("auto.queue.active_job")
expect(publish_span[:origin]).to eq(job_span_origin)
end
end

Expand Down
7 changes: 7 additions & 0 deletions sentry-rails/spec/active_job/support/harness.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
let(:adapter) { adapter }
let(:configure_sentry) { proc { } }
let(:sentry_test_config) { nil }
let(:job_span_origin) { "auto.queue.active_job" }
let(:skipped_adapter_error_events) { 0 }
let(:reports_retried_exceptions) { true }

# Canonical job fixtures shared by every backend's example suite. Specs
# that need a custom body (e.g. local variables in the failing frame)
Expand Down Expand Up @@ -147,6 +150,10 @@ def last_enqueued_payload
"Include the matching adapter shared context (e.g. 'test adapter', 'sidekiq adapter')."
end

def expected_message_body_size(delivered_job_data)
JSON.generate(delivered_job_data).bytesize
end

def job_fixture(name = nil, &block)
name ||= "JobFixture_#{SecureRandom.hex(4)}"
klass = Class.new(::ActiveJob::Base, &block)
Expand Down
9 changes: 9 additions & 0 deletions sentry-resque/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,12 @@ gem "resque-retry", "~> 1.8"

gem "sentry-rails", path: "../sentry-rails"
gem "rails", "> 5.2.0"

unless RUBY_PLATFORM.include?("java")
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.2")
gem "resque-scheduler", "~> 5.0"
gem "mock_redis"
gem "sqlite3"
gem "rspec-rails"
end
end
22 changes: 21 additions & 1 deletion sentry-resque/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,24 @@ gem "sentry-ruby"
gem "sentry-resque"
```

Then you're all set! `sentry-resque` will automatically insert a custom middleware and error handler to capture exceptions from your workers!
Then you're all set! `sentry-resque` captures exceptions and starts a `queue.resque` transaction for every job your Resque workers perform.

## Maintenance Mode

`sentry-resque` is in maintenance mode. The integration for plain Resque jobs is preserved and keeps receiving fixes, but new background job features land in `sentry-rails` through its ActiveJob integration.

### ActiveJob on Resque

By default, ActiveJob jobs running on Resque are still reported by `sentry-resque`, exactly as before. Rails apps can opt in to the `sentry-rails` ActiveJob integration instead:

```ruby
# config/initializers/sentry.rb
Sentry.init do |config|
# ...
config.resque.active_job_integration = :rails
end
```

Once opted in, `sentry-rails` reports those jobs and `sentry-resque` enriches them with Resque data: the `resque.queue` tag, the `Active-Job` context, and the `messaging.*` span data for the Resque queue. `sentry-resque` still reports errors raised before the job starts, such as a job class that can no longer be loaded. If `ActiveJob::QueueAdapters::ResqueAdapter` is listed in `config.rails.skippable_job_adapters`, `sentry-resque` keeps reporting those jobs itself. Plain Resque jobs are not affected by this setting.

Errors from ActiveJob jobs on Resque that `retry_on` retries are not reported, regardless of `config.rails.active_job_report_on_retry_error`.
20 changes: 18 additions & 2 deletions sentry-resque/Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,24 @@
require "bundler/gem_tasks"
require "rspec/core/rake_task"

RSpec::Core::RakeTask.new(:spec).tap do |task|
RSpec::Core::RakeTask.new(:spec) do |task|
task.pattern = "spec/sentry/**/*_spec.rb"
task.rspec_opts = "--order rand"
end

task default: :spec
namespace :spec do
isolated_tasks = Dir["spec/isolated/**/*_spec.rb"].sort.map do |file|
task_name = "isolated:#{file.delete_prefix("spec/isolated/").delete_suffix("_spec.rb")}"

RSpec::Core::RakeTask.new(task_name) do |task|
task.pattern = file
task.rspec_opts = "--format progress"
end

task_name
end

task isolated: isolated_tasks
end

task default: [:spec, :"spec:isolated"]
47 changes: 39 additions & 8 deletions sentry-resque/gemfiles/ruby-3.2.gemfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading