Commit 90b3a74e authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch 'dz-et-integrated-show-commit-info' into 'master'

Improve integrated error tracking issue details

See merge request gitlab-org/gitlab!71405
parents 1cb9d5c7 81093e5f
...@@ -128,6 +128,12 @@ export default { ...@@ -128,6 +128,12 @@ export default {
lastReleaseLink() { lastReleaseLink() {
return `${this.error.externalBaseUrl}/releases/${this.error.lastReleaseVersion}`; return `${this.error.externalBaseUrl}/releases/${this.error.lastReleaseVersion}`;
}, },
firstCommitLink() {
return `${this.error.externalBaseUrl}/-/commit/${this.error.firstReleaseVersion}`;
},
lastCommitLink() {
return `${this.error.externalBaseUrl}/-/commit/${this.error.lastReleaseVersion}`;
},
showStacktrace() { showStacktrace() {
return Boolean(this.stacktrace?.length); return Boolean(this.stacktrace?.length);
}, },
...@@ -394,7 +400,7 @@ export default { ...@@ -394,7 +400,7 @@ export default {
<span>{{ error.gitlabIssuePath }}</span> <span>{{ error.gitlabIssuePath }}</span>
</gl-link> </gl-link>
</li> </li>
<li> <li v-if="!error.integrated">
<strong class="bold">{{ __('Sentry event') }}:</strong> <strong class="bold">{{ __('Sentry event') }}:</strong>
<gl-link <gl-link
v-track-event="trackClickErrorLinkToSentryOptions(error.externalUrl)" v-track-event="trackClickErrorLinkToSentryOptions(error.externalUrl)"
...@@ -409,15 +415,21 @@ export default { ...@@ -409,15 +415,21 @@ export default {
<li v-if="error.firstReleaseVersion"> <li v-if="error.firstReleaseVersion">
<strong class="bold">{{ __('First seen') }}:</strong> <strong class="bold">{{ __('First seen') }}:</strong>
<time-ago-tooltip :time="error.firstSeen" /> <time-ago-tooltip :time="error.firstSeen" />
<gl-link :href="firstReleaseLink" target="_blank"> <gl-link v-if="error.integrated" :href="firstCommitLink">
<span>{{ __('Release') }}: {{ error.firstReleaseVersion }}</span> {{ __('GitLab commit') }}: {{ error.firstReleaseVersion }}
</gl-link>
<gl-link v-else :href="firstReleaseLink" target="_blank">
{{ __('Release') }}: {{ error.firstReleaseVersion }}
</gl-link> </gl-link>
</li> </li>
<li v-if="error.lastReleaseVersion"> <li v-if="error.lastReleaseVersion">
<strong class="bold">{{ __('Last seen') }}:</strong> <strong class="bold">{{ __('Last seen') }}:</strong>
<time-ago-tooltip :time="error.lastSeen" /> <time-ago-tooltip :time="error.lastSeen" />
<gl-link :href="lastReleaseLink" target="_blank"> <gl-link v-if="error.integrated" :href="lastCommitLink">
<span>{{ __('Release') }}: {{ error.lastReleaseVersion }}</span> {{ __('GitLab commit') }}: {{ error.lastReleaseVersion }}
</gl-link>
<gl-link v-else :href="lastReleaseLink" target="_blank">
{{ __('Release') }}: {{ error.lastReleaseVersion }}
</gl-link> </gl-link>
</li> </li>
<li> <li>
......
...@@ -23,6 +23,7 @@ query errorDetails($fullPath: ID!, $errorId: ID!) { ...@@ -23,6 +23,7 @@ query errorDetails($fullPath: ID!, $errorId: ID!) {
gitlabCommit gitlabCommit
gitlabCommitPath gitlabCommitPath
gitlabIssuePath gitlabIssuePath
integrated
} }
} }
} }
......
...@@ -13,6 +13,9 @@ module Types ...@@ -13,6 +13,9 @@ module Types
field :id, GraphQL::Types::ID, field :id, GraphQL::Types::ID,
null: false, null: false,
description: 'ID (global ID) of the error.' description: 'ID (global ID) of the error.'
field :integrated, GraphQL::Types::Boolean,
null: true,
description: 'Error tracking backend.'
field :sentry_id, GraphQL::Types::String, field :sentry_id, GraphQL::Types::String,
method: :id, method: :id,
null: false, null: false,
......
...@@ -7,6 +7,14 @@ class ErrorTracking::Error < ApplicationRecord ...@@ -7,6 +7,14 @@ class ErrorTracking::Error < ApplicationRecord
has_many :events, class_name: 'ErrorTracking::ErrorEvent' has_many :events, class_name: 'ErrorTracking::ErrorEvent'
has_one :first_event,
-> { order(id: :asc) },
class_name: 'ErrorTracking::ErrorEvent'
has_one :last_event,
-> { order(id: :desc) },
class_name: 'ErrorTracking::ErrorEvent'
scope :for_status, -> (status) { where(status: status) } scope :for_status, -> (status) { where(status: status) }
validates :project, presence: true validates :project, presence: true
...@@ -90,7 +98,10 @@ class ErrorTracking::Error < ApplicationRecord ...@@ -90,7 +98,10 @@ class ErrorTracking::Error < ApplicationRecord
status: status, status: status,
tags: { level: nil, logger: nil }, tags: { level: nil, logger: nil },
external_url: external_url, external_url: external_url,
external_base_url: external_base_url external_base_url: external_base_url,
integrated: true,
first_release_version: first_event&.release,
last_release_version: last_event&.release
) )
end end
...@@ -106,6 +117,6 @@ class ErrorTracking::Error < ApplicationRecord ...@@ -106,6 +117,6 @@ class ErrorTracking::Error < ApplicationRecord
# For compatibility with sentry integration # For compatibility with sentry integration
def external_base_url def external_base_url
Gitlab::Routing.url_helpers.root_url Gitlab::Routing.url_helpers.project_url(project)
end end
end end
...@@ -22,6 +22,10 @@ class ErrorTracking::ErrorEvent < ApplicationRecord ...@@ -22,6 +22,10 @@ class ErrorTracking::ErrorEvent < ApplicationRecord
) )
end end
def release
payload.dig('release')
end
private private
def build_stacktrace def build_stacktrace
......
...@@ -13901,6 +13901,7 @@ A Sentry error. ...@@ -13901,6 +13901,7 @@ A Sentry error.
| <a id="sentrydetailederrorgitlabcommitpath"></a>`gitlabCommitPath` | [`String`](#string) | Path to the GitLab page for the GitLab commit attributed to the error. | | <a id="sentrydetailederrorgitlabcommitpath"></a>`gitlabCommitPath` | [`String`](#string) | Path to the GitLab page for the GitLab commit attributed to the error. |
| <a id="sentrydetailederrorgitlabissuepath"></a>`gitlabIssuePath` | [`String`](#string) | URL of GitLab Issue. | | <a id="sentrydetailederrorgitlabissuepath"></a>`gitlabIssuePath` | [`String`](#string) | URL of GitLab Issue. |
| <a id="sentrydetailederrorid"></a>`id` | [`ID!`](#id) | ID (global ID) of the error. | | <a id="sentrydetailederrorid"></a>`id` | [`ID!`](#id) | ID (global ID) of the error. |
| <a id="sentrydetailederrorintegrated"></a>`integrated` | [`Boolean`](#boolean) | Error tracking backend. |
| <a id="sentrydetailederrorlastreleaselastcommit"></a>`lastReleaseLastCommit` | [`String`](#string) | Commit the error was last seen. | | <a id="sentrydetailederrorlastreleaselastcommit"></a>`lastReleaseLastCommit` | [`String`](#string) | Commit the error was last seen. |
| <a id="sentrydetailederrorlastreleaseshortversion"></a>`lastReleaseShortVersion` | [`String`](#string) | Release short version the error was last seen. | | <a id="sentrydetailederrorlastreleaseshortversion"></a>`lastReleaseShortVersion` | [`String`](#string) | Release short version the error was last seen. |
| <a id="sentrydetailederrorlastreleaseversion"></a>`lastReleaseVersion` | [`String`](#string) | Release version the error was last seen. | | <a id="sentrydetailederrorlastreleaseversion"></a>`lastReleaseVersion` | [`String`](#string) | Release version the error was last seen. |
......
...@@ -167,7 +167,8 @@ module ErrorTracking ...@@ -167,7 +167,8 @@ module ErrorTracking
first_release_version: issue.dig('firstRelease', 'version'), first_release_version: issue.dig('firstRelease', 'version'),
last_release_last_commit: issue.dig('lastRelease', 'lastCommit'), last_release_last_commit: issue.dig('lastRelease', 'lastCommit'),
last_release_short_version: issue.dig('lastRelease', 'shortVersion'), last_release_short_version: issue.dig('lastRelease', 'shortVersion'),
last_release_version: issue.dig('lastRelease', 'version') last_release_version: issue.dig('lastRelease', 'version'),
integrated: false
}) })
end end
......
...@@ -22,6 +22,7 @@ module Gitlab ...@@ -22,6 +22,7 @@ module Gitlab
:gitlab_issue, :gitlab_issue,
:gitlab_project, :gitlab_project,
:id, :id,
:integrated,
:last_release_last_commit, :last_release_last_commit,
:last_release_short_version, :last_release_short_version,
:last_release_version, :last_release_version,
......
...@@ -503,6 +503,53 @@ describe('ErrorDetails', () => { ...@@ -503,6 +503,53 @@ describe('ErrorDetails', () => {
}); });
}); });
}); });
describe('Release links', () => {
const firstReleaseVersion = '7975be01';
const firstCommitLink = '/gitlab/-/commit/7975be01';
const firstReleaseLink = '/sentry/releases/7975be01';
const findFirstCommitLink = () => wrapper.find(`[href$="${firstCommitLink}"]`);
const findFirstReleaseLink = () => wrapper.find(`[href$="${firstReleaseLink}"]`);
const lastReleaseVersion = '6ca5a5c1';
const lastCommitLink = '/gitlab/-/commit/6ca5a5c1';
const lastReleaseLink = '/sentry/releases/6ca5a5c1';
const findLastCommitLink = () => wrapper.find(`[href$="${lastCommitLink}"]`);
const findLastReleaseLink = () => wrapper.find(`[href$="${lastReleaseLink}"]`);
it('should display links to Sentry', async () => {
mocks.$apollo.queries.error.loading = false;
await wrapper.setData({
error: {
firstReleaseVersion,
lastReleaseVersion,
externalBaseUrl: '/sentry',
},
});
expect(findFirstReleaseLink().exists()).toBe(true);
expect(findLastReleaseLink().exists()).toBe(true);
expect(findFirstCommitLink().exists()).toBe(false);
expect(findLastCommitLink().exists()).toBe(false);
});
it('should display links to GitLab when integrated', async () => {
mocks.$apollo.queries.error.loading = false;
await wrapper.setData({
error: {
firstReleaseVersion,
lastReleaseVersion,
integrated: true,
externalBaseUrl: '/gitlab',
},
});
expect(findFirstCommitLink().exists()).toBe(true);
expect(findLastCommitLink().exists()).toBe(true);
expect(findFirstReleaseLink().exists()).toBe(false);
expect(findLastReleaseLink().exists()).toBe(false);
});
});
}); });
describe('Snowplow tracking', () => { describe('Snowplow tracking', () => {
......
...@@ -10,6 +10,7 @@ RSpec.describe GitlabSchema.types['SentryDetailedError'] do ...@@ -10,6 +10,7 @@ RSpec.describe GitlabSchema.types['SentryDetailedError'] do
it 'exposes the expected fields' do it 'exposes the expected fields' do
expected_fields = %i[ expected_fields = %i[
id id
integrated
sentryId sentryId
title title
type type
......
...@@ -257,6 +257,10 @@ RSpec.describe ErrorTracking::SentryClient::Issue do ...@@ -257,6 +257,10 @@ RSpec.describe ErrorTracking::SentryClient::Issue do
expect(subject.gitlab_issue).to eq('https://gitlab.com/gitlab-org/gitlab/issues/1') expect(subject.gitlab_issue).to eq('https://gitlab.com/gitlab-org/gitlab/issues/1')
end end
it 'has an integrated attribute set to false' do
expect(subject.integrated).to be_falsey
end
context 'when issue annotations exist' do context 'when issue annotations exist' do
before do before do
issue_sample_response['annotations'] = [ issue_sample_response['annotations'] = [
......
...@@ -81,6 +81,13 @@ RSpec.describe ErrorTracking::Error, type: :model do ...@@ -81,6 +81,13 @@ RSpec.describe ErrorTracking::Error, type: :model do
end end
describe '#to_sentry_detailed_error' do describe '#to_sentry_detailed_error' do
it { expect(error.to_sentry_detailed_error).to be_kind_of(Gitlab::ErrorTracking::DetailedError) } let_it_be(:event) { create(:error_tracking_error_event, error: error) }
subject { error.to_sentry_detailed_error }
it { is_expected.to be_kind_of(Gitlab::ErrorTracking::DetailedError) }
it { expect(subject.integrated).to be_truthy }
it { expect(subject.first_release_version).to eq('db853d7') }
it { expect(subject.last_release_version).to eq('db853d7') }
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment