Revert "Alerting: Fix mathexp.NoData in ConditionsCmd (#56812)" (#58423)

This reverts commit 5fa0936b7e.
This commit is contained in:
George Robinson 2022-11-08 13:35:58 +00:00 committed by GitHub
parent bfd14709c9
commit aa69a8463f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -69,106 +69,104 @@ func (cmd *ConditionsCmd) NeedsVars() []string {
// Execute runs the command and returns the results or an error if the command // Execute runs the command and returns the results or an error if the command
// failed to execute. // failed to execute.
func (cmd *ConditionsCmd) Execute(_ context.Context, _ time.Time, vars mathexp.Vars) (mathexp.Results, error) { func (cmd *ConditionsCmd) Execute(_ context.Context, _ time.Time, vars mathexp.Vars) (mathexp.Results, error) {
// isFiring and isNoData tracks whether ConditionsCmd is firing or no data firing := true
var isFiring, isNoData bool newRes := mathexp.Results{}
var res mathexp.Results noDataFound := true
matches := make([]EvalMatch, 0) matches := []EvalMatch{}
for ix, cond := range cmd.Conditions {
// isCondFiring and isCondNoData tracks whether the condition is firing or no data
//
// There are a number of reasons a condition can have no data:
//
// 1. The input data vars[cond.InputRefID] has no values
// 2. The input data has one or more values, however all are mathexp.NoData
// 3. The input data has one or more values of mathexp.Number or mathexp.Series,
// however the either all mathexp.Number have a nil float64 or the reduce function
// for all mathexp.Series returns a mathexp.Number with a nil float64
// 4. The input data is a combination of all mathexp.NoData, mathexp.Number with a nil
// float64, or mathexp.Series that reduce to a nil float64
var isCondFiring, isCondNoData bool
var numSeriesNoData int
series := vars[cond.InputRefID] for i, c := range cmd.Conditions {
for _, value := range series.Values { querySeriesSet := vars[c.InputRefID]
var ( nilReducedCount := 0
name string firingCount := 0
number mathexp.Number for _, val := range querySeriesSet.Values {
) var reducedNum mathexp.Number
switch v := value.(type) { var name string
switch v := val.(type) {
case mathexp.NoData: case mathexp.NoData:
// Reduce expressions return v.New(), however classic conditions use the operator
// in the condition to determine if the outcome of ConditionsCmd is no data.
// To keep this code as simple as possible we translate mathexp.NoData into a // To keep this code as simple as possible we translate mathexp.NoData into a
// mathexp.Number with a nil value so number.GetFloat64Value() returns nil // mathexp.Number with a nil value so number.GetFloat64Value() returns nil
number = mathexp.NewNumber("no data", nil) reducedNum = mathexp.NewNumber("no data", nil)
number.SetValue(nil) reducedNum.SetValue(nil)
case mathexp.Series:
reducedNum = c.Reducer.Reduce(v)
name = v.GetName()
case mathexp.Number: case mathexp.Number:
reducedNum = v
if len(v.Frame.Fields) > 0 { if len(v.Frame.Fields) > 0 {
name = v.Frame.Fields[0].Name name = v.Frame.Fields[0].Name
} }
number = v
case mathexp.Series:
name = v.GetName()
number = cond.Reducer.Reduce(v)
default: default:
return res, fmt.Errorf("can only reduce type series, got type %v", v.Type()) return newRes, fmt.Errorf("can only reduce type series, got type %v", val.Type())
} }
// Check if the value was either a mathexp.NoData, a mathexp.Number with a nil float64, // TODO handle error / no data signals
// or mathexp.Series that reduced to a nil float64 thisCondNoDataFound := reducedNum.GetFloat64Value() == nil
if number.GetFloat64Value() == nil {
numSeriesNoData += 1 if thisCondNoDataFound {
} else if isValueFiring := cond.Evaluator.Eval(number); isValueFiring { nilReducedCount++
isCondFiring = true }
// If the condition is met then add it to the list of matching conditions
labels := number.GetLabels() evalRes := c.Evaluator.Eval(reducedNum)
if labels != nil {
labels = labels.Copy() if evalRes {
} match := EvalMatch{
matches = append(matches, EvalMatch{ Value: reducedNum.GetFloat64Value(),
Metric: name, Metric: name,
Value: number.GetFloat64Value(), }
Labels: labels, if reducedNum.GetLabels() != nil {
}) match.Labels = reducedNum.GetLabels().Copy()
}
matches = append(matches, match)
firingCount++
} }
} }
// The condition is no data iff all the input data is a combination of all mathexp.NoData, thisCondFiring := firingCount > 0
// mathexp.Number with a nil loat64, or mathexp.Series that reduce to a nil float64 thisCondNoData := len(querySeriesSet.Values) == nilReducedCount
isCondNoData = numSeriesNoData == len(series.Values)
if isCondNoData { if i == 0 {
firing = thisCondFiring
noDataFound = thisCondNoData
}
if c.Operator == "or" {
firing = firing || thisCondFiring
noDataFound = noDataFound || thisCondNoData
} else {
firing = firing && thisCondFiring
noDataFound = noDataFound && thisCondNoData
}
if thisCondNoData {
matches = append(matches, EvalMatch{ matches = append(matches, EvalMatch{
Metric: "NoData", Metric: "NoData",
}) })
noDataFound = true
} }
if ix == 0 { firingCount = 0
isFiring = isCondFiring nilReducedCount = 0
isNoData = isCondNoData
} else if cond.Operator == "or" {
isFiring = isFiring || isCondFiring
isNoData = isNoData || isCondNoData
} else {
isFiring = isFiring && isCondFiring
isNoData = isNoData && isCondNoData
}
} }
num := mathexp.NewNumber("", nil)
num.SetMeta(matches)
var v float64 var v float64
number := mathexp.NewNumber("", nil) switch {
number.SetMeta(matches) case noDataFound:
if isFiring { num.SetValue(nil)
case firing:
v = 1 v = 1
number.SetValue(&v) num.SetValue(&v)
} else if isNoData { case !firing:
number.SetValue(nil) num.SetValue(&v)
} else {
number.SetValue(&v)
} }
res.Values = append(res.Values, number) newRes.Values = append(newRes.Values, num)
return res, nil
return newRes, nil
} }
// EvalMatch represents the series violating the threshold. // EvalMatch represents the series violating the threshold.