class StackifyRubyAPM::InstrumenterHelper

@api private

Constants

TRACETYPE

Attributes

custom_class_info[RW]

rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/PerceivedComplexity rubocop:disable Lint/UselessAssignment rubocop:disable Security/Eval

custom_instrumented[RW]

rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/PerceivedComplexity rubocop:disable Lint/UselessAssignment rubocop:disable Security/Eval

Public Class Methods

custom_instrumented_reset() click to toggle source
# File lib/stackify_apm/instrumenter_helper.rb, line 17
def self.custom_instrumented_reset
  @custom_instrumented.each do |custom_instrument, values|
    current_class = custom_instrument
    module_consget = Module.const_get(current_class)
    values.each_key do |current_method|
      is_method_exists = StackifyRubyAPM::Spies.ismethod_exists(current_class, current_method)
      if is_method_exists
        @custom_instrumented[current_class.to_s][current_method.to_s] = false
      end
    end
  end
end
m_class(tracked_func, current_class, class_path, **options) click to toggle source
# File lib/stackify_apm/instrumenter_helper.rb, line 30
    def self.m_class(tracked_func, current_class, class_path, **options)
      current_method = options[:current_method] || nil
      tracked_function_name = options[:tracked_function_name] || nil
      transaction = options[:is_transaction] || nil
      module_consget = Module.const_get(current_class)
      classspyitem = "#{current_class}Spy"
      module_consget_spy = Module.const_get(current_class)
      current_method_without = "_without_apm_#{current_method}"
      is_private_method = options[:is_private_method] || false
      is_protected_method = options[:is_protected_method] || false

      unless @custom_instrumented[current_class.to_s]
        @custom_instrumented[current_class.to_s] = {}
      end

      unless @custom_instrumented[current_class.to_s][current_method.to_s]
        @custom_instrumented[current_class.to_s][current_method.to_s] = false
      end

      unless @custom_class_info[current_class.to_s]
        @custom_class_info[current_class.to_s] = {}
      end

      unless @custom_class_info[current_class.to_s]['controller']
        @custom_class_info[current_class.to_s]['controller'] = false
      end

      unless @custom_class_info[current_class.to_s]['model']
        @custom_class_info[current_class.to_s]['model'] = false
      end

      return unless @custom_instrumented[current_class.to_s][current_method.to_s] == false

      eval <<-RUBY
        class #{classspyitem}
          def install
            #{current_class}.class_eval do
              alias_method "#{current_method_without}", "#{current_method}"
              
              #{
                if is_private_method
                  then "private"
                elsif is_protected_method
                  then "protected"
                end
              }
              def #{current_method}(*args, &block)
                if StackifyRubyAPM.current_transaction.nil? && #{!transaction.nil?}
                  t = StackifyRubyAPM.transaction("custom.#{current_class}.#{current_method}", TRACETYPE)
                  begin
                    req = #{current_method_without}(*args, &block)
                  rescue Exception => e
                    StackifyRubyAPM.report(e)
                    raise e
                  ensure
                    t.submit
                  end
                  return req
                elsif StackifyRubyAPM.current_transaction
                  name = "Custom Instrument"
                  type = "#{current_class}##{current_method}"
                  ctx = if "#{tracked_func}" == 'true'
                          Span::Context.new(
                            CATEGORY: 'Ruby',
                            TRACKED_FUNC: "#{tracked_function_name}"
                          )
                        else
                          Span::Context.new(
                            CATEGORY: 'Ruby'
                          )
                        end

                  StackifyRubyAPM.span name, type, context: ctx do
                    #{current_method_without}(*args, &block)
                  end
                else
                  return #{current_method_without}(*args, &block)
                end
              end
            end
          end
        end
        StackifyRubyAPM::Spies.register current_class.to_s, class_path.to_s, #{classspyitem}.new, true, "#{current_method}", "#{tracked_func}", "#{tracked_function_name}"
      RUBY

      @custom_instrumented[current_class.to_s][current_method.to_s] = true
      @custom_class_info[current_class.to_s]['controller'] = true if class_path && class_path.include?('controllers')
      @custom_class_info[current_class.to_s]['model'] = true if class_path && class_path.include?('models')
    end
m_singleton(tracked_func, current_class, class_path, **options) click to toggle source
# File lib/stackify_apm/instrumenter_helper.rb, line 120
    def self.m_singleton(tracked_func, current_class, class_path, **options)
      current_method = options[:current_method] || nil
      tracked_function_name = options[:tracked_function_name] || nil
      transaction = options[:is_transaction] || nil
      module_consget = Module.const_get(current_class)
      classspyitem = "#{current_class}Spy"

      unless @custom_instrumented[current_class.to_s]
        @custom_instrumented[current_class.to_s] = {}
      end

      unless @custom_instrumented[current_class.to_s][current_method.to_s]
        @custom_instrumented[current_class.to_s][current_method.to_s] = false
      end

      unless @custom_class_info[current_class.to_s]
        @custom_class_info[current_class.to_s] = {}
      end

      unless @custom_class_info[current_class.to_s]['controller']
        @custom_class_info[current_class.to_s]['controller'] = false
      end

      unless @custom_class_info[current_class.to_s]['model']
        @custom_class_info[current_class.to_s]['model'] = false
      end

      return unless @custom_instrumented[current_class.to_s][current_method.to_s] == false

      eval <<-RUBY
        class #{classspyitem}
          def install
            #{current_class}.class_eval do
              singleton_class.send(:alias_method, :"_self_without_apm_#{current_method}", :"#{current_method}")

              def self.#{current_method}(*args, &block)
                if StackifyRubyAPM.current_transaction.nil? && #{!transaction.nil?}
                  t = StackifyRubyAPM.transaction("custom.#{current_class}.#{current_method}", TRACETYPE)
                  begin
                    req = _self_without_apm_#{current_method}(*args, &block)
                  rescue Exception => e
                    StackifyRubyAPM.report(e)
                    raise e
                  ensure
                    t.submit
                  end
                  return req
                elsif StackifyRubyAPM.current_transaction
                  name = "Custom Instrument"
                  type = "#{current_class}##{current_method}"
                  ctx = if "#{tracked_func}" == 'true'
                          Span::Context.new(
                            CATEGORY: 'Ruby',
                            TRACKED_FUNC: "#{tracked_function_name}"
                          )
                        else
                          Span::Context.new(
                            CATEGORY: 'Ruby'
                          )
                        end

                  StackifyRubyAPM.span name, type, context: ctx do
                    _self_without_apm_#{current_method}(*args, &block)
                  end
                else
                  return _self_without_apm_#{current_method}(*args, &block)
                end
              end

              def self.get_class_name
                return self.class.name
              end
            end
          end
        end
        StackifyRubyAPM::Spies.register current_class.to_s, class_path.to_s, #{classspyitem}.new, true, "#{current_method}", "#{tracked_func}", "#{tracked_function_name}"
      RUBY
      @custom_instrumented[current_class.to_s][current_method.to_s] = true
      @custom_class_info[current_class.to_s]['controller'] = true if class_path && class_path.include?('controllers')
      @custom_class_info[current_class.to_s]['model'] = true if class_path && class_path.include?('models')
    end
patched_module(tracked_func, current_module, class_path, **options) click to toggle source

Monkey patch the single ruby module file.

tracked_func - trackedFunction variable in stackify.json current_module - module variable in stackify.json class_path - file_path variable in stackify.json options - other options such as trackedFunctionName

# File lib/stackify_apm/instrumenter_helper.rb, line 208
    def self.patched_module(tracked_func, current_module, class_path, **options)
      current_method = options[:current_method] || nil
      tracked_function_name = options[:tracked_function_name] || nil
      transaction = options[:is_transaction] || nil
      mod_spy = "#{current_module}Spy"

      unless @custom_instrumented[current_module.to_s]
        @custom_instrumented[current_module.to_s] = {}
      end

      unless @custom_instrumented[current_module.to_s][current_method.to_s]
        @custom_instrumented[current_module.to_s][current_method.to_s] = false
      end

      unless @custom_class_info[current_module.to_s]
        @custom_class_info[current_module.to_s] = {}
      end

      unless @custom_class_info[current_module.to_s]['controller']
        @custom_class_info[current_module.to_s]['controller'] = false
      end

      unless @custom_class_info[current_module.to_s]['model']
        @custom_class_info[current_module.to_s]['model'] = false
      end

      return unless @custom_instrumented[current_module.to_s][current_method.to_s] == false

      eval <<-RUBY
        module #{mod_spy}
          def self.install
            #{current_module}.class_eval do
              class<< self
                alias_method "#{current_method}_without_apm", "#{current_method}"

                def #{current_method}(*args, &block)
                  if StackifyRubyAPM.current_transaction.nil? && #{!transaction.nil?}
                    t = StackifyRubyAPM.transaction("custom.#{current_module}.#{current_method}", TRACETYPE)
                    begin
                      req = #{current_method}_without_apm(*args, &block)
                    rescue Exception => e
                      StackifyRubyAPM.report(e)
                      raise e
                    ensure
                      t.submit
                    end
                    return req
                  elsif StackifyRubyAPM.current_transaction
                    name = "Custom Instrument"
                    type = "#{current_module}##{current_method}"
                    ctx = if "#{tracked_func}" == 'true'
                            Span::Context.new(
                              CATEGORY: 'Ruby',
                              TRACKED_FUNC: "#{tracked_function_name}"
                            )
                          else
                            Span::Context.new(
                              CATEGORY: 'Ruby'
                            )
                          end

                    StackifyRubyAPM.span name, type, context: ctx do
                      #{current_method}_without_apm(*args, &block)
                    end
                  else
                    return #{current_method}_without_apm(*args, &block)
                  end
                end
              end
            end
          end
        end

        StackifyRubyAPM::Spies.register current_module.to_s, class_path.to_s, #{mod_spy}, true, "#{current_method}", "#{tracked_func}", "#{tracked_function_name}"
      RUBY
      @custom_instrumented[current_module.to_s][current_method.to_s] = true
      @custom_class_info[current_module.to_s]['controller'] = true if class_path && class_path.include?('controllers')
      @custom_class_info[current_module.to_s]['model'] = true if class_path && class_path.include?('models')
    end