diff options
Diffstat (limited to 'lib/error_tracking/stacktrace_builder.rb')
-rw-r--r-- | lib/error_tracking/stacktrace_builder.rb | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/lib/error_tracking/stacktrace_builder.rb b/lib/error_tracking/stacktrace_builder.rb new file mode 100644 index 00000000000..4f331bc4e06 --- /dev/null +++ b/lib/error_tracking/stacktrace_builder.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +module ErrorTracking + class StacktraceBuilder + attr_reader :stacktrace + + def initialize(payload) + @stacktrace = build_stacktrace(payload) + end + + private + + def build_stacktrace(payload) + raw_stacktrace = raw_stacktrace_from_payload(payload) + return [] unless raw_stacktrace + + raw_stacktrace.map do |entry| + { + 'lineNo' => entry['lineno'], + 'context' => build_stacktrace_context(entry), + 'filename' => entry['filename'], + 'function' => entry['function'], + 'colNo' => 0 # we don't support colNo yet. + } + end + end + + def raw_stacktrace_from_payload(payload) + exception_entry = payload['exception'] + return unless exception_entry + + exception_values = exception_entry['values'] + stack_trace_entry = exception_values&.detect { |h| h['stacktrace'].present? } + stack_trace_entry&.dig('stacktrace', 'frames') + end + + def build_stacktrace_context(entry) + error_line = entry['context_line'] + error_line_no = entry['lineno'] + pre_context = entry['pre_context'] + post_context = entry['post_context'] + + context = [] + context.concat lines_with_position(pre_context, error_line_no - pre_context.size) if pre_context + context.concat lines_with_position([error_line], error_line_no) + context.concat lines_with_position(post_context, error_line_no + 1) if post_context + + context.reject(&:blank?) + end + + def lines_with_position(lines, position) + return [] if lines.blank? + + lines.map.with_index do |line, index| + next unless line + + [position + index, line] + end + end + end +end |