In Depth

Before reading this section, we suggest going through our advanced features page which contains documentation on adding features that may not be automatically added – including Deploy Tracking, Request Queueing, Auto Instruments and Custom Context

Request Policies

By default the way that we choose which traces to collect involves a factor of 4 things:

  1. Throughput through the endpoint
  2. Deviation from mean response of that endpoint (for example, if the average response time is usually 100ms but this request took 500ms it’s interesting)
  3. Total response time
  4. Time since last seen (this ensures we capture endpoints that don’t have as much throughput through it)

https://github.com/scoutapp/scout_apm_ruby/tree/master/lib/scout_apm/slow_policy

In 4.0.0 we added the ability to add custom request policies.

For example, let says you were doing some testing and wanted to report more traces for an endpoint that had changes made to it. You can add a custom request policy for this:

# config/initializers/scout_custom_policy.rb

# values should be between 0 - 5. The max value of the percentile policy for example is 1.7
require 'scout_apm'
class AddPolicy < ScoutApm::SlowPolicy::Policy
  ENDPOINT_SCORES = { "Controller/users/index" => 2}
  # BACKGROUND_SCORES = { "Job/mailers/DigestEmail::DeliverJob" => 2}

  # Called for every tracked request (both web requests and background jobs), giving a score, to be compared with other requests of 
  # that minute to find the best traces to store details.
  def call(req)
    ENDPOINT_SCORES.fetch(req.unique_name, 0)
    
    # or for background jobs
    # BACKGROUND_SCORES.fetch(req.unique_name, 0)
  end

  # Called when a request actually gets stored as a detailed trace
  def stored!(req)
  end
end

ScoutApm::Agent.instance.context.slow_request_policy.add(AddPolicy.new(ScoutApm::Agent.instance.context)))

The best way to find the endpoint slug (Controller/users/index) is to find the endpoint name you want to capture more traces for on the endpoints page: For Scout we are app 6, you will need to replace the app id with yours. https://scoutapm.com/apps/6/endpoints

Then once on the endpoints page you want to capture more traces for, grab the url (for example): https://scoutapm.com/apps/6/endpoints/YXBpL21ldHJpY3Mvc2hvdw==

And take the base64 part at the end (YXBpL21ldHJpY3Mvc2hvdw==) and decode it (api/metrics/show) and prepend Controller/ to it. Case does matter here: Controller/api/metrics/show This will be the endpoint that you place in ENDPOINT_SCORES above.

This same method can be used for background jobs as well, but instead of Controller/ it is Job/

Plugins

In 2.4.11 we added the ability for transaction and periodic callbacks.

This can be useful if you want to get additional insights into queue_time for example.

To add a transaction callback (a callback that occurs for every web request and background job): ScoutApm::Extensions::Config.add_transaction_callback(klass.new)

To add a periodic callback (a callback that happens after every minute before the payload is sent): ScoutApm::Extensions::Config.add_periodic_callback(klass.new)

The transaction callback will take a single param of the payload, while the period callback takes two params of reporting_periods_payload, and metadata

Example of logging each transaction’s queue_time, duration, and transaction name:

class LogQueueTimeCallack
  def call(payload)
    Rails.logger.info(
      msg: "ScoutApm Transaction",
      queue_time: payload.queue_time_ms,
      duration: payload.duration_ms,
      transaction_name: payload.transaction_name
    ) if payload.transaction_type_slug == "web"
  end
end
ScoutApm::Extensions::Config.add_transaction_callback(LogQueueTimeCallack.new)