Watch the real transaction
Measurement starts when the actual BEGIN finishes and ends when COMMIT or ROLLBACK starts. Work before a lazy transaction opens is excluded.
Your database did its job. What happened in between?
Txnap finds time spent away from the database while an Active Record transaction is open and locks may still be held.
A Ruby gem. No separate service to run.
BEGIN0 msUPDATE users112 msNo database work.
A row lock may still be held.
INSERT audit_logs854 msCOMMIT1,024 msAn external request. A file read. A little too much Ruby. Work between queries can keep a transaction open long after the database is done. Slow-query tools don’t expose that gap. Txnap does.
Measurement starts when the actual BEGIN finishes and ends when COMMIT or ROLLBACK starts. Work before a lazy transaction opens is excluded.
See the interval between database events, the SQL on either side, and the application call sites. The default reporting threshold is 100 ms.
Get likely lock candidates in your logs, raise in tests, or send the idle_gap.txnap notification to your existing APM.
The report points to the queries around the gap and the code that issued them. Start there, then move slow non-database work outside the transaction.
Lock detection is heuristic: a candidate isn’t proof that a lock is still held. Txnap observes transactions; it never changes their behavior.
See what is measuredTxnap::IdleGapDetected
Transaction held for 1,024 ms (BEGIN → COMMIT)
Database time: 31 ms
Longest non-database gap: 742 ms
Gap occurred between:
after: UPDATE "users" SET ...
(app/services/checkout.rb:88)
before: INSERT INTO "audit_logs" ...
(app/services/checkout.rb:131)
Locks possibly held during the gap:
UPDATE users (row lock)
app/services/checkout.rb:88
Add the gem, set a threshold, and let your application run. Rails installs the notification subscribers automatically.
Explore all configuration optionsUntil the first release, install directly from GitHub.
gem "txnap", github: "ydah/txnap"
bundle install
# config/initializers/txnap.rb
Txnap.configure do |config|
config.mode = :log
config.gap_threshold = 0.1 # seconds
end
Using Active Record without Rails? Call Txnap.install! after configuration.