Skip to content

Commit

Permalink
feat(alerts): EAP alerts confidence refactor (#81730)
Browse files Browse the repository at this point in the history
Updates EAP Alerts to use `determineSeriesConfidence` +
`combineConfidence` instead of `isLowConfidenceTimeSeries`. Also renames
file to `determineSeriesConfidence.tsx` and cleans up unused confidence
attribute in events stats data bucket.
  • Loading branch information
edwardgou-sentry authored Dec 6, 2024
1 parent a825405 commit cf6da02
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 115 deletions.
3 changes: 0 additions & 3 deletions static/app/components/charts/eventsRequest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -462,9 +462,6 @@ class EventsRequest extends PureComponent<EventsRequestProps, EventsRequestState
data: data.map(([timestamp, countsForTimestamp]) => ({
name: timestamp * 1000,
value: countsForTimestamp.reduce((acc, {count}) => acc + count, 0) * scale,
...(countsForTimestamp[0]?.confidence
? {confidence: countsForTimestamp[0].confidence}
: {}),
})),
},
];
Expand Down
1 change: 0 additions & 1 deletion static/app/types/echarts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export type SeriesDataUnit = {
// number because we sometimes use timestamps
name: string | number;
value: number;
confidence?: Confidence;
itemStyle?: {
color?: string;
};
Expand Down
5 changes: 1 addition & 4 deletions static/app/types/organization.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -295,10 +295,7 @@ export type SavedQueryState = {

export type Confidence = 'high' | 'low' | null;

export type EventsStatsData = [
number,
{count: number; comparisonCount?: number; confidence?: Confidence}[],
][];
export type EventsStatsData = [number, {count: number; comparisonCount?: number}[]][];

export type ConfidenceStatsData = [number, {count: Confidence}[]][];

Expand Down
14 changes: 12 additions & 2 deletions static/app/views/alerts/rules/metric/ruleForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,13 @@ import RuleNameOwnerForm from 'sentry/views/alerts/rules/metric/ruleNameOwnerFor
import ThresholdTypeForm from 'sentry/views/alerts/rules/metric/thresholdTypeForm';
import Triggers from 'sentry/views/alerts/rules/metric/triggers';
import TriggersChart, {ErrorChart} from 'sentry/views/alerts/rules/metric/triggers/chart';
import {
determineMultiSeriesConfidence,
determineSeriesConfidence,
} from 'sentry/views/alerts/rules/metric/utils/determineSeriesConfidence';
import {getEventTypeFilter} from 'sentry/views/alerts/rules/metric/utils/getEventTypeFilter';
import hasThresholdValue from 'sentry/views/alerts/rules/metric/utils/hasThresholdValue';
import {isCustomMetricAlert} from 'sentry/views/alerts/rules/metric/utils/isCustomMetricAlert';
import {isLowConfidenceTimeSeries} from 'sentry/views/alerts/rules/metric/utils/isLowConfidenceTimeSeries';
import {isOnDemandMetricAlert} from 'sentry/views/alerts/rules/metric/utils/onDemandMetricAlert';
import {AlertRuleType, type Anomaly} from 'sentry/views/alerts/types';
import {ruleNeedsErrorMigration} from 'sentry/views/alerts/utils/migrationUi';
Expand All @@ -68,6 +71,7 @@ import {
DatasetMEPAlertQueryTypes,
} from 'sentry/views/alerts/wizard/options';
import {getAlertTypeFromAggregateDataset} from 'sentry/views/alerts/wizard/utils';
import {isEventsStats} from 'sentry/views/insights/common/queries/useSortedTimeSeries';
import {MetricsBetaEndAlert} from 'sentry/views/metrics/metricsBetaEndAlert';
import PermissionAlert from 'sentry/views/settings/project/permissionAlert';

Expand Down Expand Up @@ -1053,7 +1057,13 @@ class RuleFormContainer extends DeprecatedAsyncComponent<Props, State> {
handleConfidenceTimeSeriesDataFetched(
data: EventsStats | MultiSeriesEventsStats | null
) {
this.setState({isLowConfidenceChartData: isLowConfidenceTimeSeries(data)});
if (!data) {
return;
}
const confidence = isEventsStats(data)
? determineSeriesConfidence(data)
: determineMultiSeriesConfidence(data);
this.setState({isLowConfidenceChartData: confidence === 'low'});
}

handleHistoricalTimeSeriesDataFetched(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,92 +1,4 @@
import type {EventsStats, MultiSeriesEventsStats} from 'sentry/types/organization';
import {
determineSeriesConfidence,
isLowConfidenceTimeSeries,
} from 'sentry/views/alerts/rules/metric/utils/isLowConfidenceTimeSeries';

describe('isLowConfidenceTimeSeries', () => {
describe('EventsStats', () => {
it('should return false when no data points have low confidence', () => {
const eventsStats: EventsStats = {
data: [
[1731556800, [{count: 100}]],
[1731560400, [{count: 200}]],
],
confidence: [
[1731556800, [{count: 'high'}]],
[1731560400, [{count: 'high'}]],
],
};
expect(isLowConfidenceTimeSeries(eventsStats)).toBe(false);
});
it('should return true when any data points have low confidence', () => {
const eventsStats: EventsStats = {
data: [
[1731556800, [{count: 100}]],
[1731560400, [{count: 200}]],
],
confidence: [
[1731556800, [{count: 'low'}]],
[1731560400, [{count: 'high'}]],
],
};
expect(isLowConfidenceTimeSeries(eventsStats)).toBe(true);
});
});

describe('MultiSeriesEventsStats', () => {
it('should return false when no data points have low confidence', () => {
const multiSeriesEventsStats: MultiSeriesEventsStats = {
a: {
data: [
[1731556800, [{count: 100}]],
[1731560400, [{count: 200}]],
],
confidence: [
[1731556800, [{count: 'high'}]],
[1731560400, [{count: 'high'}]],
],
},
b: {
data: [
[1731556800, [{count: 100}]],
[1731560400, [{count: 200}]],
],
confidence: [
[1731556800, [{count: 'high'}]],
[1731560400, [{count: 'high'}]],
],
},
};
expect(isLowConfidenceTimeSeries(multiSeriesEventsStats)).toBe(false);
});
it('should return true when any data points have low confidence', () => {
const multiSeriesEventsStats: MultiSeriesEventsStats = {
a: {
data: [
[1731556800, [{count: 100}]],
[1731560400, [{count: 200}]],
],
confidence: [
[1731556800, [{count: 'low'}]],
[1731560400, [{count: 'high'}]],
],
},
b: {
data: [
[1731556800, [{count: 100}]],
[1731560400, [{count: 200}]],
],
confidence: [
[1731556800, [{count: 'high'}]],
[1731560400, [{count: 'high'}]],
],
},
};
expect(isLowConfidenceTimeSeries(multiSeriesEventsStats)).toBe(true);
});
});
});
import {determineSeriesConfidence} from 'sentry/views/alerts/rules/metric/utils/determineSeriesConfidence';

describe('determineSeriesConfidence', () => {
it('equal null if no data', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,6 @@ import type {
MultiSeriesEventsStats,
} from 'sentry/types/organization';
import {defined} from 'sentry/utils';
import {isEventsStats} from 'sentry/views/insights/common/queries/useSortedTimeSeries';

// Returns true if any of the time series are low confidence
export function isLowConfidenceTimeSeries(
data: EventsStats | MultiSeriesEventsStats | null
) {
if (data) {
if (isEventsStats(data)) {
return determineSeriesConfidence(data) === 'low';
}
return Object.values(data).some(d => determineSeriesConfidence(d) === 'low');
}
return false;
}

// Timeseries with more than this ratio of low confidence intervals will be considered low confidence
const LOW_CONFIDENCE_THRESHOLD = 0.25;
Expand Down Expand Up @@ -63,7 +49,18 @@ export function determineSeriesConfidence(
return 'high';
}

function combineConfidence(a: Confidence, b: Confidence): Confidence {
export function determineMultiSeriesConfidence(
data: MultiSeriesEventsStats,
threshold = LOW_CONFIDENCE_THRESHOLD
): Confidence {
return Object.values(data).reduce(
(acc, eventsStats) =>
combineConfidence(acc, determineSeriesConfidence(eventsStats, threshold)),
null as Confidence
);
}

export function combineConfidence(a: Confidence, b: Confidence): Confidence {
if (!defined(a)) {
return b;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import type {MutableSearch} from 'sentry/utils/tokenizeSearch';
import {useLocation} from 'sentry/utils/useLocation';
import useOrganization from 'sentry/utils/useOrganization';
import usePageFilters from 'sentry/utils/usePageFilters';
import {determineSeriesConfidence} from 'sentry/views/alerts/rules/metric/utils/isLowConfidenceTimeSeries';
import {determineSeriesConfidence} from 'sentry/views/alerts/rules/metric/utils/determineSeriesConfidence';
import {getSeriesEventView} from 'sentry/views/insights/common/queries/getSeriesEventView';
import type {SpanFunctions, SpanIndexedField} from 'sentry/views/insights/types';

Expand Down

0 comments on commit cf6da02

Please sign in to comment.