feat(active_job): support for tracing#2947
Merged
Merged
Conversation
6309f45 to
03ad132
Compare
826f69d to
1c0f001
Compare
c9da666 to
d072fd5
Compare
d65c086 to
49aa99c
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 332bf25. Configure here.
036a44d to
9d90460
Compare
dingsdax
reviewed
Jun 30, 2026
The harness embedded :test-adapter specifics — the Rails 5.2 payload- preservation shim, the drain loop, and the enqueued-payload accessor. It also reached past ActiveJob::TestHelper to set ActiveJob::Base.queue_adapter directly, which conflicts with TestHelper's own _test_adapter slot (TestHelper's before_setup runs outside our around hook, so any direct assignment is silently shadowed). Switch the harness to ActiveJob's official queue_adapter_for_test hook and a small set of abstract methods (queue_adapter_for_test, with_adapter_active, drain, last_enqueued_payload, boot_adapter, reset_adapter) that adapter contexts implement. The :test-adapter shared context now owns everything specific to TestAdapter — including the Rails52FullPayloadTestAdapter shim and the drain loop. Subsequent adapter backends (e.g. Sidekiq) can compose with the harness without fighting it. Generalises the one shared-example line that reached into the TestAdapter shape (trace_propagation) via last_enqueued_payload. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…adapter Runs the common ActiveJob spec suite end-to-end against ActiveJob::QueueAdapters::SidekiqAdapter, driven by Sidekiq::Testing.fake! (block form, public API) and Sidekiq::Job.drain_all. Validates that the AJ tracing extension works as a generic, adapter- agnostic instrumentation — independent of sentry-sidekiq's native middleware. The :sidekiq context plugs into the harness via queue_adapter_for_test (installing a SidekiqAdapter instance through ActiveJob::TestHelper) and with_adapter_active (wrapping example.run in Sidekiq::Testing.fake! so fake mode is scoped per-example without touching global state). The context deliberately does not load sentry-sidekiq: loading it would install Sidekiq's client/server middleware globally and register SidekiqAdapter in skippable_job_adapters, both of which would short-circuit the AJ extension we're exercising. Sidekiq becomes a sentry-rails dev dependency, gated on Rails version (Sidekiq 7+ doesn't support Rails 5.2). The spec file and support file no-op cleanly on older matrices where the gem isn't bundled. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drives the svelte-mini app to click a new "Trigger Job" button, which fetches POST /jobs/sample on the rails-mini app. The browser SDK propagates sentry-trace + baggage to the Rails request; the AJ extension this branch adds emits a queue.publish span on the http.server transaction at enqueue, and a queue.active_job consumer transaction when the :async pool runs the job. The spec asserts all three rails-side artifacts share one trace and are correctly linked (sentry-trace header on the controller request, parent_span_id on the consumer transaction, and matching messaging.* data on the producer and consumer ends). Polls the shared envelope log because :async runs the job on a separate thread, so the HTTP response returns before the consumer transaction is recorded. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The harness was calling make_basic_app in its around-each block, which creates a fresh Rails::Application subclass and runs every initializer on each example. With 98 AJ examples that overhead dwarfed the actual test work — and worse, it left behind state (Sidekiq's @config_blocks list, accumulated routes, lingering Rails::Application subclasses) that made each subsequent make_basic_app a little slower. Under Ruby 3.4 + Rails 8.1.3 the per-example time grew 3× over the run, pushing the full sentry-rails CI past the 15-min timeout. Hoist make_basic_app to before(:all) and replicate the per-example bits of Sentry::Rails::Railtie's after_initialize hook in the around block — re-init Sentry, re-activate tracing / structured logging, re-register the AJ event handlers. The one-time extensions (controller methods, streaming reporter, backtrace cleanup, etc.) were already installed by the initial make_basic_app and persist for the group. Also memoize the SidekiqAdapter instance in the :sidekiq context. Each SidekiqAdapter.new appended to Sidekiq's internal @config_blocks list and added an on(:quiet) callback; creating a fresh adapter per example was unnecessary global churn. Result: spec/active_job goes from 33s → 0.8s, and the full sentry-rails spec task (Ruby 3.4 + Rails 8.1.3) goes from 9:22 to 2:31 — well under the CI limit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Scope reads allowed user keys as symbols, so we gotta symbolize users that we receive as plain data from the job payload.
9d90460 to
e748124
Compare
dingsdax
approved these changes
Jun 30, 2026
dingsdax
left a comment
Contributor
There was a problem hiding this comment.
lgtm, I don't see any blockers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

This branch extends Sentry's
ActiveJobinstrumentation so distributed tracing works across Resque, DelayedJob, and Sidekiq. Instead of per-adapter integrations, tracing is now driven through a single common ActiveJob extension (Sentry::Rails::ActiveJobExtensions), which hooksserialize/deserialize/perform_nowto:_sentrykey,Because the behavior lives in one extension, every adapter is verified against the same set of shared AJ specs — adding a new adapter is just a context + a one-line
it_behaves_like.New config
config.rails.active_job_propagate_traces(defaulttrue) gates trace propagation through the job payload.New shared specs
A spec wires up the shared backend harness, an adapter-specific context, and the shared example groups.
Resque:
Sidekiq:
The
"...supports distributed tracing"shared example is itself a meta-group that pulls in the individual checks, so each adapter gets full coverage for free:E2E coverage
This branch add more E2E specs (
spec/features/active_job_tracing_spec.rb) that exercises the full path: the Svelte mini app's "Trigger Job" button fetchesPOST /jobson the Rails mini app, the browser SDK propagatessentry-trace+baggage, and we assert that the browser fetch, the controllerhttp.servertransaction, thequeue.publishproducer span, and thequeue.active_jobconsumer transaction all share one trace (consumer parented on the publish span, matchingmessaging.message.id).To support worker-based adapters,
spec/apps/rails-mini/worker.rbboots the same Rails + Sentry app in a separate process and runs the job through whichever adapterSENTRY_E2E_ACTIVE_JOB_ADAPTERselects (:async/:inlinein-process, or a real worker for:sidekiq,:resque,:delayed_job) — so the same e2e assertions run across adapters via the CI matrix.Screenshots
Distributed tracing works OOTB now with any Active Job adapter 🎉