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 @@ -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 @@ -121,7 +121,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
6 changes: 6 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,8 @@
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 }

# 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 +149,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
20 changes: 19 additions & 1 deletion sentry-resque/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,22 @@ 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 keeps receiving fixes, but new background job features land in `sentry-rails` through its ActiveJob integration.

### ActiveJob on Resque

By default, `ActiveJob::QueueAdapters::ResqueAdapter` is listed in `config.rails.skippable_job_adapters`, so ActiveJob jobs running on Resque are reported by `sentry-resque`. Rails apps can opt in to the `sentry-rails` ActiveJob integration instead by removing the adapter from that list:

```ruby
# config/initializers/sentry.rb
Sentry.init do |config|
# ...
config.rails.skippable_job_adapters.delete("ActiveJob::QueueAdapters::ResqueAdapter")
end
```

Once opted in, `sentry-rails` reports those jobs with Resque data: the `resque.queue` tag, the `Active-Job` context, and the `messaging.*` span data for the Resque queue. `sentry-resque` only reports errors raised before an ActiveJob job starts, such as a job class that can no longer be loaded. Plain Resque jobs are not affected.
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"]
31 changes: 31 additions & 0 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.

31 changes: 31 additions & 0 deletions sentry-resque/gemfiles/ruby-3.3.gemfile.lock

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

Loading
Loading