gitlab-org--gitlab-foss/lib/error_tracking/stacktrace_builder.rb

66 lines
1.9 KiB
Ruby

# 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
# Some SDK send exception payload as Array. For exmple Go lang SDK.
# We need to convert it to hash format we expect.
exception_entry = { 'values' => exception_entry } if exception_entry.is_a?(Array)
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