{"id":13879561,"url":"https://github.com/igorkasyanchuk/rails_performance","last_synced_at":"2025-04-28T12:14:50.395Z","repository":{"id":40333181,"uuid":"235976018","full_name":"igorkasyanchuk/rails_performance","owner":"igorkasyanchuk","description":"Monitor performance of you Rails applications (self-hosted and free)","archived":false,"fork":false,"pushed_at":"2025-04-08T10:28:23.000Z","size":6816,"stargazers_count":1126,"open_issues_count":19,"forks_count":67,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-04-28T12:14:43.549Z","etag":null,"topics":["apm","datadog","newrelic","performance","performance-monitoring","rails","ruby","ruby-on-rails"],"latest_commit_sha":null,"homepage":"https://www.railsjazz.com/","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/igorkasyanchuk.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"MIT-LICENSE","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},"funding":{"patreon":"igorkasyanchuk"}},"created_at":"2020-01-24T09:46:01.000Z","updated_at":"2025-04-26T14:13:15.000Z","dependencies_parsed_at":"2025-01-07T18:04:11.504Z","dependency_job_id":"46e54d62-1997-415f-b51e-ed8e0ab766ba","html_url":"https://github.com/igorkasyanchuk/rails_performance","commit_stats":{"total_commits":236,"total_committers":19,"mean_commits":"12.421052631578947","dds":0.2033898305084746,"last_synced_commit":"1b3e6b023539c0655035c6b68dd19a53073779f2"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorkasyanchuk%2Frails_performance","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorkasyanchuk%2Frails_performance/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorkasyanchuk%2Frails_performance/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorkasyanchuk%2Frails_performance/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/igorkasyanchuk","download_url":"https://codeload.github.com/igorkasyanchuk/rails_performance/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251311332,"owners_count":21569009,"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":["apm","datadog","newrelic","performance","performance-monitoring","rails","ruby","ruby-on-rails"],"created_at":"2024-08-06T08:02:25.256Z","updated_at":"2025-04-28T12:14:50.376Z","avatar_url":"https://github.com/igorkasyanchuk.png","language":"Ruby","funding_links":["https://patreon.com/igorkasyanchuk"],"categories":["Ruby"],"sub_categories":[],"readme":"# Rails Performance\n\n[![Tests](https://github.com/igorkasyanchuk/rails_performance/actions/workflows/ruby.yml/badge.svg)](https://github.com/igorkasyanchuk/rails_performance/actions/workflows/ruby.yml)\n[![RailsJazz](https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/my_other.svg?raw=true)](https://www.railsjazz.com)\n[My Cheatsheets](https://cheatsheetshero.com/user/igor-kasyanchuk)\n\nA self-hosted tool to monitor the performance of your Ruby on Rails application.\n\nThis is a **simple and free alternative** to the New Relic APM, Datadog or other similar services.\n\n![Demo](docs/rails_performance.gif)\n\nA new version with P50, P90, P99, throughput, and more is available.\n\n![Home](docs/rails_performance_updated_home.png)\n\nDetailed p50, p90, p99 response time information.\n\n![Home](docs/rails_performance_recent_requests.png)\n\n(more screenshots below)\n\nIt allows you to track:\n\n- real-time monitoring on the Recent tab\n- see your p50, p90, p99 response time\n- monitor system resources (CPU, memory, disk)\n- monitor slow requests\n- throughput report (see amount of RPM (requests per minute))\n- an average response time\n- the slowest controllers \u0026 actions\n- total duration of time spent per request, views rendering, DB\n- SQL queries, rendering logs in \"Recent Requests\" section\n- simple 500-crashes reports\n- Sidekiq jobs\n- Delayed Job jobs\n- Grape API inside Rails app\n- Rake tasks performance\n- Custom events wrapped with `RailsPerformance.measure do .. end` block\n- works with Rails 4.2+ (and probably 4.1, 4.0 too) and Ruby 2.2+\n\nAll data are stored in `local` Redis and not sent to any 3rd party servers.\n\n## Production\n\nGem is production-ready. At least on my 2 applications with ~800 unique users per day it works perfectly.\n\nJust don't forget to protect performance dashboard with http basic auth or check of current_user.\n\n## Usage\n\n```\n1. Add gem to the Gemfile (in appropriate group if needed)\n2. Start rails server\n3. Make a few requests to your app\n4. open localhost:3000/rails/performance\n5. Tune the configuration and deploy to production\n```\n\nDefault configuration is listed below. But you can override it.\n\nCreate `config/initializers/rails_performance.rb` in your app:\n\n```ruby\nRailsPerformance.setup do |config|\n  config.redis    = Redis.new(url: ENV[\"REDIS_URL\"].presence || \"redis://127.0.0.1:6379/0\") # or Redis::Namespace.new(\"rails-performance\", redis: Redis.new), see below in README\n  config.duration = 4.hours\n\n  config.debug    = false # currently not used\u003e\n  config.enabled  = true\n\n  # configure Recent tab (time window and limit of requests)\n  # config.recent_requests_time_window = 60.minutes\n  # config.recent_requests_limit = nil # or 1000\n\n  # configure Slow Requests tab (time window, limit of requests and threshold)\n  # config.slow_requests_time_window = 4.hours # time window for slow requests\n  # config.slow_requests_limit = 500 # number of max rows\n  # config.slow_requests_threshold = 500 # number of ms\n\n  # default path where to mount gem,\n  # alternatively you can mount the RailsPerformance::Engine in your routes.rb\n  config.mount_at = '/rails/performance'\n\n  # protect your Performance Dashboard with HTTP BASIC password\n  config.http_basic_authentication_enabled   = false\n  config.http_basic_authentication_user_name = 'rails_performance'\n  config.http_basic_authentication_password  = 'password12'\n\n  # if you need an additional rules to check user permissions\n  config.verify_access_proc = proc { |controller| true }\n  # for example when you have `current_user`\n  # config.verify_access_proc = proc { |controller| controller.current_user \u0026\u0026 controller.current_user.admin? }\n\n  # You can ignore endpoints with Rails standard notation controller#action\n  # config.ignored_endpoints = ['HomeController#contact']\n\n  # You can ignore request paths by specifying the beginning of the path.\n  # For example, all routes starting with '/admin' can be ignored:\n  config.ignored_paths = ['/rails/performance', '/admin']\n\n  # store custom data for the request\n  # config.custom_data_proc = proc do |env|\n  #   request = Rack::Request.new(env)\n  #   {\n  #     email: request.env['warden'].user\u0026.email, # if you are using Devise for example\n  #     user_agent: request.env['HTTP_USER_AGENT']\n  #   }\n  # end\n\n  # config home button link\n  config.home_link = '/'\n\n  # To skip some Rake tasks from monitoring\n  config.skipable_rake_tasks = ['webpacker:compile']\n\n  # To monitor rake tasks performance, you need to include rake tasks\n  # config.include_rake_tasks = false\n\n  # To monitor custom events with `RailsPerformance.measure` block\n  # config.include_custom_events = true\n\n  # To monitor system resources (CPU, memory, disk)\n  # to enabled add required gems (see README)\n  # config.system_monitor_duration = 24.hours\nend if defined?(RailsPerformance)\n```\n\nAdditionally you might need to configure app time zone. You can do it in `config/application.rb`:\n\n```ruby\nconfig.time_zone = 'Eastern Time (US \u0026 Canada)'\n```\n\nGem will present charts/tables in the app timezone. If it's not set, it will use UTC.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'rails_performance'\n\n# or\n\ngroup :development, :production do\n  gem 'rails_performance'\nend\n```\n\nAnd then execute:\n\n```bash\n$ bundle\n```\n\nCreate default configuration file:\n\n```bash\n$ rails generate rails_performance:install\n```\n\nHave a look at `config/initializers/rails_performance.rb` and adjust the configuration to your needs.\n\nYou must also have installed Redis server, because this gem is storing data into it.\n\nAfter installation and configuration, start your Rails application, make a few requests, and open `https://localhost:3000/rails/performance` URL.\n\n### Alternative: Mounting the engine yourself\n\nIf you, for whatever reason (company policy, devise, ...) need to mount RailsPerformance yourself, feel free to do so by using the following snippet as inspiration.\nYou can skip the `mount_at` and `http_basic_authentication_*` configurations then, if you like.\n\n```ruby\n# config/routes.rb\nRails.application.routes.draw do\n  ...\n  # example for usage with Devise\n  authenticate :user, -\u003e (user) { user.admin? } do\n    mount RailsPerformance::Engine, at: 'rails/performance'\n  end\nend\n```\n\n### Custom data\n\nYou need to configure `config.custom_data_proc`. And you can capture current_user, HTTP User Agent, etc. This proc is executed inside middleware, and you have access to Rack \"env\".\n\n![Custom Data](docs/custom_data.png)\n\n\n### Server Monitoring\n\n![Server Monitoring](docs/rails_performance_cpu_memory_storage.png)\n\nYou can monitor system resources (CPU, memory, disk) by adding a gem to your Gemfile:\n\n```ruby\ngem \"sys-filesystem\"\ngem \"sys-cpu\"\ngem \"get_process_mem\"\n```\n\nOnce you add these gems, it will track and show you the system resources on the dashboard.\n\nIf you have multiple servers running the same app, it will use store metrics per server. You can configure the the env variable ENV[\"RAILS_PERFORMANCE_SERVER_ID\"] or using `hostname` command.\n\nBasically using this code:\n\n```ruby\n      def server_id\n        @server_id ||= ENV[\"RAILS_PERFORMANCE_SERVER_ID\"] || `hostname`.strip\n      end\n```\n\nFor Kamal for example:\n\n```yaml\nenv:\n  clear:\n    RAILS_PERFORMANCE_SERVER_ID: \"server\"\n```\n\nYou can also specifify custom \"context\" and \"role\" for monitoring, by changing the env variables:\n\n```ruby\nRailsPerformance::Extensions::ResourceMonitor.new(\n  ENV[\"RAILS_PERFORMANCE_SERVER_CONTEXT\"].presence || \"rails\",\n  ENV[\"RAILS_PERFORMANCE_SERVER_ROLE\"].presence || \"web\"\n)\n```\n\nMore information here: `lib/rails_performance/engine.rb`.\n\nPS: right now it can only distinguish between web app servers and the sidekiq servers.\n\n### Custom events\n\n```ruby\nRailsPerformance.measure(\"some label\", \"some namespace\") do\n   # your code\nend\n```\n\n## Using with Redis Namespace\n\nIf you want to use Redis namespace (for example when you have multiple apps running on the same server), you can configure it like this:\n\n```ruby\n  config.redis = Redis::Namespace.new(\"#{Rails.env}-rails-performance\", redis: Redis.new(url: ENV[\"REDIS_URL\"].presence || \"redis://127.0.0.1:6379/0\"))\n```\n\nand add a gem dependency to the Gemfile:\n\n```ruby\ngem 'redis-namespace'\n```\n\n## How it works\n\n![Schema](docs/rails_performance.png)\n\nIn addition it's wrapping gems internal methods and collecting performance information. See `./lib/rails_performance/gems/*` for more information.\n\n## Limitations\n\n- it doesn't track params of POST/PUT requests\n- it doesn't track Redis/ElasticSearch or other apps\n- it can't compare historical data\n- depending on your load you may need to reduce time of for how long you store data, because all calculations are done in memory and it could take some time for high-load apps\n\n## Redis\n\nGem is using Redis. This is the only one dependency.\n\nAll information is stored into Redis. The default expiration time is set to `config.duration` from the configuration.\n\n## Development \u0026 Testing\n\nJust clone the repo, setup dummy app (`rails db:migrate`).\n\nAfter this:\n\n- rails s\n- rake test\n\nIf you need quickly clear Redis data, you can use `rails runner 'RailsPerformance.redis.flushdb'`.\n\nLike a regular web development.\n\nPlease note that to simplify integration with other apps all CSS/JS are bundled inside, and delivered in body of the request. This is to avoid integration with assets pipeline or webpacker.\n\nFor UI changes you need to use Bulma CSS (https://bulma.io/documentation).\n\n## Why\n\nThe idea of this gem grew from curiosity how many RPM my app receiving per day. Later it evolved to something more powerful.\n\n## TODO\n\n- documentation in Readme?\n- capture stacktrace of 500 errors and show in side panel\n- time/zone config?\n- connected charts on dashboard, when zoom, when hover?\n- ability to zoom to see requests withing specific datetime range\n- better hints?\n- export to csv\n- better stats tooltip, do not show if nothing to show\n- dark mode toggle? save to the cookies?\n- integration with elastic search? or other?\n- monitor active job?\n- better logo?\n- number of requests last 24 hours, hour, etc.\n- collect deprecation.rails\n- fix misspellings?\n- show \"loading banner\" until jquery is loaded?\n- better UI on smaller screens? Recent requests when URL's are long? Truncate with CSS?\n- rules for highlighting durations? how many ms to show warning, alert\n- elastic search\n- searchkiq\n- sinatra?\n- tests to check what is actually stored in redis db after request\n- upgrade bulma\n\n## Contributing\n\nYou are welcome to contribute. I've a big list of TODO.\n\nIf \"schema\" how records are stored i Redis is changed, and this is a breaking change, update: `RailsPerformance::SCHEMA` to a newer value.\n\n## Big thanks to contributors\n\nhttps://github.com/igorkasyanchuk/rails_performance/graphs/contributors\n\n## Other\n\n[\u003cimg src=\"https://opensource-heroes.com/svg/embed/igorkasyanchuk/rails_performance\"\n/\u003e](https://opensource-heroes.com/r/igorkasyanchuk/rails_performance)\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\n[\u003cimg src=\"https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/more_gems.png?raw=true\"\n/\u003e](https://www.railsjazz.com/?utm_source=github\u0026utm_medium=bottom\u0026utm_campaign=rails_performance)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figorkasyanchuk%2Frails_performance","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Figorkasyanchuk%2Frails_performance","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figorkasyanchuk%2Frails_performance/lists"}