Rails Performance

repository·master·Indexed 22 days ago

https://github.com/igorkasyanchuk/rails_performance

A self-hosted, Redis-backed Application Performance Monitoring (APM) tool for Ruby on Rails. It provides real-time monitoring, response time percentiles (p50, p90, p99), system resource tracking (CPU, Memory, Disk), and custom event logging. It supports tracking for Rails requests, Sidekiq, Delayed Job, Grape, and Rake tasks, offering a lightweight alternative to services like New Relic or Datadog.

Tokens
4.6K
Snippets
9
Records
30
Agent score
79%

What's inside rails_performance

  1. Mount RailsPerformance manually in routes.rb

    master

    If you need to control the mounting point or wrap the dashboard in custom authentication (e.g., using Devise), you can mount the engine directly in your config/routes.rb instead of using config.mount_at.

    # config/routes.rb
    Rails.application.routes.draw do
      # Example: Restrict dashboard to admins using Devise
      authenticate :user, -> (user) { user.admin? } do
        mount RailsPerformance::Engine, at: 'rails/performance'
      end
    end
    # config/routes.rb
    Rails.application.routes.draw do
      ...
      # example for usage with Devise
      authenticate :user, -> (user) { user.admin? } do
        mount RailsPerformance::Engine, at: 'rails/performance'
      end
    end
  2. Use Redis Namespace for multiple apps

    master

    If you are running multiple applications on the same Redis server, you can use the redis-namespace gem to prevent data collisions.

    1. Add gem 'redis-namespace' to your Gemfile.
    2. Configure the redis connection in your initializer:
    config.redis = Redis::Namespace.new("#{Rails.env}-rails-performance", redis: Redis.new(url: ENV["REDIS_URL"].presence || "redis://127.0.0.1:6379/0"))
  3. Monitor system resources (CPU, Memory, Disk)

    master

    To enable system resource monitoring on the dashboard, add the following gems to your Gemfile:

    gem "sys-filesystem"
    gem "sys-cpu"
    gem "get_process_mem"

    If running on multiple servers, you can distinguish them by setting the ENV["RAILS_PERFORMANCE_SERVER_ID"] environment variable or using the hostname command. For example, in a Kamal deployment, you can set this in your config/deploy.yml.

  4. Install Rails Performance

    master

    To install the gem, add it to your Gemfile. You can include it in specific groups like :development and :production to avoid overhead in other environments.

    1. Add to Gemfile:
    group :development, :production do
      gem 'rails_performance'
    end
    1. Run bundle.
    2. Generate the configuration file:
    $ rails generate rails_performance:install

    Note: You must have a Redis server installed and running, as the gem uses Redis to store all performance data.

  5. How request recording middleware works

    master

    The RailsPerformance::Rails::Middleware intercepts incoming requests to capture performance traces and request metadata.

    Key behaviors:

    • Skipping: If the request path matches RailsPerformance.mount_at, the middleware skips recording to avoid infinite loops or recording the performance dashboard itself.
    • Data Capture: It extracts data from CurrentRequest.current.data to create a RequestRecord.
    • Status Handling: If a status is not explicitly provided in the tracing data, it defaults to the HTTP status returned by the application.
    • 404 Referer: For 404 status codes, the middleware automatically attempts to capture the HTTP_REFERER from the Rack env.
    • Custom Data: If RailsPerformance.custom_data_proc is configured, it executes that proc with the env to enrich the RequestRecord with custom_data.
    • Exclusion: If the request is marked to ignore :performance in CurrentRequest.current.ignore, no record is saved.
  6. Implement a custom Table widget

    master

    To create a custom dashboard table widget in rails_performance, you must inherit from RailsPerformance::Widgets::Table and implement the required interface.

    Subclasses must implement the following methods:

    • subtitle: Returns the subtitle text for the table.
    • data: Returns the data collection to be displayed in the table.
    • content_partial_path: Returns the path to the partial used to render the table content.

    Optional methods you can override:

    • empty_message: The message shown when no data is present (defaults to "No data to display.").
    • show_export?: Boolean determining if the export feature is enabled (defaults to true).
    • auto_update_interval: The interval for automatic updates (defaults to nil).
    • table_id: A custom ID for the table element (defaults to nil).
    • table_classes: CSS classes applied to the table (defaults to "table is-fullwidth is-hoverable").
  7. Configure Rails Performance

    master

    Configuration is handled via an initializer at config/initializers/rails_performance.rb. You can use the RailsPerformance.setup block to override default settings.

    Key configuration options include:

    • config.redis: The Redis connection instance.
    • config.duration: How long data is stored (default is 4 hours).
    • config.mount_at: The URL path where the dashboard is mounted (default: /rails/performance).
    • config.http_basic_authentication_enabled: Enable/disable HTTP Basic Auth for the dashboard.
    • config.verify_access_proc: A proc to implement custom authorization logic (e.g., checking current_user.admin?).
    • config.ignored_endpoints: Array of controller#action strings to ignore.
    • config.ignored_paths: Array of path prefixes to ignore.
    • config.custom_data_proc: A proc to capture extra request metadata (like current_user or user_agent) from the Rack env.
    RailsPerformance.setup do |config|
      config.redis    = Redis.new(url: ENV["REDIS_URL"].presence || "redis://127.0.0.1:6379/0")
      config.duration = 4.hours
      config.debug    = false
      config.enabled  = true
      config.mount_at = '/rails/performance'
      config.http_basic_authentication_enabled   = false
      config.http_basic_authentication_user_name = 'rails_performance'
      config.http_basic_authentication_password  = 'password12'
      config.verify_access_proc = proc { |controller| true }
      config.ignored_endpoints = ['HomeController#contact']
      config.ignored_paths = ['/rails/performance', '/admin']
      config.custom_data_proc = proc do |env|
        request = Rack::Request.new(env)
        { email: request.env['warden'].user&.email }
      end
      config.home_link = '/'
      config.skipable_rake_tasks = ['webpacker:compile']
      config.include_rake_tasks = false
      config.include_custom_events = true
    end if defined?(RailsPerformance)
  8. Understand the RequestRecord data structure

    master

    A RequestRecord represents a single HTTP request's performance metrics. It contains routing information, timing data, and error details.

    Core Attributes

    • controller: The controller name.
    • action: The action name.
    • format: The request format (e.g., html).
    • status: The HTTP status code.
    • method: The HTTP method (e.g., GET).
    • path: The request path.
    • request_id: The unique request identifier.
    • datetime / datetimei: Timestamp information.

    Performance & Error Metrics

    • duration: Total request duration.
    • view_runtime: Time spent in the view layer.
    • db_runtime: Time spent in database queries.
    • exception: A string representation of any exception encountered.
    • exception_object: The actual exception object (if available).
    • custom_data: A JSON field for additional context.

    Helper Methods

    • controller_action: Returns a string in the format ControllerName#action_name.
    • controller_action_format: Returns a string in the format ControllerName#action_name|format.
  9. Create custom events and deployment markers

    master

    You can manually trigger events to appear on the performance charts. This is useful for marking deployments or specific business events.

    Create a deployment event

    For Kamal users, you can run this via a post-deploy hook:

    kamal app exec -p './bin/rails runner "RailsPerformance.create_event(name: \"Deploy\")"'

    Create a custom event with styling

    You can specify colors and label orientation:

    RailsPerformance.create_event(name: "Deploy", options: {
      borderColor: "#00E396",
      label: {
        borderColor: "#00E396",
        orientation: "horizontal",
        text: "Deploy"
      }
    })
  10. Measure custom code blocks with RailsPerformance.measure

    master

    To track the performance of specific blocks of code as custom events, use the RailsPerformance.measure method. This allows you to see the duration of specific logic in your dashboard.

    RailsPerformance.measure("some label", "some namespace") do
       # your code
    end
  11. Configure Recent Requests tab

    master

    You can control the time window and the maximum number of requests displayed in the 'Recent Requests' tab using the following configuration options:

    • recent_requests_time_window: The duration of the time window to look back for recent requests (default: 60.minutes).
    • recent_requests_limit: The maximum number of requests to display (default: nil, which may show all within the window).