Skip to content

Commit 7d87c7f

Browse files
Abdkhan14Abdullah Khan
and
Abdullah Khan
authored
feat(trace-eap-waterfall): Cleaning up trace context sections (#90091)
- Only rendering contexts when we have data to populate them with. - Disabled collapse persistence for the context sections. --------- Co-authored-by: Abdullah Khan <abdullahkhan@PG9Y57YDXQ.local>
1 parent a83e8e4 commit 7d87c7f

File tree

8 files changed

+135
-79
lines changed

8 files changed

+135
-79
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ function TraceViewImpl({traceSlug}: {traceSlug: string}) {
122122
tree={tree}
123123
rootEvent={rootEvent}
124124
onScrollToNode={traceWaterfallScroll.onScrollToNode}
125+
logs={logsTableData.logsData?.data}
125126
/>
126127
)}
127128
</TraceInnerLayout>

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

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import {useCallback} from 'react';
21
import styled from '@emotion/styled';
32

43
import Feature from 'sentry/components/acl/feature';
@@ -9,6 +8,7 @@ import type {EventTransaction} from 'sentry/types/event';
98
import type {UseApiQueryResult} from 'sentry/utils/queryClient';
109
import type RequestError from 'sentry/utils/requestError/requestError';
1110
import useOrganization from 'sentry/utils/useOrganization';
11+
import type {OurLogsResponseItem} from 'sentry/views/explore/logs/types';
1212
import type {SectionKey} from 'sentry/views/issueDetails/streamline/context';
1313
import {FoldSection} from 'sentry/views/issueDetails/streamline/foldSection';
1414
import {TraceContextProfiles} from 'sentry/views/performance/newTraceDetails/traceContextProfiles';
@@ -18,28 +18,21 @@ import {TraceLinkNavigationButton} from 'sentry/views/performance/newTraceDetail
1818
import type {TraceTree} from 'sentry/views/performance/newTraceDetails/traceModels/traceTree';
1919
import type {TraceTreeNode} from 'sentry/views/performance/newTraceDetails/traceModels/traceTreeNode';
2020
import {TraceViewLogsSection} from 'sentry/views/performance/newTraceDetails/traceOurlogs';
21+
import {useTraceContextSections} from 'sentry/views/performance/newTraceDetails/useTraceContextSections';
2122

2223
type Props = {
24+
logs: OurLogsResponseItem[] | undefined;
2325
onScrollToNode: (node: TraceTreeNode<TraceTree.NodeValue>) => void;
2426
rootEvent: UseApiQueryResult<EventTransaction, RequestError>;
2527
tree: TraceTree;
2628
};
2729

28-
export function TraceContextPanel({tree, rootEvent, onScrollToNode}: Props) {
29-
const renderTags = useCallback(() => {
30-
if (!rootEvent.data) {
31-
return null;
32-
}
33-
34-
return (
35-
<EventTagsTree
36-
event={rootEvent.data}
37-
meta={rootEvent.data._meta}
38-
projectSlug={rootEvent.data.projectSlug ?? ''}
39-
tags={rootEvent.data.tags ?? []}
40-
/>
41-
);
42-
}, [rootEvent.data]);
30+
export function TraceContextPanel({tree, rootEvent, onScrollToNode, logs}: Props) {
31+
const {hasProfiles, hasLogs, hasTags} = useTraceContextSections({
32+
tree,
33+
rootEvent,
34+
logs,
35+
});
4336

4437
const organization = useOrganization();
4538
const showLinkedTraces = organization?.features.includes('trace-view-linked-traces');
@@ -71,23 +64,35 @@ export function TraceContextPanel({tree, rootEvent, onScrollToNode}: Props) {
7164
)}
7265

7366
<VitalMetersContainer id={TraceContextSectionKeys.WEB_VITALS}>
74-
<TraceContextVitals tree={tree} />
67+
<TraceContextVitals rootEvent={rootEvent} tree={tree} logs={logs} />
7568
</VitalMetersContainer>
76-
<ContextRow>
77-
<FoldSection
78-
sectionKey={TraceContextSectionKeys.TAGS as string as SectionKey}
79-
title={t('Tags')}
80-
>
81-
{renderTags()}
82-
</FoldSection>
83-
</ContextRow>
84-
<ContextRow>
85-
<TraceContextProfiles tree={tree} onScrollToNode={onScrollToNode} />
86-
</ContextRow>
87-
<Feature features={['ourlogs-enabled']}>
69+
{hasTags && rootEvent.data && (
70+
<ContextRow>
71+
<FoldSection
72+
sectionKey={TraceContextSectionKeys.TAGS as string as SectionKey}
73+
title={t('Tags')}
74+
disableCollapsePersistence
75+
>
76+
<EventTagsTree
77+
event={rootEvent.data}
78+
meta={rootEvent.data._meta}
79+
projectSlug={rootEvent.data.projectSlug ?? ''}
80+
tags={rootEvent.data.tags}
81+
/>
82+
</FoldSection>
83+
</ContextRow>
84+
)}
85+
{hasProfiles && (
8886
<ContextRow>
89-
<TraceViewLogsSection />
87+
<TraceContextProfiles tree={tree} onScrollToNode={onScrollToNode} />
9088
</ContextRow>
89+
)}
90+
<Feature features={['ourlogs-enabled']}>
91+
{hasLogs && (
92+
<ContextRow>
93+
<TraceViewLogsSection />
94+
</ContextRow>
95+
)}
9196
</Feature>
9297
</Container>
9398
);
@@ -121,5 +126,8 @@ const TraceLinksNavigationContainer = styled('div')`
121126
display: flex;
122127
justify-content: space-between;
123128
flex-direction: row;
124-
margin: ${space(1)} 0;
129+
130+
&:not(:empty) {
131+
margin-top: ${space(1)};
132+
}
125133
`;
Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
import EmptyStateWarning from 'sentry/components/emptyStateWarning';
2-
import LoadingIndicator from 'sentry/components/loadingIndicator';
31
import {t} from 'sentry/locale';
42
import type {SectionKey} from 'sentry/views/issueDetails/streamline/context';
53
import {FoldSection} from 'sentry/views/issueDetails/streamline/foldSection';
64
import {TraceProfiles} from 'sentry/views/performance/newTraceDetails/traceDrawer/tabs/traceProfiles';
75
import {TraceContextSectionKeys} from 'sentry/views/performance/newTraceDetails/traceHeader/scrollToSectionLinks';
86
import type {TraceTree} from 'sentry/views/performance/newTraceDetails/traceModels/traceTree';
97
import type {TraceTreeNode} from 'sentry/views/performance/newTraceDetails/traceModels/traceTreeNode';
10-
import {EmptyStateText} from 'sentry/views/traces/styles';
118

129
export function TraceContextProfiles({
1310
tree,
@@ -16,24 +13,13 @@ export function TraceContextProfiles({
1613
onScrollToNode: (node: TraceTreeNode<TraceTree.NodeValue>) => void;
1714
tree: TraceTree;
1815
}) {
19-
const hasProfiles = tree.profiled_events.size > 0;
20-
2116
return (
2217
<FoldSection
2318
sectionKey={TraceContextSectionKeys.PROFILES as string as SectionKey}
2419
title={t('Profiles')}
20+
disableCollapsePersistence
2521
>
26-
{tree.type === 'loading' ? (
27-
<LoadingIndicator />
28-
) : tree.type === 'trace' && hasProfiles ? (
29-
<TraceProfiles tree={tree} onScrollToNode={onScrollToNode} />
30-
) : (
31-
<EmptyStateWarning withIcon>
32-
<EmptyStateText size="fontSizeExtraLarge">
33-
{t('No profiles found')}
34-
</EmptyStateText>
35-
</EmptyStateWarning>
36-
)}
22+
<TraceProfiles tree={tree} onScrollToNode={onScrollToNode} />
3723
</FoldSection>
3824
);
3925
}

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ import styled from '@emotion/styled';
22

33
import {Tooltip} from 'sentry/components/core/tooltip';
44
import {space} from 'sentry/styles/space';
5+
import {EventTransaction} from 'sentry/types/event';
56
import getDuration from 'sentry/utils/duration/getDuration';
67
import {VITAL_DETAILS} from 'sentry/utils/performance/vitals/constants';
78
import type {Vital} from 'sentry/utils/performance/vitals/types';
9+
import {UseApiQueryResult} from 'sentry/utils/queryClient';
10+
import RequestError from 'sentry/utils/requestError/requestError';
11+
import {OurLogsResponseItem} from 'sentry/views/explore/logs/types';
812
import {VITAL_DESCRIPTIONS} from 'sentry/views/insights/browser/webVitals/components/webVitalDescription';
913
import {WEB_VITALS_METERS_CONFIG} from 'sentry/views/insights/browser/webVitals/components/webVitalMeters';
1014
import type {WebVitals} from 'sentry/views/insights/browser/webVitals/types';
@@ -17,22 +21,18 @@ import {
1721
STATUS_TEXT,
1822
} from 'sentry/views/insights/browser/webVitals/utils/scoreToStatus';
1923
import type {TraceTree} from 'sentry/views/performance/newTraceDetails/traceModels/traceTree';
24+
import {useTraceContextSections} from 'sentry/views/performance/newTraceDetails/useTraceContextSections';
2025

2126
type Props = {
27+
logs: OurLogsResponseItem[] | undefined;
28+
rootEvent: UseApiQueryResult<EventTransaction, RequestError>;
2229
tree: TraceTree;
2330
};
2431

25-
export function treeHasValidVitals(tree: TraceTree) {
26-
const allowedVitals = Object.keys(VITAL_DETAILS);
27-
return Array.from(tree.vitals.values()).some(vitalGroup =>
28-
vitalGroup.some(vital => allowedVitals.includes(`measurements.${vital.key}`))
29-
);
30-
}
31-
32-
export function TraceContextVitals({tree}: Props) {
33-
const hasValidVitals = treeHasValidVitals(tree);
32+
export function TraceContextVitals({rootEvent, tree, logs}: Props) {
33+
const {hasVitals} = useTraceContextSections({tree, rootEvent, logs});
3434

35-
if (!hasValidVitals) {
35+
if (!hasVitals) {
3636
return null;
3737
}
3838

static/app/views/performance/newTraceDetails/traceHeader/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,11 @@ export function TraceMetaDataHeader(props: TraceMetadataHeaderProps) {
241241
organization={props.organization}
242242
/>
243243
<Flex>
244-
<ScrollToSectionLinks tree={props.tree} />
244+
<ScrollToSectionLinks
245+
rootEvent={props.rootEventResults}
246+
tree={props.tree}
247+
logs={props.logs}
248+
/>
245249
<Projects projects={projects} logs={props.logs} tree={props.tree} />
246250
</Flex>
247251
</TraceHeaderComponents.HeaderRow>

static/app/views/performance/newTraceDetails/traceHeader/scrollToSectionLinks.tsx

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ import Feature from 'sentry/components/acl/feature';
55
import {LinkButton} from 'sentry/components/core/button';
66
import {t} from 'sentry/locale';
77
import {space} from 'sentry/styles/space';
8+
import type {EventTransaction} from 'sentry/types/event';
9+
import type {UseApiQueryResult} from 'sentry/utils/queryClient';
10+
import type RequestError from 'sentry/utils/requestError/requestError';
811
import {useLocation} from 'sentry/utils/useLocation';
9-
import {treeHasValidVitals} from 'sentry/views/performance/newTraceDetails/traceContextVitals';
12+
import type {OurLogsResponseItem} from 'sentry/views/explore/logs/types';
1013
import type {TraceTree} from 'sentry/views/performance/newTraceDetails/traceModels/traceTree';
14+
import {useTraceContextSections} from 'sentry/views/performance/newTraceDetails/useTraceContextSections';
1115

1216
export const enum TraceContextSectionKeys {
1317
TAGS = 'trace-context-tags',
@@ -54,29 +58,44 @@ function SectionLink({
5458
);
5559
}
5660

57-
function ScrollToSectionLinks({tree}: {tree: TraceTree}) {
61+
function ScrollToSectionLinks({
62+
rootEvent,
63+
tree,
64+
logs,
65+
}: {
66+
logs: OurLogsResponseItem[];
67+
rootEvent: UseApiQueryResult<EventTransaction, RequestError>;
68+
tree: TraceTree;
69+
}) {
5870
const location = useLocation();
59-
const hasValidVitals = treeHasValidVitals(tree);
60-
const hasProfiles = tree.profiled_events.size > 0;
71+
const {hasVitals, hasProfiles, hasLogs, hasTags} = useTraceContextSections({
72+
tree,
73+
rootEvent,
74+
logs,
75+
});
6176

62-
return (
77+
return hasVitals || hasTags || hasProfiles || hasLogs ? (
6378
<Wrapper>
6479
<div aria-hidden>{t('Jump to:')}</div>
65-
{hasValidVitals && (
80+
{hasVitals && (
6681
<SectionLink
6782
sectionKey={TraceContextSectionKeys.WEB_VITALS}
6883
location={location}
6984
/>
7085
)}
71-
<SectionLink sectionKey={TraceContextSectionKeys.TAGS} location={location} />
86+
{hasTags && (
87+
<SectionLink sectionKey={TraceContextSectionKeys.TAGS} location={location} />
88+
)}
7289
{hasProfiles && (
7390
<SectionLink sectionKey={TraceContextSectionKeys.PROFILES} location={location} />
7491
)}
7592
<Feature features={['ourlogs-enabled']}>
76-
<SectionLink sectionKey={TraceContextSectionKeys.LOGS} location={location} />
93+
{hasLogs && (
94+
<SectionLink sectionKey={TraceContextSectionKeys.LOGS} location={location} />
95+
)}
7796
</Feature>
7897
</Wrapper>
79-
);
98+
) : null;
8099
}
81100

82101
const Wrapper = styled('div')`

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

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ import {
1616
useSetLogsQuery,
1717
} from 'sentry/views/explore/contexts/logs/logsPageParams';
1818
import {LogsTable} from 'sentry/views/explore/logs/logsTable';
19-
import {InterimSection} from 'sentry/views/issueDetails/streamline/interimSection';
19+
import type {UseExploreLogsTableResult} from 'sentry/views/explore/logs/useLogsQuery';
20+
import type {SectionKey} from 'sentry/views/issueDetails/streamline/context';
21+
import {FoldSection} from 'sentry/views/issueDetails/streamline/foldSection';
2022
import {TraceContextSectionKeys} from 'sentry/views/performance/newTraceDetails/traceHeader/scrollToSectionLinks';
2123

2224
type UseTraceViewLogsDataProps = {
@@ -40,26 +42,27 @@ export function TraceViewLogsDataProvider({
4042
}
4143

4244
export function TraceViewLogsSection() {
45+
const tableData = useLogsPageData();
46+
if (!tableData?.logsData || tableData.logsData.data.length === 0) {
47+
return null;
48+
}
4349
return (
44-
<InterimSection
45-
key="logs"
46-
type={TraceContextSectionKeys.LOGS}
50+
<FoldSection
51+
sectionKey={TraceContextSectionKeys.LOGS as string as SectionKey}
4752
title={t('Logs')}
4853
data-test-id="logs-data-section"
4954
initialCollapse={false}
55+
disableCollapsePersistence
5056
>
51-
<LogsSectionContent />
52-
</InterimSection>
57+
<LogsSectionContent tableData={tableData.logsData} />
58+
</FoldSection>
5359
);
5460
}
5561

56-
function LogsSectionContent() {
62+
function LogsSectionContent({tableData}: {tableData: UseExploreLogsTableResult}) {
5763
const setLogsQuery = useSetLogsQuery();
5864
const logsSearch = useLogsSearch();
59-
const tableData = useLogsPageData();
60-
if (!tableData?.logsData) {
61-
return null;
62-
}
65+
6366
return (
6467
<Fragment>
6568
<SearchQueryBuilder
@@ -71,7 +74,7 @@ function LogsSectionContent() {
7174
onSearch={setLogsQuery}
7275
/>
7376
<TableContainer>
74-
<LogsTable tableData={tableData.logsData} showHeader={false} />
77+
<LogsTable tableData={tableData} showHeader={false} />
7578
</TableContainer>
7679
</Fragment>
7780
);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import {EventTransaction} from 'sentry/types/event';
2+
import {VITAL_DETAILS} from 'sentry/utils/performance/vitals/constants';
3+
import {UseApiQueryResult} from 'sentry/utils/queryClient';
4+
import RequestError from 'sentry/utils/requestError/requestError';
5+
import {OurLogsResponseItem} from 'sentry/views/explore/logs/types';
6+
import {TraceTree} from 'sentry/views/performance/newTraceDetails/traceModels/traceTree';
7+
8+
export function useTraceContextSections({
9+
tree,
10+
rootEvent,
11+
logs,
12+
}: {
13+
logs: OurLogsResponseItem[] | undefined;
14+
rootEvent: UseApiQueryResult<EventTransaction, RequestError>;
15+
tree: TraceTree;
16+
}) {
17+
const hasProfiles = tree.type === 'trace' && tree.profiled_events.size > 0;
18+
const hasLogs = logs && logs?.length > 0;
19+
const hasTags =
20+
rootEvent.data &&
21+
rootEvent.data.tags.length > 0 &&
22+
!(tree.type === 'empty' && hasLogs); // We don't show tags for only logs trace views
23+
24+
const allowedVitals = Object.keys(VITAL_DETAILS);
25+
const hasVitals = Array.from(tree.vitals.values()).some(vitalGroup =>
26+
vitalGroup.some(vital => allowedVitals.includes(`measurements.${vital.key}`))
27+
);
28+
29+
return {
30+
hasProfiles,
31+
hasLogs,
32+
hasTags,
33+
hasVitals,
34+
};
35+
}

0 commit comments

Comments
 (0)