Presenting a new gem for tracing Active Record, I wish existed earlier - GitHub - fatkodima/active_record_tracer: A tracer for Active Record queries
Many times I crafted code to get similar reports like in the gem - to profile slow tests, rake tasks, controllers, jobs, find the most popular queries or the most loaded records, N+1s, the lines producing the most queries/records etc.
I hope you will find it useful too.
Sample usage:
report = ActiveRecordTracer.report do
# run your code here
end
report.pretty_print
Sample output:
Total runtime: 181.36s
Total SQL queries: 8936
Total loaded records: 2648
Top SQL queries
-----------------------------------
857 SAVEPOINT active_record_1
856 RELEASE SAVEPOINT active_record_1
382 SELECT "user_roles".* FROM "user_roles" WHERE "user_roles"."id" = $1 LIMIT $2
362 SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT $2
301 INSERT INTO "accounts" ("username", "domain", "private_key") VALUES ($1, $2, $3) RETURNING "id"
219 SELECT "settings".* FROM "settings" WHERE "settings"."thing_type" IS NULL AND "settings"."thing_id" IS NULL AND "settings"."var" = $1 LIMIT $2
217 INSERT INTO "conversations" ("uri", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"
201 SELECT "statuses".* FROM "statuses" WHERE "statuses"."deleted_at" IS NULL AND "statuses"."id" = $1 ORDER BY "statuses"."id" DESC LIMIT $2
175 BEGIN
174 ROLLBACK
169 SELECT "account_stats".* = $1 LIMIT $2
158 SELECT 1 AS one FROM "instances" WHERE "instances"."domain" = $1 LIMIT $2
155 SELECT 1 AS one FROM "users" WHERE "users"."email" = $1 LIMIT $2
152 SELECT "domain_blocks".* FROM "domain_blocks" WHERE "domain_blocks"."domain" IN ($1, $2) ORDER BY CHAR_LENGTH(domain) DESC LIMIT $3
...
SQL queries by location
-----------------------------------
586 app/validators/unique_username_validator.rb:12
391 app/models/user_role.rb:112
314 app/models/concerns/account/counters.rb:54
253 app/models/concerns/account/interactions.rb:116
217 app/models/setting.rb:80
215 app/models/concerns/status/safe_reblog_insert.rb:19
168 app/models/concerns/account/counters.rb:48
165 app/models/domain_block.rb:73
158 app/models/concerns/domain_materializable.rb:13
140 app/models/email_domain_block.rb:61
137 app/models/concerns/database_view_record.rb:8
123 app/lib/activitypub/activity/create.rb:86
122 app/lib/activitypub/tag_manager.rb:185
120 app/models/status.rb:400
110 app/models/account.rb:375
98 app/models/concerns/account/finder_concern.rb:32
98 app/models/concerns/account/finder_concern.rb:16
87 app/models/status.rb:377
78 app/models/status.rb:289
74 app/models/account.rb:150
68 app/models/follow_request.rb:38
64 app/services/activitypub/fetch_featured_collection_service.rb:76
63 app/services/activitypub/process_status_update_service.rb:163
63 app/models/account.rb:265
62 app/models/status.rb:371
...
SQL queries by file
-----------------------------------
586 app/validators/unique_username_validator.rb
563 app/models/concerns/account/counters.rb
495 app/models/status.rb
392 app/models/user_role.rb
376 app/models/concerns/account/interactions.rb
340 app/models/account.rb
337 app/services/activitypub/process_status_update_service.rb
241 app/models/setting.rb
217 app/models/concerns/status/safe_reblog_insert.rb
213 app/lib/activitypub/activity/create.rb
196 app/models/concerns/account/finder_concern.rb
166 app/services/fan_out_on_write_service.rb
165 app/models/domain_block.rb
158 app/models/concerns/domain_materializable.rb
155 app/models/email_domain_block.rb
137 app/models/concerns/database_view_record.rb
134 app/lib/activitypub/tag_manager.rb
107 app/models/follow_request.rb
106 app/lib/feed_manager.rb
...
SQL queries by backtrace
-----------------------------------
539 app/validators/unique_username_validator.rb:12:in `validate'
306 app/models/user_role.rb:112:in `everyone'
app/models/user.rb:160:in `role'
app/models/user.rb:486:in `sanitize_role'
168 app/models/concerns/account/interactions.rb:116:in `follow!'
140 app/models/email_domain_block.rb:61:in `blocking?'
app/models/email_domain_block.rb:49:in `match?'
app/models/email_domain_block.rb:94:in `requires_approval?'
app/models/user.rb:470:in `sign_up_email_requires_approval?'
app/models/user.rb:416:in `set_approved'
137 app/models/concerns/domain_materializable.rb:13:in `refresh_instances_view'
124 app/models/concerns/account/counters.rb:54:in `updated_account_stat'
app/models/concerns/account/counters.rb:38:in `update_count!'
app/models/concerns/account/counters.rb:24:in `increment_count!'
app/models/status.rb:455:in `increment_counter_caches'
...
Loaded records by model
-----------------------------------
533 Account
390 UserRole
287 Status
101 AccountStat
70 Setting
64 User
29 Follow
24 AccountDeletionRequest
21 MediaAttachment
20 Conversation
17 FollowRequest
17 Tag
...
Loaded records by location
-----------------------------------
381 app/models/user_role.rb:112
98 app/models/concerns/account/finder_concern.rb:16
65 app/models/concerns/account/finder_concern.rb:32
64 app/models/setting.rb:80
61 app/models/concerns/account/counters.rb:48
53 app/lib/activitypub/tag_manager.rb:185
46 app/models/concerns/rate_limitable.rb:23
45 app/workers/distribution_worker.rb:10
45 app/services/fan_out_on_write_service.rb:14
...
Loaded records by file
-----------------------------------
385 app/models/user_role.rb
163 app/models/concerns/account/finder_concern.rb
97 app/models/concerns/account/counters.rb
70 app/models/setting.rb
68 app/models/account.rb
57 app/services/fan_out_on_write_service.rb
53 app/lib/activitypub/tag_manager.rb
...
Loaded records by backtrace
-----------------------------------
298 app/models/user_role.rb:112:in `everyone'
app/models/user.rb:160:in `role'
app/models/user.rb:486:in `sanitize_role'
61 app/models/setting.rb:80:in `block in []'
app/models/setting.rb:79:in `[]'
app/models/setting.rb:65:in `method_missing'
app/models/user.rb:474:in `open_registrations?'
app/models/user.rb:419:in `set_approved'
45 app/services/fan_out_on_write_service.rb:14:in `call'
app/workers/distribution_worker.rb:10:in `block in perform'
app/models/concerns/lockable.rb:12:in `block (2 levels) in with_redis_lock'
app/models/concerns/lockable.rb:10:in `block in with_redis_lock'
app/lib/redis_configuration.rb:10:in `with'
...