Ruby Language Metrics (Public Beta)
Last updated 16 September 2019
Table of Contents
To provide more visibility into the Ruby runtime, the Ruby language metrics feature surfaces additional language-specific time series metrics within Application Metrics. Ruby metrics include free and allocated heap object counts and number of free memory slots.
This feature is currently in public beta. If you have questions or feedback, you can reach us via https://help.heroku.com.
Ruby language metrics are available for all paid dynos (Hobby and above) and Private Spaces.
If your app is in JRuby, you will not be able to use these metrics as your app is running on top of the Java Virtual Machine (JVM). You will, however, be able to export and view JVM metrics. For more information, see the JVM Runtime Metrics document.
For general information on metrics display settings, please refer to the language runtime metrics parent document.
First, enable the Language Metrics flag on your application. You can do this via the Dashboard or the CLI. To enable it through Dashboard, open the metrics preferences panel and turn on the both the Enhanced Language Metrics toggle and the Ruby Language Metrics toggle.
Alternatively, to enable it through the Heroku CLI:
$ heroku labs:enable "runtime-heroku-metrics" -a "my-app-name" $ heroku labs:enable "ruby-language-metrics" -a "my-app-name"
Add the metrics buildpack
The next step is to add the
heroku/metrics buildpack to your application. This can be done through the CLI or the dashboard
Adding the buildpack via the CLI
To add the buildpack using the command line interface (CLI), run the following:
$ heroku buildpacks:add -i 1 heroku/metrics
If you are deploying using pipeline promotion you must add this buildpack to both your production and staging apps.
Adding the buildpack via the Dashboard
From the Settings tab for your app add the buildpack like so:
Add the Barnes gem to your application
Add the barnes gem to the Gemfile:
$ bundle install
If you’re using a forking web server, such as Puma, you’ll need to call
Barnes.start in each worker. For Puma that looks like this:
require 'barnes' before_fork do # worker specific setup Barnes.start # Must have enabled worker mode for this to block to be called end
Note: This does not work unless you’re using workers. To get this to work you must have at least one worker
Commit & Push
To finish up commit the changes and push to Heroku like so:
$ git add -A . $ git commit -am "Enable Heroku Ruby Metrics" $ git push heroku master
It may take a few minutes for these metrics to become available after the steps above are completed.
Puma Pool Usage
This metric should help you determine if your application is under or over provisioned. The metric is provided as a percentage of your applications request capacity. If the value is at, or close to 100%, that means any future requests will have to queue before your application can begin to process the request. This percentage is based on the number of Puma workers (processes) and the max-threads per worker. A good value for this metric is to be at 80% or less. This range will allow your application to maintain some “burst” capacity. If your application is going over 80% then adding an extra dyno to your application will increase your capacity to take more requests which will in turn decrease this utilization metric.
Besides increasing dyno count, adding extra workers or increasing the max-threads count will also decrease your utilization number since the maximum theoretical number of requests your application can process at a time is increased. Keep in mind that the dyno is limited by both memory and CPU. If you set the maximum number of threads to an arbitrarily high value, then it will appear that the application has plenty of capacity even though it cannot reasonably be expected to handle that many concurrent requests. A reasonable starting place is to use five threads per worker. You can increase your worker count until you are close to your 24-hour memory limit without going over.
In addition to showing the percentage of utilization, the number of spawned threads is also shown. If your application has set min-threads equal to max-threads, then this spawned value should always be at 100% as is seen in the above image.
Heroku recommends running at least two dynos to maintain dyno redundency.
To access this metric you will need Barnes gem
>= 0.0.7 and Puma gem
How to use this chart
When the pool capacity utilization consistently goes over 80%, your application is under-provisioned and could benefit from adding extra dynos to your web app. When you add a dyno then the same load will be spread across more instances and the metric should go down. Continue to add dynos until the application stabilizes at or below 80%. Running an application at around 80% utilization provides room to handle spikes of traffic.
If the pool capacity utilization is consistently at or under 20%, your application is over-provisioned and you should be able to remove dynos from your web app. When you remove a dyno the same load will be spread across fewer instances and the utilization metric should increase. It is worth noting that Heroku recommends running at least 2 dynos per application to provide resiliency to your application via dyno redundancy.
Free Memory Slots
The Free Memory Slots plot displays the minimum, maximum and average available free memory slots for the selected time interval. The most recent interval is shown as the default.
How to use this chart
Large numbers of free slots (for example more than 300,000) indicates that there is a controller action that is allocating large numbers of objects and freeing them. You can read more about this in a guide to GC.stat about the
When you see this you should reach for a performance analytics service such as Scout or Skylight that provides you with detailed information on object allocation. Alternatively, you can use Derailed Benchmarks to figure out where in your application is allocating so much memory.
Heap Objects Count
Max and average allocated and freed heap object counts are displayed on a log scale, with freed shown as mirrored below the y-axis baseline. Metrics reflect the selected time interval, with the default being the most recent one.
How to use this chart
The allocated and freed object count should both grow at roughly the same rate. There will be slightly more objects allocated over time until your application approaches it’s memory “steady state”. If however, there are drastically more objects being allocated than being freed this could indicate that somewhere in your code you are retaining objects. You will need to use a tool such as memory-profiler or Derailed Benchmarks to help find the which objects are being retained.
Disabling Metrics Collection
To disable Ruby metrics collection, simply toggle off the Enhanced Language Metrics toggle via the Metrics Preferences panel, or using this CLI command:
$ heroku labs:disable "runtime-heroku-metrics" -a "my-app-name"