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.
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.