alerts.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. import type {SchemaFormConfig} from 'sentry/views/settings/organizationIntegrations/sentryAppExternalForm';
  2. import type {IssueConfigField} from './integrations';
  3. export const enum IssueAlertActionType {
  4. SLACK = 'sentry.integrations.slack.notify_action.SlackNotifyServiceAction',
  5. NOTIFY_EMAIL = 'sentry.mail.actions.NotifyEmailAction',
  6. DISCORD = 'sentry.integrations.discord.notify_action.DiscordNotifyServiceAction',
  7. SENTRY_APP = 'sentry.rules.actions.notify_event_sentry_app.NotifyEventSentryAppAction',
  8. MS_TEAMS = 'sentry.integrations.msteams.notify_action.MsTeamsNotifyServiceAction',
  9. PAGER_DUTY = 'sentry.integrations.pagerduty.notify_action.PagerDutyNotifyServiceAction',
  10. OPSGENIE = 'sentry.integrations.opsgenie.notify_action.OpsgenieNotifyTeamAction',
  11. /**
  12. * Legacy integrations
  13. */
  14. NOTIFY_EVENT_ACTION = 'sentry.rules.actions.notify_event.NotifyEventAction',
  15. /**
  16. * Webhooks
  17. */
  18. NOTIFY_EVENT_SERVICE_ACTION = 'sentry.rules.actions.notify_event_service.NotifyEventServiceAction',
  19. /**
  20. * Ticket integrations
  21. */
  22. JIRA_CREATE_TICKET = 'sentry.integrations.jira.notify_action.JiraCreateTicketAction',
  23. JIRA_SERVER_CREATE_TICKET = 'sentry.integrations.jira_server.notify_action.JiraServerCreateTicketAction',
  24. GITHUB_CREATE_TICKET = 'sentry.integrations.github.notify_action.GitHubCreateTicketAction',
  25. GITHUB_ENTERPRISE_CREATE_TICKET = 'sentry.integrations.github_enterprise.notify_action.GitHubEnterpriseCreateTicketAction',
  26. AZURE_DEVOPS_CREATE_TICKET = 'sentry.integrations.vsts.notify_action.AzureDevopsCreateTicketAction',
  27. }
  28. export const enum IssueAlertConditionType {
  29. EVERY_EVENT = 'sentry.rules.conditions.every_event.EveryEventCondition',
  30. FIRST_SEEN_EVENT = 'sentry.rules.conditions.first_seen_event.FirstSeenEventCondition',
  31. REGRESSION_EVENT = 'sentry.rules.conditions.regression_event.RegressionEventCondition',
  32. REAPPEARED_EVENT = 'sentry.rules.conditions.reappeared_event.ReappearedEventCondition',
  33. EVENT_FREQUENCY = 'sentry.rules.conditions.event_frequency.EventFrequencyCondition',
  34. EVENT_UNIQUE_USER_FREQUENCY = 'sentry.rules.conditions.event_frequency.EventUniqueUserFrequencyCondition',
  35. EVENT_UNIQUE_USER_FREQUENCY_WITH_CONDITIONS = 'sentry.rules.conditions.event_frequency.EventUniqueUserFrequencyConditionWithConditions',
  36. EVENT_FREQUENCY_PERCENT = 'sentry.rules.conditions.event_frequency.EventFrequencyPercentCondition',
  37. NEW_HIGH_PRIORITY_ISSUE = 'sentry.rules.conditions.high_priority_issue.NewHighPriorityIssueCondition',
  38. EXISTING_HIGH_PRIORITY_ISSUE = 'sentry.rules.conditions.high_priority_issue.ExistingHighPriorityIssueCondition',
  39. }
  40. export const enum IssueAlertFilterType {
  41. AGE_COMPARISON = 'sentry.rules.filters.age_comparison.AgeComparisonFilter',
  42. ISSUE_OCCURRENCES = 'sentry.rules.filters.issue_occurrences.IssueOccurrencesFilter',
  43. ASSIGNED_TO = 'sentry.rules.filters.assigned_to.AssignedToFilter',
  44. LATEST_ADOPTED_RELEASE = 'sentry.rules.filters.latest_adopted_release_filter.LatestAdoptedReleaseFilter',
  45. LATEST_RELEASE = 'sentry.rules.filters.latest_release.LatestReleaseFilter',
  46. ISSUE_CATEGORY = 'sentry.rules.filters.issue_category.IssueCategoryFilter',
  47. EVENT_ATTRIBUTE = 'sentry.rules.filters.event_attribute.EventAttributeFilter',
  48. TAGGED_EVENT = 'sentry.rules.filters.tagged_event.TaggedEventFilter',
  49. LEVEL = 'sentry.rules.filters.level.LevelFilter',
  50. }
  51. interface IssueAlertFormFieldChoice {
  52. type: 'choice';
  53. choices?: Array<[key: string | number, name: string]>;
  54. initial?: string;
  55. placeholder?: string;
  56. }
  57. interface IssueAlertFormFieldString {
  58. type: 'string';
  59. initial?: string;
  60. placeholder?: string;
  61. }
  62. interface IssueAlertFormFieldNumber {
  63. type: 'number';
  64. initial?: string;
  65. placeholder?: number | string;
  66. }
  67. /**
  68. * The fields that are used to render the form for an action or condition.
  69. */
  70. type IssueAlertRuleFormField =
  71. | IssueAlertFormFieldChoice
  72. | IssueAlertFormFieldString
  73. | IssueAlertFormFieldNumber;
  74. /**
  75. * All issue alert configuration objects have these properties.
  76. */
  77. interface IssueAlertConfigBase {
  78. enabled: boolean;
  79. label: string;
  80. /**
  81. * "Send a Slack notification"
  82. */
  83. prompt?: string;
  84. }
  85. /**
  86. * Generic alert configuration. Do not add properties unless they are used by all filters.
  87. */
  88. interface IssueAlertGenericActionConfig extends IssueAlertConfigBase {
  89. id:
  90. | `${IssueAlertActionType.SLACK}`
  91. | `${IssueAlertActionType.NOTIFY_EMAIL}`
  92. | `${IssueAlertActionType.DISCORD}`
  93. | `${IssueAlertActionType.SENTRY_APP}`
  94. | `${IssueAlertActionType.MS_TEAMS}`
  95. | `${IssueAlertActionType.PAGER_DUTY}`
  96. | `${IssueAlertActionType.OPSGENIE}`
  97. | `${IssueAlertActionType.NOTIFY_EVENT_ACTION}`
  98. | `${IssueAlertActionType.NOTIFY_EVENT_SERVICE_ACTION}`;
  99. formFields?: Record<string, IssueAlertRuleFormField>;
  100. }
  101. /**
  102. * Currently filters and conditions are basically the same, just with different IDs.
  103. * Do not add properties unless they are used by all filters.
  104. */
  105. export interface IssueAlertGenericConditionConfig extends IssueAlertConfigBase {
  106. id: `${IssueAlertConditionType}` | `${IssueAlertFilterType}`;
  107. formFields?: Record<string, IssueAlertRuleFormField>;
  108. }
  109. /**
  110. * The object describing the options the slack action can use.
  111. */
  112. interface IssueAlertSlackConfig extends IssueAlertConfigBase {
  113. formFields: {
  114. channel: IssueAlertFormFieldString;
  115. channel_id: IssueAlertFormFieldString;
  116. tags: IssueAlertFormFieldString;
  117. workspace: IssueAlertFormFieldChoice;
  118. };
  119. id: `${IssueAlertActionType.SLACK}`;
  120. }
  121. interface IssueAlertTicketIntegrationConfig extends IssueAlertConfigBase {
  122. actionType: 'ticket';
  123. formFields: SchemaFormConfig;
  124. id:
  125. | `${IssueAlertActionType.JIRA_CREATE_TICKET}`
  126. | `${IssueAlertActionType.JIRA_SERVER_CREATE_TICKET}`
  127. | `${IssueAlertActionType.GITHUB_CREATE_TICKET}`
  128. | `${IssueAlertActionType.GITHUB_ENTERPRISE_CREATE_TICKET}`
  129. | `${IssueAlertActionType.AZURE_DEVOPS_CREATE_TICKET}`;
  130. link: string;
  131. ticketType: string;
  132. }
  133. interface IssueAlertSentryAppIntegrationConfig extends IssueAlertConfigBase {
  134. actionType: 'sentryapp';
  135. formFields: SchemaFormConfig;
  136. id: `${IssueAlertActionType.SENTRY_APP}`;
  137. sentryAppInstallationUuid: string;
  138. }
  139. /**
  140. * The actions that an organization has enabled and can be used to create an issue alert.
  141. */
  142. export type IssueAlertConfigurationAction =
  143. | IssueAlertGenericActionConfig
  144. | IssueAlertTicketIntegrationConfig
  145. | IssueAlertSentryAppIntegrationConfig
  146. | IssueAlertSlackConfig;
  147. /**
  148. * Describes the actions, filters, and conditions that can be used
  149. * to create an issue alert.
  150. */
  151. export interface IssueAlertConfiguration {
  152. actions: IssueAlertConfigurationAction[];
  153. conditions: IssueAlertGenericConditionConfig[];
  154. filters: IssueAlertGenericConditionConfig[];
  155. }
  156. /**
  157. * These templates that tell the UI how to render the action or condition
  158. * and what fields it needs
  159. */
  160. export interface IssueAlertRuleActionTemplate {
  161. enabled: boolean;
  162. id: string;
  163. label: string;
  164. actionType?: 'ticket' | 'sentryapp';
  165. formFields?:
  166. | {
  167. [key: string]: IssueAlertRuleFormField;
  168. }
  169. | SchemaFormConfig;
  170. link?: string;
  171. prompt?: string;
  172. sentryAppInstallationUuid?: string;
  173. ticketType?: string;
  174. }
  175. export type IssueAlertRuleConditionTemplate = IssueAlertRuleActionTemplate;
  176. /**
  177. * These are the action or condition data that the user is editing or has saved.
  178. */
  179. export interface IssueAlertRuleAction
  180. extends Omit<IssueAlertRuleActionTemplate, 'formFields' | 'enabled' | 'label'> {
  181. // These are the same values as the keys in `formFields` for a template
  182. [key: string]: any;
  183. dynamic_form_fields?: IssueConfigField[];
  184. }
  185. export type IssueAlertRuleCondition = Omit<
  186. IssueAlertRuleConditionTemplate,
  187. 'formFields' | 'enabled' | 'label'
  188. > & {
  189. dynamic_form_fields?: IssueConfigField[];
  190. } & {
  191. // These are the same values as the keys in `formFields` for a template
  192. [key: string]: number | string;
  193. };
  194. interface SlackAction {
  195. channel: string | undefined;
  196. id: IssueAlertActionType.SLACK;
  197. workspace: string | undefined;
  198. channel_id?: string | undefined;
  199. notes?: string | undefined;
  200. tags?: string | undefined;
  201. }
  202. interface DiscordAction {
  203. channel_id: string | undefined;
  204. id: IssueAlertActionType.DISCORD;
  205. server: string | undefined;
  206. tags?: string | undefined;
  207. }
  208. interface MSTeamsAction {
  209. channel: string | undefined;
  210. id: IssueAlertActionType.MS_TEAMS;
  211. team: string | undefined;
  212. }
  213. export type IntegrationAction = SlackAction | DiscordAction | MSTeamsAction;
  214. export interface UnsavedIssueAlertRule {
  215. /** When an issue matches [actionMatch] of the following */
  216. actionMatch: 'all' | 'any' | 'none';
  217. actions: IssueAlertRuleAction[];
  218. conditions: IssueAlertRuleCondition[];
  219. /** If that issue has [filterMatch] of these properties */
  220. filterMatch: 'all' | 'any' | 'none';
  221. filters: IssueAlertRuleCondition[];
  222. frequency: number;
  223. name: string;
  224. environment?: null | string;
  225. owner?: string | null;
  226. }
  227. // Issue-based alert rule
  228. export interface IssueAlertRule extends UnsavedIssueAlertRule {
  229. createdBy: {email: string; id: number; name: string} | null;
  230. dateCreated: string;
  231. id: string;
  232. projects: string[];
  233. snooze: boolean;
  234. status: 'active' | 'disabled';
  235. /**
  236. * Date alert is set to be disabled unless action is taken
  237. */
  238. disableDate?: string;
  239. disableReason?: 'noisy';
  240. errors?: {detail: string}[];
  241. lastTriggered?: string;
  242. /**
  243. * Set to true to opt out of the rule being automatically disabled
  244. * see also - status=disabled, disableDate, disableReason
  245. * TODO(scttcper): This is only used in the edit request and we should
  246. * move it to its own interface
  247. */
  248. optOutEdit?: boolean;
  249. snoozeCreatedBy?: string;
  250. snoozeForEveryone?: boolean;
  251. }
  252. // Project's alert rule stats
  253. export type ProjectAlertRuleStats = {
  254. count: number;
  255. date: string;
  256. };
  257. export enum MailActionTargetType {
  258. ISSUE_OWNERS = 'IssueOwners',
  259. TEAM = 'Team',
  260. MEMBER = 'Member',
  261. RELEASE_MEMBERS = 'ReleaseMembers',
  262. }
  263. export enum AssigneeTargetType {
  264. UNASSIGNED = 'Unassigned',
  265. TEAM = 'Team',
  266. MEMBER = 'Member',
  267. }
  268. export type NoteType = {
  269. mentions: string[];
  270. text: string;
  271. };
  272. /**
  273. * Used when determining what types of actions a rule has. The default action is "sentry.mail.actions.NotifyEmailAction"
  274. * while other actions can be integration (Slack, PagerDuty, etc) actions. We need to know this to determine what kind of muting
  275. * the alert should have.
  276. */
  277. export enum RuleActionsCategories {
  278. ALL_DEFAULT = 'all_default',
  279. SOME_DEFAULT = 'some_default',
  280. NO_DEFAULT = 'no_default',
  281. }
  282. export enum MonitorType {
  283. CONTINUOUS = 0,
  284. ACTIVATED = 1,
  285. }
  286. export enum ActivationConditionType {
  287. RELEASE_CREATION = 0,
  288. DEPLOY_CREATION = 1,
  289. }
  290. export type AlertRuleActivation = {
  291. activator: string;
  292. alertRuleId: string;
  293. conditionType: string;
  294. dateCreated: string;
  295. finishedAt: string;
  296. id: string;
  297. isComplete: boolean;
  298. querySubscriptionId: string;
  299. metricValue?: number;
  300. };
  301. export enum ActivationTrigger {
  302. ACTIVATED = 'activated',
  303. FINISHED = 'finished',
  304. }
  305. export type ActivationTriggerActivity = {
  306. activator: string;
  307. conditionType: string;
  308. dateCreated: string;
  309. type: ActivationTrigger;
  310. };