Ruby Agent FAQ
Heroku
Scout runs on Heroku without any special configuration. When Scout detects that an app is being served via Heroku:
- Logging is set to
STDOUT
vs. logging to a file. Log messages are prefixed with[Scout]
for easy filtering. - The dyno name (ex:
web.1
) is reported vs. the dyno hostname. Dyno hostnames are dynamically generated and don’t have any meaningful information.
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:
- Set
log_file_path: STDOUT
to send your the Scout APM log contents to the Loggregator. - Use the application name configured via Cloud Foundry to identify the app.
- 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:
- Download the contents of this gist. Place the file inside your application’s
/lib
folder or similar. - In
config/boot.rb
, add:require File.expand_path('lib/scout_sneakers.rb', __FILE__)
- In your
Worker
class, immediately following thework
method, addinclude ScoutApm::BackgroundJobIntegrations::Sneakers::Instruments
.
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"