The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/services/alerting/conditions/evaluator.go

132 lines
3.1 KiB

package conditions
import (
"encoding/json"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/alerting"
)
var (
defaultTypes []string = []string{"gt", "lt"}
rangedTypes []string = []string{"within_range", "outside_range"}
)
type AlertEvaluator interface {
Eval(reducedValue *float64) bool
}
type NoDataEvaluator struct{}
func (e *NoDataEvaluator) Eval(reducedValue *float64) bool {
return reducedValue == nil
}
type ThresholdEvaluator struct {
Type string
Threshold float64
}
func newThresholdEvaludator(typ string, model *simplejson.Json) (*ThresholdEvaluator, error) {
params := model.Get("params").MustArray()
if len(params) == 0 {
return nil, alerting.ValidationError{Reason: "Evaluator missing threshold parameter"}
}
firstParam, ok := params[0].(json.Number)
if !ok {
return nil, alerting.ValidationError{Reason: "Evaluator has invalid parameter"}
}
defaultEval := &ThresholdEvaluator{Type: typ}
defaultEval.Threshold, _ = firstParam.Float64()
return defaultEval, nil
}
func (e *ThresholdEvaluator) Eval(reducedValue *float64) bool {
if reducedValue == nil {
return false
}
switch e.Type {
case "gt":
return *reducedValue > e.Threshold
case "lt":
return *reducedValue < e.Threshold
}
return false
}
type RangedEvaluator struct {
Type string
Lower float64
Upper float64
}
func newRangedEvaluator(typ string, model *simplejson.Json) (*RangedEvaluator, error) {
params := model.Get("params").MustArray()
if len(params) == 0 {
return nil, alerting.ValidationError{Reason: "Evaluator missing threshold parameter"}
}
firstParam, ok := params[0].(json.Number)
if !ok {
return nil, alerting.ValidationError{Reason: "Evaluator has invalid parameter"}
}
secondParam, ok := params[1].(json.Number)
if !ok {
return nil, alerting.ValidationError{Reason: "Evaluator has invalid second parameter"}
}
rangedEval := &RangedEvaluator{Type: typ}
rangedEval.Lower, _ = firstParam.Float64()
rangedEval.Upper, _ = secondParam.Float64()
return rangedEval, nil
}
func (e *RangedEvaluator) Eval(reducedValue *float64) bool {
if reducedValue == nil {
return false
}
switch e.Type {
case "within_range":
return (e.Lower < *reducedValue && e.Upper > *reducedValue) || (e.Upper < *reducedValue && e.Lower > *reducedValue)
case "outside_range":
return (e.Upper < *reducedValue && e.Lower < *reducedValue) || (e.Upper > *reducedValue && e.Lower > *reducedValue)
}
return false
}
func NewAlertEvaluator(model *simplejson.Json) (AlertEvaluator, error) {
typ := model.Get("type").MustString()
if typ == "" {
return nil, alerting.ValidationError{Reason: "Evaluator missing type property"}
}
if inSlice(typ, defaultTypes) {
return newThresholdEvaludator(typ, model)
}
if inSlice(typ, rangedTypes) {
return newRangedEvaluator(typ, model)
}
if typ == "no_data" {
return &NoDataEvaluator{}, nil
}
return nil, alerting.ValidationError{Reason: "Evaludator invalid evaluator type"}
}
func inSlice(a string, list []string) bool {
for _, b := range list {
if b == a {
return true
}
}
return false
}