import {useCallback, useMemo} from 'react'; import styled from '@emotion/styled'; import SearchBar from 'sentry/components/events/searchBar'; import * as Layout from 'sentry/components/layouts/thirds'; import {DatePageFilter} from 'sentry/components/organizations/datePageFilter'; import {EnvironmentPageFilter} from 'sentry/components/organizations/environmentPageFilter'; import PageFilterBar from 'sentry/components/organizations/pageFilterBar'; import {TransactionSearchQueryBuilder} from 'sentry/components/performance/transactionSearchQueryBuilder'; import {ProfileEventsTable} from 'sentry/components/profiling/profileEventsTable'; import type {SmartSearchBarProps} from 'sentry/components/smartSearchBar'; import {MAX_QUERY_LENGTH} from 'sentry/constants'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import type {Organization} from 'sentry/types/organization'; import {browserHistory} from 'sentry/utils/browserHistory'; import EventView from 'sentry/utils/discover/eventView'; import {isAggregateField} from 'sentry/utils/discover/fields'; import type {ProfilingFieldType} from 'sentry/utils/profiling/hooks/useProfileEvents'; import { getProfilesTableFields, useProfileEvents, } from 'sentry/utils/profiling/hooks/useProfileEvents'; import {formatSort} from 'sentry/utils/profiling/hooks/utils'; import {decodeScalar} from 'sentry/utils/queryString'; import {MutableSearch} from 'sentry/utils/tokenizeSearch'; import {useLocation} from 'sentry/utils/useLocation'; import useOrganization from 'sentry/utils/useOrganization'; import useProjects from 'sentry/utils/useProjects'; import Tab from 'sentry/views/performance/transactionSummary/tabs'; import PageLayout, {redirectToPerformanceHomepage} from '../pageLayout'; import {TransactionProfilesContent} from './content'; interface ProfilesProps { organization: Organization; transaction: string; } function ProfilesLegacy({organization, transaction}: ProfilesProps) { const location = useLocation(); const {projects} = useProjects(); const profilesCursor = useMemo( () => decodeScalar(location.query.cursor), [location.query.cursor] ); const project = projects.find(p => p.id === location.query.project); const fields = getProfilesTableFields(project?.platform); const sortableFields = useMemo(() => new Set(fields), [fields]); const sort = formatSort(decodeScalar(location.query.sort), fields, { key: 'timestamp', order: 'desc', }); const rawQuery = useMemo( () => decodeScalar(location.query.query, ''), [location.query.query] ); const query = useMemo(() => { const conditions = new MutableSearch(rawQuery); conditions.setFilterValues('event.type', ['transaction']); conditions.setFilterValues('transaction', [transaction]); Object.keys(conditions.filters).forEach(field => { if (isAggregateField(field)) { conditions.removeFilter(field); } }); return conditions.formatString(); }, [transaction, rawQuery]); const profiles = useProfileEvents({ cursor: profilesCursor, fields, query, sort, limit: 30, referrer: 'api.profiling.transactions-profiles-table', }); const handleSearch: SmartSearchBarProps['onSearch'] = useCallback( (searchQuery: string) => { browserHistory.push({ ...location, query: { ...location.query, cursor: undefined, query: searchQuery || undefined, }, }); }, [location] ); const projectIds = useMemo( () => (project ? [parseInt(project?.id, 10)] : undefined), [project] ); return ( EventView.fromLocation(location)} getDocumentTitle={() => t(`Profile: %s`, transaction)} childComponent={() => { return ( {organization.features.includes('search-query-builder-performance') ? ( ) : ( parseInt(p.id, 10))} query={rawQuery} onSearch={handleSearch} maxQueryLength={MAX_QUERY_LENGTH} /> )} ); }} /> ); } function Profiles({organization, transaction}: ProfilesProps) { const location = useLocation(); const {projects} = useProjects(); const project = projects.find(p => p.id === location.query.project); const rawQuery = useMemo( () => decodeScalar(location.query.query, ''), [location.query.query] ); const query = useMemo(() => { const conditions = new MutableSearch(rawQuery); conditions.setFilterValues('event.type', ['transaction']); conditions.setFilterValues('transaction', [transaction]); Object.keys(conditions.filters).forEach(field => { if (isAggregateField(field)) { conditions.removeFilter(field); } }); return conditions.formatString(); }, [transaction, rawQuery]); const handleSearch: SmartSearchBarProps['onSearch'] = useCallback( (searchQuery: string) => { browserHistory.push({ ...location, query: { ...location.query, cursor: undefined, query: searchQuery || undefined, }, }); }, [location] ); const projectIds = useMemo( () => (project ? [parseInt(project?.id, 10)] : undefined), [project] ); return ( EventView.fromLocation(location)} getDocumentTitle={() => t(`Profile: %s`, transaction)} fillSpace childComponent={() => { return ( {organization.features.includes('search-query-builder-performance') ? ( ) : ( )} ); }} /> ); } const FilterActions = styled('div')` margin-bottom: ${space(2)}; gap: ${space(2)}; display: grid; grid-template-columns: min-content 1fr; `; const StyledMain = styled(Layout.Main)` display: flex; flex-direction: column; flex: 1; `; function ProfilesIndex() { const organization = useOrganization(); const location = useLocation(); const transaction = decodeScalar(location.query.transaction); if (!transaction) { redirectToPerformanceHomepage(organization, location); return null; } if (organization.features.includes('continuous-profiling-compat')) { return ; } return ; } export default ProfilesIndex;