Skip to content

Commit ab68219

Browse files
malwilleyandrewshie-sentry
authored andcommitted
feat(aci): Allow releases dataset to be saved for metric detector (#97506)
It turns out that the metrics dataset doesn't actually understand `crash_free_rate()` and we instead need to save `percentage(sessions_crashed, sessions) AS _crash_rate_alert_aggregate` for the aggregate. Since this doesn't work with the rest of the logic that expects the saved aggregate to match the labels, I decided to add some transformation functions to the dataset config that we can use to go between the user-friendly version and the one that's required from the endpoint.
1 parent f4a0c27 commit ab68219

19 files changed

+180
-28
lines changed

static/app/views/detectors/components/details/metric/detect.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import type {
1010
SnubaQueryDataSource,
1111
} from 'sentry/types/workflowEngine/detectors';
1212
import {getExactDuration} from 'sentry/utils/duration/getExactDuration';
13+
import {getDetectorDataset} from 'sentry/views/detectors/components/forms/metric/metricFormData';
14+
import {getDatasetConfig} from 'sentry/views/detectors/datasetConfig/getDatasetConfig';
1315

1416
interface MetricDetectorDetectProps {
1517
detector: MetricDetector;
@@ -20,13 +22,22 @@ function SnubaQueryDetails({dataSource}: {dataSource: SnubaQueryDataSource}) {
2022
return <Container>{t('Query not found.')}</Container>;
2123
}
2224

25+
const datasetConfig = getDatasetConfig(
26+
getDetectorDataset(
27+
dataSource.queryObj.snubaQuery.dataset,
28+
dataSource.queryObj.snubaQuery.eventTypes
29+
)
30+
);
31+
2332
return (
2433
<Container>
2534
<Flex direction="column" gap="xs">
2635
<Heading>{t('Query:')}</Heading>
2736
<Query>
2837
<Label>{t('visualize:')}</Label>
29-
<Value>{dataSource.queryObj.snubaQuery.aggregate}</Value>
38+
<Value>
39+
{datasetConfig.fromApiAggregate(dataSource.queryObj.snubaQuery.aggregate)}
40+
</Value>
3041
{dataSource.queryObj.snubaQuery.query && (
3142
<Fragment>
3243
<Label>{t('where:')}</Label>

static/app/views/detectors/components/forms/metric/metric.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import {EditDetectorLayout} from 'sentry/views/detectors/components/forms/editDe
3232
import type {MetricDetectorFormData} from 'sentry/views/detectors/components/forms/metric/metricFormData';
3333
import {
3434
DEFAULT_THRESHOLD_METRIC_FORM_DATA,
35-
DetectorDataset,
3635
METRIC_DETECTOR_FORM_FIELDS,
3736
metricDetectorFormDataToEndpointPayload,
3837
metricSavedDetectorToFormData,
@@ -44,6 +43,7 @@ import {Visualize} from 'sentry/views/detectors/components/forms/metric/visualiz
4443
import {NewDetectorLayout} from 'sentry/views/detectors/components/forms/newDetectorLayout';
4544
import {SectionLabel} from 'sentry/views/detectors/components/forms/sectionLabel';
4645
import {getDatasetConfig} from 'sentry/views/detectors/datasetConfig/getDatasetConfig';
46+
import {DetectorDataset} from 'sentry/views/detectors/datasetConfig/types';
4747
import {getResolutionDescription} from 'sentry/views/detectors/utils/getDetectorResolutionDescription';
4848
import {getStaticDetectorThresholdSuffix} from 'sentry/views/detectors/utils/metricDetectorSuffix';
4949

static/app/views/detectors/components/forms/metric/metricDetectorChart.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
AlertRuleThresholdType,
1616
TimePeriod,
1717
} from 'sentry/views/alerts/rules/metric/types';
18-
import type {DetectorDataset} from 'sentry/views/detectors/components/forms/metric/metricFormData';
18+
import type {DetectorDataset} from 'sentry/views/detectors/datasetConfig/types';
1919
import {useIncidentMarkers} from 'sentry/views/detectors/hooks/useIncidentMarkers';
2020
import {useMetricDetectorAnomalyPeriods} from 'sentry/views/detectors/hooks/useMetricDetectorAnomalyPeriods';
2121
import {useMetricDetectorSeries} from 'sentry/views/detectors/hooks/useMetricDetectorSeries';

static/app/views/detectors/components/forms/metric/metricFormData.tsx

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,15 @@ import {
2222
Dataset,
2323
EventTypes,
2424
} from 'sentry/views/alerts/rules/metric/types';
25+
import {getDatasetConfig} from 'sentry/views/detectors/datasetConfig/getDatasetConfig';
26+
import {DetectorDataset} from 'sentry/views/detectors/datasetConfig/types';
2527
import {getDetectorEnvironment} from 'sentry/views/detectors/utils/getDetectorEnvironment';
2628

27-
/**
28-
* Dataset types for detectors
29-
*/
30-
export const enum DetectorDataset {
31-
ERRORS = 'errors',
32-
TRANSACTIONS = 'transactions',
33-
SPANS = 'spans',
34-
RELEASES = 'releases',
35-
LOGS = 'logs',
36-
}
37-
3829
/**
3930
* Snuba query types that correspond to the backend SnubaQuery.Type enum.
4031
* These values are defined in src/sentry/snuba/models.py:
4132
*/
42-
const enum SnubaQueryType {
33+
export const enum SnubaQueryType {
4334
ERROR = 0,
4435
PERFORMANCE = 1,
4536
CRASH_RATE = 2,
@@ -319,11 +310,13 @@ function createDataSource(data: MetricDetectorFormData): NewDataSource {
319310
}
320311
};
321312

313+
const datasetConfig = getDatasetConfig(data.dataset);
314+
322315
return {
323316
queryType: getQueryType(data.dataset),
324317
dataset: getBackendDataset(data.dataset),
325318
query: data.query,
326-
aggregate: data.aggregateFunction,
319+
aggregate: datasetConfig.toApiAggregate(data.aggregateFunction),
327320
timeWindow: data.interval,
328321
environment: data.environment ? data.environment : null,
329322
eventTypes: getEventTypes(data.dataset),
@@ -449,6 +442,8 @@ export function metricSavedDetectorToFormData(
449442
? getDetectorDataset(snubaQuery.dataset, snubaQuery.eventTypes)
450443
: DetectorDataset.SPANS;
451444

445+
const datasetConfig = getDatasetConfig(dataset);
446+
452447
return {
453448
// Core detector fields
454449
name: detector.name,
@@ -458,7 +453,8 @@ export function metricSavedDetectorToFormData(
458453
owner: detector.owner || '',
459454
query: snubaQuery?.query || '',
460455
aggregateFunction:
461-
snubaQuery?.aggregate || DEFAULT_THRESHOLD_METRIC_FORM_DATA.aggregateFunction,
456+
datasetConfig.fromApiAggregate(snubaQuery?.aggregate || '') ||
457+
DEFAULT_THRESHOLD_METRIC_FORM_DATA.aggregateFunction,
462458
dataset,
463459
interval: snubaQuery?.timeWindow ?? DEFAULT_THRESHOLD_METRIC_FORM_DATA.interval,
464460

static/app/views/detectors/components/forms/metric/useIntervalChoices.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ import {useMemo} from 'react';
22

33
import getDuration from 'sentry/utils/duration/getDuration';
44
import {TimeWindow} from 'sentry/views/alerts/rules/metric/types';
5-
import {
6-
DetectorDataset,
7-
type MetricDetectorFormData,
8-
} from 'sentry/views/detectors/components/forms/metric/metricFormData';
5+
import {type MetricDetectorFormData} from 'sentry/views/detectors/components/forms/metric/metricFormData';
6+
import {DetectorDataset} from 'sentry/views/detectors/datasetConfig/types';
97

108
const baseIntervals: TimeWindow[] = [
119
TimeWindow.ONE_MINUTE,

static/app/views/detectors/components/forms/metric/visualize.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ import {unreachable} from 'sentry/utils/unreachable';
1717
import useOrganization from 'sentry/utils/useOrganization';
1818
import useTags from 'sentry/utils/useTags';
1919
import {
20-
DetectorDataset,
2120
METRIC_DETECTOR_FORM_FIELDS,
2221
useMetricDetectorFormField,
2322
} from 'sentry/views/detectors/components/forms/metric/metricFormData';
2423
import {DetectorQueryFilterBuilder} from 'sentry/views/detectors/components/forms/metric/queryFilterBuilder';
2524
import {SectionLabel} from 'sentry/views/detectors/components/forms/sectionLabel';
2625
import {getDatasetConfig} from 'sentry/views/detectors/datasetConfig/getDatasetConfig';
26+
import {DetectorDataset} from 'sentry/views/detectors/datasetConfig/types';
2727
import {useCustomMeasurements} from 'sentry/views/detectors/datasetConfig/useCustomMeasurements';
2828
import {
2929
useTraceItemNumberAttributes,

static/app/views/detectors/datasetConfig/base.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ export interface DetectorDatasetConfig<SeriesResponse> {
5858
* Default field to use when the dataset is first selected
5959
*/
6060
defaultField: QueryFieldValue;
61+
/**
62+
* Transform the aggregate function from the API response to a more user friendly title.
63+
* This is currently only used for the releases dataset.
64+
*/
65+
fromApiAggregate: (aggregate: string) => string;
6166
/**
6267
* Field options to display in the aggregate and field selectors
6368
*/
@@ -67,6 +72,11 @@ export interface DetectorDatasetConfig<SeriesResponse> {
6772
customMeasurements?: CustomMeasurementCollection
6873
) => Record<string, SelectValue<FieldValue>>;
6974
getSeriesQueryOptions: (options: DetectorSeriesQueryOptions) => ApiQueryKey;
75+
/**
76+
* Transform the user-friendly aggregate function to the API aggregate function.
77+
* This is currently only used for the releases dataset.
78+
*/
79+
toApiAggregate: (aggregate: string) => string;
7080
/**
7181
* Transform comparison series data for % change alerts
7282
*/

static/app/views/detectors/datasetConfig/errors.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,6 @@ export const DetectorErrorsConfig: DetectorDatasetConfig<ErrorsSeriesResponse> =
2727
transformComparisonSeriesData: data => {
2828
return [transformEventsStatsComparisonSeries(data)];
2929
},
30+
fromApiAggregate: aggregate => aggregate,
31+
toApiAggregate: aggregate => aggregate,
3032
};

static/app/views/detectors/datasetConfig/getDatasetConfig.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import {DetectorDataset} from 'sentry/views/detectors/components/forms/metric/metricFormData';
21
import {DetectorErrorsConfig} from 'sentry/views/detectors/datasetConfig/errors';
32
import {DetectorLogsConfig} from 'sentry/views/detectors/datasetConfig/logs';
43
import {DetectorReleasesConfig} from 'sentry/views/detectors/datasetConfig/releases';
54
import {DetectorSpansConfig} from 'sentry/views/detectors/datasetConfig/spans';
65
import {DetectorTransactionsConfig} from 'sentry/views/detectors/datasetConfig/transactions';
6+
import {DetectorDataset} from 'sentry/views/detectors/datasetConfig/types';
77

88
const DATASET_CONFIG_MAP = {
99
[DetectorDataset.ERRORS]: DetectorErrorsConfig,

static/app/views/detectors/datasetConfig/logs.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,6 @@ export const DetectorLogsConfig: DetectorDatasetConfig<LogsSeriesRepsonse> = {
2222
transformComparisonSeriesData: data => {
2323
return [transformEventsStatsComparisonSeries(data)];
2424
},
25+
fromApiAggregate: aggregate => aggregate,
26+
toApiAggregate: aggregate => aggregate,
2527
};

0 commit comments

Comments
 (0)