From 9915f15ed0461e44b8273befbc314d215d6f8db2 Mon Sep 17 00:00:00 2001 From: bergquist Date: Wed, 17 Aug 2016 07:49:03 +0200 Subject: [PATCH 1/2] feat(alerting): adds sql layer for saving execution errors --- pkg/models/alert.go | 5 ++++ pkg/services/alerting/notifiers/slack.go | 18 ++++++------- pkg/services/sqlstore/alert.go | 18 +++++++++++++ pkg/services/sqlstore/alert_test.go | 34 ++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 9 deletions(-) diff --git a/pkg/models/alert.go b/pkg/models/alert.go index 240f8509179..5d907291eae 100644 --- a/pkg/models/alert.go +++ b/pkg/models/alert.go @@ -122,6 +122,11 @@ type DeleteAlertCommand struct { AlertId int64 } +type SaveExecutionErrorCommand struct { + AlertId int64 + ExecutionError string +} + //Queries type GetAlertsQuery struct { OrgId int64 diff --git a/pkg/services/alerting/notifiers/slack.go b/pkg/services/alerting/notifiers/slack.go index d6335221b63..e099c7da690 100644 --- a/pkg/services/alerting/notifiers/slack.go +++ b/pkg/services/alerting/notifiers/slack.go @@ -64,20 +64,20 @@ func (this *SlackNotifier) Notify(context *alerting.EvalContext) { body := map[string]interface{}{ "attachments": []map[string]interface{}{ { - "color": context.GetColor(), + "color": context.GetColor(), + "title": context.GetNotificationTitle(), + "title_link": ruleUrl, + "text": context.Rule.Message, + "fields": fields, + "image_url": context.ImagePublicUrl, + "footer": "Grafana v" + setting.BuildVersion, + "footer_icon": "http://grafana.org/assets/img/fav32.png", + "ts": time.Now().Unix(), //"pretext": "Optional text that appears above the attachment block", // "author_name": "Bobby Tables", // "author_link": "http://flickr.com/bobby/", // "author_icon": "http://flickr.com/icons/bobby.jpg", - "title": context.GetNotificationTitle(), - "title_link": ruleUrl, - "text": context.Rule.Message, - "fields": fields, - "image_url": context.ImagePublicUrl, // "thumb_url": "http://example.com/path/to/thumb.png", - "footer": "Grafana v" + setting.BuildVersion, - "footer_icon": "http://grafana.org/assets/img/fav32.png", - "ts": time.Now().Unix(), }, }, } diff --git a/pkg/services/sqlstore/alert.go b/pkg/services/sqlstore/alert.go index 32c118d51b7..37825054a54 100644 --- a/pkg/services/sqlstore/alert.go +++ b/pkg/services/sqlstore/alert.go @@ -18,6 +18,24 @@ func init() { bus.AddHandler("sql", DeleteAlertById) bus.AddHandler("sql", GetAllAlertQueryHandler) bus.AddHandler("sql", SetAlertState) + bus.AddHandler("sql", SaveExecutionErrorForAlert) +} + +func SaveExecutionErrorForAlert(cmd *m.SaveExecutionErrorCommand) error { + return inTransaction(func(sess *xorm.Session) error { + alert := m.Alert{} + + if has, err := sess.Id(cmd.AlertId).Get(&alert); err != nil { + return err + } else if !has { + return fmt.Errorf("Could not find alert") + } + + alert.ExecutionError = cmd.ExecutionError + + sess.Id(alert.Id).Update(&alert) + return nil + }) } func GetAlertById(query *m.GetAlertByIdQuery) error { diff --git a/pkg/services/sqlstore/alert_test.go b/pkg/services/sqlstore/alert_test.go index e22b1c48c47..5340f102fdd 100644 --- a/pkg/services/sqlstore/alert_test.go +++ b/pkg/services/sqlstore/alert_test.go @@ -175,5 +175,39 @@ func TestAlertingDataAccess(t *testing.T) { So(len(query.Result), ShouldEqual, 0) }) }) + + Convey("Can set new execution error", func() { + items := []*m.Alert{ + { + PanelId: 1, + DashboardId: testDash.Id, + Name: "Alerting title", + Message: "Alerting message", + }, + } + + cmd := m.SaveAlertsCommand{ + Alerts: items, + DashboardId: testDash.Id, + OrgId: 1, + UserId: 1, + } + + SaveAlerts(&cmd) + + So(SaveExecutionErrorForAlert(&m.SaveExecutionErrorCommand{ + AlertId: 1, + ExecutionError: "the slacker is broken", + }), ShouldBeNil) + + Convey("Alerts should be removed", func() { + query := &m.GetAlertByIdQuery{Id: 1} + err2 := GetAlertById(query) + + So(testDash.Id, ShouldEqual, 1) + So(err2, ShouldBeNil) + So(query.Result.ExecutionError, ShouldEqual, "the slacker is broken") + }) + }) }) } From 6497b307c4fb7445b124ec414dddd7296a8c3b6f Mon Sep 17 00:00:00 2001 From: bergquist Date: Wed, 17 Aug 2016 09:27:29 +0200 Subject: [PATCH 2/2] feat(alerting): save execution error upon state changed --- pkg/models/alert.go | 15 ++++---- pkg/services/alerting/result_handler.go | 5 ++- pkg/services/sqlstore/alert.go | 19 +---------- pkg/services/sqlstore/alert_test.go | 34 ------------------- pkg/services/sqlstore/migrations/alert_mig.go | 1 - 5 files changed, 11 insertions(+), 63 deletions(-) diff --git a/pkg/models/alert.go b/pkg/models/alert.go index 5d907291eae..445fae51dfb 100644 --- a/pkg/models/alert.go +++ b/pkg/models/alert.go @@ -10,9 +10,11 @@ type AlertStateType string type AlertSeverityType string const ( - AlertStatePending AlertStateType = "pending" - AlertStateFiring AlertStateType = "firing" - AlertStateOK AlertStateType = "ok" + AlertStatePending AlertStateType = "pending" + AlertStateExeuctionError AlertStateType = "exeuction_error" + AlertStatePaused AlertStateType = "paused" + AlertStateFiring AlertStateType = "firing" + AlertStateOK AlertStateType = "ok" ) func (s AlertStateType) IsValid() bool { @@ -41,7 +43,6 @@ type Alert struct { Severity AlertSeverityType State AlertStateType Handler int64 - Paused bool Silenced bool ExecutionError string Frequency int64 @@ -115,6 +116,7 @@ type SetAlertStateCommand struct { AlertId int64 OrgId int64 State AlertStateType + Error string Timestamp time.Time } @@ -122,11 +124,6 @@ type DeleteAlertCommand struct { AlertId int64 } -type SaveExecutionErrorCommand struct { - AlertId int64 - ExecutionError string -} - //Queries type GetAlertsQuery struct { OrgId int64 diff --git a/pkg/services/alerting/result_handler.go b/pkg/services/alerting/result_handler.go index e2ce462d328..6d0803451bd 100644 --- a/pkg/services/alerting/result_handler.go +++ b/pkg/services/alerting/result_handler.go @@ -29,9 +29,11 @@ func NewResultHandler() *DefaultResultHandler { func (handler *DefaultResultHandler) Handle(ctx *EvalContext) { oldState := ctx.Rule.State + exeuctionError := "" if ctx.Error != nil { handler.log.Error("Alert Rule Result Error", "ruleId", ctx.Rule.Id, "error", ctx.Error) - ctx.Rule.State = m.AlertStatePending + ctx.Rule.State = m.AlertStateExeuctionError + exeuctionError = ctx.Error.Error() } else if ctx.Firing { ctx.Rule.State = m.AlertStateFiring } else { @@ -47,6 +49,7 @@ func (handler *DefaultResultHandler) Handle(ctx *EvalContext) { AlertId: ctx.Rule.Id, OrgId: ctx.Rule.OrgId, State: ctx.Rule.State, + Error: exeuctionError, } if err := bus.Dispatch(cmd); err != nil { diff --git a/pkg/services/sqlstore/alert.go b/pkg/services/sqlstore/alert.go index 37825054a54..1b80366663d 100644 --- a/pkg/services/sqlstore/alert.go +++ b/pkg/services/sqlstore/alert.go @@ -18,24 +18,6 @@ func init() { bus.AddHandler("sql", DeleteAlertById) bus.AddHandler("sql", GetAllAlertQueryHandler) bus.AddHandler("sql", SetAlertState) - bus.AddHandler("sql", SaveExecutionErrorForAlert) -} - -func SaveExecutionErrorForAlert(cmd *m.SaveExecutionErrorCommand) error { - return inTransaction(func(sess *xorm.Session) error { - alert := m.Alert{} - - if has, err := sess.Id(cmd.AlertId).Get(&alert); err != nil { - return err - } else if !has { - return fmt.Errorf("Could not find alert") - } - - alert.ExecutionError = cmd.ExecutionError - - sess.Id(alert.Id).Update(&alert) - return nil - }) } func GetAlertById(query *m.GetAlertByIdQuery) error { @@ -241,6 +223,7 @@ func SetAlertState(cmd *m.SetAlertStateCommand) error { alert.State = cmd.State alert.StateChanges += 1 alert.NewStateDate = time.Now() + alert.ExecutionError = cmd.Error sess.Id(alert.Id).Update(&alert) return nil diff --git a/pkg/services/sqlstore/alert_test.go b/pkg/services/sqlstore/alert_test.go index 5340f102fdd..e22b1c48c47 100644 --- a/pkg/services/sqlstore/alert_test.go +++ b/pkg/services/sqlstore/alert_test.go @@ -175,39 +175,5 @@ func TestAlertingDataAccess(t *testing.T) { So(len(query.Result), ShouldEqual, 0) }) }) - - Convey("Can set new execution error", func() { - items := []*m.Alert{ - { - PanelId: 1, - DashboardId: testDash.Id, - Name: "Alerting title", - Message: "Alerting message", - }, - } - - cmd := m.SaveAlertsCommand{ - Alerts: items, - DashboardId: testDash.Id, - OrgId: 1, - UserId: 1, - } - - SaveAlerts(&cmd) - - So(SaveExecutionErrorForAlert(&m.SaveExecutionErrorCommand{ - AlertId: 1, - ExecutionError: "the slacker is broken", - }), ShouldBeNil) - - Convey("Alerts should be removed", func() { - query := &m.GetAlertByIdQuery{Id: 1} - err2 := GetAlertById(query) - - So(testDash.Id, ShouldEqual, 1) - So(err2, ShouldBeNil) - So(query.Result.ExecutionError, ShouldEqual, "the slacker is broken") - }) - }) }) } diff --git a/pkg/services/sqlstore/migrations/alert_mig.go b/pkg/services/sqlstore/migrations/alert_mig.go index 62817e3f543..63d61d8b196 100644 --- a/pkg/services/sqlstore/migrations/alert_mig.go +++ b/pkg/services/sqlstore/migrations/alert_mig.go @@ -21,7 +21,6 @@ func addAlertMigrations(mg *Migrator) { {Name: "frequency", Type: DB_BigInt, Nullable: false}, {Name: "handler", Type: DB_BigInt, Nullable: false}, {Name: "severity", Type: DB_Text, Nullable: false}, - {Name: "paused", Type: DB_Bool, Nullable: false}, {Name: "silenced", Type: DB_Bool, Nullable: false}, {Name: "execution_error", Type: DB_Text, Nullable: false}, {Name: "eval_data", Type: DB_Text, Nullable: true},