Skip to content

feat(aci): Edit detector form #93579

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Jun 17, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
bc10e7b
feat(aci): Allow submitting detector form
scttcper Jun 11, 2025
64292e9
more support for new detector
scttcper Jun 12, 2025
a2dbcc2
fix priority tests
scttcper Jun 12, 2025
04485f6
type error
scttcper Jun 12, 2025
e38e7b2
Merge branch 'master' into scttcper/submit-detector-form
scttcper Jun 12, 2025
631eddc
add DetectorPriorityLevel with numbers
scttcper Jun 13, 2025
a4a2b7f
use DataConditionType
scttcper Jun 13, 2025
41bda89
add more DataConditionType
scttcper Jun 13, 2025
31ebe5d
template, more enum
scttcper Jun 13, 2025
6fecd84
reuse types
scttcper Jun 13, 2025
96c40b8
consolidate createConditions
scttcper Jun 13, 2025
9d8a3e9
feat(aci): Submit edit detector form
scttcper Jun 14, 2025
899e7d4
fix loading state
scttcper Jun 14, 2025
57f4708
Merge branch 'master' into scttcper/submit-detector-form
scttcper Jun 16, 2025
309b45c
preserve value when switching between kinds
scttcper Jun 16, 2025
eb27bac
Merge branch 'scttcper/submit-detector-form' into scttcper/edit-detec…
scttcper Jun 16, 2025
dce2f03
Merge branch 'master' into scttcper/edit-detector-form
scttcper Jun 16, 2025
2e9f5d4
rename detector type
scttcper Jun 16, 2025
3512dea
three dot unicode
scttcper Jun 16, 2025
ac8467a
setup detector configs
scttcper Jun 16, 2025
5f38734
remove exports
scttcper Jun 16, 2025
42e5612
remove comparison type, breaking too many types
scttcper Jun 16, 2025
2ac194b
switch to parseFunction from discover
scttcper Jun 16, 2025
4b86929
set minimum priority
scttcper Jun 16, 2025
9241551
fix type error
scttcper Jun 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
use DataConditionType
  • Loading branch information
scttcper committed Jun 13, 2025
commit a4a2b7f4ccd7c21b531e65ba13b6c0c3c9a98e46
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ import Form from 'sentry/components/forms/form';
import FormModel from 'sentry/components/forms/model';
import PriorityControl from 'sentry/components/workflowEngine/form/control/priorityControl';
import {DetectorPriorityLevel} from 'sentry/types/workflowEngine/dataConditions';
import {METRIC_DETECTOR_FORM_FIELDS} from 'sentry/views/detectors/components/forms/metricFormData';
import {
DEFAULT_THRESHOLD_METRIC_FORM_DATA,
METRIC_DETECTOR_FORM_FIELDS,
} from 'sentry/views/detectors/components/forms/metricFormData';

describe('PriorityControl', function () {
it('renders children', async function () {
const formModel = new FormModel({
initialData: {
...DEFAULT_THRESHOLD_METRIC_FORM_DATA,
[METRIC_DETECTOR_FORM_FIELDS.initialPriorityLevel]: DetectorPriorityLevel.LOW,
[METRIC_DETECTOR_FORM_FIELDS.conditionType]: 'gt',
[METRIC_DETECTOR_FORM_FIELDS.conditionValue]: '0',
[METRIC_DETECTOR_FORM_FIELDS.mediumThreshold]: '',
[METRIC_DETECTOR_FORM_FIELDS.highThreshold]: '',
},
});
render(
Expand All @@ -31,11 +31,8 @@ describe('PriorityControl', function () {
it('allows configuring priority', async function () {
const formModel = new FormModel({
initialData: {
...DEFAULT_THRESHOLD_METRIC_FORM_DATA,
[METRIC_DETECTOR_FORM_FIELDS.initialPriorityLevel]: DetectorPriorityLevel.LOW,
[METRIC_DETECTOR_FORM_FIELDS.conditionType]: 'gt',
[METRIC_DETECTOR_FORM_FIELDS.conditionValue]: '0',
[METRIC_DETECTOR_FORM_FIELDS.mediumThreshold]: '',
[METRIC_DETECTOR_FORM_FIELDS.highThreshold]: '',
},
});
render(
Expand All @@ -59,11 +56,8 @@ describe('PriorityControl', function () {
it('allows configuring medium and high thresholds', async function () {
const formModel = new FormModel({
initialData: {
...DEFAULT_THRESHOLD_METRIC_FORM_DATA,
[METRIC_DETECTOR_FORM_FIELDS.initialPriorityLevel]: DetectorPriorityLevel.LOW,
[METRIC_DETECTOR_FORM_FIELDS.conditionType]: 'gt',
[METRIC_DETECTOR_FORM_FIELDS.conditionValue]: '0',
[METRIC_DETECTOR_FORM_FIELDS.mediumThreshold]: '',
[METRIC_DETECTOR_FORM_FIELDS.highThreshold]: '',
},
});
render(
Expand All @@ -84,11 +78,8 @@ describe('PriorityControl', function () {
it('filters priority options based on minimumPriority prop', async function () {
const formModel = new FormModel({
initialData: {
...DEFAULT_THRESHOLD_METRIC_FORM_DATA,
[METRIC_DETECTOR_FORM_FIELDS.initialPriorityLevel]: DetectorPriorityLevel.MEDIUM,
[METRIC_DETECTOR_FORM_FIELDS.conditionType]: 'gt',
[METRIC_DETECTOR_FORM_FIELDS.conditionValue]: '0',
[METRIC_DETECTOR_FORM_FIELDS.mediumThreshold]: '',
[METRIC_DETECTOR_FORM_FIELDS.highThreshold]: '',
},
});

Expand Down
94 changes: 55 additions & 39 deletions static/app/views/detectors/components/forms/metric.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {IconAdd} from 'sentry/icons';
import {t} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import type {TagCollection} from 'sentry/types/group';
import {DataConditionType} from 'sentry/types/workflowEngine/dataConditions';
import {
ALLOWED_EXPLORE_VISUALIZE_AGGREGATES,
FieldKey,
Expand All @@ -27,6 +28,7 @@ import {
AlertRuleSensitivity,
AlertRuleThresholdType,
} from 'sentry/views/alerts/rules/metric/types';
import type {MetricDetectorFormData} from 'sentry/views/detectors/components/forms/metricFormData';
import {
METRIC_DETECTOR_FORM_FIELDS,
useMetricDetectorFormField,
Expand All @@ -45,26 +47,28 @@ export function MetricDetectorForm() {
}

function MonitorKind() {
const options: Array<[MetricDetectorFormData['kind'], string, string]> = [
[
'threshold',
t('Threshold'),
t('Absolute-valued thresholds, for non-seasonal data.'),
],
['change', t('Change'), t('Percentage changes over defined time windows.')],
[
'dynamic',
t('Dynamic'),
t('Auto-detect anomalies and mean deviation, for seasonal/noisy data.'),
],
];

return (
<MonitorKindField
label={t('...and monitor for changes in the following way:')}
flexibleControlStateSize
inline={false}
name={METRIC_DETECTOR_FORM_FIELDS.kind}
defaultValue="threshold"
choices={[
[
'threshold',
t('Threshold'),
t('Absolute-valued thresholds, for non-seasonal data.'),
],
['change', t('Change'), t('Percentage changes over defined time windows.')],
[
'dynamic',
t('Dynamic'),
t('Auto-detect anomalies and mean deviation, for seasonal/noisy data.'),
],
]}
choices={options}
/>
);
}
Expand Down Expand Up @@ -203,10 +207,12 @@ function DetectSection() {
flexibleControlStateSize
// For some reason, not setting a default value empties the form field
defaultValue={conditionType}
choices={[
['gt', t('Above')],
['lte', t('Below')],
]}
choices={
[
[DataConditionType.GREATER, t('Above')],
[DataConditionType.LESS, t('Below')],
] satisfies Array<[MetricDetectorFormData['conditionType'], string]>
}
required
/>
<ThresholdField
Expand Down Expand Up @@ -240,10 +246,12 @@ function DetectSection() {
flexibleControlStateSize
// For some reason, not setting a default value empties the form field
defaultValue={conditionType}
choices={[
['gt', t('higher')],
['lt', t('lower')],
]}
choices={
[
[DataConditionType.GREATER, t('higher')],
[DataConditionType.LESS, t('lower')],
] satisfies Array<[MetricDetectorFormData['conditionType'], string]>
}
required
/>
<span>{t('than the previous')}</span>
Expand All @@ -252,14 +260,18 @@ function DetectSection() {
hideLabel
inline
flexibleControlStateSize
choices={[
[5 * 60, '5 minutes'],
[15 * 60, '15 minutes'],
[60 * 60, '1 hour'],
[24 * 60 * 60, '1 day'],
[7 * 24 * 60 * 60, '1 week'],
[30 * 24 * 60 * 60, '1 month'],
]}
choices={
[
[5 * 60, '5 minutes'],
[15 * 60, '15 minutes'],
[60 * 60, '1 hour'],
[24 * 60 * 60, '1 day'],
[7 * 24 * 60 * 60, '1 week'],
[30 * 24 * 60 * 60, '1 month'],
] satisfies Array<
[MetricDetectorFormData['conditionComparisonAgo'], string]
>
}
required
/>
</Flex>
Expand All @@ -274,11 +286,13 @@ function DetectSection() {
help={t(
'Choose your level of anomaly responsiveness. Higher thresholds means alerts for most anomalies. Lower thresholds means alerts only for larger ones.'
)}
choices={[
[AlertRuleSensitivity.HIGH, t('High')],
[AlertRuleSensitivity.MEDIUM, t('Medium')],
[AlertRuleSensitivity.LOW, t('Low')],
]}
choices={
[
[AlertRuleSensitivity.HIGH, t('High')],
[AlertRuleSensitivity.MEDIUM, t('Medium')],
[AlertRuleSensitivity.LOW, t('Low')],
] satisfies Array<[MetricDetectorFormData['sensitivity'], string]>
}
/>
<SelectField
required
Expand All @@ -287,11 +301,13 @@ function DetectSection() {
help={t(
'Decide if you want to be alerted to anomalies that are moving above, below, or in both directions in relation to your threshold.'
)}
choices={[
[AlertRuleThresholdType.ABOVE, t('Above')],
[AlertRuleThresholdType.ABOVE_AND_BELOW, t('Above and Below')],
[AlertRuleThresholdType.BELOW, t('Below')],
]}
choices={
[
[AlertRuleThresholdType.ABOVE, t('Above')],
[AlertRuleThresholdType.ABOVE_AND_BELOW, t('Above and Below')],
[AlertRuleThresholdType.BELOW, t('Below')],
] satisfies Array<[MetricDetectorFormData['thresholdType'], string]>
}
/>
</Flex>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ interface MetricDetectorConditionFormData {
/**
* Both kind=threshold and kind=change
*/
conditionType?: 'gt' | 'lte';
conditionType?: DataConditionType.GREATER | DataConditionType.LESS;
/**
* When this value is exceeded the issue is created at initialPriorityLevel
* Both kind=threshold and kind=change
Expand Down Expand Up @@ -105,7 +105,7 @@ export const DEFAULT_THRESHOLD_METRIC_FORM_DATA = {
// Priority level fields
// Metric detectors only support MEDIUM and HIGH priority levels
initialPriorityLevel: DetectorPriorityLevel.MEDIUM,
conditionType: 'gt',
conditionType: DataConditionType.GREATER,
conditionValue: '',
conditionComparisonAgo: 60 * 60, // One hour in seconds
resolveThreshold: '',
Expand Down