Skip to content

Commit 7518d18

Browse files
Abdkhan14Abdullah Khan
andauthored
feat(tracing-without-performance): Replay compatibility and ui improvements. (#54700)
This PR aims to make the new orphan error views compatible with traceview in replayDetails and adds hidden messages for orphan error search in traceviews, under the feature flag `organizations:performance-tracing-without-performance`. Testing with yarn dev-ui: - Orphan errors traceview for testing search hidden messages: [link](https://sentry.dev.getsentry.net:7999/performance/trace/2f870c047f0349888080e65a8fa69df5/?pageEnd=2023-08-15T03%3A23%3A45.496&pageStart=2023-08-14T03%3A23%3A45.496) - Replay details trace should now load:[ link](https://sentry.dev.getsentry.net:7999/replays/3487099c4a6d41bb8b3b68bbaf4c8548/?query=&referrer=%2Freplays%2F&statsPeriod=14d&t_main=trace&yAxis=count%28%29) Changes: ![Screenshot 2023-08-14 at 1 00 58 PM](https://github.com/getsentry/sentry/assets/60121741/f060d40b-a094-4782-b950-14ee29ffce07) <img width="660" alt="Screenshot 2023-08-14 at 1 02 10 PM" src="https://github.com/getsentry/sentry/assets/60121741/7494a331-e979-4857-ab46-f4c72df6bdcd"> Context: We now want to show trace views for traces that contain orphan errors. [JIRA-TICKET](https://getsentry.atlassian.net/browse/PERF-2052) --------- Co-authored-by: Abdullah Khan <[email protected]>
1 parent 1ea6a2e commit 7518d18

File tree

5 files changed

+169
-72
lines changed

5 files changed

+169
-72
lines changed

static/app/views/performance/traceDetails/index.tsx

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,16 @@ import {QueryError} from 'sentry/utils/discover/genericDiscoverQuery';
1414
import {TraceFullDetailedQuery} from 'sentry/utils/performance/quickTrace/traceFullQuery';
1515
import TraceMetaQuery from 'sentry/utils/performance/quickTrace/traceMetaQuery';
1616
import {
17-
TraceError,
1817
TraceFullDetailed,
1918
TraceMeta,
2019
TraceSplitResults,
2120
} from 'sentry/utils/performance/quickTrace/types';
22-
import {isTraceSplitResult} from 'sentry/utils/performance/quickTrace/utils';
2321
import {decodeScalar} from 'sentry/utils/queryString';
2422
import withApi from 'sentry/utils/withApi';
2523
import withOrganization from 'sentry/utils/withOrganization';
2624

2725
import TraceDetailsContent from './content';
26+
import {getTraceSplitResults} from './utils';
2827

2928
type Props = RouteComponentProps<{traceSlug: string}, {}> & {
3029
api: Client;
@@ -87,18 +86,10 @@ class TraceSummary extends Component<Props> {
8786
meta: TraceMeta | null;
8887
traces: (TraceFullDetailed[] | TraceSplitResults<TraceFullDetailed>) | null;
8988
}) => {
90-
let transactions: TraceFullDetailed[] | undefined;
91-
let orphanErrors: TraceError[] | undefined;
92-
if (
93-
traces &&
94-
organization.features.includes('performance-tracing-without-performance') &&
95-
isTraceSplitResult<TraceSplitResults<TraceFullDetailed>, TraceFullDetailed[]>(
96-
traces
97-
)
98-
) {
99-
orphanErrors = traces.orphan_errors;
100-
transactions = traces.transactions;
101-
}
89+
const {transactions, orphanErrors} = getTraceSplitResults<TraceFullDetailed>(
90+
traces ?? [],
91+
organization
92+
);
10293

10394
return (
10495
<TraceDetailsContent

static/app/views/performance/traceDetails/traceView.tsx

Lines changed: 83 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
boundsGenerator,
1111
getMeasurements,
1212
} from 'sentry/components/events/interfaces/spans/utils';
13+
import Panel from 'sentry/components/panels/panel';
1314
import {MessageRow} from 'sentry/components/performance/waterfall/messageRow';
1415
import {
1516
DividerSpacer,
@@ -29,7 +30,6 @@ import {
2930
} from 'sentry/utils/performance/quickTrace/types';
3031
import {
3132
TraceDetailBody,
32-
TracePanel,
3333
TraceViewContainer,
3434
TraceViewHeaderContainer,
3535
} from 'sentry/views/performance/traceDetails/styles';
@@ -64,24 +64,50 @@ type Props = Pick<RouteComponentProps<{}, {}>, 'location'> & {
6464
function TraceHiddenMessage({
6565
isVisible,
6666
numberOfHiddenTransactionsAbove,
67+
numberOfHiddenErrorsAbove,
6768
}: {
6869
isVisible: boolean;
70+
numberOfHiddenErrorsAbove: number;
6971
numberOfHiddenTransactionsAbove: number;
7072
}) {
71-
if (!isVisible || numberOfHiddenTransactionsAbove < 1) {
73+
if (
74+
!isVisible ||
75+
(numberOfHiddenTransactionsAbove < 1 && numberOfHiddenErrorsAbove < 1)
76+
) {
7277
return null;
7378
}
7479

80+
const numOfTransaction = <strong>{numberOfHiddenTransactionsAbove}</strong>;
81+
const numOfErrors = <strong>{numberOfHiddenErrorsAbove}</strong>;
82+
83+
const hiddenTransactionsMessage =
84+
numberOfHiddenTransactionsAbove < 1
85+
? ''
86+
: numberOfHiddenTransactionsAbove === 1
87+
? tct('[numOfTransaction] hidden transaction', {
88+
numOfTransaction,
89+
})
90+
: tct('[numOfTransaction] hidden transactions', {
91+
numOfTransaction,
92+
});
93+
94+
const hiddenErrorsMessage =
95+
numberOfHiddenErrorsAbove < 1
96+
? ''
97+
: numberOfHiddenErrorsAbove === 1
98+
? tct('[numOfErrors] hidden error', {
99+
numOfErrors,
100+
})
101+
: tct('[numOfErrors] hidden errors', {
102+
numOfErrors,
103+
});
104+
75105
return (
76106
<MessageRow>
77107
<span key="trace-info-message">
78-
{numberOfHiddenTransactionsAbove === 1
79-
? tct('[numOfTransaction] hidden transaction', {
80-
numOfTransaction: <strong>{numberOfHiddenTransactionsAbove}</strong>,
81-
})
82-
: tct('[numOfTransaction] hidden transactions', {
83-
numOfTransaction: <strong>{numberOfHiddenTransactionsAbove}</strong>,
84-
})}
108+
{hiddenTransactionsMessage}
109+
{hiddenErrorsMessage && hiddenTransactionsMessage && ', '}
110+
{hiddenErrorsMessage}
85111
</span>
86112
</MessageRow>
87113
);
@@ -193,6 +219,7 @@ export default function TraceView({
193219
<TraceHiddenMessage
194220
isVisible={isVisible}
195221
numberOfHiddenTransactionsAbove={numberOfHiddenTransactionsAbove}
222+
numberOfHiddenErrorsAbove={0}
196223
/>
197224
<TransactionGroup
198225
location={location}
@@ -283,33 +310,53 @@ export default function TraceView({
283310
);
284311

285312
// Build transaction groups for orphan errors
313+
let numOfHiddenErrorsAbove = 0;
314+
let totalNumOfHiddenErrors = 0;
286315
if (hasOrphanErrors) {
287316
orphanErrors.forEach((error, index) => {
288317
const isLastError = index === orphanErrors.length - 1;
318+
const isVisible = isRowVisible(error, filteredEventIds);
319+
const currentHiddenCount = numOfHiddenErrorsAbove;
320+
321+
if (!isVisible) {
322+
numOfHiddenErrorsAbove += 1;
323+
totalNumOfHiddenErrors += 1;
324+
} else {
325+
numOfHiddenErrorsAbove = 0;
326+
}
327+
289328
transactionGroups.push(
290-
<TransactionGroup
291-
key={error.event_id}
292-
location={location}
293-
organization={organization}
294-
traceInfo={traceInfo}
295-
transaction={{
296-
...error,
297-
generation: 1,
298-
}}
299-
generateBounds={generateBounds(traceInfo)}
300-
measurements={
301-
traces && traces.length > 0
302-
? getMeasurements(traces[0], generateBounds(traceInfo))
303-
: undefined
304-
}
305-
continuingDepths={[]}
306-
isOrphan
307-
isLast={isLastError}
308-
index={lastIndex + index + 1}
309-
isVisible={isRowVisible(error, filteredEventIds)}
310-
hasGuideAnchor
311-
renderedChildren={[]}
312-
/>
329+
<React.Fragment key={error.event_id}>
330+
<TraceHiddenMessage
331+
isVisible={isVisible}
332+
numberOfHiddenTransactionsAbove={
333+
index === 0 ? numberOfHiddenTransactionsAbove : 0
334+
}
335+
numberOfHiddenErrorsAbove={index > 0 ? currentHiddenCount : 0}
336+
/>
337+
<TransactionGroup
338+
location={location}
339+
organization={organization}
340+
traceInfo={traceInfo}
341+
transaction={{
342+
...error,
343+
generation: 1,
344+
}}
345+
generateBounds={generateBounds(traceInfo)}
346+
measurements={
347+
traces && traces.length > 0
348+
? getMeasurements(traces[0], generateBounds(traceInfo))
349+
: undefined
350+
}
351+
continuingDepths={[]}
352+
isOrphan
353+
isLast={isLastError}
354+
index={lastIndex + index + 1}
355+
isVisible={isVisible}
356+
hasGuideAnchor
357+
renderedChildren={[]}
358+
/>
359+
</React.Fragment>
313360
);
314361
});
315362
}
@@ -399,6 +446,7 @@ export default function TraceView({
399446
<TraceHiddenMessage
400447
isVisible
401448
numberOfHiddenTransactionsAbove={numberOfHiddenTransactionsAbove}
449+
numberOfHiddenErrorsAbove={totalNumOfHiddenErrors}
402450
/>
403451
<LimitExceededMessage
404452
traceInfo={traceInfo}
@@ -420,8 +468,9 @@ export default function TraceView({
420468
return traceView;
421469
}
422470

423-
const StyledTracePanel = styled(TracePanel)`
424-
overflow: visible;
471+
export const StyledTracePanel = styled(Panel)`
472+
height: 100%;
473+
overflow-x: visible;
425474
426475
${TraceViewContainer} {
427476
overflow-x: visible;

static/app/views/performance/traceDetails/utils.tsx

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import {LocationDescriptor, Query} from 'history';
22

33
import {PAGE_URL_PARAM} from 'sentry/constants/pageFilters';
4-
import {OrganizationSummary} from 'sentry/types';
5-
import {TraceError, TraceFullDetailed} from 'sentry/utils/performance/quickTrace/types';
6-
import {reduceTrace} from 'sentry/utils/performance/quickTrace/utils';
4+
import {Organization, OrganizationSummary} from 'sentry/types';
5+
import {
6+
TraceError,
7+
TraceFull,
8+
TraceFullDetailed,
9+
TraceSplitResults,
10+
} from 'sentry/utils/performance/quickTrace/types';
11+
import {isTraceSplitResult, reduceTrace} from 'sentry/utils/performance/quickTrace/utils';
712

813
import {TraceInfo} from './types';
914

@@ -50,14 +55,32 @@ function transactionVisitor() {
5055
}
5156

5257
export function hasTraceData(
53-
traces: TraceFullDetailed[] | null,
58+
traces: TraceFullDetailed[] | null | undefined,
5459
orphanErrors: TraceError[] | undefined
5560
): boolean {
5661
return Boolean(
5762
(traces && traces.length > 0) || (orphanErrors && orphanErrors.length > 0)
5863
);
5964
}
6065

66+
export function getTraceSplitResults<U extends TraceFullDetailed | TraceFull>(
67+
trace: TraceSplitResults<U> | U[],
68+
organization: Organization
69+
) {
70+
let transactions: U[] | undefined;
71+
let orphanErrors: TraceError[] | undefined;
72+
if (
73+
trace &&
74+
organization.features.includes('performance-tracing-without-performance') &&
75+
isTraceSplitResult<TraceSplitResults<U>, U[]>(trace)
76+
) {
77+
orphanErrors = trace.orphan_errors;
78+
transactions = trace.transactions;
79+
}
80+
81+
return {transactions, orphanErrors};
82+
}
83+
6184
export function getTraceInfo(
6285
traces: TraceFullDetailed[] = [],
6386
orphanErrors: TraceError[] = []

static/app/views/replays/detail/trace/replayTransactionContext.tsx

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@ import type {TableData} from 'sentry/utils/discover/discoverQuery';
1515
import EventView from 'sentry/utils/discover/eventView';
1616
import {doDiscoverQuery} from 'sentry/utils/discover/genericDiscoverQuery';
1717
import parseLinkHeader, {ParsedHeader} from 'sentry/utils/parseLinkHeader';
18-
import {TraceFullDetailed} from 'sentry/utils/performance/quickTrace/types';
18+
import {
19+
TraceError,
20+
TraceFullDetailed,
21+
TraceSplitResults,
22+
} from 'sentry/utils/performance/quickTrace/types';
1923
import {
2024
getTraceRequestPayload,
2125
makeEventView,
2226
} from 'sentry/utils/performance/quickTrace/utils';
2327
import useApi from 'sentry/utils/useApi';
2428
import useOrganization from 'sentry/utils/useOrganization';
29+
import {getTraceSplitResults} from 'sentry/views/performance/traceDetails/utils';
2530
import type {ReplayRecord} from 'sentry/views/replays/types';
2631

2732
type Options = {
@@ -38,13 +43,15 @@ type InternalState = {
3843
indexError: undefined | Error;
3944
isFetching: boolean;
4045
traces: undefined | TraceFullDetailed[];
46+
orphanErrors?: TraceError[];
4147
};
4248

4349
type ExternalState = {
4450
didInit: boolean;
4551
errors: Error[];
4652
isFetching: boolean;
4753
traces: undefined | TraceFullDetailed[];
54+
orphanErrors?: TraceError[];
4855
};
4956

5057
const INITIAL_STATE: InternalState = {
@@ -56,6 +63,7 @@ const INITIAL_STATE: InternalState = {
5663
indexError: undefined,
5764
isFetching: false,
5865
traces: undefined,
66+
orphanErrors: undefined,
5967
};
6068

6169
type TxnContextProps = {
@@ -111,27 +119,36 @@ function ReplayTransactionContext({children, replayRecord}: Options) {
111119
const fetchSingleTraceData = useCallback(
112120
async traceId => {
113121
try {
114-
const [trace, , _traceResp] = await doDiscoverQuery(
115-
api,
116-
`/organizations/${orgSlug}/events-trace/${traceId}/`,
117-
singleTracePayload
122+
const [trace, _traceResp] = await doDiscoverQuery<
123+
TraceSplitResults<TraceFullDetailed> | TraceFullDetailed[]
124+
>(api, `/organizations/${orgSlug}/events-trace/${traceId}/`, singleTracePayload);
125+
126+
const {transactions, orphanErrors} = getTraceSplitResults<TraceFullDetailed>(
127+
trace,
128+
organization
118129
);
119130

120-
setState(prev => ({
121-
...prev,
122-
traces: sortBy(
123-
(prev.traces || []).concat(trace as TraceFullDetailed),
124-
'start_timestamp'
125-
),
126-
}));
131+
setState(prev => {
132+
return {
133+
...prev,
134+
traces: sortBy(
135+
(prev.traces || []).concat(transactions ?? (trace as TraceFullDetailed[])),
136+
'start_timestamp'
137+
),
138+
orphanErrors: sortBy(
139+
(prev.orphanErrors || []).concat(orphanErrors ?? []),
140+
'timestamp'
141+
),
142+
};
143+
});
127144
} catch (error) {
128145
setState(prev => ({
129146
...prev,
130147
detailsErrors: prev.detailsErrors.concat(error),
131148
}));
132149
}
133150
},
134-
[api, orgSlug, singleTracePayload]
151+
[api, orgSlug, singleTracePayload, organization]
135152
);
136153

137154
const fetchTransactionData = useCallback(async () => {
@@ -229,6 +246,7 @@ function internalToExternalState({
229246
indexComplete,
230247
indexError,
231248
traces,
249+
orphanErrors,
232250
}: InternalState): ExternalState {
233251
const isComplete = indexComplete && detailsRequests === detailsResponses;
234252

@@ -237,6 +255,7 @@ function internalToExternalState({
237255
errors: indexError ? [indexError] : [], // Ignoring detailsErrors for now
238256
isFetching: !isComplete,
239257
traces,
258+
orphanErrors,
240259
};
241260
}
242261

0 commit comments

Comments
 (0)