MemHealth
A Rails engine for monitoring memory health, detecting growth patterns (leaks & bloats) and memory swap operations. Helps you identify requests that consume high amounts of RAM and is compatible with Heroku.
Installation
Add this line to your application's Gemfile:
gem "memhealth"Use initializer /config/memhealth.rb to configure Redis connection:
MemHealth.configure do |config|
config.redis_url = ENV.fetch("REDIS_URL", "redis://localhost:6379/0")
endEnable memory tracking via ENV variable:
MEM_HEALTH_ENABLED=trueDashboard setup
Mount the engine in your routes within an authenticated section:
# config/routes.rb
Rails.application.routes.draw do
# ... other routes ...
# Mount within authenticated admin section
authenticate :admin_user do
mount MemHealth::Engine, at: "/admin/memhealth"
end
endWorker tracking setup (Sidekiq)
To track memory usage in background jobs, add the middleware to your Sidekiq configuration:
# config/initializers/sidekiq.rb
Sidekiq.configure_server do |config|
config.server_middleware do |chain|
chain.add MemHealth::JobTrackingMiddleware
end
endThe dashboard will show two tabs:
- Web Servers: Tracks memory usage for HTTP requests
- Worker Servers: Tracks memory usage for Sidekiq background jobs
Features
- Real-time memory usage monitoring for web and worker servers
- Track highest memory consuming requests and background jobs
- Account-level tracking for multi-tenant apps
- Redis-based data storage
- Web dashboard with separate views for web and worker metrics
- Configurable thresholds and limits
Heroku Memory Issues
If you're getting R14 - Memory quota exceeded errors, it means your application is using swap memory. Swap uses the disk to store memory instead of RAM. Disk speed is significantly slower than RAM, so page access time is greatly increased. This leads to a significant degradation in application performance. An application that is swapping will be much slower than one that is not. No one wants a slow application, so getting rid of R14 Memory quota exceeded errors on your application is very important.
MemHealth helps you identify which specific requests are consuming excessive memory, allowing you to pinpoint and fix the root cause of these performance issues.
ENVIRONMENT VARIABLES
Configure Memhealth using environment variables:
| Environment Variable | Description | Default Value |
|---|---|---|
MEM_HEALTH_ENABLED |
Enable/disable memory tracking | false |
MEM_HEALTH_SKIP_REQUESTS |
Number of initial requests to skip (avoids class loading overhead) | 10 |
MEM_HEALTH_MEMORY_THRESHOLD_MB |
Minimum memory difference (MB) to track a request | 1 |
MEM_HEALTH_RAM_BEFORE_THRESHOLD |
Minimum RAM usage (MB) before tracking (prevents tracking low-memory requests) | 0 |
MEM_HEALTH_MAX_STORED_URLS |
Maximum number of URLs to store in Redis | 20 |
MEM_HEALTH_REDIS_KEY |
Name of environment variable containing Redis URL (e.g., REDISCLOUD_URL) |
REDIS_URL |
The gem will read the Redis connection URL from the environment variable specified in MEM_HEALTH_REDIS_KEY, falling back to REDIS_URL if not specified.
ActiveAdmin Integration
To add Memhealth to your ActiveAdmin Operations menu, add this to your ActiveAdmin initializer:
# config/initializers/active_admin.rb
ActiveAdmin.setup do |config|
# ... other config ...
config.namespace :admin do |admin|
admin.build_menu do |menu|
# ... other menu items ...
menu.add label: "MemHealth", url: "/admin/memhealth", parent: "Operations"
end
end
endConsole Usage
# View web statistics
MemHealth::Tracker.print_stats
# Get top memory consuming URLs (web)
MemHealth::Tracker.top_memory_urls
# Get top memory consuming jobs (worker)
MemHealth::Tracker.top_memory_jobs
# Get worker statistics
MemHealth::Tracker.worker_stats
# Get max memory diff for web or worker
MemHealth::Tracker.max_memory_diff(type: :web)
MemHealth::Tracker.max_memory_diff(type: :worker)
# Clear all data (web and worker)
MemHealth::Tracker.clear_all_dataLicense
The gem is available as open source under the MIT License.