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



167
168
169
170
171
# File 'lib/new_relic/agent/method_tracer.rb', line 167

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"


137
138
139
140
# File 'lib/new_relic/agent/method_tracer.rb', line 137

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

#_nr_derived_class_nameObject



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

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.



162
163
164
# File 'lib/new_relic/agent/method_tracer.rb', line 162

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



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

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)


155
156
157
158
159
# File 'lib/new_relic/agent/method_tracer.rb', line 155

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)


145
146
147
148
149
# File 'lib/new_relic/agent/method_tracer.rb', line 145

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