NewRelic RPM with ActionController::Metal
As part of our work with the QFive API for internal consumption we’ve built it out using Rails’ ActionController::Metal. We quickly realized that incoming requests to the API were not being tracked by NewRelic and looked for a way to resolve this. A quick google search will yield this documentation from New Relic which includes the following example:
class SteelController < ActionController::Metal
include ActionController::Rendering
def show
render :text => "Here is some text"
end
include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
add_transaction_tracer :show
end
While this works, the problem remains that now you will need to add a transaction tracer for each and every controller action you add.
With this in mind I went in search of a better solution which could streamline the solution. Digging around the NewRelic RPM gem internals I was able to find the ‘magic’ behind the way New Relic integrates into requests. Within lib/new_relic/agent/instrumentation/rails3/action_controller.rb
you can find the following:
DependencyDetection.defer do
@name = :rails3_controller
depends_on do
defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i == 3
end
depends_on do
defined?(ActionController) && defined?(ActionController::Base)
end
executes do
NewRelic::Agent.logger.debug 'Installing Rails 3 Controller instrumentation'
end
executes do
class ActionController::Base
include NewRelic::Agent::Instrumentation::ControllerInstrumentation
include NewRelic::Agent::Instrumentation::Rails3::ActionController
end
end
end
Which handles including the various instrumentation tools for ActionController. With this in mind we can follow the same logic in our API BaseController:
require 'new_relic/agent/instrumentation/controller_instrumentation'
require 'new_relic/agent/instrumentation/rails3/action_controller'
require 'new_relic/agent/instrumentation/rails3/errors'
class Api::V1::BaseController < ActionController::Metal
include ActionController::Instrumentation
include ActionController::Rescue
# ...
# In order to enable NewRelic RPM monitoring in the API we'll need to include it
include NewRelic::Agent::Instrumentation::ControllerInstrumentation
include NewRelic::Agent::Instrumentation::Rails3::ActionController
include NewRelic::Agent::Instrumentation::Rails3::Errors
end