2016-07-27 09:29:28 -05:00
|
|
|
package alerting
|
|
|
|
|
|
|
|
import (
|
2016-11-17 03:28:17 -06:00
|
|
|
"strconv"
|
2016-11-17 08:48:15 -06:00
|
|
|
"strings"
|
2016-07-27 09:29:28 -05:00
|
|
|
"time"
|
|
|
|
|
2019-05-13 01:45:54 -05:00
|
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
2019-02-23 16:35:26 -06:00
|
|
|
"github.com/grafana/grafana/pkg/infra/metrics"
|
2021-11-10 04:52:16 -06:00
|
|
|
"github.com/grafana/grafana/pkg/tsdb/legacydata"
|
2016-07-27 09:29:28 -05:00
|
|
|
)
|
|
|
|
|
2019-05-20 05:13:32 -05:00
|
|
|
// DefaultEvalHandler is responsible for evaluating the alert rule.
|
2016-07-27 09:29:28 -05:00
|
|
|
type DefaultEvalHandler struct {
|
|
|
|
log log.Logger
|
|
|
|
alertJobTimeout time.Duration
|
2021-11-10 04:52:16 -06:00
|
|
|
requestHandler legacydata.RequestHandler
|
2016-07-27 09:29:28 -05:00
|
|
|
}
|
|
|
|
|
2019-05-20 05:13:32 -05:00
|
|
|
// NewEvalHandler is the `DefaultEvalHandler` constructor.
|
2021-11-10 04:52:16 -06:00
|
|
|
func NewEvalHandler(requestHandler legacydata.RequestHandler) *DefaultEvalHandler {
|
2016-07-27 09:29:28 -05:00
|
|
|
return &DefaultEvalHandler{
|
2016-07-28 10:03:53 -05:00
|
|
|
log: log.New("alerting.evalHandler"),
|
2016-10-03 02:38:03 -05:00
|
|
|
alertJobTimeout: time.Second * 5,
|
2021-03-08 00:02:49 -06:00
|
|
|
requestHandler: requestHandler,
|
2016-07-27 09:29:28 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-20 05:13:32 -05:00
|
|
|
// Eval evaluated the alert rule.
|
2016-07-27 09:29:28 -05:00
|
|
|
func (e *DefaultEvalHandler) Eval(context *EvalContext) {
|
2016-11-03 09:26:17 -05:00
|
|
|
firing := true
|
2016-11-22 04:44:25 -06:00
|
|
|
noDataFound := true
|
2016-11-17 08:48:15 -06:00
|
|
|
conditionEvals := ""
|
|
|
|
|
2016-11-17 03:28:17 -06:00
|
|
|
for i := 0; i < len(context.Rule.Conditions); i++ {
|
|
|
|
condition := context.Rule.Conditions[i]
|
2021-03-08 00:02:49 -06:00
|
|
|
cr, err := condition.Eval(context, e.requestHandler)
|
2016-11-03 09:26:17 -05:00
|
|
|
if err != nil {
|
|
|
|
context.Error = err
|
|
|
|
}
|
2016-07-27 09:29:28 -05:00
|
|
|
|
|
|
|
// break if condition could not be evaluated
|
|
|
|
if context.Error != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2017-12-13 06:37:10 -06:00
|
|
|
if i == 0 {
|
|
|
|
firing = cr.Firing
|
|
|
|
noDataFound = cr.NoDataFound
|
|
|
|
}
|
|
|
|
|
2016-11-15 08:35:25 -06:00
|
|
|
// calculating Firing based on operator
|
|
|
|
if cr.Operator == "or" {
|
|
|
|
firing = firing || cr.Firing
|
|
|
|
} else {
|
|
|
|
firing = firing && cr.Firing
|
2016-07-27 09:29:28 -05:00
|
|
|
}
|
2016-11-03 09:26:17 -05:00
|
|
|
|
2021-11-10 04:28:49 -06:00
|
|
|
// We cannot evaluate the expression when one or more conditions are missing data
|
|
|
|
// and so noDataFound should be true if at least one condition returns no data,
|
|
|
|
// irrespective of the operator.
|
|
|
|
noDataFound = noDataFound || cr.NoDataFound
|
|
|
|
|
2016-11-17 03:28:17 -06:00
|
|
|
if i > 0 {
|
2016-11-17 08:48:15 -06:00
|
|
|
conditionEvals = "[" + conditionEvals + " " + strings.ToUpper(cr.Operator) + " " + strconv.FormatBool(cr.Firing) + "]"
|
2016-11-17 03:28:17 -06:00
|
|
|
} else {
|
2016-11-17 08:48:15 -06:00
|
|
|
conditionEvals = strconv.FormatBool(firing)
|
2016-11-17 03:28:17 -06:00
|
|
|
}
|
|
|
|
|
2016-11-03 09:26:17 -05:00
|
|
|
context.EvalMatches = append(context.EvalMatches, cr.EvalMatches...)
|
2022-04-13 15:04:10 -05:00
|
|
|
context.AllMatches = append(context.AllMatches, cr.AllMatches...)
|
2016-07-27 09:29:28 -05:00
|
|
|
}
|
|
|
|
|
2016-11-17 08:48:15 -06:00
|
|
|
context.ConditionEvals = conditionEvals + " = " + strconv.FormatBool(firing)
|
2016-11-03 09:26:17 -05:00
|
|
|
context.Firing = firing
|
2016-11-22 04:44:25 -06:00
|
|
|
context.NoDataFound = noDataFound
|
2016-07-27 09:29:28 -05:00
|
|
|
context.EndTime = time.Now()
|
2017-01-13 03:24:40 -06:00
|
|
|
|
2017-09-14 12:28:54 -05:00
|
|
|
elapsedTime := context.EndTime.Sub(context.StartTime).Nanoseconds() / int64(time.Millisecond)
|
2019-07-16 09:58:46 -05:00
|
|
|
metrics.MAlertingExecutionTime.Observe(float64(elapsedTime))
|
2016-07-27 09:29:28 -05:00
|
|
|
}
|