Skip to content

Commit 2a5c30a

Browse files
authored
feat(issues): GA new trace view performance issues (#87951)
1 parent 425d675 commit 2a5c30a

File tree

10 files changed

+86
-226
lines changed

10 files changed

+86
-226
lines changed

fixtures/page_objects/base.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
from selenium.webdriver.common.by import By
22

3+
from sentry.testutils.pytest.selenium import Browser
4+
35

46
class BasePage:
57
"""Base class for PageObjects"""
68

7-
def __init__(self, browser):
9+
def __init__(self, browser: Browser):
810
self.browser = browser
911

1012
@property

fixtures/page_objects/issue_details.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ def visit_issue(self, org, groupid):
1616
self.browser.get(f"/organizations/{org}/issues/{groupid}/")
1717
self.wait_until_loaded()
1818

19+
def visit_performance_issue(self, org, groupid):
20+
"""
21+
Trace view can take a long time to load, just wait until the trace evidence is loaded
22+
"""
23+
self.browser.get(f"/organizations/{org}/issues/{groupid}/")
24+
self.browser.wait_until("#span-evidence")
25+
1926
def visit_issue_activity(self, org, groupid):
2027
self.browser.get(f"/organizations/{org}/issues/{groupid}/activity/")
2128
self.browser.wait_until_not('[data-test-id="loading-indicator"]')

static/app/components/events/interfaces/performance/eventTraceView.spec.tsx

Lines changed: 1 addition & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {initializeData} from 'sentry-test/performance/initializePerformanceData'
55
import {render, screen} from 'sentry-test/reactTestingLibrary';
66

77
import {EntryType} from 'sentry/types/event';
8-
import {IssueCategory, IssueTitle} from 'sentry/types/group';
98
import type {TraceEventResponse} from 'sentry/views/issueDetails/traceTimeline/useTraceTimelineEvents';
109
import {
1110
makeTraceError,
@@ -14,17 +13,9 @@ import {
1413

1514
import {EventTraceView} from './eventTraceView';
1615

17-
class ResizeObserver {
18-
observe() {}
19-
unobserve() {}
20-
disconnect() {}
21-
}
22-
23-
window.ResizeObserver = ResizeObserver;
24-
2516
describe('EventTraceView', () => {
2617
const traceId = 'this-is-a-good-trace-id';
27-
const {organization, project} = initializeData({
18+
const {organization} = initializeData({
2819
features: ['profiling'],
2920
});
3021
const group = GroupFixture();
@@ -124,61 +115,6 @@ describe('EventTraceView', () => {
124115
expect(document.querySelectorAll('.TraceRow')).toHaveLength(8);
125116
});
126117

127-
it('still renders trace link for performance issues', async () => {
128-
const oneOtherIssueEvent: TraceEventResponse = {
129-
data: [
130-
{
131-
// In issuePlatform, the message contains the title and the transaction
132-
message: '/api/slow/ Slow DB Query SELECT "sentry_monitorcheckin"."monitor_id"',
133-
timestamp: '2024-01-24T09:09:03+00:00',
134-
'issue.id': 1000,
135-
project: project.slug,
136-
'project.name': project.name,
137-
title: 'Slow DB Query',
138-
id: 'abc',
139-
transaction: 'n/a',
140-
culprit: '/api/slow/',
141-
'event.type': '',
142-
},
143-
],
144-
meta: {fields: {}, units: {}},
145-
};
146-
MockApiClient.addMockResponse({
147-
url: `/organizations/${organization.slug}/events/`,
148-
body: oneOtherIssueEvent,
149-
});
150-
MockApiClient.addMockResponse({
151-
url: `/organizations/${organization.slug}/projects/`,
152-
body: [],
153-
});
154-
const perfGroup = GroupFixture({issueCategory: IssueCategory.PERFORMANCE});
155-
const perfEvent = EventFixture({
156-
occurrence: {
157-
type: 1001,
158-
issueTitle: IssueTitle.PERFORMANCE_SLOW_DB_QUERY,
159-
},
160-
entries: [
161-
{
162-
data: [],
163-
type: EntryType.SPANS,
164-
},
165-
],
166-
contexts: {
167-
trace: {
168-
trace_id: traceId,
169-
},
170-
},
171-
});
172-
173-
render(
174-
<EventTraceView group={perfGroup} event={perfEvent} organization={organization} />
175-
);
176-
expect(await screen.findByText('Trace Preview')).toBeInTheDocument();
177-
expect(
178-
screen.getByText('One other issue appears in the same trace.')
179-
).toBeInTheDocument();
180-
});
181-
182118
it('does not render the trace preview if it has no transactions', async () => {
183119
MockApiClient.addMockResponse({
184120
url: '/subscriptions/org-slug/',

static/app/components/events/interfaces/performance/eventTraceView.tsx

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,7 @@ export function EventTraceView({group, event, organization}: EventTraceViewProps
142142
const location = useLocation();
143143

144144
// Performance issues have a Span Evidence section that contains the trace view
145-
const isHiddenForPerformanceIssues =
146-
group.issueCategory === IssueCategory.PERFORMANCE &&
147-
organization.features.includes('issue-details-new-performance-trace-view');
148-
149-
if (!traceId || isHiddenForPerformanceIssues) {
145+
if (!traceId || group.issueCategory === IssueCategory.PERFORMANCE) {
150146
return null;
151147
}
152148

@@ -163,11 +159,7 @@ export function EventTraceView({group, event, organization}: EventTraceViewProps
163159
TraceViewSources.ISSUE_DETAILS
164160
);
165161

166-
const hasProfilingFeature = organization.features.includes('profiling');
167-
const hasTracePreviewFeature =
168-
hasProfilingFeature &&
169-
// Only display this for error or default events since performance events are handled elsewhere
170-
group.issueCategory !== IssueCategory.PERFORMANCE;
162+
const hasTracePreviewFeature = organization.features.includes('profiling');
171163

172164
return (
173165
<InterimSection

static/app/components/events/interfaces/performance/spanEvidence.spec.tsx

Lines changed: 59 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,90 @@
11
import {EventFixture} from 'sentry-fixture/event';
22

33
import {initializeData} from 'sentry-test/performance/initializePerformanceData';
4-
import {
5-
MockSpan,
6-
ProblemSpan,
7-
TransactionEventBuilder,
8-
} from 'sentry-test/performance/utils';
94
import {render, screen} from 'sentry-test/reactTestingLibrary';
105

116
import type {EventTransaction} from 'sentry/types/event';
127
import {EntryType} from 'sentry/types/event';
138
import {IssueTitle, IssueType} from 'sentry/types/group';
149
import {sanitizeQuerySelector} from 'sentry/utils/sanitizeQuerySelector';
10+
import {
11+
makeTraceError,
12+
makeTransaction,
13+
} from 'sentry/views/performance/newTraceDetails/traceModels/traceTreeTestUtils';
1514

1615
import {SpanEvidenceSection} from './spanEvidence';
1716

1817
const {organization, project} = initializeData();
1918

2019
describe('spanEvidence', () => {
21-
it('renders and highlights the correct data in the span evidence section', () => {
22-
const builder = new TransactionEventBuilder();
23-
builder.addSpan(
24-
new MockSpan({
25-
startTimestamp: 0,
26-
endTimestamp: 100,
27-
op: 'http',
28-
description: 'do a thing',
29-
})
30-
);
31-
32-
builder.addSpan(
33-
new MockSpan({
34-
startTimestamp: 100,
35-
endTimestamp: 200,
36-
op: 'db',
37-
description: 'SELECT col FROM table',
38-
})
39-
);
40-
41-
builder.addSpan(
42-
new MockSpan({
43-
startTimestamp: 200,
44-
endTimestamp: 300,
45-
op: 'db',
46-
description: 'SELECT col2 FROM table',
47-
})
48-
);
20+
beforeEach(() => {
21+
MockApiClient.clearMockResponses();
22+
});
4923

50-
builder.addSpan(
51-
new MockSpan({
52-
startTimestamp: 200,
53-
endTimestamp: 300,
54-
op: 'db',
55-
description: 'SELECT col3 FROM table',
56-
})
57-
);
24+
it('renders and attempts to render the trace preview', async () => {
25+
const traceId = 'trace-id';
26+
const event = EventFixture({
27+
contexts: {
28+
trace: {
29+
trace_id: traceId,
30+
},
31+
},
32+
});
5833

59-
const parentProblemSpan = new MockSpan({
60-
startTimestamp: 300,
61-
endTimestamp: 600,
62-
op: 'db',
63-
description: 'connect',
64-
problemSpan: ProblemSpan.PARENT,
34+
MockApiClient.addMockResponse({
35+
url: '/subscriptions/org-slug/',
36+
method: 'GET',
37+
body: {},
6538
});
66-
parentProblemSpan.addChild(
67-
{
68-
startTimestamp: 300,
69-
endTimestamp: 600,
70-
op: 'db',
71-
description: 'group me',
72-
problemSpan: ProblemSpan.OFFENDER,
39+
MockApiClient.addMockResponse({
40+
method: 'GET',
41+
url: `/organizations/${organization.slug}/events-trace-meta/${traceId}/`,
42+
body: {
43+
errors: 1,
44+
performance_issues: 1,
45+
projects: 1,
46+
transactions: 1,
47+
transaction_child_count_map: new Array(20)
48+
.fill(0)
49+
.map((_, i) => [{'transaction.id': i.toString(), count: 1}]),
50+
span_count: 0,
51+
span_count_map: {},
7352
},
74-
9
75-
);
76-
77-
builder.addSpan(parentProblemSpan);
53+
});
54+
MockApiClient.addMockResponse({
55+
url: `/organizations/org-slug/events-trace/${traceId}/`,
56+
method: 'GET',
57+
body: {
58+
transactions: Array.from({length: 20}, (_, i) =>
59+
makeTransaction({
60+
'transaction.op': `transaction-op-${i + 1}`,
61+
project_slug: `project-slug-${i + 1}`,
62+
event_id: `event-id-${i + 1}`,
63+
errors: i === 0 ? [makeTraceError({event_id: 'issue-5'})] : [],
64+
})
65+
),
66+
orphan_errors: [makeTraceError()],
67+
},
68+
});
69+
MockApiClient.addMockResponse({
70+
url: `/organizations/${organization.slug}/events/project-slug-1:event-id-1/`,
71+
method: 'GET',
72+
body: {
73+
entries: [{type: EntryType.SPANS, data: []}],
74+
},
75+
});
7876

7977
render(
8078
<SpanEvidenceSection
81-
event={builder.getEventFixture()}
79+
event={event as EventTransaction}
8280
organization={organization}
8381
projectSlug={project.slug}
8482
/>,
8583
{organization}
8684
);
8785

88-
// Verify that the correct spans are hi-lighted on the span tree as affected spans
89-
const affectedSpan = screen.getByTestId('row-title-content-affected');
90-
expect(affectedSpan).toBeInTheDocument();
91-
expect(affectedSpan).toHaveTextContent('db — connect');
86+
// Verify that the trace preview is rendered
87+
expect(await screen.findByTestId('trace-virtualized-list')).toBeInTheDocument();
9288
});
9389

9490
it('renders settings button for issue with configurable thresholds', () => {

0 commit comments

Comments
 (0)