Module: TingYun::Agent::MethodTracer::ClassMethods::AddMethodTracer

Included in:
TingYun::Agent::MethodTracer::ClassMethods
Defined in:
lib/ting_yun/agent/method_tracer.rb

Overview

contains methods refactored out of the #add_method_tracer method

Instance Method Summary collapse

Instance Method Details

#_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)


74
75
76
77
78
# File 'lib/ting_yun/agent/method_tracer.rb', line 74

def _method_exists?(method_name)
  exists = method_defined?(method_name) || private_method_defined?(method_name)
  ::TingYun::Agent.logger.error("Did not trace #{self.name}##{method_name} because that method does not exist") unless exists
  exists
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



144
145
146
147
148
# File 'lib/ting_yun/agent/method_tracer.rb', line 144

def assemble_code_header(method_name, metric_name_code, options)
  # header = "return #{_untraced_method_name(method_name, metric_name_code)}(*args, &block) unless TingYun::Agent.tl_is_execution_traced?\n"
  header += options[:code_header].to_s
  header
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.



100
101
102
103
104
105
106
107
# File 'lib/ting_yun/agent/method_tracer.rb', line 100

def code_to_eval(method_name, metric_name_code, options)
  options = validate_options(method_name, options)
  if options[:push_scope]
    method_with_push_scope(method_name, metric_name_code, options)
  else
    method_without_push_scope(method_name, metric_name_code, options)
  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"


84
85
86
# File 'lib/ting_yun/agent/method_tracer.rb', line 84

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



111
112
113
114
115
116
117
118
119
120
121
# File 'lib/ting_yun/agent/method_tracer.rb', line 111

def method_with_push_scope(method_name, metric_name_code, options)
  "def #{_traced_method_name(method_name, metric_name_code)}(*args, &block)
    #{options[:code_header]}
    result = ::TingYun::Agent::MethodTracerHelpers.trace_execution_scoped(\"#{metric_name_code}\",
              :metric => #{options[:metric]}) do
      #{_untraced_method_name(method_name, metric_name_code)}(*args, &block)
    end
    #{options[: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.



126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/ting_yun/agent/method_tracer.rb', line 126

def method_without_push_scope(method_name, metric_name_code, options)
  "def #{_traced_method_name(method_name, metric_name_code)}(*args, &block)
    #{assemble_code_header(method_name, metric_name_code, options)}
    t0 = Time.now
    begin
      #{_untraced_method_name(method_name, metric_name_code)}(*args, &block)\n
    ensure
      duration = (Time.now - t0).to_f
      ::TingYun::Agent.record_metric(\"#{metric_name_code}\", duration)
      #{options[:code_footer]}
    end
  end"
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.

Returns:

  • (Boolean)


92
93
94
95
96
# File 'lib/ting_yun/agent/method_tracer.rb', line 92

def traced_method_exists?(method_name, metric_name_code)
  exists = method_defined?(_traced_method_name(method_name, metric_name_code))
  ::TingYun::Agent.logger.error("Attempt to trace a method twice with the same metric: Method = #{method_name}, Metric Name = #{metric_name_code}") if exists
  exists
end