mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(alerting): add support for alert_rule updates
This commit is contained in:
@@ -2,10 +2,12 @@ package models
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"time"
|
||||
)
|
||||
|
||||
type AlertRule struct {
|
||||
Id int64
|
||||
OrgId int64
|
||||
DashboardId int64
|
||||
PanelId int64
|
||||
Query string
|
||||
@@ -19,6 +21,13 @@ type AlertRule struct {
|
||||
Aggregator string
|
||||
}
|
||||
|
||||
type AlertRuleChange struct {
|
||||
OrgId int64
|
||||
AlertId int64
|
||||
Type string
|
||||
Created time.Time
|
||||
}
|
||||
|
||||
func (cmd *SaveDashboardCommand) GetAlertModels() *[]AlertRule {
|
||||
alerts := make([]AlertRule, 0)
|
||||
|
||||
@@ -31,6 +40,7 @@ func (cmd *SaveDashboardCommand) GetAlertModels() *[]AlertRule {
|
||||
alerting := panel.Get("alerting")
|
||||
alert := AlertRule{
|
||||
DashboardId: cmd.Result.Id,
|
||||
OrgId: cmd.Result.OrgId,
|
||||
PanelId: panel.Get("id").MustInt64(),
|
||||
Id: alerting.Get("id").MustInt64(),
|
||||
QueryRefId: alerting.Get("query_ref").MustString(),
|
||||
|
||||
@@ -2,14 +2,49 @@ package sqlstore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/go-xorm/xorm"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
bus.AddHandler("sql", SaveAlerts)
|
||||
}
|
||||
|
||||
func SaveAlertChange(change string, alert m.AlertRule) error {
|
||||
return inTransaction(func(sess *xorm.Session) error {
|
||||
_, err := sess.Insert(&m.AlertRuleChange{
|
||||
OrgId: alert.OrgId,
|
||||
Type: change,
|
||||
Created: time.Now(),
|
||||
AlertId: alert.Id,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func alertIsDifferent(rule1, rule2 m.AlertRule) bool {
|
||||
result := false
|
||||
|
||||
result = result || rule1.Aggregator != rule2.Aggregator
|
||||
result = result || rule1.CritLevel != rule2.CritLevel
|
||||
result = result || rule1.WarnLevel != rule2.WarnLevel
|
||||
result = result || rule1.Query != rule2.Query
|
||||
result = result || rule1.QueryRefId != rule2.QueryRefId
|
||||
result = result || rule1.Interval != rule2.Interval
|
||||
result = result || rule1.Title != rule2.Title
|
||||
result = result || rule1.Description != rule2.Description
|
||||
result = result || rule1.QueryRange != rule2.QueryRange
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func SaveAlerts(cmd *m.SaveAlertsCommand) error {
|
||||
//this function should be refactored
|
||||
|
||||
@@ -22,24 +57,33 @@ func SaveAlerts(cmd *m.SaveAlertsCommand) error {
|
||||
|
||||
for _, alert := range *cmd.Alerts {
|
||||
update := false
|
||||
var alertToUpdate m.AlertRule
|
||||
|
||||
for _, k := range alerts {
|
||||
if alert.PanelId == k.PanelId {
|
||||
update = true
|
||||
alert.Id = k.Id
|
||||
alertToUpdate = k
|
||||
}
|
||||
}
|
||||
|
||||
if update {
|
||||
_, err = x.Id(alert.Id).Update(&alert)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
if alertIsDifferent(alertToUpdate, alert) {
|
||||
_, err = x.Id(alert.Id).Update(&alert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
SaveAlertChange("UPDATED", alert)
|
||||
}
|
||||
|
||||
} else {
|
||||
_, err = x.Insert(&alert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
SaveAlertChange("CREATED", alert)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +102,7 @@ func SaveAlerts(cmd *m.SaveAlertsCommand) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SaveAlertChange("DELETED", missingAlert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -95,3 +140,14 @@ func GetAlertsByDashboardAndPanelId(dashboardId, panelId int64) (m.AlertRule, er
|
||||
|
||||
return alerts[0], nil
|
||||
}
|
||||
|
||||
func GetAlertRuleChanges(orgid int64) ([]m.AlertRuleChange, error) {
|
||||
alertChanges := make([]m.AlertRuleChange, 0)
|
||||
err := x.Where("org_id = ?", orgid).Find(&alertChanges)
|
||||
|
||||
if err != nil {
|
||||
return []m.AlertRuleChange{}, err
|
||||
}
|
||||
|
||||
return alertChanges, nil
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ func TestAlertingDataAccess(t *testing.T) {
|
||||
{
|
||||
PanelId: 1,
|
||||
DashboardId: testDash.Id,
|
||||
OrgId: testDash.OrgId,
|
||||
Query: "Query",
|
||||
QueryRefId: "A",
|
||||
WarnLevel: "> 30",
|
||||
@@ -41,6 +42,10 @@ func TestAlertingDataAccess(t *testing.T) {
|
||||
|
||||
Convey("Can create one alert", func() {
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
alertChanges, er := GetAlertRuleChanges(1)
|
||||
So(er, ShouldBeNil)
|
||||
So(len(alertChanges), ShouldEqual, 1)
|
||||
})
|
||||
|
||||
Convey("Can read properties", func() {
|
||||
@@ -82,6 +87,15 @@ func TestAlertingDataAccess(t *testing.T) {
|
||||
So(len(alerts), ShouldEqual, 1)
|
||||
So(alerts[0].Query, ShouldEqual, "Updated Query")
|
||||
})
|
||||
|
||||
Convey("Updates without changes should be ignored", func() {
|
||||
err3 := SaveAlerts(&modifiedCmd)
|
||||
So(err3, ShouldBeNil)
|
||||
|
||||
alertChanges, er := GetAlertRuleChanges(1)
|
||||
So(er, ShouldBeNil)
|
||||
So(len(alertChanges), ShouldEqual, 2)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Multiple alerts per dashboard", func() {
|
||||
@@ -90,16 +104,19 @@ func TestAlertingDataAccess(t *testing.T) {
|
||||
DashboardId: testDash.Id,
|
||||
PanelId: 1,
|
||||
Query: "1",
|
||||
OrgId: 1,
|
||||
},
|
||||
{
|
||||
DashboardId: testDash.Id,
|
||||
PanelId: 2,
|
||||
Query: "2",
|
||||
OrgId: 1,
|
||||
},
|
||||
{
|
||||
DashboardId: testDash.Id,
|
||||
PanelId: 3,
|
||||
Query: "3",
|
||||
OrgId: 1,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -112,6 +129,9 @@ func TestAlertingDataAccess(t *testing.T) {
|
||||
alerts, err2 := GetAlertsByDashboardId(testDash.Id)
|
||||
So(err2, ShouldBeNil)
|
||||
So(len(alerts), ShouldEqual, 3)
|
||||
alertChanges, er := GetAlertRuleChanges(1)
|
||||
So(er, ShouldBeNil)
|
||||
So(len(alertChanges), ShouldEqual, 4)
|
||||
})
|
||||
|
||||
Convey("should updated two dashboards and delete one", func() {
|
||||
@@ -125,6 +145,12 @@ func TestAlertingDataAccess(t *testing.T) {
|
||||
So(err2, ShouldBeNil)
|
||||
So(len(alerts), ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("should add one more alert_rule_change", func() {
|
||||
alertChanges, er := GetAlertRuleChanges(1)
|
||||
So(er, ShouldBeNil)
|
||||
So(len(alertChanges), ShouldEqual, 6)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ func addAlertMigrations(mg *Migrator) {
|
||||
{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
|
||||
{Name: "dashboard_id", Type: DB_BigInt, Nullable: false},
|
||||
{Name: "panel_id", Type: DB_BigInt, Nullable: false},
|
||||
{Name: "org_id", Type: DB_BigInt, Nullable: false},
|
||||
{Name: "query", Type: DB_Text, Nullable: false},
|
||||
{Name: "query_ref_id", Type: DB_NVarchar, Length: 255, Nullable: false},
|
||||
{Name: "warn_level", Type: DB_NVarchar, Length: 255, Nullable: false},
|
||||
@@ -22,14 +23,15 @@ func addAlertMigrations(mg *Migrator) {
|
||||
}
|
||||
|
||||
// create table
|
||||
mg.AddMigration("create alert table v1", NewAddTableMigration(alertV1))
|
||||
mg.AddMigration("create alert_rule table v1", NewAddTableMigration(alertV1))
|
||||
|
||||
alert_changes := Table{
|
||||
Name: "alert_rule_updates",
|
||||
Name: "alert_rule_change",
|
||||
Columns: []*Column{
|
||||
{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
|
||||
{Name: "alert_id", Type: DB_BigInt, Nullable: false},
|
||||
{Name: "org_id", Type: DB_BigInt, Nullable: false},
|
||||
{Name: "type", Type: DB_NVarchar, Length: 50, Nullable: false},
|
||||
{Name: "created", Type: DB_DateTime, Nullable: false},
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user