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 {ProjectPageFilter} from 'sentry/components/organizations/projectPageFilter'; import TransactionNameSearchBar from 'sentry/components/performance/searchBar'; import * as TeamKeyTransactionManager from 'sentry/components/performance/teamKeyTransactionsManager'; 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 {useOnboardingProject} from 'sentry/views/insights/common/queries/useOnboardingProject'; import {ViewTrendsButton} from 'sentry/views/insights/common/viewTrendsButton'; import {BackendHeader} from 'sentry/views/insights/pages/backend/backendPageHeader'; import {BACKEND_LANDING_TITLE} from 'sentry/views/insights/pages/backend/settings'; import {DomainOverviewPageProviders} from 'sentry/views/insights/pages/domainOverviewPageProviders'; import {OVERVIEW_PAGE_ALLOWED_OPS as FRONTEND_OVERVIEW_PAGE_OPS} from 'sentry/views/insights/pages/frontend/settings'; import {OVERVIEW_PAGE_ALLOWED_OPS as BACKEND_OVERVIEW_PAGE_OPS} from 'sentry/views/insights/pages/mobile/settings'; import {generateBackendPerformanceEventView} from 'sentry/views/performance/data'; import { DoubleChartRow, 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 BACKEND_COLUMN_TITLES = [ 'http method', 'transaction', 'operation', 'project', 'tpm', 'p50()', 'p95()', 'failure rate', 'apdex', 'users', 'user misery', ]; function BackendOverviewPage() { 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 = generateBackendPerformanceEventView( location, withStaticFilters, organization ); // TODO - this should come from MetricsField / EAP fields eventView.fields = [ {field: 'team_key_transaction'}, {field: 'http.method'}, {field: 'transaction'}, {field: 'transaction.op'}, {field: 'project'}, {field: 'tpm()'}, {field: 'p50()'}, {field: 'p95()'}, {field: 'failure_rate()'}, {field: 'apdex()'}, {field: 'count_unique(user)'}, {field: 'count_miserable(user)'}, {field: 'user_misery()'}, ].map(field => ({...field, width: COL_WIDTH_UNDEFINED})); const doubleChartRowEventView = eventView.clone(); // some of the double chart rows rely on span metrics, so they can't be queried with the same tags/filters const disallowedOps = [ ...new Set([...FRONTEND_OVERVIEW_PAGE_OPS, ...BACKEND_OVERVIEW_PAGE_OPS]), ]; const existingQuery = new MutableSearch(eventView.query); existingQuery.addFilterValues('!transaction.op', disallowedOps); eventView.query = existingQuery.formatString(); const showOnboarding = onboardingProject !== undefined; const doubleChartRowCharts = [ PerformanceWidgetSetting.SLOW_HTTP_OPS, PerformanceWidgetSetting.SLOW_DB_OPS, ]; 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, PerformanceWidgetSetting.APDEX_AREA, ], mepSetting ); if (organization.features.includes('insights-initial-modules')) { doubleChartRowCharts.unshift( PerformanceWidgetSetting.HIGHEST_CACHE_MISS_RATE_TRANSACTIONS ); doubleChartRowCharts.unshift(PerformanceWidgetSetting.MOST_TIME_CONSUMING_DOMAINS); doubleChartRowCharts.unshift(PerformanceWidgetSetting.MOST_TIME_SPENT_DB_QUERIES); } 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.backend.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 ( } /> {!showOnboarding && ( { handleSearch(query); }} query={getFreeTextFromQuery(derivedQuery)} /> )} {!showOnboarding && ( )} {showOnboarding && ( )} ); } function BackendOverviewPageWithProviders() { return ( ); } const StyledTransactionNameSearchBar = styled(TransactionNameSearchBar)` flex: 2; `; export default BackendOverviewPageWithProviders;