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 =
[:force, :metric, :push_scope, :deduct_call_time_from_parent, :code_header, :code_footer, :scoped_metric_only].freeze
- DEFAULT_SETTINGS =
{:push_scope => true, :metric => true, :force => false, :code_header => "", :code_footer => "", :scoped_metric_only => false}.freeze
Instance Method Summary collapse
-
#any_unrecognized_keys?(expected, given) ⇒ Boolean
used to verify that the keys passed to NewRelic::Agent::MethodTracer::ClassMethods#add_method_tracer are valid.
-
#assemble_code_header(method_name, metric_name_code, options) ⇒ Object
Returns a code snippet to be eval’d that skips tracing when the agent is not tracing execution.
-
#check_for_illegal_keys!(options) ⇒ Object
raises an error when the NewRelic::Agent::MethodTracer::ClassMethods#add_method_tracer method is called with improper keys.
-
#check_for_push_scope_and_metric(options) ⇒ Object
validity checking - add_method_tracer must receive either push scope or metric, or else it would record no data.
-
#code_to_eval(method_name, metric_name_code, options) ⇒ Object
Decides which code snippet we should be eval’ing in this context, based on the options.
-
#default_metric_name_code(method_name) ⇒ Object
Default to the class where the method is defined.
-
#method_with_push_scope(method_name, metric_name_code, options) ⇒ Object
returns an eval-able string that contains the tracing code for a fully traced metric including scoping.
-
#method_without_push_scope(method_name, metric_name_code, options) ⇒ Object
returns an eval-able string that contains the traced method code used if the agent is not creating a scope for use in scoped metrics.
-
#newrelic_method_exists?(method_name) ⇒ Boolean
Checks to see if the method we are attempting to trace actually exists or not.
-
#set_deduct_call_time_based_on_metric(options) ⇒ Object
Sets the options for deducting call time from parents.
-
#traced_method_exists?(method_name, metric_name_code) ⇒ Boolean
Checks to see if we have already traced a method with a given metric by checking to see if the traced method exists.
-
#unrecognized_keys(expected, given) ⇒ Object
used to verify that the keys passed to NewRelic::Agent::MethodTracer::ClassMethods#add_method_tracer are valid.
-
#validate_options(options) ⇒ Object
Checks the provided options to make sure that they make sense.
Instance Method Details
#any_unrecognized_keys?(expected, given) ⇒ Boolean
used to verify that the keys passed to NewRelic::Agent::MethodTracer::ClassMethods#add_method_tracer are valid. checks the expected list against the list actually provided
270 271 272 |
# File 'lib/new_relic/agent/method_tracer.rb', line 270 def any_unrecognized_keys?(expected, given) unrecognized_keys(expected, given).any? end |
#assemble_code_header(method_name, metric_name_code, options) ⇒ Object
Returns a code snippet to be eval’d that skips tracing when the agent is not tracing execution. turns instrumentation into effectively one method call overhead when the agent is disabled
348 349 350 351 352 |
# File 'lib/new_relic/agent/method_tracer.rb', line 348 def assemble_code_header(method_name, metric_name_code, ) unless [:force] "return #{_untraced_method_name(method_name, metric_name_code)}(*args, &block) unless NewRelic::Agent.is_execution_traced?\n" end.to_s + [:code_header].to_s end |
#check_for_illegal_keys!(options) ⇒ Object
raises an error when the NewRelic::Agent::MethodTracer::ClassMethods#add_method_tracer method is called with improper keys. This aids in debugging new instrumentation by failing fast
278 279 280 281 282 |
# File 'lib/new_relic/agent/method_tracer.rb', line 278 def check_for_illegal_keys!() if any_unrecognized_keys?(ALLOWED_KEYS, ) raise "Unrecognized options in add_method_tracer_call: #{unrecognized_keys(ALLOWED_KEYS, ).join(', ')}" end end |
#check_for_push_scope_and_metric(options) ⇒ Object
validity checking - add_method_tracer must receive either push scope or metric, or else it would record no data. Raises an error if this is the case
297 298 299 300 301 |
# File 'lib/new_relic/agent/method_tracer.rb', line 297 def check_for_push_scope_and_metric() unless [:push_scope] || [:metric] raise "Can't add a tracer where push_scope is false and metric is false" end end |
#code_to_eval(method_name, metric_name_code, options) ⇒ Object
Decides which code snippet we should be eval’ing in this context, based on the options.
395 396 397 398 399 400 401 402 |
# File 'lib/new_relic/agent/method_tracer.rb', line 395 def code_to_eval(method_name, metric_name_code, ) = () if [:push_scope] method_with_push_scope(method_name, metric_name_code, ) else method_without_push_scope(method_name, metric_name_code, ) end end |
#default_metric_name_code(method_name) ⇒ Object
Default to the class where the method is defined.
Example:
Foo.default_metric_name_code('bar') #=> "Custom/#{Foo.name}/bar"
321 322 323 |
# File 'lib/new_relic/agent/method_tracer.rb', line 321 def default_metric_name_code(method_name) "Custom/#{self.name}/#{method_name.to_s}" end |
#method_with_push_scope(method_name, metric_name_code, options) ⇒ Object
returns an eval-able string that contains the tracing code for a fully traced metric including scoping
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 |
# File 'lib/new_relic/agent/method_tracer.rb', line 376 def method_with_push_scope(method_name, metric_name_code, ) klass = (self === Module) ? "self" : "self.class" "def #{_traced_method_name(method_name, metric_name_code)}(*args, &block) #{[:code_header]} result = #{klass}.trace_execution_scoped(\"#{metric_name_code}\", :metric => #{[:metric]}, :forced => #{[:force]}, :deduct_call_time_from_parent => #{[:deduct_call_time_from_parent]}, :scoped_metric_only => #{[:scoped_metric_only]}) do #{_untraced_method_name(method_name, metric_name_code)}(*args, &block) end #{[:code_footer]} result end" end |
#method_without_push_scope(method_name, metric_name_code, options) ⇒ Object
returns an eval-able string that contains the traced method code used if the agent is not creating a scope for use in scoped metrics.
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
# File 'lib/new_relic/agent/method_tracer.rb', line 357 def method_without_push_scope(method_name, metric_name_code, ) "def #{_traced_method_name(method_name, metric_name_code)}(*args, &block) #{assemble_code_header(method_name, metric_name_code, )} t0 = Time.now stats = NewRelic::Agent.instance.stats_engine.get_stats_no_scope \"#{metric_name_code}\" begin #{"NewRelic::Agent.instance.push_trace_execution_flag(true)\n" if [:force]} #{_untraced_method_name(method_name, metric_name_code)}(*args, &block)\n ensure #{"NewRelic::Agent.instance.pop_trace_execution_flag\n" if [:force] } duration = (Time.now - t0).to_f stats.trace_call(duration) #{[:code_footer]} end end" 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.
328 329 330 331 332 |
# File 'lib/new_relic/agent/method_tracer.rb', line 328 def newrelic_method_exists?(method_name) exists = method_defined?(method_name) || private_method_defined?(method_name) NewRelic::Control.instance.log.warn("Did not trace #{self.name}##{method_name} because that method does not exist") unless exists exists end |
#set_deduct_call_time_based_on_metric(options) ⇒ Object
Sets the options for deducting call time from parents. This defaults to true if we are recording a metric, but can be overridden by the user if desired.
has the effect of not allowing overlapping times, and should generally be true
290 291 292 |
# File 'lib/new_relic/agent/method_tracer.rb', line 290 def set_deduct_call_time_based_on_metric() {:deduct_call_time_from_parent => !![:metric]}.merge() end |
#traced_method_exists?(method_name, metric_name_code) ⇒ 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.
338 339 340 341 342 |
# File 'lib/new_relic/agent/method_tracer.rb', line 338 def traced_method_exists?(method_name, metric_name_code) exists = method_defined?(_traced_method_name(method_name, metric_name_code)) NewRelic::Control.instance.log.warn("Attempt to trace a method twice with the same metric: Method = #{method_name}, Metric Name = #{metric_name_code}") if exists exists end |
#unrecognized_keys(expected, given) ⇒ Object
used to verify that the keys passed to NewRelic::Agent::MethodTracer::ClassMethods#add_method_tracer are valid. Returns a list of keys that were unexpected
262 263 264 |
# File 'lib/new_relic/agent/method_tracer.rb', line 262 def unrecognized_keys(expected, given) given.keys - expected end |
#validate_options(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
309 310 311 312 313 314 315 |
# File 'lib/new_relic/agent/method_tracer.rb', line 309 def () raise TypeError.new("provided options must be a Hash") unless .is_a?(Hash) check_for_illegal_keys!() = set_deduct_call_time_based_on_metric(DEFAULT_SETTINGS.merge()) check_for_push_scope_and_metric() end |