Skip to content

Commit 4e35128

Browse files
authored
feat(insights): create ai overview page (#78499)
1 parent 3b84fb9 commit 4e35128

File tree

1 file changed

+182
-9
lines changed

1 file changed

+182
-9
lines changed
Lines changed: 182 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,194 @@
1-
import {Fragment} from 'react';
1+
import styled from '@emotion/styled';
22

3+
import Feature from 'sentry/components/acl/feature';
4+
import {COL_WIDTH_UNDEFINED} from 'sentry/components/gridEditable';
35
import * as Layout from 'sentry/components/layouts/thirds';
4-
import {PageAlert} from 'sentry/utils/performance/contexts/pageAlert';
6+
import {NoAccess} from 'sentry/components/noAccess';
7+
import {DatePageFilter} from 'sentry/components/organizations/datePageFilter';
8+
import {EnvironmentPageFilter} from 'sentry/components/organizations/environmentPageFilter';
9+
import PageFilterBar from 'sentry/components/organizations/pageFilterBar';
10+
import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
11+
import {ProjectPageFilter} from 'sentry/components/organizations/projectPageFilter';
12+
import TransactionNameSearchBar from 'sentry/components/performance/searchBar';
13+
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
14+
import {trackAnalytics} from 'sentry/utils/analytics';
15+
import {canUseMetricsData} from 'sentry/utils/performance/contexts/metricsEnhancedSetting';
16+
import {PageAlert, usePageAlert} from 'sentry/utils/performance/contexts/pageAlert';
17+
import {PerformanceDisplayProvider} from 'sentry/utils/performance/contexts/performanceDisplayContext';
18+
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
19+
import {useLocation} from 'sentry/utils/useLocation';
20+
import {useNavigate} from 'sentry/utils/useNavigate';
21+
import useOrganization from 'sentry/utils/useOrganization';
22+
import useProjects from 'sentry/utils/useProjects';
23+
import * as ModuleLayout from 'sentry/views/insights/common/components/moduleLayout';
24+
import {ToolRibbon} from 'sentry/views/insights/common/components/ribbon';
25+
import {useOnboardingProject} from 'sentry/views/insights/common/queries/useOnboardingProject';
526
import {AiHeader} from 'sentry/views/insights/pages/ai/aiPageHeader';
27+
import {OVERVIEW_PAGE_TITLE} from 'sentry/views/insights/pages/settings';
28+
import {generateGenericPerformanceEventView} from 'sentry/views/performance/data';
29+
import {TripleChartRow} from 'sentry/views/performance/landing/widgets/components/widgetChartRow';
30+
import {PerformanceWidgetSetting} from 'sentry/views/performance/landing/widgets/widgetDefinitions';
31+
import Onboarding from 'sentry/views/performance/onboarding';
32+
import Table from 'sentry/views/performance/table';
33+
import {
34+
getTransactionSearchQuery,
35+
ProjectPerformanceType,
36+
} from 'sentry/views/performance/utils';
37+
38+
export const AI_COLUMN_TITLES = [
39+
'transaction',
40+
'project',
41+
'operation',
42+
'tpm',
43+
'p50()',
44+
'p75()',
45+
'p95()',
46+
'users',
47+
];
648

749
function AiOverviewPage() {
50+
const organization = useOrganization();
51+
const location = useLocation();
52+
const {setPageError} = usePageAlert();
53+
const {projects} = useProjects();
54+
const onboardingProject = useOnboardingProject();
55+
const navigate = useNavigate();
56+
57+
const withStaticFilters = canUseMetricsData(organization);
58+
const eventView = generateGenericPerformanceEventView(
59+
location,
60+
withStaticFilters,
61+
organization
62+
);
63+
64+
// TODO - this should come from MetricsField / EAP fields
65+
eventView.fields = [
66+
{field: 'team_key_transaction'},
67+
{field: 'transaction'},
68+
{field: 'project'},
69+
{field: 'transaction.op'},
70+
{field: 'tpm()'},
71+
{field: 'p50(transaction.duration)'},
72+
{field: 'p75(transaction.duration)'},
73+
{field: 'p95(transaction.duration)'},
74+
].map(field => ({...field, width: COL_WIDTH_UNDEFINED}));
75+
76+
const showOnboarding = onboardingProject !== undefined;
77+
78+
const tripleChartRowCharts = [
79+
PerformanceWidgetSetting.TPM_AREA,
80+
PerformanceWidgetSetting.DURATION_HISTOGRAM,
81+
PerformanceWidgetSetting.P50_DURATION_AREA,
82+
PerformanceWidgetSetting.P75_DURATION_AREA,
83+
PerformanceWidgetSetting.P95_DURATION_AREA,
84+
PerformanceWidgetSetting.P99_DURATION_AREA,
85+
PerformanceWidgetSetting.FAILURE_RATE_AREA,
86+
];
87+
88+
const sharedProps = {eventView, location, organization, withStaticFilters};
89+
90+
const getFreeTextFromQuery = (query: string) => {
91+
const conditions = new MutableSearch(query);
92+
const transactionValues = conditions.getFilterValues('transaction');
93+
if (transactionValues.length) {
94+
return transactionValues[0];
95+
}
96+
if (conditions.freeText.length > 0) {
97+
// raw text query will be wrapped in wildcards in generatePerformanceEventView
98+
// so no need to wrap it here
99+
return conditions.freeText.join(' ');
100+
}
101+
return '';
102+
};
103+
104+
function handleSearch(searchQuery: string) {
105+
trackAnalytics('performance.domains.ai.search', {organization});
106+
107+
navigate({
108+
pathname: location.pathname,
109+
query: {
110+
...location.query,
111+
cursor: undefined,
112+
query: String(searchQuery).trim() || undefined,
113+
isDefaultQuery: false,
114+
},
115+
});
116+
}
117+
118+
const derivedQuery = getTransactionSearchQuery(location, eventView.query);
119+
8120
return (
9-
<Fragment>
121+
<Feature
122+
features="insights-domain-view"
123+
organization={organization}
124+
renderDisabled={NoAccess}
125+
>
10126
<Layout.Header>
11127
<AiHeader />
12128
</Layout.Header>
13-
<Layout.Main fullWidth>
14-
<PageAlert />
15-
{'overview page'}
16-
</Layout.Main>
17-
</Fragment>
129+
<Layout.Body>
130+
<Layout.Main fullWidth>
131+
<ModuleLayout.Layout>
132+
<ModuleLayout.Full>
133+
<ToolRibbon>
134+
<PageFilterBar condensed>
135+
<ProjectPageFilter />
136+
<EnvironmentPageFilter />
137+
<DatePageFilter />
138+
</PageFilterBar>
139+
{!showOnboarding && (
140+
<StyledTransactionNameSearchBar
141+
organization={organization}
142+
eventView={eventView}
143+
onSearch={(query: string) => {
144+
handleSearch(query);
145+
}}
146+
query={getFreeTextFromQuery(derivedQuery)}
147+
/>
148+
)}
149+
</ToolRibbon>
150+
</ModuleLayout.Full>
151+
<PageAlert />
152+
<ModuleLayout.Full>
153+
{!showOnboarding && (
154+
<PerformanceDisplayProvider
155+
value={{performanceType: ProjectPerformanceType.ANY}}
156+
>
157+
<TripleChartRow allowedCharts={tripleChartRowCharts} {...sharedProps} />
158+
<Table
159+
projects={projects}
160+
columnTitles={AI_COLUMN_TITLES}
161+
setError={setPageError}
162+
{...sharedProps}
163+
/>
164+
</PerformanceDisplayProvider>
165+
)}
166+
167+
{showOnboarding && (
168+
<Onboarding project={onboardingProject} organization={organization} />
169+
)}
170+
</ModuleLayout.Full>
171+
</ModuleLayout.Layout>
172+
</Layout.Main>
173+
</Layout.Body>
174+
</Feature>
18175
);
19176
}
20177

21-
export default AiOverviewPage;
178+
function AiOverviewPageWithProviders() {
179+
const organization = useOrganization();
180+
181+
return (
182+
<PageFiltersContainer>
183+
<SentryDocumentTitle title={OVERVIEW_PAGE_TITLE} orgSlug={organization.slug}>
184+
<AiOverviewPage />
185+
</SentryDocumentTitle>
186+
</PageFiltersContainer>
187+
);
188+
}
189+
190+
const StyledTransactionNameSearchBar = styled(TransactionNameSearchBar)`
191+
flex: 2;
192+
`;
193+
194+
export default AiOverviewPageWithProviders;

0 commit comments

Comments
 (0)