File: stacktrace_builder.rb

package info (click to toggle)
ruby-sentry-ruby-core 5.3.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 412 kB
  • sloc: ruby: 3,030; makefile: 8; sh: 4
file content (79 lines) | stat: -rw-r--r-- 2,334 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# frozen_string_literal: true

module Sentry
  class StacktraceBuilder
    # @return [String]
    attr_reader :project_root

    # @return [Regexp, nil]
    attr_reader :app_dirs_pattern

    # @return [LineCache]
    attr_reader :linecache

    # @return [Integer, nil]
    attr_reader :context_lines

    # @return [Proc, nil]
    attr_reader :backtrace_cleanup_callback

    # @param project_root [String]
    # @param app_dirs_pattern [Regexp, nil]
    # @param linecache [LineCache]
    # @param context_lines [Integer, nil]
    # @param backtrace_cleanup_callback [Proc, nil]
    # @see Configuration#project_root
    # @see Configuration#app_dirs_pattern
    # @see Configuration#linecache
    # @see Configuration#context_lines
    # @see Configuration#backtrace_cleanup_callback
    def initialize(project_root:, app_dirs_pattern:, linecache:, context_lines:, backtrace_cleanup_callback: nil)
      @project_root = project_root
      @app_dirs_pattern = app_dirs_pattern
      @linecache = linecache
      @context_lines = context_lines
      @backtrace_cleanup_callback = backtrace_cleanup_callback
    end

    # Generates a StacktraceInterface with the given backtrace.
    # You can pass a block to customize/exclude frames:
    #
    # @example
    #   builder.build(backtrace) do |frame|
    #     if frame.module.match?(/a_gem/)
    #       nil
    #     else
    #       frame
    #     end
    #   end
    # @param backtrace [Array<String>]
    # @param frame_callback [Proc]
    # @yieldparam frame [StacktraceInterface::Frame]
    # @return [StacktraceInterface]
    def build(backtrace:, &frame_callback)
      parsed_lines = parse_backtrace_lines(backtrace).select(&:file)

      frames = parsed_lines.reverse.map do |line|
        frame = convert_parsed_line_into_frame(line)
        frame = frame_callback.call(frame) if frame_callback
        frame
      end.compact

      StacktraceInterface.new(frames: frames)
    end

    private

    def convert_parsed_line_into_frame(line)
      frame = StacktraceInterface::Frame.new(project_root, line)
      frame.set_context(linecache, context_lines) if context_lines
      frame
    end

    def parse_backtrace_lines(backtrace)
      Backtrace.parse(
        backtrace, project_root, app_dirs_pattern, &backtrace_cleanup_callback
      ).lines
    end
  end
end