Browse Source

feat(alerts): Get latest incident with alert rule (#33557)

Scott Cooper 2 years ago
parent
commit
6310685b67

+ 8 - 2
static/app/views/alerts/incidentRules/types.tsx

@@ -1,6 +1,8 @@
 import {t} from 'sentry/locale';
 import type {SchemaFormConfig} from 'sentry/views/organizationIntegrations/sentryAppExternalForm';
 
+import type {Incident} from '../types';
+
 export enum AlertRuleThresholdType {
   ABOVE,
   BELOW,
@@ -91,7 +93,7 @@ export type UnsavedIncidentRule = {
   owner?: string | null;
 };
 
-export type SavedIncidentRule = UnsavedIncidentRule & {
+export interface SavedIncidentRule extends UnsavedIncidentRule {
   dateCreated: string;
   dateModified: string;
   id: string;
@@ -99,8 +101,12 @@ export type SavedIncidentRule = UnsavedIncidentRule & {
   status: number;
   createdBy?: {email: string; id: number; name: string} | null;
   errors?: {detail: string}[];
+  /**
+   * Returned with the expand=latestIncident query parameter
+   */
+  latestIncident?: Incident | null;
   originalAlertRuleId?: number | null;
-};
+}
 
 export type IncidentRule = Partial<SavedIncidentRule> & UnsavedIncidentRule;
 

+ 1 - 1
static/app/views/alerts/rules/details/body.tsx

@@ -236,7 +236,7 @@ export default class DetailsBody extends React.Component<Props> {
             </DetailWrapper>
           </Layout.Main>
           <Layout.Side>
-            <Sidebar incidents={incidents} rule={rule} />
+            <Sidebar rule={rule} />
           </Layout.Side>
         </Layout.Body>
       </React.Fragment>

+ 1 - 1
static/app/views/alerts/rules/details/index.tsx

@@ -146,7 +146,7 @@ class MetricAlertDetails extends Component<Props, State> {
     const rulePromise =
       ruleId === this.state.rule?.id
         ? Promise.resolve(this.state.rule)
-        : fetchAlertRule(orgId, ruleId);
+        : fetchAlertRule(orgId, ruleId, {expand: 'latestIncident'});
 
     // Fetch selected incident, if it exists. We need this to set the selected date range
     let selectedIncident: Incident | null = null;

+ 8 - 14
static/app/views/alerts/rules/details/sidebar.tsx

@@ -24,12 +24,11 @@ import {
 import {AlertWizardAlertNames} from 'sentry/views/alerts/wizard/options';
 import {getAlertTypeFromAggregateDataset} from 'sentry/views/alerts/wizard/utils';
 
-import {Incident, IncidentStatus} from '../../types';
+import {IncidentStatus} from '../../types';
 
-type Props = {
+interface Props {
   rule: IncidentRule;
-  incidents?: Incident[];
-};
+}
 
 export default class Sidebar extends PureComponent<Props> {
   getTimeWindow(): ReactNode {
@@ -125,19 +124,14 @@ export default class Sidebar extends PureComponent<Props> {
   }
 
   render() {
-    const {incidents, rule} = this.props;
+    const {rule} = this.props;
 
     // get current status
-    const activeIncident = incidents?.find(({dateClosed}) => !dateClosed);
-    const status = activeIncident ? activeIncident.status : IncidentStatus.CLOSED;
-
-    const latestIncident = incidents?.length ? incidents[0] : null;
+    const latestIncident = rule.latestIncident;
+    const status = latestIncident ? latestIncident.status : IncidentStatus.CLOSED;
     // The date at which the alert was triggered or resolved
-    const activityDate = activeIncident
-      ? activeIncident.dateStarted
-      : latestIncident
-      ? latestIncident.dateClosed
-      : null;
+    const activityDate =
+      latestIncident?.dateClosed ?? latestIncident?.dateStarted ?? null;
 
     const criticalTrigger = rule?.triggers.find(
       ({label}) => label === AlertRuleTriggerType.CRITICAL

+ 7 - 2
static/app/views/alerts/utils/index.tsx

@@ -21,9 +21,14 @@ import {AlertRuleStatus, Incident, IncidentStats} from '../types';
 // Use this api for requests that are getting cancelled
 const uncancellableApi = new Client();
 
-export function fetchAlertRule(orgId: string, ruleId: string): Promise<IncidentRule> {
+export function fetchAlertRule(
+  orgId: string,
+  ruleId: string,
+  query?: Record<string, string>
+): Promise<IncidentRule> {
   return uncancellableApi.requestPromise(
-    `/organizations/${orgId}/alert-rules/${ruleId}/`
+    `/organizations/${orgId}/alert-rules/${ruleId}/`,
+    {query}
   );
 }
 

+ 4 - 1
tests/js/spec/views/alerts/rules/details.spec.tsx

@@ -37,8 +37,11 @@ describe('MetricAlertDetails', () => {
 
   it('renders', async () => {
     const {routerContext, organization, router} = initializeOrg();
-    const rule = TestStubs.IncidentRule({projects: [project.slug]});
     const incident = TestStubs.Incident();
+    const rule = TestStubs.IncidentRule({
+      projects: [project.slug],
+      latestIncident: incident,
+    });
 
     MockApiClient.addMockResponse({
       url: `/organizations/org-slug/alert-rules/${rule.id}/`,