123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- import styled from '@emotion/styled';
- import Feature from 'sentry/components/acl/feature';
- import {COL_WIDTH_UNDEFINED} from 'sentry/components/gridEditable';
- import * as Layout from 'sentry/components/layouts/thirds';
- import {NoAccess} from 'sentry/components/noAccess';
- import {DatePageFilter} from 'sentry/components/organizations/datePageFilter';
- import {EnvironmentPageFilter} from 'sentry/components/organizations/environmentPageFilter';
- import PageFilterBar from 'sentry/components/organizations/pageFilterBar';
- import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
- import {ProjectPageFilter} from 'sentry/components/organizations/projectPageFilter';
- import TransactionNameSearchBar from 'sentry/components/performance/searchBar';
- import * as TeamKeyTransactionManager from 'sentry/components/performance/teamKeyTransactionsManager';
- import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
- import {trackAnalytics} from 'sentry/utils/analytics';
- import {
- canUseMetricsData,
- useMEPSettingContext,
- } from 'sentry/utils/performance/contexts/metricsEnhancedSetting';
- import {PageAlert, usePageAlert} from 'sentry/utils/performance/contexts/pageAlert';
- import {PerformanceDisplayProvider} from 'sentry/utils/performance/contexts/performanceDisplayContext';
- import {MutableSearch} from 'sentry/utils/tokenizeSearch';
- import {useLocation} from 'sentry/utils/useLocation';
- import {useNavigate} from 'sentry/utils/useNavigate';
- import useOrganization from 'sentry/utils/useOrganization';
- import useProjects from 'sentry/utils/useProjects';
- import {useUserTeams} from 'sentry/utils/useUserTeams';
- import * as ModuleLayout from 'sentry/views/insights/common/components/moduleLayout';
- import {ToolRibbon} from 'sentry/views/insights/common/components/ribbon';
- import {ViewTrendsButton} from 'sentry/views/insights/common/components/viewTrendsButton';
- import {useOnboardingProject} from 'sentry/views/insights/common/queries/useOnboardingProject';
- import {AiHeader} from 'sentry/views/insights/pages/ai/aiPageHeader';
- import {AI_LANDING_TITLE} from 'sentry/views/insights/pages/ai/settings';
- import {OVERVIEW_PAGE_TITLE} from 'sentry/views/insights/pages/settings';
- import {generateGenericPerformanceEventView} from 'sentry/views/performance/data';
- import {TripleChartRow} from 'sentry/views/performance/landing/widgets/components/widgetChartRow';
- import {filterAllowedChartsMetrics} from 'sentry/views/performance/landing/widgets/utils';
- import {PerformanceWidgetSetting} from 'sentry/views/performance/landing/widgets/widgetDefinitions';
- import Onboarding from 'sentry/views/performance/onboarding';
- import Table from 'sentry/views/performance/table';
- import {
- getTransactionSearchQuery,
- ProjectPerformanceType,
- } from 'sentry/views/performance/utils';
- export const AI_COLUMN_TITLES = [
- 'transaction',
- 'project',
- 'operation',
- 'tpm',
- 'p50()',
- 'p75()',
- 'p95()',
- 'users',
- ];
- function AiOverviewPage() {
- const organization = useOrganization();
- const location = useLocation();
- const {setPageError} = usePageAlert();
- const {projects} = useProjects();
- const onboardingProject = useOnboardingProject();
- const navigate = useNavigate();
- const {teams} = useUserTeams();
- const mepSetting = useMEPSettingContext();
- const withStaticFilters = canUseMetricsData(organization);
- const eventView = generateGenericPerformanceEventView(
- location,
- withStaticFilters,
- organization
- );
- // TODO - this should come from MetricsField / EAP fields
- eventView.fields = [
- {field: 'team_key_transaction'},
- {field: 'transaction'},
- {field: 'project'},
- {field: 'transaction.op'},
- {field: 'tpm()'},
- {field: 'p50(transaction.duration)'},
- {field: 'p75(transaction.duration)'},
- {field: 'p95(transaction.duration)'},
- ].map(field => ({...field, width: COL_WIDTH_UNDEFINED}));
- const showOnboarding = onboardingProject !== undefined;
- const tripleChartRowCharts = filterAllowedChartsMetrics(
- organization,
- [
- PerformanceWidgetSetting.TPM_AREA,
- PerformanceWidgetSetting.DURATION_HISTOGRAM,
- PerformanceWidgetSetting.P50_DURATION_AREA,
- PerformanceWidgetSetting.P75_DURATION_AREA,
- PerformanceWidgetSetting.P95_DURATION_AREA,
- PerformanceWidgetSetting.P99_DURATION_AREA,
- PerformanceWidgetSetting.FAILURE_RATE_AREA,
- ],
- mepSetting
- );
- const sharedProps = {eventView, location, organization, withStaticFilters};
- const getFreeTextFromQuery = (query: string) => {
- const conditions = new MutableSearch(query);
- const transactionValues = conditions.getFilterValues('transaction');
- if (transactionValues.length) {
- return transactionValues[0];
- }
- if (conditions.freeText.length > 0) {
- // raw text query will be wrapped in wildcards in generatePerformanceEventView
- // so no need to wrap it here
- return conditions.freeText.join(' ');
- }
- return '';
- };
- function handleSearch(searchQuery: string) {
- trackAnalytics('performance.domains.ai.search', {organization});
- navigate({
- pathname: location.pathname,
- query: {
- ...location.query,
- cursor: undefined,
- query: String(searchQuery).trim() || undefined,
- isDefaultQuery: false,
- },
- });
- }
- const derivedQuery = getTransactionSearchQuery(location, eventView.query);
- return (
- <Feature
- features="insights-domain-view"
- organization={organization}
- renderDisabled={NoAccess}
- >
- <AiHeader headerTitle={AI_LANDING_TITLE} headerActions={<ViewTrendsButton />} />
- <Layout.Body>
- <Layout.Main fullWidth>
- <ModuleLayout.Layout>
- <ModuleLayout.Full>
- <ToolRibbon>
- <PageFilterBar condensed>
- <ProjectPageFilter />
- <EnvironmentPageFilter />
- <DatePageFilter />
- </PageFilterBar>
- {!showOnboarding && (
- <StyledTransactionNameSearchBar
- organization={organization}
- eventView={eventView}
- onSearch={(query: string) => {
- handleSearch(query);
- }}
- query={getFreeTextFromQuery(derivedQuery)}
- />
- )}
- </ToolRibbon>
- </ModuleLayout.Full>
- <PageAlert />
- <ModuleLayout.Full>
- {!showOnboarding && (
- <PerformanceDisplayProvider
- value={{performanceType: ProjectPerformanceType.ANY}}
- >
- <TeamKeyTransactionManager.Provider
- organization={organization}
- teams={teams}
- selectedTeams={['myteams']}
- selectedProjects={eventView.project.map(String)}
- >
- <TripleChartRow
- allowedCharts={tripleChartRowCharts}
- {...sharedProps}
- />
- <Table
- projects={projects}
- columnTitles={AI_COLUMN_TITLES}
- setError={setPageError}
- {...sharedProps}
- />
- </TeamKeyTransactionManager.Provider>
- </PerformanceDisplayProvider>
- )}
- {showOnboarding && (
- <Onboarding project={onboardingProject} organization={organization} />
- )}
- </ModuleLayout.Full>
- </ModuleLayout.Layout>
- </Layout.Main>
- </Layout.Body>
- </Feature>
- );
- }
- function AiOverviewPageWithProviders() {
- const organization = useOrganization();
- return (
- <PageFiltersContainer>
- <SentryDocumentTitle title={OVERVIEW_PAGE_TITLE} orgSlug={organization.slug}>
- <AiOverviewPage />
- </SentryDocumentTitle>
- </PageFiltersContainer>
- );
- }
- const StyledTransactionNameSearchBar = styled(TransactionNameSearchBar)`
- flex: 2;
- `;
- export default AiOverviewPageWithProviders;
|