123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- import {Client} from 'sentry/api';
- import {IconGraph} from 'sentry/icons';
- import {t} from 'sentry/locale';
- import {Organization, Project} from 'sentry/types';
- import {uniqueId} from 'sentry/utils/guid';
- import {AlertType} from '../../wizard/options';
- import {
- ActionType,
- AlertRuleComparisonType,
- AlertRuleThresholdType,
- AlertRuleTriggerType,
- Dataset,
- EventTypes,
- TargetType,
- Trigger,
- } from './types';
- export type PresetContext = {
- aggregate: string;
- comparisonType: AlertRuleComparisonType;
- dataset: Dataset;
- eventTypes: EventTypes[];
- name: string;
- thresholdType: AlertRuleThresholdType;
- triggers: Trigger[];
- comparisonDelta?: number;
- query?: string;
- timeWindow?: number;
- };
- export type Preset = {
- Icon: typeof IconGraph;
- // Will be shown on the corresponding alert type in the wizard.
- alertType: AlertType;
- description: string;
- id: string;
- makeContext(
- client: Client,
- project: Project,
- organization: Organization
- ): Promise<PresetContext>;
- makeUnqueriedContext(project: Project, organization: Organization): PresetContext;
- title: string;
- };
- async function getHighestVolumeTransaction(
- client: Client,
- organizationSlug: string,
- projectId: string
- ): Promise<[string, number] | null> {
- const result = await client.requestPromise(
- `/organizations/${organizationSlug}/events/`,
- {
- method: 'GET',
- data: {
- statsPeriod: '7d',
- project: projectId,
- field: ['count()', 'transaction'],
- sort: '-count',
- referrer: 'alert.presets.highest-volume',
- query: 'event.type:transaction',
- per_page: 1,
- },
- }
- );
- const transaction = result.data[0];
- if (transaction) {
- return [transaction.transaction, transaction['count()']];
- }
- return null;
- }
- function makeTeamCriticalAlert(project: Project, threshold: number = 200) {
- return {
- label: AlertRuleTriggerType.CRITICAL,
- alertThreshold: threshold,
- actions: project.teams.slice(0, 4).map(team => ({
- type: ActionType.EMAIL,
- targetType: TargetType.TEAM,
- targetIdentifier: team.id,
- unsavedDateCreated: new Date().toISOString(),
- inputChannelId: null,
- options: null,
- unsavedId: uniqueId(),
- })),
- };
- }
- function makeTeamWarningAlert(threshold: number = 100) {
- return {
- label: AlertRuleTriggerType.WARNING,
- alertThreshold: threshold,
- actions: [],
- };
- }
- export const PRESET_AGGREGATES: readonly Preset[] = [
- {
- id: 'p95-highest-volume',
- title: t('Slow transactions'),
- description: 'Get notified when important transactions are slower on average',
- Icon: IconGraph,
- alertType: 'trans_duration',
- makeUnqueriedContext(project, _) {
- return {
- name: t('p95 Alert for %s', [project.slug]),
- aggregate: 'p95(transaction.duration)',
- dataset: Dataset.TRANSACTIONS,
- eventTypes: [EventTypes.TRANSACTION],
- timeWindow: 60,
- comparisonDelta: 1440,
- comparisonType: AlertRuleComparisonType.CHANGE,
- thresholdType: AlertRuleThresholdType.ABOVE,
- triggers: [makeTeamCriticalAlert(project), makeTeamWarningAlert()],
- };
- },
- async makeContext(client, project, organization) {
- const transaction = (
- await getHighestVolumeTransaction(client, organization.slug, project.id)
- )?.[0];
- return {
- ...this.makeUnqueriedContext(project, organization),
- query: 'transaction:' + transaction,
- };
- },
- },
- {
- id: 'throughput-highest-volume',
- title: t('Throttled throughput'),
- description: 'Send an alert when transaction throughput drops significantly',
- Icon: IconGraph,
- alertType: 'throughput',
- makeUnqueriedContext(project, _) {
- return {
- name: t('Throughput Alert for %s', [project.slug]),
- aggregate: 'count()',
- dataset: Dataset.TRANSACTIONS,
- eventTypes: [EventTypes.TRANSACTION],
- timeWindow: 30,
- comparisonDelta: 24 * 60 * 7,
- comparisonType: AlertRuleComparisonType.CHANGE,
- thresholdType: AlertRuleThresholdType.BELOW,
- triggers: [makeTeamCriticalAlert(project, 500), makeTeamWarningAlert(300)],
- };
- },
- async makeContext(client, project, organization) {
- const transaction = (
- await getHighestVolumeTransaction(client, organization.slug, project.id)
- )?.[0];
- return {
- ...this.makeUnqueriedContext(project, organization),
- query: 'transaction:' + transaction,
- };
- },
- },
- {
- id: 'apdex-highest-volume',
- title: t('Apdex Score'),
- description:
- 'Learn when the ratio of satisfactory, tolerable, and frustrated requests drop',
- Icon: IconGraph,
- alertType: 'apdex',
- makeUnqueriedContext(project, _) {
- return {
- name: t('Apdex regression for %s', [project.slug]),
- aggregate: 'apdex(300)',
- dataset: Dataset.TRANSACTIONS,
- eventTypes: [EventTypes.TRANSACTION],
- timeWindow: 30,
- comparisonDelta: 24 * 60 * 7,
- comparisonType: AlertRuleComparisonType.CHANGE,
- thresholdType: AlertRuleThresholdType.BELOW,
- triggers: [makeTeamCriticalAlert(project), makeTeamWarningAlert()],
- };
- },
- async makeContext(client, project, organization) {
- const transaction = (
- await getHighestVolumeTransaction(client, organization.slug, project.id)
- )?.[0];
- return {
- ...this.makeUnqueriedContext(project, organization),
- query: 'transaction:' + transaction,
- };
- },
- },
- ] as const;
|