Class: Bugwatch::BacktraceCleaner

Inherits:
Object
  • Object
show all
Defined in:
lib/bugwatch/backtrace_cleaner.rb

Constant Summary collapse

STDLIB_PATHS =
[
  RbConfig::CONFIG["rubylibdir"],
  RbConfig::CONFIG["rubyarchdir"],
  Gem.default_dir
].compact.map { |p| Regexp.escape(p) }
GEM_PATH_RE =
/\/gems\//
STDLIB_RE =
Regexp.union(*STDLIB_PATHS)

Class Method Summary collapse

Class Method Details

.clean(backtrace) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/bugwatch/backtrace_cleaner.rb', line 12

def self.clean(backtrace)
  return [] unless backtrace

  backtrace.map do |line|
    path, lineno, label = parse_frame(line)
    in_app = in_app?(path)

    frame = {
      file:   path,
      line:   lineno,
      method: label,
      in_app: in_app
    }

    if in_app && path && File.exist?(path)
      frame[:source_context] = read_source_context(path, lineno)
    end

    frame
  end
end

.in_app?(path) ⇒ Boolean

Returns:

  • (Boolean)


44
45
46
47
48
49
# File 'lib/bugwatch/backtrace_cleaner.rb', line 44

def self.in_app?(path)
  return false if path.nil?
  return false if path.match?(GEM_PATH_RE)
  return false if defined?(STDLIB_RE) && path.match?(STDLIB_RE)
  true
end

.parse_frame(line) ⇒ Object



34
35
36
37
38
39
40
41
42
# File 'lib/bugwatch/backtrace_cleaner.rb', line 34

def self.parse_frame(line)
  if line =~ /\A(.+?):(\d+):in `(.*)'\z/
    [$1, $2.to_i, $3]
  elsif line =~ /\A(.+?):(\d+)\z/
    [$1, $2.to_i, nil]
  else
    [line, 0, nil]
  end
end

.read_source_context(path, lineno, context_lines: 3) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
# File 'lib/bugwatch/backtrace_cleaner.rb', line 51

def self.read_source_context(path, lineno, context_lines: 3)
  lines = File.readlines(path)
  first = [lineno - context_lines - 1, 0].max
  last  = [lineno + context_lines - 1, lines.size - 1].min

  lines[first..last].each_with_object({}).with_index(first + 1) do |(source_line, hash), n|
    hash[n] = source_line.chomp
  end
rescue Errno::ENOENT, Errno::EACCES
  {}
end