2021-09-30 23:02:18 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
class ErrorTracking::Error < ApplicationRecord
|
2021-11-11 11:23:49 +05:30
|
|
|
include Sortable
|
|
|
|
|
2021-09-30 23:02:18 +05:30
|
|
|
belongs_to :project
|
|
|
|
|
|
|
|
has_many :events, class_name: 'ErrorTracking::ErrorEvent'
|
|
|
|
|
2021-11-18 22:05:49 +05:30
|
|
|
has_one :first_event,
|
|
|
|
-> { order(id: :asc) },
|
|
|
|
class_name: 'ErrorTracking::ErrorEvent'
|
|
|
|
|
|
|
|
has_one :last_event,
|
|
|
|
-> { order(id: :desc) },
|
|
|
|
class_name: 'ErrorTracking::ErrorEvent'
|
|
|
|
|
2021-10-27 15:23:28 +05:30
|
|
|
scope :for_status, -> (status) { where(status: status) }
|
|
|
|
|
2021-09-30 23:02:18 +05:30
|
|
|
validates :project, presence: true
|
|
|
|
validates :name, presence: true
|
|
|
|
validates :description, presence: true
|
|
|
|
validates :actor, presence: true
|
2021-10-27 15:23:28 +05:30
|
|
|
validates :status, presence: true
|
|
|
|
|
|
|
|
enum status: {
|
|
|
|
unresolved: 0,
|
|
|
|
resolved: 1,
|
|
|
|
ignored: 2
|
|
|
|
}
|
2021-09-30 23:02:18 +05:30
|
|
|
|
|
|
|
def self.report_error(name:, description:, actor:, platform:, timestamp:)
|
|
|
|
safe_find_or_create_by(
|
|
|
|
name: name,
|
|
|
|
actor: actor,
|
|
|
|
platform: platform
|
2021-11-11 11:23:49 +05:30
|
|
|
).tap do |error|
|
|
|
|
error.update!(
|
|
|
|
# Description can contain object id, so it can't be
|
|
|
|
# used as a group criteria for similar errors.
|
|
|
|
description: description,
|
|
|
|
last_seen_at: timestamp
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.sort_by_attribute(method)
|
|
|
|
case method.to_s
|
|
|
|
when 'last_seen'
|
|
|
|
order(last_seen_at: :desc)
|
|
|
|
when 'first_seen'
|
|
|
|
order(first_seen_at: :desc)
|
|
|
|
when 'frequency'
|
|
|
|
order(events_count: :desc)
|
|
|
|
else
|
|
|
|
order_id_desc
|
2021-09-30 23:02:18 +05:30
|
|
|
end
|
|
|
|
end
|
2021-10-27 15:23:28 +05:30
|
|
|
|
|
|
|
def title
|
|
|
|
if description.present?
|
|
|
|
"#{name} #{description}"
|
|
|
|
else
|
|
|
|
name
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def title_truncated
|
|
|
|
title.truncate(64)
|
|
|
|
end
|
|
|
|
|
|
|
|
# For compatibility with sentry integration
|
|
|
|
def to_sentry_error
|
|
|
|
Gitlab::ErrorTracking::Error.new(
|
|
|
|
id: id,
|
|
|
|
title: title_truncated,
|
|
|
|
message: description,
|
|
|
|
culprit: actor,
|
|
|
|
first_seen: first_seen_at,
|
|
|
|
last_seen: last_seen_at,
|
|
|
|
status: status,
|
|
|
|
count: events_count
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
# For compatibility with sentry integration
|
|
|
|
def to_sentry_detailed_error
|
|
|
|
Gitlab::ErrorTracking::DetailedError.new(
|
|
|
|
id: id,
|
|
|
|
title: title_truncated,
|
|
|
|
message: description,
|
|
|
|
culprit: actor,
|
|
|
|
first_seen: first_seen_at.to_s,
|
|
|
|
last_seen: last_seen_at.to_s,
|
|
|
|
count: events_count,
|
|
|
|
user_count: 0, # we don't support user count yet.
|
|
|
|
project_id: project.id,
|
|
|
|
status: status,
|
|
|
|
tags: { level: nil, logger: nil },
|
|
|
|
external_url: external_url,
|
2021-11-18 22:05:49 +05:30
|
|
|
external_base_url: external_base_url,
|
|
|
|
integrated: true,
|
|
|
|
first_release_version: first_event&.release,
|
|
|
|
last_release_version: last_event&.release
|
2021-10-27 15:23:28 +05:30
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
# For compatibility with sentry integration
|
|
|
|
def external_url
|
|
|
|
Gitlab::Routing.url_helpers.details_namespace_project_error_tracking_index_url(
|
|
|
|
namespace_id: project.namespace,
|
|
|
|
project_id: project,
|
|
|
|
issue_id: id)
|
|
|
|
end
|
|
|
|
|
|
|
|
# For compatibility with sentry integration
|
|
|
|
def external_base_url
|
2021-11-18 22:05:49 +05:30
|
|
|
Gitlab::Routing.url_helpers.project_url(project)
|
2021-10-27 15:23:28 +05:30
|
|
|
end
|
2021-09-30 23:02:18 +05:30
|
|
|
end
|