{"id":13877878,"url":"https://github.com/fatkodima/active_record_tracer","last_synced_at":"2025-04-06T07:15:26.408Z","repository":{"id":247779946,"uuid":"826826499","full_name":"fatkodima/active_record_tracer","owner":"fatkodima","description":"A tracer for Active Record queries","archived":false,"fork":false,"pushed_at":"2024-08-10T10:27:31.000Z","size":17,"stargazers_count":182,"open_issues_count":0,"forks_count":0,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-30T06:09:15.705Z","etag":null,"topics":["activerecord","gem","rails","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fatkodima.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-10T13:03:02.000Z","updated_at":"2025-03-18T11:47:25.000Z","dependencies_parsed_at":"2024-09-21T22:30:40.950Z","dependency_job_id":null,"html_url":"https://github.com/fatkodima/active_record_tracer","commit_stats":{"total_commits":10,"total_committers":1,"mean_commits":10.0,"dds":0.0,"last_synced_commit":"804224ae0c7eb879ffcd0cbb3f15ab69d93be1b5"},"previous_names":["fatkodima/active_record_tracer"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fatkodima%2Factive_record_tracer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fatkodima%2Factive_record_tracer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fatkodima%2Factive_record_tracer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fatkodima%2Factive_record_tracer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fatkodima","download_url":"https://codeload.github.com/fatkodima/active_record_tracer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247445682,"owners_count":20939961,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["activerecord","gem","rails","ruby"],"created_at":"2024-08-06T08:01:33.820Z","updated_at":"2025-04-06T07:15:26.386Z","avatar_url":"https://github.com/fatkodima.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# ActiveRecordTracer\n\nA tracer for Active Record queries\n\n[![Build Status](https://github.com/fatkodima/active_record_tracer/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/fatkodima/active_record_tracer/actions/workflows/test.yml)\n\nYou identified (or suspect) that the reason for the slowness of some code is Active Record,\nspecifically lots of queries and/or loaded records. How do you easily detect which queries,\nwhich records are loaded the most, and the sources of those? This tool to the rescue!\n\n## Requirements\n\n- ruby 3.1+\n- activerecord 7.0+\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem \"active_record_tracer\", group: [:development, :test]\n```\n\nAnd then execute:\n\n```sh\n$ bundle\n```\n\nOr install it yourself as:\n\n```sh\n$ gem install active_record_tracer\n```\n\n## Usage\n\n```ruby\nrequire \"active_record_tracer\"\nreport = ActiveRecordTracer.report do\n  # run your code here\nend\n\nreport.pretty_print\n```\n\nOr, you can use the `.start`/`.stop` API as well:\n\n```ruby\nrequire \"active_record_tracer\"\n\nActiveRecordTracer.start\n\n# run your code\n\nreport = ActiveRecordTracer.stop\nreport.pretty_print\n```\n\n**NOTE**: `.start`/`.stop` can only be run once per report, and `.stop` will\nbe the only time you can retrieve the report using this API.\n\n### Tracing tests\n\nTo trace tests, use the folloding somewhere in the `rails_helper.rb`/`test_helper.rb`:\n\n```ruby\nActiveRecordTracer.start\nat_exit do\n  report = ActiveRecordTracer.stop\n  report.pretty_print(to_file: \"tmp/active_record_tracer-tests.txt\")\nend\n```\n\n## Options\n\n### `report`\n\nThe `report` method can take a few options:\n\n* `top`: maximum number of entries to display in a report (default is `50`)\n* `backtrace_lines`: maximum number of backtrace lines to include in the report (default is `5`)\n* `ignore_cached_queries`: whether to ignore cached queries (default is `false`)\n* `ignore_schema_queries`: whether to ignore schema queries (default is `true`)\n\nCheck out `Reporter#new` for more details.\n\n### `pretty_print`\n\nThe `pretty_print` method can take a few options:\n\n* `to_file`: a path to your log file - can be given a String\n* `detailed_report`: whether to include detailed information - can be given a Boolean\n\nCheck out `Report#pretty_print` for more details.\n\n## Example output\n\n```\nTotal runtime: 181.36s\nTotal SQL queries: 8936\nTotal loaded records: 2648\n\nTop SQL queries\n-----------------------------------\n     857  SAVEPOINT active_record_1\n\n     856  RELEASE SAVEPOINT active_record_1\n\n     382  SELECT \"user_roles\".* FROM \"user_roles\" WHERE \"user_roles\".\"id\" = $1 LIMIT $2\n\n     362  SELECT \"accounts\".* FROM \"accounts\" WHERE \"accounts\".\"id\" = $1 LIMIT $2\n\n     301  INSERT INTO \"accounts\" (\"username\", \"domain\", \"private_key\") VALUES ($1, $2, $3) RETURNING \"id\"\n\n     219  SELECT \"settings\".* FROM \"settings\" WHERE \"settings\".\"thing_type\" IS NULL AND \"settings\".\"thing_id\" IS NULL AND \"settings\".\"var\" = $1 LIMIT $2\n\n     217  INSERT INTO \"conversations\" (\"uri\", \"created_at\", \"updated_at\") VALUES ($1, $2, $3) RETURNING \"id\"\n\n     201  SELECT \"statuses\".* FROM \"statuses\" WHERE \"statuses\".\"deleted_at\" IS NULL AND \"statuses\".\"id\" = $1 ORDER BY \"statuses\".\"id\" DESC LIMIT $2\n\n     175  BEGIN\n\n     174  ROLLBACK\n\n     169  SELECT \"account_stats\".* = $1 LIMIT $2\n\n     158  SELECT 1 AS one FROM \"instances\" WHERE \"instances\".\"domain\" = $1 LIMIT $2\n\n     155  SELECT 1 AS one FROM \"users\" WHERE \"users\".\"email\" = $1 LIMIT $2\n\n     152  SELECT \"domain_blocks\".* FROM \"domain_blocks\" WHERE \"domain_blocks\".\"domain\" IN ($1, $2) ORDER BY CHAR_LENGTH(domain) DESC LIMIT $3\n...\n\nSQL queries by location\n-----------------------------------\n     586  app/validators/unique_username_validator.rb:12\n     391  app/models/user_role.rb:112\n     314  app/models/concerns/account/counters.rb:54\n     253  app/models/concerns/account/interactions.rb:116\n     217  app/models/setting.rb:80\n     215  app/models/concerns/status/safe_reblog_insert.rb:19\n     168  app/models/concerns/account/counters.rb:48\n     165  app/models/domain_block.rb:73\n     158  app/models/concerns/domain_materializable.rb:13\n     140  app/models/email_domain_block.rb:61\n     137  app/models/concerns/database_view_record.rb:8\n     123  app/lib/activitypub/activity/create.rb:86\n     122  app/lib/activitypub/tag_manager.rb:185\n     120  app/models/status.rb:400\n     110  app/models/account.rb:375\n      98  app/models/concerns/account/finder_concern.rb:32\n      98  app/models/concerns/account/finder_concern.rb:16\n      87  app/models/status.rb:377\n      78  app/models/status.rb:289\n      74  app/models/account.rb:150\n      68  app/models/follow_request.rb:38\n      64  app/services/activitypub/fetch_featured_collection_service.rb:76\n      63  app/services/activitypub/process_status_update_service.rb:163\n      63  app/models/account.rb:265\n      62  app/models/status.rb:371\n...\n\nSQL queries by file\n-----------------------------------\n     586  app/validators/unique_username_validator.rb\n     563  app/models/concerns/account/counters.rb\n     495  app/models/status.rb\n     392  app/models/user_role.rb\n     376  app/models/concerns/account/interactions.rb\n     340  app/models/account.rb\n     337  app/services/activitypub/process_status_update_service.rb\n     241  app/models/setting.rb\n     217  app/models/concerns/status/safe_reblog_insert.rb\n     213  app/lib/activitypub/activity/create.rb\n     196  app/models/concerns/account/finder_concern.rb\n     166  app/services/fan_out_on_write_service.rb\n     165  app/models/domain_block.rb\n     158  app/models/concerns/domain_materializable.rb\n     155  app/models/email_domain_block.rb\n     137  app/models/concerns/database_view_record.rb\n     134  app/lib/activitypub/tag_manager.rb\n     107  app/models/follow_request.rb\n     106  app/lib/feed_manager.rb\n...\n\nSQL queries by backtrace\n-----------------------------------\n     539  app/validators/unique_username_validator.rb:12:in `validate'\n\n     306  app/models/user_role.rb:112:in `everyone'\n          app/models/user.rb:160:in `role'\n          app/models/user.rb:486:in `sanitize_role'\n\n     168  app/models/concerns/account/interactions.rb:116:in `follow!'\n\n     140  app/models/email_domain_block.rb:61:in `blocking?'\n          app/models/email_domain_block.rb:49:in `match?'\n          app/models/email_domain_block.rb:94:in `requires_approval?'\n          app/models/user.rb:470:in `sign_up_email_requires_approval?'\n          app/models/user.rb:416:in `set_approved'\n\n     137  app/models/concerns/domain_materializable.rb:13:in `refresh_instances_view'\n\n     124  app/models/concerns/account/counters.rb:54:in `updated_account_stat'\n          app/models/concerns/account/counters.rb:38:in `update_count!'\n          app/models/concerns/account/counters.rb:24:in `increment_count!'\n          app/models/status.rb:455:in `increment_counter_caches'\n...\n\nLoaded records by model\n-----------------------------------\n     533  Account\n     390  UserRole\n     287  Status\n     101  AccountStat\n      70  Setting\n      64  User\n      29  Follow\n      24  AccountDeletionRequest\n      21  MediaAttachment\n      20  Conversation\n      17  FollowRequest\n      17  Tag\n...\n\nLoaded records by location\n-----------------------------------\n     381  app/models/user_role.rb:112\n      98  app/models/concerns/account/finder_concern.rb:16\n      65  app/models/concerns/account/finder_concern.rb:32\n      64  app/models/setting.rb:80\n      61  app/models/concerns/account/counters.rb:48\n      53  app/lib/activitypub/tag_manager.rb:185\n      46  app/models/concerns/rate_limitable.rb:23\n      45  app/workers/distribution_worker.rb:10\n      45  app/services/fan_out_on_write_service.rb:14\n...\n\nLoaded records by file\n-----------------------------------\n     385  app/models/user_role.rb\n     163  app/models/concerns/account/finder_concern.rb\n      97  app/models/concerns/account/counters.rb\n      70  app/models/setting.rb\n      68  app/models/account.rb\n      57  app/services/fan_out_on_write_service.rb\n      53  app/lib/activitypub/tag_manager.rb\n...\n\nLoaded records by backtrace\n-----------------------------------\n     298  app/models/user_role.rb:112:in `everyone'\n          app/models/user.rb:160:in `role'\n          app/models/user.rb:486:in `sanitize_role'\n\n      61  app/models/setting.rb:80:in `block in []'\n          app/models/setting.rb:79:in `[]'\n          app/models/setting.rb:65:in `method_missing'\n          app/models/user.rb:474:in `open_registrations?'\n          app/models/user.rb:419:in `set_approved'\n\n      45  app/services/fan_out_on_write_service.rb:14:in `call'\n          app/workers/distribution_worker.rb:10:in `block in perform'\n          app/models/concerns/lockable.rb:12:in `block (2 levels) in with_redis_lock'\n          app/models/concerns/lockable.rb:10:in `block in with_redis_lock'\n          app/lib/redis_configuration.rb:10:in `with'\n...\n```\n\n## Development\n\nAfter checking out the repo, run `bundle install` to install dependencies. Then, run `bundle exec rake test` to run the tests. This project uses multiple Gemfiles to test against multiple versions of Active Record; you can run the tests against the specific version with `BUNDLE_GEMFILE=gemfiles/activerecord_70.gemfile bundle exec rake test`.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/fatkodima/active_record_tracer.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffatkodima%2Factive_record_tracer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffatkodima%2Factive_record_tracer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffatkodima%2Factive_record_tracer/lists"}