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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sentry/client.rb')
-rw-r--r--lib/sentry/client.rb122
1 files changed, 107 insertions, 15 deletions
diff --git a/lib/sentry/client.rb b/lib/sentry/client.rb
index 07cca1c8d1e..6191d69c870 100644
--- a/lib/sentry/client.rb
+++ b/lib/sentry/client.rb
@@ -4,6 +4,7 @@ module Sentry
class Client
Error = Class.new(StandardError)
MissingKeysError = Class.new(StandardError)
+ ResponseInvalidSizeError = Class.new(StandardError)
attr_accessor :url, :token
@@ -12,9 +13,23 @@ module Sentry
@token = token
end
+ def issue_details(issue_id:)
+ issue = get_issue(issue_id: issue_id)
+
+ map_to_detailed_error(issue)
+ end
+
+ def issue_latest_event(issue_id:)
+ latest_event = get_issue_latest_event(issue_id: issue_id)
+
+ map_to_event(latest_event)
+ end
+
def list_issues(issue_status:, limit:)
issues = get_issues(issue_status: issue_status, limit: limit)
+ validate_size(issues)
+
handle_mapping_exceptions do
map_to_errors(issues)
end
@@ -30,6 +45,12 @@ module Sentry
private
+ def validate_size(issues)
+ return if Gitlab::Utils::DeepSize.new(issues).valid?
+
+ raise Client::ResponseInvalidSizeError, "Sentry API response is too big. Limit is #{Gitlab::Utils::DeepSize.human_default_max_size}."
+ end
+
def handle_mapping_exceptions(&block)
yield
rescue KeyError => e
@@ -61,6 +82,14 @@ module Sentry
})
end
+ def get_issue(issue_id:)
+ http_get(issue_api_url(issue_id))
+ end
+
+ def get_issue_latest_event(issue_id:)
+ http_get(issue_latest_event_api_url(issue_id))
+ end
+
def get_projects
http_get(projects_api_url)
end
@@ -88,7 +117,7 @@ module Sentry
raise_error "Sentry response status code: #{response.code}"
end
- response
+ response.parsed_response
end
def raise_error(message)
@@ -102,6 +131,20 @@ module Sentry
projects_url
end
+ def issue_api_url(issue_id)
+ issue_url = URI(@url)
+ issue_url.path = "/api/0/issues/#{issue_id}/"
+
+ issue_url
+ end
+
+ def issue_latest_event_api_url(issue_id)
+ latest_event_url = URI(@url)
+ latest_event_url.path = "/api/0/issues/#{issue_id}/events/latest/"
+
+ latest_event_url
+ end
+
def issues_api_url
issues_url = URI(@url + '/issues/')
issues_url.path.squeeze!('/')
@@ -119,38 +162,87 @@ module Sentry
def issue_url(id)
issues_url = @url + "/issues/#{id}"
- issues_url = ErrorTracking::ProjectErrorTrackingSetting.extract_sentry_external_url(issues_url)
- uri = URI(issues_url)
+ parse_sentry_url(issues_url)
+ end
+
+ def project_url
+ parse_sentry_url(@url)
+ end
+
+ def parse_sentry_url(api_url)
+ url = ErrorTracking::ProjectErrorTrackingSetting.extract_sentry_external_url(api_url)
+
+ uri = URI(url)
uri.path.squeeze!('/')
+ # Remove trailing spaces
+ uri = uri.to_s.gsub(/\/\z/, '')
- uri.to_s
+ uri
end
- def map_to_error(issue)
- id = issue.fetch('id')
+ def map_to_event(event)
+ stack_trace = parse_stack_trace(event)
- count = issue.fetch('count', nil)
+ Gitlab::ErrorTracking::ErrorEvent.new(
+ issue_id: event.dig('groupID'),
+ date_received: event.dig('dateReceived'),
+ stack_trace_entries: stack_trace
+ )
+ end
- frequency = issue.dig('stats', '24h')
- message = issue.dig('metadata', 'value')
+ def parse_stack_trace(event)
+ exception_entry = event.dig('entries')&.detect { |h| h['type'] == 'exception' }
+ return unless exception_entry
- external_url = issue_url(id)
+ exception_values = exception_entry.dig('data', 'values')
+ stack_trace_entry = exception_values&.detect { |h| h['stacktrace'].present? }
+ return unless stack_trace_entry
+
+ stack_trace_entry.dig('stacktrace', 'frames')
+ end
+
+ def map_to_detailed_error(issue)
+ Gitlab::ErrorTracking::DetailedError.new(
+ id: issue.fetch('id'),
+ first_seen: issue.fetch('firstSeen', nil),
+ last_seen: issue.fetch('lastSeen', nil),
+ title: issue.fetch('title', nil),
+ type: issue.fetch('type', nil),
+ user_count: issue.fetch('userCount', nil),
+ count: issue.fetch('count', nil),
+ message: issue.dig('metadata', 'value'),
+ culprit: issue.fetch('culprit', nil),
+ external_url: issue_url(issue.fetch('id')),
+ external_base_url: project_url,
+ short_id: issue.fetch('shortId', nil),
+ status: issue.fetch('status', nil),
+ frequency: issue.dig('stats', '24h'),
+ project_id: issue.dig('project', 'id'),
+ project_name: issue.dig('project', 'name'),
+ project_slug: issue.dig('project', 'slug'),
+ first_release_last_commit: issue.dig('firstRelease', 'lastCommit'),
+ last_release_last_commit: issue.dig('lastRelease', 'lastCommit'),
+ first_release_short_version: issue.dig('firstRelease', 'shortVersion'),
+ last_release_short_version: issue.dig('lastRelease', 'shortVersion')
+ )
+ end
+ def map_to_error(issue)
Gitlab::ErrorTracking::Error.new(
- id: id,
+ id: issue.fetch('id'),
first_seen: issue.fetch('firstSeen', nil),
last_seen: issue.fetch('lastSeen', nil),
title: issue.fetch('title', nil),
type: issue.fetch('type', nil),
user_count: issue.fetch('userCount', nil),
- count: count,
- message: message,
+ count: issue.fetch('count', nil),
+ message: issue.dig('metadata', 'value'),
culprit: issue.fetch('culprit', nil),
- external_url: external_url,
+ external_url: issue_url(issue.fetch('id')),
short_id: issue.fetch('shortId', nil),
status: issue.fetch('status', nil),
- frequency: frequency,
+ frequency: issue.dig('stats', '24h'),
project_id: issue.dig('project', 'id'),
project_name: issue.dig('project', 'name'),
project_slug: issue.dig('project', 'slug')