import type {Location} from 'history'; import {COL_WIDTH_UNDEFINED} from 'sentry/components/gridEditable'; import {wrapQueryInWildcards} from 'sentry/components/performance/searchBar'; import {t} from 'sentry/locale'; import type {NewQuery, Organization, PageFilters} from 'sentry/types'; import EventView from 'sentry/utils/discover/eventView'; import {DiscoverDatasets} from 'sentry/utils/discover/types'; import {decodeScalar} from 'sentry/utils/queryString'; import {MutableSearch} from 'sentry/utils/tokenizeSearch'; import {STARFISH_TYPE_FOR_PROJECT} from 'sentry/views/starfish/allowedProjects'; import {StarfishType} from 'sentry/views/starfish/types'; const DEFAULT_STATS_PERIOD = '7d'; const TOKEN_KEYS_SUPPORTED_IN_LIMITED_SEARCH = ['transaction']; export const TIME_SPENT_IN_SERVICE = 'time_spent_percentage()'; const getDefaultStatsPeriod = (organization: Organization) => { if (organization?.features?.includes('performance-landing-page-stats-period')) { return '14d'; } return DEFAULT_STATS_PERIOD; }; function prepareQueryForLandingPage(searchQuery, withStaticFilters) { const conditions = new MutableSearch(searchQuery); // If there is a bare text search, we want to treat it as a search // on the transaction name. if (conditions.freeText.length > 0) { const parsedFreeText = conditions.freeText.join(' '); // the query here is a user entered condition, no need to escape it conditions.setFilterValues( 'transaction', [wrapQueryInWildcards(parsedFreeText)], false ); conditions.freeText = []; } if (withStaticFilters) { conditions.tokens = conditions.tokens.filter( token => token.key && TOKEN_KEYS_SUPPORTED_IN_LIMITED_SEARCH.includes(token.key) ); } return conditions.formatString(); } export function generateWebServiceEventView( location: Location, {withStaticFilters = false} = {}, organization: Organization, selection: PageFilters ) { const {query} = location; const project = selection.projects[0]; const starfishType = STARFISH_TYPE_FOR_PROJECT[project] || StarfishType.BACKEND; const getSavedQuery = () => { switch (starfishType) { case StarfishType.MOBILE: return generateMobileServiceSavedQuery(location); case StarfishType.BACKEND: default: return generateWebServiceSavedQuery(location); } }; const savedQuery = getSavedQuery(); const hasStartAndEnd = query.start && query.end; const widths = Array(savedQuery.fields.length).fill(COL_WIDTH_UNDEFINED); widths[savedQuery.fields.length - 1] = '110'; savedQuery.widths = widths; if (!query.statsPeriod && !hasStartAndEnd) { savedQuery.range = getDefaultStatsPeriod(organization); } const searchQuery = decodeScalar(query.query, ''); savedQuery.query = `${savedQuery.query} ${prepareQueryForLandingPage( searchQuery, withStaticFilters )}`; const eventView = EventView.fromNewQueryWithLocation(savedQuery, location); return eventView; } export function generateMobileServiceSavedQuery(location: Location) { const {query} = location; const orderby = decodeScalar(query.sort, `-eps`); const fields = [ 'transaction', 'eps()', 'p75(measurements.frames_slow_rate)', 'p75(measurements.time_to_initial_display)', ]; const savedQuery: NewQuery = { id: undefined, name: t('Performance'), query: 'event.type:transaction transaction.op:ui.load', fields, version: 2, dataset: DiscoverDatasets.METRICS, }; savedQuery.orderby = orderby; return savedQuery; } function generateWebServiceSavedQuery(location: Location) { const {query} = location; const orderby = decodeScalar(query.sort, `-time_spent_percentage`); const fields = [ 'transaction', 'http.method', 'tps()', 'avg(transaction.duration)', 'http_error_count()', 'time_spent_percentage()', 'sum(transaction.duration)', ]; const savedQuery: NewQuery = { id: undefined, name: t('Performance'), query: 'event.type:transaction has:http.method transaction.op:http.server', fields, version: 2, dataset: DiscoverDatasets.METRICS, }; savedQuery.orderby = orderby; return savedQuery; }