Module: NewRelic::Agent::MethodTracer::ClassMethods::AddMethodTracer

Included in:
NewRelic::Agent::MethodTracer::ClassMethods
Defined in:
lib/new_relic/agent/method_tracer.rb

Overview

contains methods refactored out of the #add_method_tracer method

Constant Summary collapse

ALLOWED_KEYS =
[:metric, :push_scope, :code_header, :code_information, :code_footer].freeze
DEFAULT_SETTINGS =
{:push_scope => true, :metric => true, :code_header => '', :code_footer => ''}.freeze

Instance Method Summary collapse

Instance Method Details

#_nr_clear_traced_methods!Object

for testing only



165
166
167
168
169
# File 'lib/new_relic/agent/method_tracer.rb', line 165

def _nr_clear_traced_methods!
  _nr_traced_method_module.module_eval do
    self.instance_methods.each { |m| remove_method(m) }
  end
end

#_nr_default_metric_name(method_name) ⇒ Object

Default to the class where the method is defined.

Example:

Foo._nr_default_metric_name_code('bar') #=> "Custom/#{Foo.name}/bar"


135
136
137
138
# File 'lib/new_relic/agent/method_tracer.rb', line 135

def _nr_default_metric_name(method_name)
  class_name = _nr_derived_class_name
  ->(*) { "Custom/#{class_name}/#{method_name}" }
end

#_nr_derived_class_nameObject



171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/new_relic/agent/method_tracer.rb', line 171

def _nr_derived_class_name
  return self.name if self.name && !self.name.empty?
  return 'AnonymousModule' if self.to_s.start_with?('#<Module:')

  # trying to get the "MyClass" portion of "#<Class:MyClass>"
  name = self.to_s[/^#<Class:(.+)>$/, 1]
  if name.start_with?('0x')
    'AnonymousClass'
  elsif name.start_with?('#<Class:')
    'AnonymousClass/Class'
  else
    "#{name}/Class"
  end
end

#_nr_traced_method_moduleObject

Returns an anonymous module that stores prepended trace methods.



160
161
162
# File 'lib/new_relic/agent/method_tracer.rb', line 160

def _nr_traced_method_module
  @_nr_traced_method_module ||= Module.new
end

#_nr_validate_method_tracer_options(method_name, options) ⇒ Object

Checks the provided options to make sure that they make sense. Raises an error if the options are incorrect to assist with debugging, so that errors occur at class construction time rather than instrumentation run time



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/new_relic/agent/method_tracer.rb', line 112

def _nr_validate_method_tracer_options(method_name, options)
  unless options.is_a?(Hash)
    raise TypeError.new("Error adding method tracer to #{method_name}: provided options must be a Hash")
  end

  unrecognized_keys = options.keys - ALLOWED_KEYS
  if unrecognized_keys.any?
    raise "Unrecognized options when adding method tracer to #{method_name}: " +
      unrecognized_keys.join(', ')
  end

  options = DEFAULT_SETTINGS.merge(options)
  unless options[:push_scope] || options[:metric]
    raise "Can't add a tracer where push_scope is false and metric is false"
  end

  options
end

#method_traced?(method_name) ⇒ Boolean

Checks to see if we have already traced a method with a given metric by checking to see if the traced method exists. Warns the user if methods are being double-traced to help with debugging custom instrumentation.

Returns:

  • (Boolean)


153
154
155
156
157
# File 'lib/new_relic/agent/method_tracer.rb', line 153

def method_traced?(method_name)
  exists = method_name && _nr_traced_method_module.method_defined?(method_name)
  ::NewRelic::Agent.logger.error("Attempt to trace a method twice: Method = #{method_name}") if exists
  exists
end

#newrelic_method_exists?(method_name) ⇒ Boolean

Checks to see if the method we are attempting to trace actually exists or not. #add_method_tracer can’t do anything if the method doesn’t exist.

Returns:

  • (Boolean)


143
144
145
146
147
# File 'lib/new_relic/agent/method_tracer.rb', line 143

def newrelic_method_exists?(method_name)
  exists = method_defined?(method_name) || private_method_defined?(method_name)
  ::NewRelic::Agent.logger.error("Did not trace #{_nr_derived_class_name}##{method_name} because that method does not exist") unless exists
  exists
end