Ruby custom instrumentation

The New Relic Ruby agent automatically collects many metrics. It also includes an API you can use to collect additional metrics about your application. If you see large Application Code segments in transaction trace details, custom instrumentation can give a more complete picture of what is going on in your application.

Collecting too many metrics can impact the performance of your application and New Relic. To avoid data problems, keep the total number of unique metrics introduced by custom instrumentation under 2000.

Method tracers

The easiest way to capture custom instrumentation is by tracing calls to a particular method. Tracing a method as described below will insert an additional node in your transaction traces for each invocation of that method, providing greater detail about where time is going in your transactions.

Method tracers are software probes you can put on a method of any class. The probes use alias method chaining to insert themselves when the target methods execute and gather custom instrumentation on their performance.

Tracing in class definitions

Method tracers can be used within normal class definitions, as long as the target method has been defined first:

require 'new_relic/agent/method_tracer'
class Foo
  include ::NewRelic::Agent::MethodTracer

  def generate_image
    ...
  end

  add_method_tracer :generate_image, 'Custom/generate_image'
end  

To instrument a class method, add the method tracer in the class singleton:

require 'new_relic/agent/method_tracer'
class Foo
  def self.generate_image
     ...
  end

  class << self
    include ::NewRelic::Agent::MethodTracer

    add_method_tracer :generate_image, 'Custom/generate_image'
  end
end

add_method_tracer takes an optional metric name and a hash of options. For more information, see add_method_tracer in the New Relic RubyDoc .

Tracing initializers

For Rails, a common way to add instrumentation is to create an initializer and "monkey patch" the instrumentation directives.

For example, to add a method tracer to MyCache#get:

  1. Make sure the MyCache class is loaded before adding the method tracer.
  2. Add the following in a file named config/initializers/rpm_instrumentation.rb:
require 'new_relic/agent/method_tracer'

MyCache.class_eval do
  include ::NewRelic::Agent::MethodTracer

  add_method_tracer :get
end  

Tracing blocks of code

Sometimes a single method is so complex that tracking overall time doesn't give enough detail. In these cases, you can wrap a block of code with a tracer. Call trace_execution_scoped passing the code to trace as a block:

extend ::NewRelic::Agent::MethodTracer

def slow_action
  self.class.trace_execution_scoped(['Custom/slow_action/beginning_work']) do
    # do stuff and report execution time with a custom metric name
  end

  # more stuff, whose time will be "blamed" to slow_action
end  

For more information, see add_method_tracer in the New Relic RubyDoc .

Naming transactions

Instrumented transactions are used to determine the throughput and overall response time for your application. The name of the method and the class will be used for the name of the transaction as reported to New Relic. For more information, see Viewing transaction traces.

Normally the agent automatically chooses the transaction name. If you want to change the name of a transaction while it is still running, use NewRelic::Agent.set_transaction_name and the corresponding NewRelic::Agent.get_transaction_name.

Do not use brackets [suffix] at the end of your transaction name. New Relic automatically strips brackets from the name. Instead, use parentheses (suffix) or other symbols if needed.

This is useful if you want to segment your transaction based on some criteria. For example, if you wanted to vary the transaction name by response format in Rails:

class UsersController
  def index
    @users = User.all
    respond_to do |format|
      format.html
      format.json do 
        NewRelic::Agent.set_transaction_name('Users/index.json')
        render :json => @users
      end
      format.xml do 
        NewRelic::Agent.set_transaction_name('Users/index.xml')
        render :xml => @users
      end
    end
  end
end  

Renaming transactions can also be used to segment your requests around some business criteria. For example, you could segment a transaction into "Big Customer" and "Small Customer" with code like this:

class UsersController

  before_filter :segment_new_relic_by_customer_size

  def segment_new_relic_by_customer_size
    new_relic_name = NewRelic::Agent.get_transaction_name
    if current_user.big_customer?
      NewRelic::Agent.set_transaction_name("#{new_relic_name} - big customer")
    else
      NewRelic::Agent.set_transaction_name("#{new_relic_name} - small customer")
    end
  end

end  

Tracing transaction entry points

Ordinarily the agent will be able to identify transactions within your application, but if you're not using a supported framework, or if you'd like to record transactions that the agent is not automatically recording, you can define methods as being transaction entry points:

class Controller
  include NewRelic::Agent::Instrumentation::ControllerInstrumentation

  def transaction
    # execute a transaction
  end
  add_transaction_tracer :transaction
end  

Instrumenting non-web transactions

Along with method-level tracing, you can instrument non-web transactions, such as background tasks, with the same level of transaction and error detail as web transactions. For more information, see Monitoring Ruby background processes and daemons.

For more help

Additional documentation resources include:

Join the discussion about Ruby in the New Relic Online Technical Community! The Technical Community is a public platform to discuss and troubleshoot your New Relic toolset.

If you need additional help, get support at support.newrelic.com.