Welcome to mirror list, hosted at ThFree Co, Russian Federation.

error_event.rb « error_tracking « models « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 0b638f65768aef71333a934cf67d0f184c5e2a79 (plain)
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
80
81
82
# frozen_string_literal: true

class ErrorTracking::ErrorEvent < ApplicationRecord
  belongs_to :error, counter_cache: :events_count

  validates :payload, json_schema: { filename: 'error_tracking_event_payload' }

  validates :error, presence: true
  validates :description, presence: true, length: { maximum: 1024 }
  validates :level, length: { maximum: 255 }
  validates :environment, length: { maximum: 255 }
  validates :occurred_at, presence: true

  def stacktrace
    @stacktrace ||= build_stacktrace
  end

  # For compatibility with sentry integration
  def to_sentry_error_event
    Gitlab::ErrorTracking::ErrorEvent.new(
      issue_id: error_id,
      date_received: occurred_at,
      stack_trace_entries: stacktrace
    )
  end

  def release
    payload.dig('release')
  end

  private

  def build_stacktrace
    raw_stacktrace = find_stacktrace_from_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 find_stacktrace_from_payload
    exception_entry = payload.dig('exception')

    if exception_entry
      exception_values = exception_entry.dig('values')
      stack_trace_entry = exception_values&.detect { |h| h['stacktrace'].present? }
      stack_trace_entry&.dig('stacktrace', 'frames')
    end
  end

  def build_stacktrace_context(entry)
    context = []
    error_line = entry['context_line']
    error_line_no = entry['lineno']
    pre_context = entry['pre_context']
    post_context = entry['post_context']

    context += lines_with_position(pre_context, error_line_no - pre_context.size) if pre_context
    context += lines_with_position([error_line], error_line_no)
    context += 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