Module: NewRelic::Agent::Instrumentation::ControllerInstrumentation

Included in:
Rack, Sinatra
Defined in:
lib/new_relic/agent/instrumentation/controller_instrumentation.rb

Overview

NewRelic instrumentation for controllers

This instrumentation is applied to the action controller by default if the agent is actively collecting statistics. It will collect statistics for the given action.

In cases where you don’t want to instrument the top level action, but instead have other methods which are dispatched to by your action, and you want to treat these as distinct actions, then what you need to do is use #perform_action_with_newrelic_trace

Defined Under Namespace

Modules: ClassMethods, ClassMethodsShim, Shim

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(clazz) ⇒ Object

:nodoc:



16
17
18
# File 'lib/new_relic/agent/instrumentation/controller_instrumentation.rb', line 16

def self.included(clazz) # :nodoc:
  clazz.extend(ClassMethods)
end

Instance Method Details

#newrelic_metric_path(action_name_override = nil) ⇒ Object

Must be implemented in the controller class: Determine the path that is used in the metric name for the called controller action. Of the form controller_path/action_name



152
153
154
# File 'lib/new_relic/agent/instrumentation/controller_instrumentation.rb', line 152

def newrelic_metric_path(action_name_override = nil) # :nodoc:
  raise "Not implemented!"
end

#perform_action_with_newrelic_trace(*args, &block) ⇒ Object

Yield to the given block with NewRelic tracing. Used by default instrumentation on controller actions in Rails and Merb. But it can also be used in custom instrumentation of controller methods and background tasks.

This is the method invoked by instrumentation added by the ClassMethods#add_transaction_tracer.

Here’s a more verbose version of the example shown in ClassMethods#add_transaction_tracer using this method instead of #add_transaction_tracer.

Below is a controller with an invoke_operation action which dispatches to more specific operation methods based on a parameter (very dangerous, btw!). With this instrumentation, the invoke_operation action is ignored but the operation methods show up in RPM as if they were first class controller actions

MyController < ActionController::Base
  include NewRelic::Agent::Instrumentation::ControllerInstrumentation
  # dispatch the given op to the method given by the service parameter.
  def invoke_operation
    op = params['operation']
    perform_action_with_newrelic_trace(:name => op) do
      send op, params['message']
    end
  end
  # Ignore the invoker to avoid double counting
  newrelic_ignore :only => 'invoke_operation'
end

When invoking this method explicitly as in the example above, pass in a block to measure with some combination of options:

  • :category => :controller indicates that this is a controller action and will appear with all the other actions. This is the default.

  • :category => :task indicates that this is a background task and will show up in RPM with other background tasks instead of in the controllers list

  • :category => :rack if you are instrumenting a rack middleware call. The :name is optional, useful if you have more than one potential transaction in the #call.

  • :category => :uri indicates that this is a web transaction whose name is a normalized URI, where ‘normalized’ means the URI does not have any elements with data in them such as in many REST URIs.

  • :name => action_name is used to specify the action name used as part of the metric name

  • :params => {...} to provide information about the context of the call, used in transaction trace display, for example: :params => { :account => @account.name, :file => file.name }

Seldomly used options:

  • :force => true indicates you should capture all metrics even if the #newrelic_ignore directive was specified

  • :class_name => aClass.name is used to override the name of the class when used inside the metric name. Default is the current class.

  • :path => metric_path is deprecated in the public API. It allows you to set the entire metric after the category part. Overrides all the other options.

If a single argument is passed in, it is treated as a metric path. This form is deprecated.



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/new_relic/agent/instrumentation/controller_instrumentation.rb', line 224

def perform_action_with_newrelic_trace(*args, &block)
  
  NewRelic::Agent.instance.ensure_worker_thread_started
  
  # Skip instrumentation based on the value of 'do_not_trace' and if 
  # we aren't calling directly with a block.
  if !block_given? && _is_filtered?('do_not_trace')
    # Also ignore all instrumentation in the call sequence
    NewRelic::Agent.disable_all_tracing do
      return perform_action_without_newrelic_trace(*args)
    end
  end
  
  return perform_action_with_newrelic_profile(args, &block) if NewRelic::Control.instance.profiling?
  
  frame_data = _push_metric_frame(block_given? ? args : [])
  
  NewRelic::Agent.trace_execution_scoped frame_data.recorded_metrics, :force => frame_data.force_flag do
    frame_data.start_transaction
    begin
      NewRelic::Agent::BusyCalculator.dispatcher_start frame_data.start
      if block_given?
        yield
      else
        perform_action_without_newrelic_trace(*args)
      end
    rescue Exception => e
      frame_data.notice_error(e)
      raise
    ensure
      NewRelic::Agent::BusyCalculator.dispatcher_finish
      # Look for a metric frame in the thread local and process it.
      # Clear the thread local when finished to ensure it only gets called once.
      frame_data.record_apdex unless _is_filtered?('ignore_apdex')
      frame_data.pop
    end
  end
end