Ruby Agent FAQ

Heroku

Scout runs on Heroku without any special configuration. When Scout detects that an app is being served via Heroku:

Configuration

Scout can be configured via environment variables. This means you can use heroku config:set to configure the agent. For example, you can set the application name that appears in the Scout UI with:

heroku config:set SCOUT_NAME='My Heroku App'

See the configuration section for more information on the available config settings and environment variable functionality.

Using the Scout Heroku Add-on

Scout is also available as a Heroku Add-on. The add-on automates setting the proper Heroku config variables during the provisioning process.

Docker

Scout runs within Docker containers without any special configuration.

It’s common to configure Docker containers with environment variables. Scout can use environment variables instead of the scout_apm.yml config file.

Cloud Foundry

Scout runs on Cloud Foundry without any special configuration.

We suggest a few configuration changes in the scout_apm.yml file to best take advantage of Cloud Foundry:

  1. Set log_file_path: STDOUT to send your the Scout APM log contents to the Loggregator.
  2. Use the application name configured via Cloud Foundry to identify the app.
  3. Override the hostname reported to Scout. Cloud Foundry hostnames are dynamically generated and don’t have any meaningful information. We suggest using a combination of the application name and the instance index.

A sample config for Cloud Foundry that implements the above suggestions:

common: &defaults
  key: YOUR_KEY
  monitor: true
  # use the configured application name to identify the app.
  name: <%= ENV['VCAP_APPLICATION'] ? JSON.parse(ENV['VCAP_APPLICATION'])['application_name'] : "YOUR APP NAME (#{Rails.env})" %>
  # make logs available to the Loggregator
  log_file_path: STDOUT
  # reports w/a more identifiable instance name using the application name and instance index. ex: rails-sample.0
  hostname: <%= ENV['VCAP_APPLICATION'] ? "#{JSON.parse(ENV['VCAP_APPLICATION'])['application_name']}.#{ENV['CF_INSTANCE_INDEX']}"  : Socket.gethostname %>

production:
  <<: *defaults

development:
  <<: *defaults
  monitor: false

test:
  <<: *defaults
  monitor: false

staging:
  <<: *defaults

ActionController::Metal

Prior to agent version 2.1.26, an extra step was required to instrument ActionController::Metal and ActionController::Api controllers. After 2.1.26, this is automatic.

The previous instructions which had an explicit include are no longer needed, but if that code is still in your controller, it will not harm anything. It will be ignored by the agent and have no effect.

Rake + Rails Runner

Scout doesn’t have a dedicated API for instrumenting rake tasks or transactions called via rails runner. Instead, we suggest creating basic wrapper tasks that spawn a background job in a framework we support. These jobs are automatically monitored by Scout and appear in the Scout UI under “background jobs”.

For example, the following is a CronJob that triggers the execution of an IntercomSync background job:

10 * * * * cd /home/deploy/your_app/current && rails runner 'IntercomSync.perform_later'

Sneakers

Scout doesn’t instrument Sneakers (a background processing framework for Ruby and RabbitMQ) automatically. To add Sneakers instrumentation:

This treats calls to the work method as distinct transactions, named with the worker class.

Example usage:

class BaseWorker
  include Sneakers::Worker

  def work(attributes)
    # Do work
  end
  # This MUST be included AFTER the work method is defined.
  include ScoutApm::BackgroundJobIntegrations::Sneakers::Instruments
end

Overhead Considerations

Scout is built for production monitoring and is engineered to add minimal overhead. We test against several open-source benchmarks on significant releases to prevent releasing performance regressions.

There are a couple of scenarios worth mentioning where more overhead than expected may be observed.

Enabling the detailed_middleware option

By default, Scout aggregates all middleware timings together into a single “Middleware” category. Scout can provide a detailed breakdown of middleware timings by setting detailed_middleware: true in the configuration settings.

This is false by default as instrumenting each piece of middleware adds additional overhead. It’s common for Rails apps to use more than a dozen pieces of middleware. Typically, time spent in middleware is very small and isn’t worth instrumenting. Additionally, most of these middleware pieces are maintained by third-parties and are thus more difficult to optimize.

Resque Instrumentation

Since Resque works by forking a child process to run each job and exiting immediately when the job is finished, our instrumentation needs a way to aggregate the timing results and traces into a central store before reporting the information to our service. To support Resque, the Resque child process sends a simple payload to the parent which is listening via WEBRick on localhost. As long as there is one WEBRick instance listening on the configured port, then any Resque children will be able to send results back to it.

The overhead is usually small, but it is more significant than instrumenting background job frameworks like Sidekiq and DelayedJob that do not use forking. The lighter the jobs are, more overhead is incurred in the serialization and reporting to WEBRick. In our testing, for jobs that took ~18 ms each, we found that the overhead is about ~8%. If your jobs take longer than that, on average, the overhead will be lower.

Transactions

What is a transaction

A transaction is anytime that you application handles a request or runs a background job. To get a better understanding of your transaction volume, visit your usage page for more info

Ignoring transactions

Note: When a transaction is ignored, we will not collect metric data or traces for the request. When ignoring transactions and using sampling, data may be skewed and important traces may be missed.

There are a couple of approaches to ignore web requests and background jobs you don’t care to instrument. These approaches are listed below.

In your code

To selectively ignore a web request or background job in your code, add the following within the transaction:

ScoutApm::Transaction.ignore!

Sampling configuration

There are a few configuration options that allow you to sample requests to specific web endpoints or background jobs. This is useful to reduce overall volume or ignore select endpoints or jobs entirely. By default, no sampling or ignoring is applied, and all requests are captured.

Sampling Precedence

More specific sampling configurations take precedence over broader ones. If sample_endpoints is used, requests matching those URI prefixes will always be sampled at the rate specified for the matching prefix, regardless of endpoint_sample_rate or sample_rate. All endpoints that don’t match any prefixes in sample_endpoints will be sampled according to endpoint_sample_rate, regardless of sample_rate. Finally, sample_rate is the global catch-all. The same goes for backgound job sampling using sample_jobs and job_sample_rate.

The order in which endpoints are listed in sample_endpoints will determine the precedence. More specific endpoints should be listed before others with the same base. The rate specified for the first matching endpoint prefix will be used. For example, if you have ['/api/v1:50', '/api:90'], requests to /api/v1 will be sampled at 50%, and the other requests to /api will be sampled at 90%.

You can also disable all background jobs by setting enable_background_jobs: false in your configuration file. See the configuration option.

Example Sampling Configurations

These configuration options could be added to your scout_apm.yml

Global Sampling of 50%

sample_rate: 50

Sampling 10% of Jobs, and 50% of Web Requests

endpoint_sample_rate: 50
job_sample_rate: 10

Sampling 10% of Jobs and 50% of Web Requests, capturing all of a specified web endpoint

endpoint_sample_rate: 50
job_sample_rate: 10
sample_endpoints: "/foo/bar:100"