Skip to content

Commit 9cebd49

Browse files
authored
fix: anomaly with below operator negates the target (#9288)
1 parent a22ef64 commit 9cebd49

File tree

4 files changed

+367
-11
lines changed

4 files changed

+367
-11
lines changed

ee/anomaly/seasonal.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ func (p *BaseSeasonalProvider) getPredictedSeries(
232232
// moving avg of the previous period series + z score threshold * std dev of the series
233233
// moving avg of the previous period series - z score threshold * std dev of the series
234234
func (p *BaseSeasonalProvider) getBounds(
235-
series, predictedSeries *qbtypes.TimeSeries,
235+
series, predictedSeries, weekSeries *qbtypes.TimeSeries,
236236
zScoreThreshold float64,
237237
) (*qbtypes.TimeSeries, *qbtypes.TimeSeries) {
238238
upperBoundSeries := &qbtypes.TimeSeries{
@@ -246,8 +246,8 @@ func (p *BaseSeasonalProvider) getBounds(
246246
}
247247

248248
for idx, curr := range series.Values {
249-
upperBound := p.getMovingAvg(predictedSeries, movingAvgWindowSize, idx) + zScoreThreshold*p.getStdDev(series)
250-
lowerBound := p.getMovingAvg(predictedSeries, movingAvgWindowSize, idx) - zScoreThreshold*p.getStdDev(series)
249+
upperBound := p.getMovingAvg(predictedSeries, movingAvgWindowSize, idx) + zScoreThreshold*p.getStdDev(weekSeries)
250+
lowerBound := p.getMovingAvg(predictedSeries, movingAvgWindowSize, idx) - zScoreThreshold*p.getStdDev(weekSeries)
251251
upperBoundSeries.Values = append(upperBoundSeries.Values, &qbtypes.TimeSeriesValue{
252252
Timestamp: curr.Timestamp,
253253
Value: upperBound,
@@ -398,15 +398,16 @@ func (p *BaseSeasonalProvider) getAnomalies(ctx context.Context, orgID valuer.UU
398398
aggOfInterest := result.Aggregations[0]
399399

400400
for _, series := range aggOfInterest.Series {
401-
stdDev := p.getStdDev(series)
402-
p.logger.InfoContext(ctx, "calculated standard deviation for series", "anomaly_std_dev", stdDev, "anomaly_labels", series.Labels)
403401

404402
pastPeriodSeries := p.getMatchingSeries(ctx, pastPeriodResult, series)
405403
currentSeasonSeries := p.getMatchingSeries(ctx, currentSeasonResult, series)
406404
pastSeasonSeries := p.getMatchingSeries(ctx, pastSeasonResult, series)
407405
past2SeasonSeries := p.getMatchingSeries(ctx, past2SeasonResult, series)
408406
past3SeasonSeries := p.getMatchingSeries(ctx, past3SeasonResult, series)
409407

408+
stdDev := p.getStdDev(currentSeasonSeries)
409+
p.logger.InfoContext(ctx, "calculated standard deviation for series", "anomaly_std_dev", stdDev, "anomaly_labels", series.Labels)
410+
410411
prevSeriesAvg := p.getAvg(pastPeriodSeries)
411412
currentSeasonSeriesAvg := p.getAvg(currentSeasonSeries)
412413
pastSeasonSeriesAvg := p.getAvg(pastSeasonSeries)
@@ -435,6 +436,7 @@ func (p *BaseSeasonalProvider) getAnomalies(ctx context.Context, orgID valuer.UU
435436
upperBoundSeries, lowerBoundSeries := p.getBounds(
436437
series,
437438
predictedSeries,
439+
currentSeasonSeries,
438440
zScoreThreshold,
439441
)
440442
aggOfInterest.UpperBoundSeries = append(aggOfInterest.UpperBoundSeries, upperBoundSeries)

ee/query-service/rules/anomaly.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,6 @@ func NewAnomalyRule(
7878

7979
opts = append(opts, baserules.WithLogger(logger))
8080

81-
if p.RuleCondition.CompareOp == ruletypes.ValueIsBelow {
82-
target := -1 * *p.RuleCondition.Target
83-
p.RuleCondition.Target = &target
84-
}
85-
8681
baseRule, err := baserules.NewBaseRule(id, orgID, p, reader, opts...)
8782
if err != nil {
8883
return nil, err

pkg/types/ruletypes/api_params.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ func (r *PostableRule) processRuleDefaults() error {
207207
q.Expression = qLabel
208208
}
209209
}
210+
210211
//added alerts v2 fields
211212
if r.SchemaVersion == DefaultSchemaVersion {
212213
thresholdName := CriticalThresholdName
@@ -215,12 +216,20 @@ func (r *PostableRule) processRuleDefaults() error {
215216
thresholdName = severity
216217
}
217218
}
219+
220+
// For anomaly detection with ValueIsBelow, negate the target
221+
targetValue := r.RuleCondition.Target
222+
if r.RuleType == RuleTypeAnomaly && r.RuleCondition.CompareOp == ValueIsBelow && targetValue != nil {
223+
negated := -1 * *targetValue
224+
targetValue = &negated
225+
}
226+
218227
thresholdData := RuleThresholdData{
219228
Kind: BasicThresholdKind,
220229
Spec: BasicRuleThresholds{{
221230
Name: thresholdName,
222231
TargetUnit: r.RuleCondition.TargetUnit,
223-
TargetValue: r.RuleCondition.Target,
232+
TargetValue: targetValue,
224233
MatchType: r.RuleCondition.MatchType,
225234
CompareOp: r.RuleCondition.CompareOp,
226235
Channels: r.PreferredChannels,

0 commit comments

Comments
 (0)