feat(alerting): add support for alert_rule updates

pull/5622/head
bergquist 9 years ago
parent c83af353b2
commit 25f6ec8b53
  1. 10
      pkg/models/alerts.go
  2. 62
      pkg/services/sqlstore/alerting.go
  3. 26
      pkg/services/sqlstore/alerting_test.go
  4. 6
      pkg/services/sqlstore/migrations/alert_mig.go

@ -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},
},
}

Loading…
Cancel
Save