Browse Source

feat(alerts): Handle % change alert incident reason text (#53819)

Scott Cooper 1 year ago
parent
commit
eb2b12d99f

+ 12 - 1
static/app/views/alerts/rules/metric/details/metricHistory.spec.tsx

@@ -13,10 +13,21 @@ describe('MetricHistory', () => {
   it('renders a critical incident', () => {
     render(<MetricHistory incidents={[TestStubs.Incident()]} />);
     expect(screen.getByRole('link', {name: '#123'})).toBeInTheDocument();
-    expect(screen.getByText('Number of Errors above 70')).toBeInTheDocument();
+    expect(screen.getByText('Number of errors above 70 in 1 hour')).toBeInTheDocument();
     expect(screen.getByText('12hr')).toBeInTheDocument();
   });
 
+  it('renders a critical % change incident', () => {
+    const incident = TestStubs.Incident();
+    incident.alertRule.comparisonDelta = 60;
+    render(<MetricHistory incidents={[incident]} />);
+    expect(
+      screen.getByText(
+        'Number of errors 70% higher in 1 hour compared to the same time one hour ago'
+      )
+    ).toBeInTheDocument();
+  });
+
   it('collapses the incidents panel if the number of incidents > 3', async () => {
     const incidents = range(0, 10).map(id =>
       TestStubs.Incident({id: `${id}`, identifier: `${id}`})

+ 30 - 5
static/app/views/alerts/rules/metric/details/metricHistory.tsx

@@ -1,6 +1,7 @@
 import {Fragment} from 'react';
 import {css} from '@emotion/react';
 import styled from '@emotion/styled';
+import capitalize from 'lodash/capitalize';
 import moment from 'moment-timezone';
 
 import CollapsePanel from 'sentry/components/collapsePanel';
@@ -12,8 +13,10 @@ import StatusIndicator from 'sentry/components/statusIndicator';
 import {t, tn} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
 import type {Organization} from 'sentry/types';
+import {getDuration} from 'sentry/utils/formatters';
 import getDynamicText from 'sentry/utils/getDynamicText';
 import useOrganization from 'sentry/utils/useOrganization';
+import {COMPARISON_DELTA_OPTIONS} from 'sentry/views/alerts/rules/metric/constants';
 import {AlertRuleThresholdType} from 'sentry/views/alerts/rules/metric/types';
 import type {ActivityType} from 'sentry/views/alerts/types';
 import {Incident, IncidentActivityType, IncidentStatus} from 'sentry/views/alerts/types';
@@ -56,6 +59,10 @@ function MetricAlertActivity({organization, incident}: MetricAlertActivityProps)
   const curentTrigger = incident.alertRule.triggers.find(
     trigger => trigger.label === triggerLabel
   );
+  const timeWindow = getDuration(incident.alertRule.timeWindow * 60);
+  const alertName = capitalize(
+    AlertWizardAlertNames[getAlertTypeFromAggregateDataset(incident.alertRule)]
+  );
 
   return (
     <Fragment>
@@ -76,11 +83,29 @@ function MetricAlertActivity({organization, incident}: MetricAlertActivityProps)
         </Link>
       </Cell>
       <Cell>
-        {AlertWizardAlertNames[getAlertTypeFromAggregateDataset(incident.alertRule)]}{' '}
-        {incident.alertRule.thresholdType === AlertRuleThresholdType.ABOVE
-          ? t('above')
-          : t('below')}{' '}
-        {curentTrigger?.alertThreshold}
+        {incident.alertRule.comparisonDelta ? (
+          <Fragment>
+            {alertName} {curentTrigger?.alertThreshold}%
+            {t(
+              ' %s in %s compared to the ',
+              incident.alertRule.thresholdType === AlertRuleThresholdType.ABOVE
+                ? t('higher')
+                : t('lower'),
+              timeWindow
+            )}
+            {COMPARISON_DELTA_OPTIONS.find(
+              ({value}) => value === incident.alertRule.comparisonDelta
+            )?.label ?? COMPARISON_DELTA_OPTIONS[0].label}
+          </Fragment>
+        ) : (
+          <Fragment>
+            {alertName}{' '}
+            {incident.alertRule.thresholdType === AlertRuleThresholdType.ABOVE
+              ? t('above')
+              : t('below')}{' '}
+            {curentTrigger?.alertThreshold} {t('in')} {timeWindow}
+          </Fragment>
+        )}
       </Cell>
       <Cell>
         {activityDuration &&

+ 7 - 3
static/app/views/alerts/rules/metric/details/sidebar.tsx

@@ -1,5 +1,6 @@
 import {Fragment} from 'react';
 import styled from '@emotion/styled';
+import capitalize from 'lodash/capitalize';
 
 import AlertBadge from 'sentry/components/alertBadge';
 import ActorAvatar from 'sentry/components/avatar/actorAvatar';
@@ -68,12 +69,15 @@ function TriggerDescription({
     ? t('lower')
     : t('below');
   const timeWindow = <Duration seconds={rule.timeWindow * 60} />;
+  const metricName = capitalize(
+    AlertWizardAlertNames[getAlertTypeFromAggregateDataset(rule)]
+  );
 
   const thresholdText = rule.comparisonDelta
     ? tct(
-        '[metric] is [threshold]% [comparisonType] in [timeWindow] compared to [comparisonDelta]',
+        '[metric] is [threshold]% [comparisonType] in [timeWindow] compared to the [comparisonDelta]',
         {
-          metric: AlertWizardAlertNames[getAlertTypeFromAggregateDataset(rule)],
+          metric: metricName,
           threshold,
           comparisonType: thresholdTypeText,
           timeWindow,
@@ -84,7 +88,7 @@ function TriggerDescription({
         }
       )
     : tct('[metric] is [condition] in [timeWindow]', {
-        metric: AlertWizardAlertNames[getAlertTypeFromAggregateDataset(rule)],
+        metric: metricName,
         condition: `${thresholdTypeText} ${threshold}`,
         timeWindow,
       });