class StackifyRubyAPM::StacktraceBuilder

@api private

Constants

JAVA_FORMAT
JRUBY_ORG_REGEX
Method
RUBY_FORMAT
RUBY_VERS_REGEX

Attributes

config[R]

Public Class Methods

new(agent) click to toggle source
# File lib/stackify_apm/stacktrace_builder.rb, line 17
def initialize(agent)
  @config = agent.config
  @cache = Util::LruCache.new(2048, &method(:build_frame))
end

Public Instance Methods

build(backtrace, type) click to toggle source
# File lib/stackify_apm/stacktrace_builder.rb, line 24
def build(backtrace, type)
  Stacktrace.new.tap do |s|
    s.frames = backtrace.map do |line|
      @cache[[line, type]]
    end
  end
end

Private Instance Methods

build_frame(cache, keys) click to toggle source
# File lib/stackify_apm/stacktrace_builder.rb, line 34
def build_frame(cache, keys)
  line, type = keys
  abs_path, lineno, function, _module_name = parse_line(line)
  current_filename = strip_load_path(abs_path)
  library_frame = library_frame?(config, abs_path)

  frame = Stacktrace::Frame.new
  # frame.abs_path = abs_path
  # frame.filename = strip_load_path(abs_path)
  frame.Method = "#{function} (#{current_filename}:#{lineno})"
  # frame.lineno = lineno.to_i
  # frame.library_frame = library_frame?(config, abs_path)

  line_count =
    context_lines_for(config, type, library_frame)
  frame.build_context line_count

  cache[[line, type]] = frame
end
context_lines_for(config, type, library_frame) click to toggle source
# File lib/stackify_apm/stacktrace_builder.rb, line 96
def context_lines_for(config, type, library_frame)
  key = "source_lines_#{type}_#{library_frame ? 'library' : 'app'}_frames"
  config.send(key.to_sym)
end
library_frame?(config, abs_path) click to toggle source
# File lib/stackify_apm/stacktrace_builder.rb, line 69
def library_frame?(config, abs_path)
  return false unless abs_path

  if abs_path.start_with?(config.root_path)
    return true if abs_path.start_with?(config.root_path + '/vendor')

    return false
  end

  return true if abs_path.match(RUBY_VERS_REGEX)
  return true if abs_path.match(JRUBY_ORG_REGEX)

  false
end
parse_line(line) click to toggle source
# File lib/stackify_apm/stacktrace_builder.rb, line 54
def parse_line(line)
  ruby_match = line.match(RUBY_FORMAT)

  if ruby_match
    _, file, number, method = ruby_match.to_a
    file.sub!(/\.class$/, '.rb')
    module_name = nil
  else
    java_match = line.match(JAVA_FORMAT)
    _, module_name, method, file, number = java_match.to_a
  end

  [file, number, method, module_name]
end
strip_load_path(path) click to toggle source
# File lib/stackify_apm/stacktrace_builder.rb, line 84
def strip_load_path(path)
  return nil if path.nil?

  prefix =
    $LOAD_PATH
    .map(&:to_s)
    .select { |s| path.start_with?(s) }
    .max_by(&:length)

  prefix ? path[prefix.chomp(File::SEPARATOR).length + 1..-1] : path
end