123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- import Link from 'app/components/links/link';
- import {t} from 'app/locale';
- import {Project} from 'app/types';
- import {DisplayModes} from 'app/utils/discover/types';
- import {tokenizeSearch} from 'app/utils/tokenizeSearch';
- import {Incident, IncidentStats} from 'app/views/alerts/types';
- import {getStartEndFromStats} from 'app/views/alerts/utils';
- import {getIncidentDiscoverUrl} from 'app/views/alerts/utils/getIncidentDiscoverUrl';
- import {transactionSummaryRouteWithQuery} from 'app/views/performance/transactionSummary/utils';
- import {Dataset} from './types';
- type PresetCta = {
- /**
- * The location to direct to upon clicking the CTA.
- */
- to: React.ComponentProps<typeof Link>['to'];
- /**
- * The CTA text
- */
- buttonText: string;
- /**
- * The tooltip title for the CTA button, may be empty.
- */
- title?: string;
- };
- type PresetCtaOpts = {
- orgSlug: string;
- projects: Project[];
- incident?: Incident;
- stats?: IncidentStats;
- };
- type Preset = {
- /**
- * The regex used to match aggregates to this preset.
- */
- match: RegExp;
- /**
- * The name of the preset
- */
- name: string;
- /**
- * The dataset that this preset applys to.
- */
- validDataset: Dataset[];
- /**
- * The default aggregate to use when selecting this preset
- */
- default: string;
- /**
- * Generates the CTA component
- */
- makeCtaParams: (opts: PresetCtaOpts) => PresetCta;
- };
- export const PRESET_AGGREGATES: Preset[] = [
- {
- name: t('Error count'),
- match: /^count\(\)/,
- validDataset: [Dataset.ERRORS],
- default: 'count()',
- /**
- * Simple "Open in Discover" button
- */
- makeCtaParams: makeDefaultCta,
- },
- {
- name: t('Users affected'),
- match: /^count_unique\(tags\[sentry:user\]\)/,
- validDataset: [Dataset.ERRORS],
- default: 'count_unique(tags[sentry:user])',
- /**
- * Simple "Open in Discover" button
- */
- makeCtaParams: makeDefaultCta,
- },
- {
- name: t('Latency'),
- match: /^(p[0-9]{2,3}|percentile\(transaction\.duration,[^)]+\)|avg\([^)]+\))/,
- validDataset: [Dataset.TRANSACTIONS],
- default: 'percentile(transaction.duration, 0.95)',
- /**
- * see: makeGenericTransactionCta
- */
- makeCtaParams: opts =>
- makeGenericTransactionCta({
- opts,
- tooltip: t('Latency by Transaction'),
- }),
- },
- {
- name: t('Apdex'),
- match: /^apdex\([0-9.]+\)/,
- validDataset: [Dataset.TRANSACTIONS],
- default: 'apdex(300)',
- /**
- * see: makeGenericTransactionCta
- */
- makeCtaParams: opts =>
- makeGenericTransactionCta({
- opts,
- tooltip: t('Apdex by Transaction'),
- }),
- },
- {
- name: t('Transaction Count'),
- match: /^count\(\)/,
- validDataset: [Dataset.TRANSACTIONS],
- default: 'count()',
- /**
- * see: makeGenericTransactionCta
- */
- makeCtaParams: opts => makeGenericTransactionCta({opts}),
- },
- {
- name: t('Failure rate'),
- match: /^failure_rate\(\)/,
- validDataset: [Dataset.TRANSACTIONS],
- default: 'failure_rate()',
- /**
- * See makeFailureRateCta
- */
- makeCtaParams: makeFailureRateCta,
- },
- ];
- /**
- * - CASE 1: If has a specific transaction filter
- * - CTA is: "View Transaction Summary"
- * - Tooltip is the transaction name
- * - the same period as the alert graph (i.e. with alert start time in the middle)
- *
- * - CASE 2: If transaction is NOT filtered, or has a * filter:
- * - "Open in Discover" button with optional tooltip which opens a discover view with...
- * - fields {transaction, count(), <metric>} sorted by count()
- * - top-5 activated
- */
- function makeGenericTransactionCta(opts: {
- opts: PresetCtaOpts;
- tooltip?: string;
- }): PresetCta {
- const {
- opts: {orgSlug, projects, incident, stats},
- tooltip,
- } = opts;
- if (!incident || !stats) {
- return {to: '', buttonText: t('Incident details')};
- }
- const query = tokenizeSearch(incident.discoverQuery ?? '');
- const transaction = query
- .getTagValues('transaction')
- ?.find(filter => !filter.includes('*'));
- // CASE 1
- if (transaction !== undefined) {
- const period = getStartEndFromStats(stats);
- const summaryUrl = transactionSummaryRouteWithQuery({
- orgSlug,
- transaction,
- projectID: projects
- .filter(({slug}) => incident.projects.includes(slug))
- .map(({id}) => id),
- query: {...period},
- });
- return {
- to: summaryUrl,
- buttonText: t('View Transaction Summary'),
- title: transaction,
- };
- }
- // CASE 2
- const extraQueryParams = {
- fields: [...new Set(['transaction', 'count()', incident.alertRule.aggregate])],
- orderby: '-count',
- display: DisplayModes.TOP5,
- };
- const discoverUrl = getIncidentDiscoverUrl({
- orgSlug,
- projects,
- incident,
- stats,
- extraQueryParams,
- });
- return {
- to: discoverUrl,
- buttonText: t('Open in Discover'),
- title: tooltip,
- };
- }
- /**
- * - CASE 1: Filtered to a specific transaction, "Open in Discover" with...
- * - fields [transaction.status, count()] sorted by count(),
- * - "Top 5 period" activated.
- *
- * - CASE 2: If filtered on multiple transactions, "Open in Discover" button
- * with tooltip "Failure rate by transaction" which opens a discover view
- * - fields [transaction, failure_rate()] sorted by failure_rate
- * - top 5 activated
- */
- function makeFailureRateCta({orgSlug, incident, projects, stats}: PresetCtaOpts) {
- if (!incident || !stats) {
- return {to: '', buttonText: t('Incident details')};
- }
- const query = tokenizeSearch(incident.discoverQuery ?? '');
- const transaction = query
- .getTagValues('transaction')
- ?.find(filter => !filter.includes('*'));
- const extraQueryParams =
- transaction !== undefined
- ? // CASE 1
- {
- fields: ['transaction.status', 'count()'],
- orderby: '-count',
- display: DisplayModes.TOP5,
- }
- : // Case 2
- {
- fields: ['transaction', 'failure_rate()'],
- orderby: '-failure_rate',
- display: DisplayModes.TOP5,
- };
- const discoverUrl = getIncidentDiscoverUrl({
- orgSlug,
- projects,
- incident,
- stats,
- extraQueryParams,
- });
- return {
- to: discoverUrl,
- buttonText: t('Open in Discover'),
- title: transaction === undefined ? t('Failure rate by transaction') : undefined,
- };
- }
- /**
- * Get the CTA used for alerts that do not have a preset
- */
- export function makeDefaultCta({
- orgSlug,
- projects,
- incident,
- stats,
- }: PresetCtaOpts): PresetCta {
- if (!incident) {
- return {
- buttonText: t('Open in Discover'),
- to: '',
- };
- }
- const extraQueryParams = {
- display: DisplayModes.TOP5,
- };
- return {
- buttonText: t('Open in Discover'),
- to: getIncidentDiscoverUrl({orgSlug, projects, incident, stats, extraQueryParams}),
- };
- }
|