fix: window size for small time ranges (#6964)

This commit is contained in:
Srikanth Chekuri 2025-01-29 14:47:47 +05:30 committed by GitHub
parent ea83a7e62d
commit 333f90d8ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 20 additions and 16 deletions

View File

@ -59,7 +59,7 @@ type anomalyQueryParams struct {
// The results obtained from this query are used to compare with predicted values // The results obtained from this query are used to compare with predicted values
// and to detect anomalies // and to detect anomalies
CurrentPeriodQuery *v3.QueryRangeParamsV3 CurrentPeriodQuery *v3.QueryRangeParamsV3
// PastPeriodQuery is the query range params for past seasonal period // PastPeriodQuery is the query range params for past period of seasonality
// Example: For weekly seasonality, (now-1w-5m, now-1w) // Example: For weekly seasonality, (now-1w-5m, now-1w)
// : For daily seasonality, (now-1d-5m, now-1d) // : For daily seasonality, (now-1d-5m, now-1d)
// : For hourly seasonality, (now-1h-5m, now-1h) // : For hourly seasonality, (now-1h-5m, now-1h)
@ -74,7 +74,6 @@ type anomalyQueryParams struct {
// : For daily seasonality, this is the query range params for the (now-2d-5m, now-1d) // : For daily seasonality, this is the query range params for the (now-2d-5m, now-1d)
// : For hourly seasonality, this is the query range params for the (now-2h-5m, now-1h) // : For hourly seasonality, this is the query range params for the (now-2h-5m, now-1h)
PastSeasonQuery *v3.QueryRangeParamsV3 PastSeasonQuery *v3.QueryRangeParamsV3
// Past2SeasonQuery is the query range params for past 2 seasonal period to the current season // Past2SeasonQuery is the query range params for past 2 seasonal period to the current season
// Example: For weekly seasonality, this is the query range params for the (now-3w-5m, now-2w) // Example: For weekly seasonality, this is the query range params for the (now-3w-5m, now-2w)
// : For daily seasonality, this is the query range params for the (now-3d-5m, now-2d) // : For daily seasonality, this is the query range params for the (now-3d-5m, now-2d)
@ -144,13 +143,13 @@ func prepareAnomalyQueryParams(req *v3.QueryRangeParamsV3, seasonality Seasonali
switch seasonality { switch seasonality {
case SeasonalityWeekly: case SeasonalityWeekly:
currentGrowthPeriodStart = start - oneWeekOffset currentGrowthPeriodStart = start - oneWeekOffset
currentGrowthPeriodEnd = end currentGrowthPeriodEnd = start
case SeasonalityDaily: case SeasonalityDaily:
currentGrowthPeriodStart = start - oneDayOffset currentGrowthPeriodStart = start - oneDayOffset
currentGrowthPeriodEnd = end currentGrowthPeriodEnd = start
case SeasonalityHourly: case SeasonalityHourly:
currentGrowthPeriodStart = start - oneHourOffset currentGrowthPeriodStart = start - oneHourOffset
currentGrowthPeriodEnd = end currentGrowthPeriodEnd = start
} }
currentGrowthQuery := &v3.QueryRangeParamsV3{ currentGrowthQuery := &v3.QueryRangeParamsV3{

View File

@ -194,10 +194,11 @@ func (p *BaseSeasonalProvider) getMovingAvg(series *v3.Series, movingAvgWindowSi
} }
var sum float64 var sum float64
points := series.Points[startIdx:] points := series.Points[startIdx:]
for i := 0; i < movingAvgWindowSize && i < len(points); i++ { windowSize := int(math.Min(float64(movingAvgWindowSize), float64(len(points))))
for i := 0; i < windowSize; i++ {
sum += points[i].Value sum += points[i].Value
} }
avg := sum / float64(movingAvgWindowSize) avg := sum / float64(windowSize)
return avg return avg
} }
@ -226,21 +227,25 @@ func (p *BaseSeasonalProvider) getPredictedSeries(
// plus the average of the current season series // plus the average of the current season series
// minus the mean of the past season series, past2 season series and past3 season series // minus the mean of the past season series, past2 season series and past3 season series
for idx, curr := range series.Points { for idx, curr := range series.Points {
predictedValue := movingAvg := p.getMovingAvg(prevSeries, movingAvgWindowSize, idx)
p.getMovingAvg(prevSeries, movingAvgWindowSize, idx) + avg := p.getAvg(currentSeasonSeries)
p.getAvg(currentSeasonSeries) - mean := p.getMean(p.getAvg(pastSeasonSeries), p.getAvg(past2SeasonSeries), p.getAvg(past3SeasonSeries))
p.getMean(p.getAvg(pastSeasonSeries), p.getAvg(past2SeasonSeries), p.getAvg(past3SeasonSeries)) predictedValue := movingAvg + avg - mean
if predictedValue < 0 { if predictedValue < 0 {
// this should not happen (except when the data has extreme outliers)
// we will use the moving avg of the previous period series in this case
zap.L().Warn("predictedValue is less than 0", zap.Float64("predictedValue", predictedValue), zap.Any("labels", series.Labels))
predictedValue = p.getMovingAvg(prevSeries, movingAvgWindowSize, idx) predictedValue = p.getMovingAvg(prevSeries, movingAvgWindowSize, idx)
} }
zap.L().Info("predictedSeries", zap.L().Debug("predictedSeries",
zap.Float64("movingAvg", p.getMovingAvg(prevSeries, movingAvgWindowSize, idx)), zap.Float64("movingAvg", movingAvg),
zap.Float64("avg", p.getAvg(currentSeasonSeries)), zap.Float64("avg", avg),
zap.Float64("mean", p.getMean(p.getAvg(pastSeasonSeries), p.getAvg(past2SeasonSeries), p.getAvg(past3SeasonSeries))), zap.Float64("mean", mean),
zap.Any("labels", series.Labels), zap.Any("labels", series.Labels),
zap.Float64("predictedValue", predictedValue), zap.Float64("predictedValue", predictedValue),
zap.Float64("curr", curr.Value),
) )
predictedSeries.Points = append(predictedSeries.Points, v3.Point{ predictedSeries.Points = append(predictedSeries.Points, v3.Point{
Timestamp: curr.Timestamp, Timestamp: curr.Timestamp,

View File

@ -616,7 +616,7 @@ func (r *ruleDB) GetAlertsInfo(ctx context.Context) (*model.AlertsInfo, error) {
} }
} }
alertsInfo.TotalAlerts = alertsInfo.TotalAlerts + 1 alertsInfo.TotalAlerts = alertsInfo.TotalAlerts + 1
if rule.PostableRule.Disabled == false { if !rule.PostableRule.Disabled {
alertsInfo.TotalActiveAlerts = alertsInfo.TotalActiveAlerts + 1 alertsInfo.TotalActiveAlerts = alertsInfo.TotalActiveAlerts + 1
} }
} }