alerts.tsx 10 KB

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