diff options
Diffstat (limited to 'lib/sentry/client/issue.rb')
-rw-r--r-- | lib/sentry/client/issue.rb | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/lib/sentry/client/issue.rb b/lib/sentry/client/issue.rb index 4a11c87faa4..b6f2e07d233 100644 --- a/lib/sentry/client/issue.rb +++ b/lib/sentry/client/issue.rb @@ -3,6 +3,31 @@ module Sentry class Client module Issue + BadRequestError = Class.new(StandardError) + + SENTRY_API_SORT_VALUE_MAP = { + # <accepted_by_client> => <accepted_by_sentry_api> + 'frequency' => 'freq', + 'first_seen' => 'new', + 'last_seen' => nil + }.freeze + + def list_issues(**keyword_args) + response = get_issues(keyword_args) + + issues = response[:issues] + pagination = response[:pagination] + + validate_size(issues) + + handle_mapping_exceptions do + { + issues: map_to_errors(issues), + pagination: pagination + } + end + end + def issue_details(issue_id:) issue = get_issue(issue_id: issue_id) @@ -11,6 +36,37 @@ module Sentry private + def get_issues(**keyword_args) + response = http_get( + issues_api_url, + query: list_issue_sentry_query(keyword_args) + ) + + { + issues: response[:body], + pagination: Sentry::PaginationParser.parse(response[:headers]) + } + end + + def list_issue_sentry_query(issue_status:, limit:, sort: nil, search_term: '', cursor: nil) + unless SENTRY_API_SORT_VALUE_MAP.key?(sort) + raise BadRequestError, 'Invalid value for sort param' + end + + { + query: "is:#{issue_status} #{search_term}".strip, + limit: limit, + sort: SENTRY_API_SORT_VALUE_MAP[sort], + cursor: cursor + }.compact + end + + def validate_size(issues) + return if Gitlab::Utils::DeepSize.new(issues).valid? + + raise ResponseInvalidSizeError, "Sentry API response is too big. Limit is #{Gitlab::Utils::DeepSize.human_default_max_size}." + end + def get_issue(issue_id:) http_get(issue_api_url(issue_id))[:body] end @@ -19,6 +75,13 @@ module Sentry http_put(issue_api_url(issue_id), params)[:body] end + def issues_api_url + issues_url = URI("#{url}/issues/") + issues_url.path.squeeze!('/') + + issues_url + end + def issue_api_url(issue_id) issue_url = URI(url) issue_url.path = "/api/0/issues/#{CGI.escape(issue_id.to_s)}/" @@ -35,6 +98,50 @@ module Sentry gitlab_plugin.dig('issue', 'url') end + def issue_url(id) + parse_sentry_url("#{url}/issues/#{id}") + 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 slash + uri = uri.to_s.gsub(/\/\z/, '') + + uri + end + + def map_to_errors(issues) + issues.map(&method(:map_to_error)) + end + + def map_to_error(issue) + Gitlab::ErrorTracking::Error.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')), + 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') + ) + end + def map_to_detailed_error(issue) Gitlab::ErrorTracking::DetailedError.new( id: issue.fetch('id'), |