Skip to content

Commit e804456

Browse files
authored
feat(issues): Add overlays to each trace row (#87371)
1 parent df94b91 commit e804456

File tree

4 files changed

+230
-107
lines changed

4 files changed

+230
-107
lines changed

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

+3-42
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,21 @@
11
import {Fragment, useMemo} from 'react';
22
import styled from '@emotion/styled';
3-
import type {LocationDescriptor} from 'history';
43

54
import ButtonBar from 'sentry/components/buttonBar';
65
import {LinkButton} from 'sentry/components/core/button';
7-
import Link from 'sentry/components/links/link';
86
import {generateTraceTarget} from 'sentry/components/quickTrace/utils';
97
import {t} from 'sentry/locale';
108
import type {Event} from 'sentry/types/event';
119
import {type Group, IssueCategory} from 'sentry/types/group';
1210
import type {Organization} from 'sentry/types/organization';
13-
import {defined} from 'sentry/utils';
14-
import {trackAnalytics} from 'sentry/utils/analytics';
1511
import useRouteAnalyticsParams from 'sentry/utils/routeAnalytics/useRouteAnalyticsParams';
1612
import {useLocation} from 'sentry/utils/useLocation';
1713
import {SectionKey} from 'sentry/views/issueDetails/streamline/context';
1814
import {InterimSection} from 'sentry/views/issueDetails/streamline/interimSection';
1915
import {TraceIssueEvent} from 'sentry/views/issueDetails/traceTimeline/traceIssue';
2016
import {useTraceTimelineEvents} from 'sentry/views/issueDetails/traceTimeline/useTraceTimelineEvents';
2117
import {IssuesTraceWaterfall} from 'sentry/views/performance/newTraceDetails/issuesTraceWaterfall';
18+
import {getTraceLinkForIssue} from 'sentry/views/performance/newTraceDetails/issuesTraceWaterfallOverlay';
2219
import {useIssuesTraceTree} from 'sentry/views/performance/newTraceDetails/traceApi/useIssuesTraceTree';
2320
import {useTrace} from 'sentry/views/performance/newTraceDetails/traceApi/useTrace';
2421
import {useTraceMeta} from 'sentry/views/performance/newTraceDetails/traceApi/useTraceMeta';
@@ -59,15 +56,9 @@ interface EventTraceViewInnerProps {
5956
event: Event;
6057
organization: Organization;
6158
traceId: string;
62-
traceTarget: LocationDescriptor;
6359
}
6460

65-
function EventTraceViewInner({
66-
event,
67-
organization,
68-
traceId,
69-
traceTarget,
70-
}: EventTraceViewInnerProps) {
61+
function EventTraceViewInner({event, organization, traceId}: EventTraceViewInnerProps) {
7162
const timestamp = new Date(event.dateReceived).getTime() / 1e3;
7263

7364
const trace = useTrace({
@@ -115,34 +106,11 @@ function EventTraceViewInner({
115106
replay={null}
116107
event={event}
117108
/>
118-
<IssuesTraceOverlayContainer
119-
to={getHrefFromTraceTarget(traceTarget)}
120-
onClick={() => {
121-
trackAnalytics('issue_details.view_full_trace_waterfall_clicked', {
122-
organization,
123-
});
124-
}}
125-
/>
126109
</IssuesTraceContainer>
127110
</TraceStateProvider>
128111
);
129112
}
130113

131-
function getHrefFromTraceTarget(traceTarget: LocationDescriptor) {
132-
if (typeof traceTarget === 'string') {
133-
return traceTarget;
134-
}
135-
136-
const searchParams = new URLSearchParams();
137-
for (const key in traceTarget.query) {
138-
if (defined(traceTarget.query[key])) {
139-
searchParams.append(key, traceTarget.query[key]);
140-
}
141-
}
142-
143-
return `${traceTarget.pathname}?${searchParams.toString()}`;
144-
}
145-
146114
function OneOtherIssueEvent({event}: {event: Event}) {
147115
const {isLoading, oneOtherIssueEvent} = useTraceTimelineEvents({event});
148116
useRouteAnalyticsParams(oneOtherIssueEvent ? {has_related_trace_issue: true} : {});
@@ -163,12 +131,6 @@ const IssuesTraceContainer = styled('div')`
163131
position: relative;
164132
`;
165133

166-
const IssuesTraceOverlayContainer = styled(Link)`
167-
position: absolute;
168-
inset: 0;
169-
z-index: 10;
170-
`;
171-
172134
interface EventTraceViewProps {
173135
event: Event;
174136
group: Group;
@@ -216,7 +178,7 @@ export function EventTraceView({group, event, organization}: EventTraceViewProps
216178
<SwitchToNonEAPTraceButton location={location} organization={organization} />
217179
<LinkButton
218180
size="xs"
219-
to={getHrefFromTraceTarget(traceTarget)}
181+
to={getTraceLinkForIssue(traceTarget)}
220182
analyticsEventName="Issue Details: View Full Trace Action Button Clicked"
221183
analyticsEventKey="issue_details.view_full_trace_action_button_clicked"
222184
>
@@ -231,7 +193,6 @@ export function EventTraceView({group, event, organization}: EventTraceViewProps
231193
event={event}
232194
organization={organization}
233195
traceId={traceId}
234-
traceTarget={traceTarget}
235196
/>
236197
)}
237198
</InterimSection>

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

-50
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
import {lazy, Suspense, useMemo} from 'react';
22
import styled from '@emotion/styled';
3-
import type {LocationDescriptor} from 'history';
43

5-
import Link from 'sentry/components/links/link';
6-
import {generateTraceTarget} from 'sentry/components/quickTrace/utils';
74
import type {Event} from 'sentry/types/event';
85
import type {Organization} from 'sentry/types/organization';
9-
import {defined} from 'sentry/utils';
10-
import {trackAnalytics} from 'sentry/utils/analytics';
11-
import {useLocation} from 'sentry/utils/useLocation';
126
import {useIssuesTraceTree} from 'sentry/views/performance/newTraceDetails/traceApi/useIssuesTraceTree';
137
import {useTrace} from 'sentry/views/performance/newTraceDetails/traceApi/useTrace';
148
import {useTraceMeta} from 'sentry/views/performance/newTraceDetails/traceApi/useTraceMeta';
159
import {useTraceRootEvent} from 'sentry/views/performance/newTraceDetails/traceApi/useTraceRootEvent';
16-
import {TraceViewSources} from 'sentry/views/performance/newTraceDetails/traceHeader/breadcrumbs';
1710
import {
1811
loadTraceViewPreferences,
1912
type TracePreferencesState,
@@ -28,21 +21,6 @@ const LazyIssuesTraceWaterfall = lazy(() =>
2821
)
2922
);
3023

31-
function getHrefFromTraceTarget(traceTarget: LocationDescriptor) {
32-
if (typeof traceTarget === 'string') {
33-
return traceTarget;
34-
}
35-
36-
const searchParams = new URLSearchParams();
37-
for (const key in traceTarget.query) {
38-
if (defined(traceTarget.query[key])) {
39-
searchParams.append(key, traceTarget.query[key]);
40-
}
41-
}
42-
43-
return `${traceTarget.pathname}?${searchParams.toString()}`;
44-
}
45-
4624
const DEFAULT_ISSUE_DETAILS_TRACE_VIEW_PREFERENCES: TracePreferencesState = {
4725
drawer: {
4826
minimized: true,
@@ -78,7 +56,6 @@ export function SpanEvidenceTraceView({
7856
}: SpanEvidenceTraceViewProps) {
7957
const timestamp = new Date(event.dateReceived).getTime() / 1e3;
8058

81-
const location = useLocation();
8259
const trace = useTrace({
8360
timestamp,
8461
traceSlug: traceId,
@@ -104,19 +81,6 @@ export function SpanEvidenceTraceView({
10481
return null;
10582
}
10683

107-
const traceTarget = generateTraceTarget(
108-
event,
109-
organization,
110-
{
111-
...location,
112-
query: {
113-
...location.query,
114-
groupId: event.groupID,
115-
},
116-
},
117-
TraceViewSources.ISSUE_DETAILS
118-
);
119-
12084
return (
12185
<TraceStateProvider
12286
initialPreferences={preferences}
@@ -137,14 +101,6 @@ export function SpanEvidenceTraceView({
137101
event={event}
138102
/>
139103
</Suspense>
140-
<IssuesTraceOverlayContainer
141-
to={getHrefFromTraceTarget(traceTarget)}
142-
onClick={() => {
143-
trackAnalytics('issue_details.view_full_trace_waterfall_clicked', {
144-
organization,
145-
});
146-
}}
147-
/>
148104
</IssuesTraceContainer>
149105
</TraceStateProvider>
150106
);
@@ -153,9 +109,3 @@ export function SpanEvidenceTraceView({
153109
const IssuesTraceContainer = styled('div')`
154110
position: relative;
155111
`;
156-
157-
const IssuesTraceOverlayContainer = styled(Link)`
158-
position: absolute;
159-
inset: 0;
160-
z-index: 10;
161-
`;

static/app/views/performance/newTraceDetails/issuesTraceWaterfall.tsx

+33-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import type React from 'react';
21
import {
32
Fragment,
43
useCallback,
@@ -16,6 +15,7 @@ import type {Project} from 'sentry/types/project';
1615
import {trackAnalytics} from 'sentry/utils/analytics';
1716
import useOrganization from 'sentry/utils/useOrganization';
1817
import useProjects from 'sentry/utils/useProjects';
18+
import {IssueTraceWaterfallOverlay} from 'sentry/views/performance/newTraceDetails/issuesTraceWaterfallOverlay';
1919
import {
2020
isSpanNode,
2121
isTraceErrorNode,
@@ -58,6 +58,7 @@ export function IssuesTraceWaterfall(props: IssuesTraceWaterfallProps) {
5858
const organization = useOrganization();
5959
const traceState = useTraceState();
6060
const traceDispatch = useTraceStateDispatch();
61+
const containerRef = useRef<HTMLDivElement>(null);
6162

6263
const [forceRender, rerender] = useReducer(x => (x + 1) % Number.MAX_SAFE_INTEGER, 0);
6364

@@ -318,21 +319,32 @@ export function IssuesTraceWaterfall(props: IssuesTraceWaterfallProps) {
318319
: 8
319320
}
320321
>
321-
<IssuesPointerDisabled>
322-
<Trace
323-
metaQueryResults={props.meta}
324-
trace={props.tree}
325-
rerender={rerender}
326-
trace_id={props.traceSlug}
327-
onRowClick={onRowClick}
328-
onTraceSearch={noopTraceSearch}
329-
previouslyFocusedNodeRef={previouslyFocusedNodeRef}
330-
manager={viewManager}
331-
scheduler={traceScheduler}
332-
forceRerender={forceRender}
333-
isLoading={props.tree.type === 'loading' || onLoadScrollStatus === 'pending'}
322+
<IssuesTraceContainer ref={containerRef}>
323+
<IssuesPointerDisabled>
324+
<Trace
325+
metaQueryResults={props.meta}
326+
trace={props.tree}
327+
rerender={rerender}
328+
trace_id={props.traceSlug}
329+
onRowClick={onRowClick}
330+
onTraceSearch={noopTraceSearch}
331+
previouslyFocusedNodeRef={previouslyFocusedNodeRef}
332+
manager={viewManager}
333+
scheduler={traceScheduler}
334+
forceRerender={forceRender}
335+
isLoading={
336+
props.tree.type === 'loading' || onLoadScrollStatus === 'pending'
337+
}
338+
/>
339+
</IssuesPointerDisabled>
340+
<IssueTraceWaterfallOverlay
341+
containerRef={containerRef}
342+
event={props.event}
343+
groupId={props.event.groupID}
344+
tree={props.tree}
345+
viewManager={viewManager}
334346
/>
335-
</IssuesPointerDisabled>
347+
</IssuesTraceContainer>
336348

337349
{props.tree.type === 'loading' || onLoadScrollStatus === 'pending' ? (
338350
<TraceWaterfallState.Loading />
@@ -370,3 +382,9 @@ const IssuesTraceGrid = styled(TraceGrid)<{
370382
Math.min(Math.max(p.rowCount, MIN_ROW_COUNT), MAX_ROW_COUNT) * ROW_HEIGHT +
371383
HEADER_HEIGHT}px;
372384
`;
385+
386+
const IssuesTraceContainer = styled('div')`
387+
position: relative;
388+
height: 100%;
389+
width: 100%;
390+
`;

0 commit comments

Comments
 (0)