module ScoutApm::Tracer::ClassMethods

Public Instance Methods

instrument(type, name, options={}, &block) click to toggle source

See ScoutApm::Tracer.instrument

# File lib/scout_apm/tracer.rb, line 43
def instrument(type, name, options={}, &block)
  ScoutApm::Tracer.instrument(type, name, options, &block)
end
instrument_method(method_name, options = {}) click to toggle source

Wraps a method in a call to instrument via aggressive monkey patching.

Options: type - “View” or “ActiveRecord” and similar name - “users/show”, “App#find”

# File lib/scout_apm/tracer.rb, line 52
def instrument_method(method_name, options = {})
  ScoutApm::Agent.instance.context.logger.info "Instrumenting #{method_name}"
  type = options[:type] || "Custom"
  name = options[:name] || "#{self.name}/#{method_name.to_s}"

  instrumented_name, uninstrumented_name = _determine_instrumented_name(method_name, type)

  ScoutApm::Agent.instance.context.logger.info "Instrumenting #{instrumented_name}, #{uninstrumented_name}"

  return if !_instrumentable?(method_name) or _instrumented?(instrumented_name, method_name)

  class_eval(
    _instrumented_method_string(instrumented_name, uninstrumented_name, type, name, {:scope => options[:scope] }),
    __FILE__, __LINE__
  )

  alias_method uninstrumented_name, method_name
  alias_method method_name, instrumented_name
end

Private Instance Methods

_determine_instrumented_name(method_name, type) click to toggle source
# File lib/scout_apm/tracer.rb, line 74
def _determine_instrumented_name(method_name, type)
  inst = _find_unused_method_name { _instrumented_method_name(method_name, type) }
  uninst = _find_unused_method_name { _uninstrumented_method_name(method_name, type) }

  return inst, uninst
end
_find_unused_method_name() { || ... } click to toggle source
# File lib/scout_apm/tracer.rb, line 81
def _find_unused_method_name
  raw_name = name = yield

  i = 0
  while method_defined?(name) && i < 100
    i += 1
    name = "#{raw_name}_#{i}"
  end
  name
end
_instrumentable?(method_name) click to toggle source

The method must exist to be instrumented.

# File lib/scout_apm/tracer.rb, line 115
def _instrumentable?(method_name)
  exists = method_defined?(method_name) || private_method_defined?(method_name)
  ScoutApm::Agent.instance.context.logger.warn "The method [#{self.name}##{method_name}] does not exist and will not be instrumented" unless exists
  exists
end
_instrumented?(instrumented_name, method_name) click to toggle source

True if the method is already instrumented.

# File lib/scout_apm/tracer.rb, line 122
def _instrumented?(instrumented_name, method_name)
  instrumented = method_defined?(instrumented_name)
  ScoutApm::Agent.instance.context.logger.warn("The method [#{self.name}##{method_name}] has already been instrumented") if instrumented
  instrumented
end
_instrumented_method_name(method_name, type) click to toggle source

given a method and a metric, this method returns the traced alias of the method name

# File lib/scout_apm/tracer.rb, line 136
def _instrumented_method_name(method_name, type)
  "#{_sanitize_name(method_name)}_with_scout_instrument"
end
_instrumented_method_string(instrumented_name, uninstrumented_name, type, name, options={}) click to toggle source
# File lib/scout_apm/tracer.rb, line 92
      def _instrumented_method_string(instrumented_name, uninstrumented_name, type, name, options={})
        method_str = <<-EOF
        def #{instrumented_name}(*args#{", **kwargs" if ScoutApm::Agent.instance.context.environment.supports_kwarg_delegation?}, &block)
          name = begin
                   "#{name}"
                 rescue => e
                   ScoutApm::Agent.instance.context.logger.error("Error raised while interpreting instrumented name: %s, %s" % ['#{name}', e.message])
                   "Unknown"
                 end

          ::ScoutApm::Tracer.instrument( "#{type}",
                               name,
                               {:scope => #{options[:scope] || false}}
                             ) do
            #{uninstrumented_name}(*args#{", **kwargs" if ScoutApm::Agent.instance.context.environment.supports_kwarg_delegation?}, &block)
          end
        end
        EOF

        method_str
      end
_sanitize_name(name) click to toggle source

Method names like any? or replace! contain a trailing character that would break when eval'd as ? and ! aren't allowed inside method names.

# File lib/scout_apm/tracer.rb, line 142
def _sanitize_name(name)
  name.to_s.tr_s('^a-zA-Z0-9', '_')
end
_uninstrumented_method_name(method_name, type) click to toggle source

given a method and a metric, this method returns the untraced alias of the method name

# File lib/scout_apm/tracer.rb, line 130
def _uninstrumented_method_name(method_name, type)
  "#{_sanitize_name(method_name)}_without_scout_instrument"
end