Scout Ruby Custom Instrumentation¶
Traces that allocate significant amount of time to Controller or Job are good candidates to add custom instrumentation. This indicates a significant amount of time is falling outside our default instrumentation.
Limits¶
We limit the number of metrics that can be instrumented. Tracking too many unique metrics can impact the performance of our UI. Do not dynamically generate metric types in your instrumentation (ie self.class.instrument("user_#{user.id}", "generate") { ... }) as this can quickly exceed our rate limits.
Instrumenting method calls¶
To instrument a method call, add the following to the class containing the method:
class User
include ScoutApm::Tracer
def export_activity
# Do export work
end
instrument_method :export_activity
end
The call to instrument_method should be after the method definition.
Naming methods instrumented via instrument_method¶
In the example above, the metric will appear in traces as User#export_activity. On timeseries charts, the time will be allocated to a Custom type.
To modify the type:
instrument_method :export_activity, type: 'Exporting'
A new Exporting metric will now appear on charts. The trace item will be displayed as Exporting/User/export_activity.
To modify the name:
instrument_method :export_activity, type: 'Exporting', name: 'user_activity'
The trace item will now be displayed as Exporting/user_activity.
Instrumenting blocks of code¶
To instrument a method call, add the following:
class User
include ScoutApm::Tracer
def generate_profile_pic
self.class.instrument("User", "generate_profile_pic") do
# Do work
end
end
end
Naming methods instrumented via instrument(type, name)¶
In the example above, the metric appear in traces as User/generate_profile_pic. On timeseries charts, the time will be allocated to a User type. To modify the type or simply, simply change the instrument corresponding method arguments.
Renaming transactions
There may be cases where you require more control over how Scout names transactions. For example, if you have a controller-action that renders both JSON and HTML formats and the rendering time varies significantly between the two, it may make sense to define a unique transaction name for each.
Use ScoutApm::Transaction#rename:
class PostsController < ApplicationController
def index
ScoutApm::Transaction.rename("posts/foobar")
@posts = Post.all
end
end
In the example above, the default name for the transaction is posts/index, which appears as PostsController#index in the Scout UI. Renaming the transaction to posts/foobar identifies the transaction as PostsController#foobar in the Scout UI.
Do not generate highly cardinality transaction names (ex: ScoutApm::Transaction.rename("posts/foobar_#{current_user.id}")) as we limit the number of transactions that can be tracked. High-cardinality transaction names can quickly surpass this limit.
Testing instrumentation
Improper instrumentation can break your application. It’s important to test before deploying to production. The easiest way to validate your instrumentation is by running DevTrace and ensuring the new metric appears as desired.
After restarting your dev server with DevTrace enabled, refresh the browser page and view the trace output. The new metric should appear in the trace:
