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.

By the web endpoint path name

You can ignore requests to web endpoints that match specific paths (like /health_check). See the ignore setting in the configuration options

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

Use probability sampling to limit the number of web requests or background jobs Scout analyzes:

# app/controllers/application_controller.rb
before_action :sample_requests_for_scout

def sample_requests_for_scout
  # Sample rate should range from 0-1:
  # * 0: captures no requests
  # * 0.9: captures 90% of requests
  # * 1: captures all requests
  sample_rate = 0.9

  if rand > sample_rate
    Rails.logger.debug("[Scout] Ignoring request: #{request.original_url}")
    ScoutApm::Transaction.ignore!
  end
end

Ignoring all background jobs

You can ignore all background jobs by setting enable_background_jobs: false in your configuration file. See the configuration options.