require 'new_relic/agent/instrumentation/controller_instrumentation' DependencyDetection.defer do @name = :sinatra depends_on do defined?(::Sinatra) && defined?(::Sinatra::Base) && !defined?(::WeaselDiesel) && Sinatra::Base.private_method_defined?(:dispatch!) end executes do ::NewRelic::Agent.logger.info 'Installing Sinatra instrumentation' end executes do ::Sinatra::Base.class_eval do include NewRelic::Agent::Instrumentation::Sinatra alias dispatch_without_newrelic dispatch! alias dispatch! dispatch_with_newrelic end end end module NewRelic module Agent module Instrumentation # NewRelic instrumentation for Sinatra applications. Sinatra actions will # appear in the UI similar to controller actions, and have breakdown charts # and transaction traces. # # The actions in the UI will correspond to the pattern expression used # to match them. HTTP operations are not distinguished. Multiple matches # will all be tracked as separate actions. module Sinatra include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation def dispatch_with_newrelic txn_name = NewRelic.transaction_name(self.class.routes, @request) do |pattern, keys, conditions| process_route(pattern, keys, conditions) do pattern.source end end perform_action_with_newrelic_trace(:category => :sinatra, :name => txn_name, :params => @request.params) do dispatch_without_newrelic end end # Define Request Header accessor for Sinatra def newrelic_request_headers request.env end module NewRelic extend self def http_verb(request) request.request_method if request.respond_to?(:request_method) end def transaction_name(routes, request) name = '(unknown)' verb = http_verb(request) Array(routes[verb]).each do |pattern, keys, conditions, block| if route = yield(pattern, keys, conditions) name = route # it's important we short circuit here. Otherwise we risk # applying conditions from lower priority routes which can # break the action. break end end name.gsub!(%r{^[/^]*(.*?)[/\$\?]*$}, '\1') if verb name = verb + ' ' + name end name end end end end end end