diff --git a/static/app/views/alerts/list/rules/alertRuleStatus.tsx b/static/app/views/alerts/list/rules/alertRuleStatus.tsx
index e2c611038ccb2e..4af320f34067c1 100644
--- a/static/app/views/alerts/list/rules/alertRuleStatus.tsx
+++ b/static/app/views/alerts/list/rules/alertRuleStatus.tsx
@@ -69,6 +69,9 @@ export default function AlertRuleStatus({rule}: Props) {
? t('Above')
: t('Below');
+ // Anomaly detection alerts have different labels
+ const statusLabel = activeIncident ? t('Bad') : t('Good');
+
if (activeIncident) {
iconColor =
trigger?.label === AlertRuleTriggerType.CRITICAL
@@ -86,20 +89,26 @@ export default function AlertRuleStatus({rule}: Props) {
return (
-
-
- {`${thresholdTypeText} ${
- rule.latestIncident || (!rule.latestIncident && !resolvedTrigger)
- ? trigger?.alertThreshold?.toLocaleString()
- : resolvedTrigger?.toLocaleString()
- }`}
- {getThresholdUnits(
- rule.aggregate,
- rule.comparisonDelta
- ? AlertRuleComparisonType.CHANGE
- : AlertRuleComparisonType.COUNT
- )}
-
+ {rule.detectionType !== AlertRuleComparisonType.DYNAMIC && (
+
+ )}
+ {rule.detectionType !== AlertRuleComparisonType.DYNAMIC ? (
+
+ {`${thresholdTypeText} ${
+ rule.latestIncident || (!rule.latestIncident && !resolvedTrigger)
+ ? trigger?.alertThreshold?.toLocaleString()
+ : resolvedTrigger?.toLocaleString()
+ }`}
+ {getThresholdUnits(
+ rule.aggregate,
+ rule.comparisonDelta
+ ? AlertRuleComparisonType.CHANGE
+ : AlertRuleComparisonType.COUNT
+ )}
+
+ ) : (
+ {statusLabel}
+ )}
);
}
diff --git a/static/app/views/alerts/rules/metric/constants.tsx b/static/app/views/alerts/rules/metric/constants.tsx
index 55b89617864df4..faa94df601f961 100644
--- a/static/app/views/alerts/rules/metric/constants.tsx
+++ b/static/app/views/alerts/rules/metric/constants.tsx
@@ -172,7 +172,7 @@ export function createDefaultRule(
environment: null,
resolveThreshold: '',
thresholdType: AlertRuleThresholdType.ABOVE,
- detectionType: AlertRuleComparisonType.COUNT,
+ detectionType: AlertRuleComparisonType.STATIC,
...defaultRuleOptions,
};
}
diff --git a/static/app/views/alerts/rules/metric/details/sidebar.tsx b/static/app/views/alerts/rules/metric/details/sidebar.tsx
index 16cee54e67b558..7b0a63d12f2701 100644
--- a/static/app/views/alerts/rules/metric/details/sidebar.tsx
+++ b/static/app/views/alerts/rules/metric/details/sidebar.tsx
@@ -20,6 +20,7 @@ import {capitalize} from 'sentry/utils/string/capitalize';
import {COMPARISON_DELTA_OPTIONS} from 'sentry/views/alerts/rules/metric/constants';
import type {Action, MetricRule} from 'sentry/views/alerts/rules/metric/types';
import {
+ AlertRuleComparisonType,
AlertRuleThresholdType,
AlertRuleTriggerType,
} from 'sentry/views/alerts/rules/metric/types';
@@ -90,11 +91,13 @@ function TriggerDescription({
).label,
}
)
- : tct('[metric] is [condition] in [timeWindow]', {
- metric: metricName,
- condition: `${thresholdTypeText} ${threshold}`,
- timeWindow,
- });
+ : rule.detectionType === AlertRuleComparisonType.DYNAMIC
+ ? 'Dynamic threshold is reached'
+ : tct('[metric] is [condition] in [timeWindow]', {
+ metric: metricName,
+ condition: `${thresholdTypeText} ${threshold}`,
+ timeWindow,
+ });
return (
@@ -260,6 +263,30 @@ export function MetricDetailsSidebar({
teamActor ? : t('Unassigned')
}
/>
+ {rule.detectionType === AlertRuleComparisonType.DYNAMIC && (
+
+ )}
+ {rule.detectionType === AlertRuleComparisonType.DYNAMIC && (
+
+ {rule.thresholdType === AlertRuleThresholdType.ABOVE
+ ? 'Above threshold'
+ : rule.thresholdType === AlertRuleThresholdType.ABOVE_AND_BELOW
+ ? 'Above and below threshold'
+ : 'Below threshold'}
+
+ }
+ />
+ )}
diff --git a/static/app/views/alerts/rules/metric/ruleForm.tsx b/static/app/views/alerts/rules/metric/ruleForm.tsx
index 52f78c3963a06b..b0bb7d2d304c9a 100644
--- a/static/app/views/alerts/rules/metric/ruleForm.tsx
+++ b/static/app/views/alerts/rules/metric/ruleForm.tsx
@@ -938,7 +938,7 @@ class RuleFormContainer extends DeprecatedAsyncComponent {
? this.state.sensitivity || AlertRuleSensitivity.MEDIUM
: undefined;
const seasonality =
- value === AlertRuleComparisonType.DYNAMIC ? AlertRuleSeasonality.AUTO : undefined; // TODO: replace "auto" with the correct constant
+ value === AlertRuleComparisonType.DYNAMIC ? AlertRuleSeasonality.AUTO : undefined;
this.setState({
comparisonType: value,
comparisonDelta,
diff --git a/static/app/views/alerts/rules/metric/types.tsx b/static/app/views/alerts/rules/metric/types.tsx
index dce46532a68556..3bb2c0fc95f260 100644
--- a/static/app/views/alerts/rules/metric/types.tsx
+++ b/static/app/views/alerts/rules/metric/types.tsx
@@ -26,6 +26,7 @@ export enum AlertRuleComparisonType {
CHANGE = 'change',
PERCENT = 'percent',
DYNAMIC = 'dynamic',
+ STATIC = 'static',
}
export enum Dataset {