Add support for ActiveRecord async queries
Fixes #3465
Async query execution, introduced in Rails 7.0.0 and expanded in Rails 7.1.0, now correctly parents the async spans to the context where the query resolution happens.
This context is the place where the results from the async query were consumed. For example: async_relation = Model.load_async schedules the async query, but the query span is only attached to the active trace at relation.load time). This only affects parenting, as the execution time of the async span is always accurate.
The active trace, started in a thread, will now see spans from a background async thread attached to it.
Change log entry Yes. Add support for ActiveRecord async queries
Additional Notes:
How to test the change?
⚠️ Warnings
🧪 5 Tests failed
ActiveRecord instantiation instrumentation when a model is instantiated and service_name is not set is expected to equal 2fromrspec(Datadog) (✨ Fix with BitsAI)expected #<Integer:5> => 2 got #<Integer:7> => 3 Compared using equal?, which compares object identity, but expected and actual are not the same object. Use \`expect(actual).to eq(expected)\` if you don't care about object identity in this example. Failure/Error: expect(spans.length).to be(2) ...
ActiveRecord instantiation instrumentation when a model is instantiated and service_name is set is expected to equal 2fromrspec(Datadog) (✨ Fix with BitsAI)expected #<Integer:5> => 2 got #<Integer:7> => 3 Compared using equal?, which compares object identity, but expected and actual are not the same object. Use \`expect(actual).to eq(expected)\` if you don't care about object identity in this example. Failure/Error: expect(spans.length).to be(2) ...View all
ActiveRecord instantiation instrumentation when a model is instantiated behaves like analytics for integration when configured by configuration options and explicitly disabled and global flag is explicitly disabled behaves like sample rate value isn't set is expected to equal 2fromrspec(Datadog) (✨ Fix with BitsAI)expected #<Integer:5> => 2 got #<Integer:7> => 3 Compared using equal?, which compares object identity, but expected and actual are not the same object. Use \`expect(actual).to eq(expected)\` if you don't care about object identity in this example. Failure/Error: expect(spans.length).to be(2) ...
ℹ️ Info
❄️ No new flaky tests detected
This comment will be updated automatically if new data arrives.🔗 Commit SHA: 48f5976 | Docs | Was this helpful? Give us feedback!
Benchmarks
Benchmark execution time: 2025-10-06 13:25:01
Comparing candidate commit 48f5976b82271cae1595665988d37fbabab207db in PR branch fix-load-async with baseline commit 49a5c68571fe1b486f04525e3e6a99c3d6e49c0e in branch master.
Found 0 performance improvements and 2 performance regressions! Performance is the same for 42 metrics, 2 unstable metrics.
scenario:line instrumentation - targeted
- 🟥
throughput[-15239.050op/s; -14638.509op/s] or [-9.818%; -9.431%]
scenario:method instrumentation
- 🟥
throughput[-11448.569op/s; -10771.757op/s] or [-6.559%; -6.171%]