Created
February 22, 2012 04:03
-
-
Save geeksam/1881240 to your computer and use it in GitHub Desktop.
Slightly friendlier API for adding custom method traces to NewRelic
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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