mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(alerting): add support for "no_value" evaluator
This commit is contained in:
@@ -9,37 +9,86 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
defaultTypes []string = []string{"gt", "lt"}
|
||||
rangedTypes []string = []string{"within_range", "outside_range"}
|
||||
defaultTypes []string = []string{"gt", "lt"}
|
||||
rangedTypes []string = []string{"within_range", "outside_range"}
|
||||
paramlessTypes []string = []string{"no_value"}
|
||||
)
|
||||
|
||||
type AlertEvaluator interface {
|
||||
Eval(timeSeries *tsdb.TimeSeries, reducedValue float64) bool
|
||||
}
|
||||
|
||||
type DefaultAlertEvaluator struct {
|
||||
type ParameterlessEvaluator struct {
|
||||
Type string
|
||||
}
|
||||
|
||||
func (e *ParameterlessEvaluator) Eval(series *tsdb.TimeSeries, reducedValue float64) bool {
|
||||
return len(series.Points) == 0
|
||||
}
|
||||
|
||||
type ThresholdEvaluator struct {
|
||||
Type string
|
||||
Threshold float64
|
||||
}
|
||||
|
||||
func (e *DefaultAlertEvaluator) Eval(series *tsdb.TimeSeries, reducedValue float64) bool {
|
||||
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(series *tsdb.TimeSeries, reducedValue float64) bool {
|
||||
switch e.Type {
|
||||
case "gt":
|
||||
return reducedValue > e.Threshold
|
||||
case "lt":
|
||||
return reducedValue < e.Threshold
|
||||
case "no_value":
|
||||
return len(series.Points) == 0
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type RangedAlertEvaluator struct {
|
||||
type RangedEvaluator struct {
|
||||
Type string
|
||||
Lower float64
|
||||
Upper float64
|
||||
}
|
||||
|
||||
func (e *RangedAlertEvaluator) Eval(series *tsdb.TimeSeries, reducedValue float64) bool {
|
||||
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(series *tsdb.TimeSeries, reducedValue float64) bool {
|
||||
switch e.Type {
|
||||
case "within_range":
|
||||
return (e.Lower < reducedValue && e.Upper > reducedValue) || (e.Upper < reducedValue && e.Lower > reducedValue)
|
||||
@@ -56,32 +105,16 @@ func NewAlertEvaluator(model *simplejson.Json) (AlertEvaluator, error) {
|
||||
return nil, alerting.ValidationError{Reason: "Evaluator missing type property"}
|
||||
}
|
||||
|
||||
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"}
|
||||
}
|
||||
|
||||
if inSlice(typ, defaultTypes) {
|
||||
defaultEval := &DefaultAlertEvaluator{Type: typ}
|
||||
defaultEval.Threshold, _ = firstParam.Float64()
|
||||
return defaultEval, nil
|
||||
return newThresholdEvaludator(typ, model)
|
||||
}
|
||||
|
||||
if inSlice(typ, rangedTypes) {
|
||||
secondParam, ok := params[1].(json.Number)
|
||||
if !ok {
|
||||
return nil, alerting.ValidationError{Reason: "Evaluator has invalid second parameter"}
|
||||
}
|
||||
return newRangedEvaluator(typ, model)
|
||||
}
|
||||
|
||||
rangedEval := &RangedAlertEvaluator{Type: typ}
|
||||
rangedEval.Lower, _ = firstParam.Float64()
|
||||
rangedEval.Upper, _ = secondParam.Float64()
|
||||
return rangedEval, nil
|
||||
if inSlice(typ, paramlessTypes) {
|
||||
return &ParameterlessEvaluator{Type: typ}, nil
|
||||
}
|
||||
|
||||
return nil, alerting.ValidationError{Reason: "Evaludator invalid evaluator type"}
|
||||
|
||||
@@ -42,4 +42,8 @@ func TestEvalutors(t *testing.T) {
|
||||
So(test(`{"type": "outside_range", "params": [100, 1] }`, 1000), ShouldBeTrue)
|
||||
So(test(`{"type": "outside_range", "params": [100, 1] }`, 50), ShouldBeFalse)
|
||||
})
|
||||
|
||||
Convey("no_value", t, func() {
|
||||
So(test(`{"type": "no_value", "params": [] }`, 1000), ShouldBeTrue)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestQueryCondition(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("Can read evaluator", func() {
|
||||
evaluator, ok := ctx.condition.Evaluator.(*DefaultAlertEvaluator)
|
||||
evaluator, ok := ctx.condition.Evaluator.(*ThresholdEvaluator)
|
||||
So(ok, ShouldBeTrue)
|
||||
So(evaluator.Type, ShouldEqual, "gt")
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user