Skip to content

Instantly share code, notes, and snippets.

@geeksam
Created February 22, 2012 04:03
Show Gist options
  • Save geeksam/1881240 to your computer and use it in GitHub Desktop.
Save geeksam/1881240 to your computer and use it in GitHub Desktop.
Slightly friendlier API for adding custom method traces to NewRelic
require 'new_relic/agent/method_tracer'
class NR
# Convenience method for adding NewRelic tracing around specific methods of interest.
#
# Note about performance:
#
# " CAUTION - adding probes to your code adds overhead.
# Each probe burns about 20 microseconds of CPU.
# Be careful not to probe a method that's called frequently in a loop. "
# Source: http://newrelic.com/docs/ruby/ruby-agent-configuration
#
# Note about reporting:
#
# > The :metric => false option tells the Ruby Agent to have this probe
# > only participate in transaction traces and not produce streams of
# > metric data, which would not be visible except in Custom Dashboards.
# Source: http://newrelic.com/docs/ruby/ruby-agent-configuration
#
# However, when I tried this using :metric => false, the traces didn't show
# up in the Performance Breakdown view that NR gives for specific controller
# actions. So, the default here is :metric => true.
#
# More examples of adding tracing are available in the Ruby section at:
# http://newrelic.com/docs/docs/custom-metric-collection
#
# And the API documentation for add_method_tracer can be found at:
# http://newrelic.github.com/rpm/NewRelic/Agent/MethodTracer/ClassMethods.html#method-i-add_method_tracer
# (Possibly of interest: it takes :code_header => '' and :code_footer => '' as Ruby strings and inserts
# them before or after calling the traced method.)
#
#
#
# Usage Examples (note the use of '.' and '#' to distinguish between class and instance methods):
#
# NRInstrumentation.instrument 'Foo::Bar.baz' # add tracing to a class method on the Foo::Bar module
# NRInstrumentation.instrument 'Spam.new_tin' # add tracing to a class method on the Spam class
# NRInstrumentation.instrument 'Spam#temperature' # add tracing to an instance method on the Spam class
#
def self.instrument(fully_qualified_method, options = {})
new.instrument(fully_qualified_method, options)
end
DefaultOptions = {
:metric => true,
:deduct_call_time_from_parent => true,
}
def instrument(fully_qualified_method, options = {})
target = target_for_tracing(fully_qualified_method)
teh_codez = code_for_eval(fully_qualified_method, options.reverse_merge(DefaultOptions))
# puts '', target.name, teh_codez # uncomment if you're confused
target.module_eval(teh_codez)
end
protected
def target_for_tracing(fully_qualified_method)
unless fully_qualified_method.match(/^(.*)(?:[\.\#].*)$/)
raise "Couldn't understand fully_qualified_method: #{fully_qualified_method.inspect}"
end
$1.constantize
end
def code_for_eval(fully_qualified_method, options)
glyph, method = *fully_qualified_method.match(/^(?:.*)([\.\#])(.*)$/).captures
lines = [
enable_tracing_line,
add_method_trace_line(fully_qualified_method, options)
]
lines = go_meta(lines) if '.' == glyph
lines.join('; ')
end
def go_meta(lines)
# To enable tracing on class/module methods, we need to eval against the class's (metaclass/singleton class/eigenclass/whatever)
['class << self'] + lines + ['end']
end
def enable_tracing_line
# Make sure the #add_method_tracer macro is available
'include NewRelic::Agent::MethodTracer unless ancestors.include?(NewRelic::Agent::MethodTracer)'
end
def add_method_trace_line(fully_qualified_method, options)
# Invoke the add_method_tracer macro
method = *fully_qualified_method.match(/^(?:.*[\.\#])(.*)$/).captures
metric_name = "Custom/#{fully_qualified_method}"
'add_method_tracer %s, %s, %s' % [method.to_sym, metric_name, options].map(&:inspect)
end
end
NR.instrument 'Brochure.find'
NR.instrument 'Brochure.liquid_render'
NR.instrument 'Platypus::CmsGateway.boc'
NR.instrument 'Platypus::CmsGateway::Remote#boc'
NR.instrument 'Platypus::CmsGateway::Remote#preview_boc'
NR.instrument 'Platypus::CmsGateway::Remote#get'
NR.instrument 'Platypus::CmsGateway::Remote#get_cached'
NR.instrument 'Platypus::CmsGateway::Remote#get_uncached'
NR.instrument 'Platypus::CmsGateway::Remote#parse_response'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment