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/rule.go

117 lines
2.8 KiB

package alerting
import (
"fmt"
"regexp"
"strconv"
"github.com/grafana/grafana/pkg/components/simplejson"
m "github.com/grafana/grafana/pkg/models"
)
type Rule struct {
Id int64
OrgId int64
DashboardId int64
PanelId int64
Frequency int64
Name string
Message string
NoDataState m.AlertStateType
State m.AlertStateType
Conditions []Condition
Notifications []int64
}
type ValidationError struct {
Reason string
}
func (e ValidationError) Error() string {
return e.Reason
}
var (
ValueFormatRegex = regexp.MustCompile("^\\d+")
UnitFormatRegex = regexp.MustCompile("\\w{1}$")
)
var unitMultiplier = map[string]int{
"s": 1,
"m": 60,
"h": 3600,
}
func getTimeDurationStringToSeconds(str string) (int64, error) {
multiplier := 1
matches := ValueFormatRegex.FindAllString(str, 1)
if len(matches) <= 0 {
return 0, fmt.Errorf("Frequency could not be parsed")
}
value, err := strconv.Atoi(matches[0])
if err != nil {
return 0, err
}
unit := UnitFormatRegex.FindAllString(str, 1)[0]
if val, ok := unitMultiplier[unit]; ok {
multiplier = val
}
return int64(value * multiplier), nil
}
func NewRuleFromDBAlert(ruleDef *m.Alert) (*Rule, error) {
model := &Rule{}
model.Id = ruleDef.Id
model.OrgId = ruleDef.OrgId
model.DashboardId = ruleDef.DashboardId
model.PanelId = ruleDef.PanelId
model.Name = ruleDef.Name
model.Message = ruleDef.Message
model.Frequency = ruleDef.Frequency
model.State = ruleDef.State
model.NoDataState = m.AlertStateType(ruleDef.Settings.Get("noDataState").MustString("no_data"))
for _, v := range ruleDef.Settings.Get("notifications").MustArray() {
jsonModel := simplejson.NewFromAny(v)
if id, err := jsonModel.Get("id").Int64(); err != nil {
return nil, ValidationError{Reason: "Invalid notification schema"}
} else {
model.Notifications = append(model.Notifications, id)
}
}
for index, condition := range ruleDef.Settings.Get("conditions").MustArray() {
conditionModel := simplejson.NewFromAny(condition)
conditionType := conditionModel.Get("type").MustString()
if factory, exist := conditionFactories[conditionType]; !exist {
return nil, ValidationError{Reason: "Unknown alert condition: " + conditionType}
} else {
if queryCondition, err := factory(conditionModel, index); err != nil {
return nil, err
} else {
model.Conditions = append(model.Conditions, queryCondition)
}
}
}
if len(model.Conditions) == 0 {
return nil, fmt.Errorf("Alert is missing conditions")
}
return model, nil
}
type ConditionFactory func(model *simplejson.Json, index int) (Condition, error)
var conditionFactories map[string]ConditionFactory = make(map[string]ConditionFactory)
func RegisterCondition(typeName string, factory ConditionFactory) {
conditionFactories[typeName] = factory
}