From db77dfea7a8cb2c8133926ed3a7c42dc0bcbdc08 Mon Sep 17 00:00:00 2001 From: Mani Soundararajan Date: Sun, 6 Nov 2016 20:48:14 +0530 Subject: [PATCH 01/15] Update github auth docs In Github's "allowed organizations" scenario, it makes sense to have `allow_sign_up` to be `true` as most administrators will expect their org's github users to be able to sign in without further steps like creating a local user first. --- docs/sources/installation/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/installation/configuration.md b/docs/sources/installation/configuration.md index 9525855573f..bb9c34a6a44 100644 --- a/docs/sources/installation/configuration.md +++ b/docs/sources/installation/configuration.md @@ -339,7 +339,7 @@ your Grafana instance. For example scopes = user:email,read:org auth_url = https://github.com/login/oauth/authorize token_url = https://github.com/login/oauth/access_token - allow_sign_up = false + allow_sign_up = true # space-delimited organization names allowed_organizations = github google From 139bbecc10a16bdea7595986d6d6780e5f0e7acf Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Fri, 28 Oct 2016 22:19:51 -0700 Subject: [PATCH 02/15] Added Pagerduty basic alerting --- pkg/metrics/metrics.go | 75 +++++++++-------- pkg/services/alerting/notifiers/pagerduty.go | 83 +++++++++++++++++++ .../app/features/alerting/alert_tab_ctrl.ts | 1 + .../alerting/partials/notification_edit.html | 37 ++++++++- 4 files changed, 159 insertions(+), 37 deletions(-) create mode 100644 pkg/services/alerting/notifiers/pagerduty.go diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index 481818aab23..25fa43d8d2f 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -9,42 +9,44 @@ func init() { } var ( - M_Instance_Start Counter - M_Page_Status_200 Counter - M_Page_Status_500 Counter - M_Page_Status_404 Counter - M_Page_Status_Unknown Counter - M_Api_Status_200 Counter - M_Api_Status_404 Counter - M_Api_Status_500 Counter - M_Api_Status_Unknown Counter - M_Proxy_Status_200 Counter - M_Proxy_Status_404 Counter - M_Proxy_Status_500 Counter - M_Proxy_Status_Unknown Counter - M_Api_User_SignUpStarted Counter - M_Api_User_SignUpCompleted Counter - M_Api_User_SignUpInvite Counter - M_Api_Dashboard_Save Timer - M_Api_Dashboard_Get Timer - M_Api_Dashboard_Search Timer - M_Api_Admin_User_Create Counter - M_Api_Login_Post Counter - M_Api_Login_OAuth Counter - M_Api_Org_Create Counter - M_Api_Dashboard_Snapshot_Create Counter - M_Api_Dashboard_Snapshot_External Counter - M_Api_Dashboard_Snapshot_Get Counter - M_Models_Dashboard_Insert Counter - M_Alerting_Result_State_Alerting Counter - M_Alerting_Result_State_Ok Counter - M_Alerting_Result_State_Paused Counter - M_Alerting_Result_State_NoData Counter - M_Alerting_Result_State_Pending Counter - M_Alerting_Active_Alerts Counter - M_Alerting_Notification_Sent_Slack Counter - M_Alerting_Notification_Sent_Email Counter - M_Alerting_Notification_Sent_Webhook Counter + M_Instance_Start Counter + M_Page_Status_200 Counter + M_Page_Status_500 Counter + M_Page_Status_404 Counter + M_Page_Status_Unknown Counter + M_Api_Status_200 Counter + M_Api_Status_404 Counter + M_Api_Status_500 Counter + M_Api_Status_Unknown Counter + M_Proxy_Status_200 Counter + M_Proxy_Status_404 Counter + M_Proxy_Status_500 Counter + M_Proxy_Status_Unknown Counter + M_Api_User_SignUpStarted Counter + M_Api_User_SignUpCompleted Counter + M_Api_User_SignUpInvite Counter + M_Api_Dashboard_Save Timer + M_Api_Dashboard_Get Timer + M_Api_Dashboard_Search Timer + M_Api_Admin_User_Create Counter + M_Api_Login_Post Counter + M_Api_Login_OAuth Counter + M_Api_Org_Create Counter + M_Api_Dashboard_Snapshot_Create Counter + M_Api_Dashboard_Snapshot_External Counter + M_Api_Dashboard_Snapshot_Get Counter + M_Models_Dashboard_Insert Counter + M_Alerting_Result_State_Alerting Counter + M_Alerting_Result_State_Ok Counter + M_Alerting_Result_State_Paused Counter + M_Alerting_Result_State_NoData Counter + M_Alerting_Result_State_Pending Counter + M_Alerting_Active_Alerts Counter + M_Alerting_Notification_Sent_Slack Counter + M_Alerting_Notification_Sent_Email Counter + M_Alerting_Notification_Sent_Webhook Counter + M_Alerting_Notification_Sent_PagerDuty Counter + // Timers M_DataSource_ProxyReq_Timer Timer @@ -107,6 +109,7 @@ func initMetricVars(settings *MetricSettings) { M_Alerting_Notification_Sent_Slack = RegCounter("alerting.notifications_sent", "type", "slack") M_Alerting_Notification_Sent_Email = RegCounter("alerting.notifications_sent", "type", "email") M_Alerting_Notification_Sent_Webhook = RegCounter("alerting.notifications_sent", "type", "webhook") + M_Alerting_Notification_Sent_PagerDuty = RegCounter("alerting.notifications_sent", "type", "pagerduty") // Timers M_DataSource_ProxyReq_Timer = RegTimer("api.dataproxy.request.all") diff --git a/pkg/services/alerting/notifiers/pagerduty.go b/pkg/services/alerting/notifiers/pagerduty.go new file mode 100644 index 00000000000..7ccde7524d2 --- /dev/null +++ b/pkg/services/alerting/notifiers/pagerduty.go @@ -0,0 +1,83 @@ +package notifiers + +import ( + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/metrics" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/alerting" +) + +func init() { + alerting.RegisterNotifier("pagerduty", NewPagerdutyNotifier) +} + +func NewPagerdutyNotifier(model *m.AlertNotification) (alerting.Notifier, error) { + key := model.Settings.Get("integrationKey").MustString() + if key == "" { + return nil, alerting.ValidationError{Reason: "Could not find integration key property in settings"} + } + + return &PagerdutyNotifier{ + NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), + Key: key, + log: log.New("alerting.notifier.pagerduty"), + }, nil +} + +type PagerdutyNotifier struct { + NotifierBase + Key string + log log.Logger +} + +func (this *PagerdutyNotifier) Notify(evalContext *alerting.EvalContext) error { + this.log.Info("Notifying Pagerduty") + metrics.M_Alerting_Notification_Sent_PagerDuty.Inc(1) + + if evalContext.Rule.State == m.AlertStateAlerting { + + // Pagerduty Events API URL + pgEventsUrl := "https://events.pagerduty.com/generic/2010-04-15/create_event.json" + + bodyJSON := simplejson.New() + bodyJSON.Set("service_key", this.Key) + bodyJSON.Set("description", evalContext.Rule.Name + "-" + evalContext.Rule.Message) + bodyJSON.Set("client", "Grafana") + bodyJSON.Set("event_type", "trigger") + + ruleUrl, err := evalContext.GetRuleUrl() + if err != nil { + this.log.Error("Failed get rule link", "error", err) + return err + } + bodyJSON.Set("client_url", ruleUrl) + + if evalContext.ImagePublicUrl != "" { + var contexts []interface{} + imageJSON := simplejson.New() + imageJSON.Set("type", "image") + imageJSON.Set("src", evalContext.ImagePublicUrl) + contexts[0] = imageJSON + bodyJSON.Set("contexts", contexts) + } + + body, _ := bodyJSON.MarshalJSON() + + cmd := &m.SendWebhook{ + Url: pgEventsUrl, + Body: string(body), + HttpMethod: "POST", + } + + if err := bus.Dispatch(cmd); err != nil { + this.log.Error("Failed to send notification to Pagerduty", "error", err, "body", string(body)) + } + + } else { + this.log.Info("Not sending a trigger to Pagerduty", "state", evalContext.Rule.State) + } + + return nil +} diff --git a/public/app/features/alerting/alert_tab_ctrl.ts b/public/app/features/alerting/alert_tab_ctrl.ts index e505f9be361..c882a6ac3bf 100644 --- a/public/app/features/alerting/alert_tab_ctrl.ts +++ b/public/app/features/alerting/alert_tab_ctrl.ts @@ -90,6 +90,7 @@ export class AlertTabCtrl { case "email": return "fa fa-envelope"; case "slack": return "fa fa-slack"; case "webhook": return "fa fa-cubes"; + case "pagerduty": return "fa fa-bullhorn"; } } diff --git a/public/app/features/alerting/partials/notification_edit.html b/public/app/features/alerting/partials/notification_edit.html index efb22e2e05a..cfd890a0ed2 100644 --- a/public/app/features/alerting/partials/notification_edit.html +++ b/public/app/features/alerting/partials/notification_edit.html @@ -19,7 +19,7 @@
Type
-
@@ -97,6 +97,41 @@ +
+

Pagerduty settings

+
+ Integration Key + +
+
+ + +
+
+ + +
+
+ + +
+
+
From df8cd764b22f865983a1212315cb31705b49ea02 Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Mon, 31 Oct 2016 23:48:59 -0700 Subject: [PATCH 03/15] Added trigger options with Pagerduty --- pkg/services/alerting/notifiers/pagerduty.go | 32 +++++++++++++++---- .../alerting/partials/notification_edit.html | 9 ------ 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/pkg/services/alerting/notifiers/pagerduty.go b/pkg/services/alerting/notifiers/pagerduty.go index 7ccde7524d2..a90e7635a04 100644 --- a/pkg/services/alerting/notifiers/pagerduty.go +++ b/pkg/services/alerting/notifiers/pagerduty.go @@ -19,24 +19,44 @@ func NewPagerdutyNotifier(model *m.AlertNotification) (alerting.Notifier, error) return nil, alerting.ValidationError{Reason: "Could not find integration key property in settings"} } + alertingStates := make([]m.AlertStateType, 0) + alertingStates = append(alertingStates, m.AlertStateAlerting) + if model.Settings.Get("alertOnExecError").MustBool() { + alertingStates = append(alertingStates, m.AlertStateExecError) + } + if model.Settings.Get("alertOnNoData").MustBool() { + alertingStates = append(alertingStates, m.AlertStateNoData) + } + return &PagerdutyNotifier{ - NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), - Key: key, - log: log.New("alerting.notifier.pagerduty"), + NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), + Key: key, + AlertingStates: alertingStates, + log: log.New("alerting.notifier.pagerduty"), }, nil } type PagerdutyNotifier struct { NotifierBase - Key string - log log.Logger + Key string + AlertingStates []m.AlertStateType + log log.Logger } func (this *PagerdutyNotifier) Notify(evalContext *alerting.EvalContext) error { this.log.Info("Notifying Pagerduty") metrics.M_Alerting_Notification_Sent_PagerDuty.Inc(1) - if evalContext.Rule.State == m.AlertStateAlerting { + shouldNotify := false + + for _, state := range this.AlertingStates { + if evalContext.Rule.State == state { + shouldNotify = true + break + } + } + + if shouldNotify { // Pagerduty Events API URL pgEventsUrl := "https://events.pagerduty.com/generic/2010-04-15/create_event.json" diff --git a/public/app/features/alerting/partials/notification_edit.html b/public/app/features/alerting/partials/notification_edit.html index cfd890a0ed2..379eca2e168 100644 --- a/public/app/features/alerting/partials/notification_edit.html +++ b/public/app/features/alerting/partials/notification_edit.html @@ -121,15 +121,6 @@ tooltip="Trigger incident on Execution Error">
-
- - -
From de0fa3d479575a8ca9971065f8dfdd50991a0f7b Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Tue, 1 Nov 2016 00:19:43 -0700 Subject: [PATCH 04/15] Added pagerduty tests --- .../alerting/notifiers/pagerduty_test.go | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 pkg/services/alerting/notifiers/pagerduty_test.go diff --git a/pkg/services/alerting/notifiers/pagerduty_test.go b/pkg/services/alerting/notifiers/pagerduty_test.go new file mode 100644 index 00000000000..d75126527d5 --- /dev/null +++ b/pkg/services/alerting/notifiers/pagerduty_test.go @@ -0,0 +1,106 @@ +package notifiers + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestPagerdutyNotifier(t *testing.T) { + Convey("Pagerduty notifier tests", t, func() { + + Convey("Parsing alert notification from settings", func() { + Convey("empty settings should return error", func() { + json := `{ }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "pageduty_testing", + Type: "pagerduty", + Settings: settingsJSON, + } + + _, err := NewPagerdutyNotifier(model) + So(err, ShouldNotBeNil) + }) + + Convey("settings with only integrationKey should contain AlertStateAlerting", func() { + json := ` + { + "integrationKey": "abcdefgh0123456789" + }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "pagerduty_testing", + Type: "pagerduty", + Settings: settingsJSON, + } + + not, err := NewPagerdutyNotifier(model) + pagerdutyNotifier := not.(*PagerdutyNotifier) + + So(err, ShouldBeNil) + So(pagerdutyNotifier.Name, ShouldEqual, "pagerduty_testing") + So(pagerdutyNotifier.Type, ShouldEqual, "pagerduty") + So(pagerdutyNotifier.Key, ShouldEqual, "abcdefgh0123456789") + So(pagerdutyNotifier.AlertingStates, ShouldContain, m.AlertStateAlerting) + }) + + Convey("settings with alertOnNoData should contain AlertStateNoData too", func() { + json := ` + { + "integrationKey": "abcdefgh0123456789", + "alertOnNoData": true + }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "pagerduty_testing", + Type: "pagerduty", + Settings: settingsJSON, + } + + not, err := NewPagerdutyNotifier(model) + pagerdutyNotifier := not.(*PagerdutyNotifier) + + So(err, ShouldBeNil) + So(pagerdutyNotifier.Name, ShouldEqual, "pagerduty_testing") + So(pagerdutyNotifier.Type, ShouldEqual, "pagerduty") + So(pagerdutyNotifier.Key, ShouldEqual, "abcdefgh0123456789") + So(pagerdutyNotifier.AlertingStates, ShouldContain, m.AlertStateNoData) + So(pagerdutyNotifier.AlertingStates, ShouldContain, m.AlertStateAlerting) + }) + + Convey("settings with alertOnNoData, alertOnExecError should contain both", func() { + json := ` + { + "integrationKey": "abcdefgh0123456789", + "alertOnNoData": true, + "alertOnExecError": true + }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "pagerduty_testing", + Type: "pagerduty", + Settings: settingsJSON, + } + + not, err := NewPagerdutyNotifier(model) + pagerdutyNotifier := not.(*PagerdutyNotifier) + + So(err, ShouldBeNil) + So(pagerdutyNotifier.Name, ShouldEqual, "pagerduty_testing") + So(pagerdutyNotifier.Type, ShouldEqual, "pagerduty") + So(pagerdutyNotifier.Key, ShouldEqual, "abcdefgh0123456789") + So(pagerdutyNotifier.AlertingStates, ShouldContain, m.AlertStateNoData) + So(pagerdutyNotifier.AlertingStates, ShouldContain, m.AlertStateAlerting) + So(pagerdutyNotifier.AlertingStates, ShouldContain, m.AlertStateExecError) + }) + + }) + }) +} From 638d3bcb42bf3676a341768f47370c3d4cafae77 Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Wed, 2 Nov 2016 11:08:51 -0700 Subject: [PATCH 05/15] Removed NoData option --- pkg/services/alerting/notifiers/pagerduty.go | 35 +++--------- .../alerting/notifiers/pagerduty_test.go | 55 +------------------ .../alerting/partials/notification_edit.html | 11 +--- 3 files changed, 12 insertions(+), 89 deletions(-) diff --git a/pkg/services/alerting/notifiers/pagerduty.go b/pkg/services/alerting/notifiers/pagerduty.go index a90e7635a04..f9b0af39602 100644 --- a/pkg/services/alerting/notifiers/pagerduty.go +++ b/pkg/services/alerting/notifiers/pagerduty.go @@ -19,54 +19,37 @@ func NewPagerdutyNotifier(model *m.AlertNotification) (alerting.Notifier, error) return nil, alerting.ValidationError{Reason: "Could not find integration key property in settings"} } - alertingStates := make([]m.AlertStateType, 0) - alertingStates = append(alertingStates, m.AlertStateAlerting) - if model.Settings.Get("alertOnExecError").MustBool() { - alertingStates = append(alertingStates, m.AlertStateExecError) - } - if model.Settings.Get("alertOnNoData").MustBool() { - alertingStates = append(alertingStates, m.AlertStateNoData) - } - return &PagerdutyNotifier{ - NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), + NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), Key: key, - AlertingStates: alertingStates, + AlertOnExecError: model.Settings.Get("alertOnExecError").MustBool(), log: log.New("alerting.notifier.pagerduty"), }, nil } type PagerdutyNotifier struct { NotifierBase - Key string - AlertingStates []m.AlertStateType - log log.Logger + Key string + AlertOnExecError bool + log log.Logger } func (this *PagerdutyNotifier) Notify(evalContext *alerting.EvalContext) error { this.log.Info("Notifying Pagerduty") metrics.M_Alerting_Notification_Sent_PagerDuty.Inc(1) - shouldNotify := false - - for _, state := range this.AlertingStates { - if evalContext.Rule.State == state { - shouldNotify = true - break - } - } - - if shouldNotify { + if (evalContext.Rule.State == m.AlertStateAlerting) || + ((this.AlertOnExecError) && (evalContext.Rule.State == m.AlertStateExecError)) { // Pagerduty Events API URL pgEventsUrl := "https://events.pagerduty.com/generic/2010-04-15/create_event.json" bodyJSON := simplejson.New() bodyJSON.Set("service_key", this.Key) - bodyJSON.Set("description", evalContext.Rule.Name + "-" + evalContext.Rule.Message) + bodyJSON.Set("description", evalContext.Rule.Name+"-"+evalContext.Rule.Message) bodyJSON.Set("client", "Grafana") bodyJSON.Set("event_type", "trigger") - + ruleUrl, err := evalContext.GetRuleUrl() if err != nil { this.log.Error("Failed get rule link", "error", err) diff --git a/pkg/services/alerting/notifiers/pagerduty_test.go b/pkg/services/alerting/notifiers/pagerduty_test.go index d75126527d5..fb20450d930 100644 --- a/pkg/services/alerting/notifiers/pagerduty_test.go +++ b/pkg/services/alerting/notifiers/pagerduty_test.go @@ -26,59 +26,10 @@ func TestPagerdutyNotifier(t *testing.T) { So(err, ShouldNotBeNil) }) - Convey("settings with only integrationKey should contain AlertStateAlerting", func() { - json := ` - { - "integrationKey": "abcdefgh0123456789" - }` - - settingsJSON, _ := simplejson.NewJson([]byte(json)) - model := &m.AlertNotification{ - Name: "pagerduty_testing", - Type: "pagerduty", - Settings: settingsJSON, - } - - not, err := NewPagerdutyNotifier(model) - pagerdutyNotifier := not.(*PagerdutyNotifier) - - So(err, ShouldBeNil) - So(pagerdutyNotifier.Name, ShouldEqual, "pagerduty_testing") - So(pagerdutyNotifier.Type, ShouldEqual, "pagerduty") - So(pagerdutyNotifier.Key, ShouldEqual, "abcdefgh0123456789") - So(pagerdutyNotifier.AlertingStates, ShouldContain, m.AlertStateAlerting) - }) - - Convey("settings with alertOnNoData should contain AlertStateNoData too", func() { + Convey("settings with alertOnExecError should trigger incident", func() { json := ` { "integrationKey": "abcdefgh0123456789", - "alertOnNoData": true - }` - - settingsJSON, _ := simplejson.NewJson([]byte(json)) - model := &m.AlertNotification{ - Name: "pagerduty_testing", - Type: "pagerduty", - Settings: settingsJSON, - } - - not, err := NewPagerdutyNotifier(model) - pagerdutyNotifier := not.(*PagerdutyNotifier) - - So(err, ShouldBeNil) - So(pagerdutyNotifier.Name, ShouldEqual, "pagerduty_testing") - So(pagerdutyNotifier.Type, ShouldEqual, "pagerduty") - So(pagerdutyNotifier.Key, ShouldEqual, "abcdefgh0123456789") - So(pagerdutyNotifier.AlertingStates, ShouldContain, m.AlertStateNoData) - So(pagerdutyNotifier.AlertingStates, ShouldContain, m.AlertStateAlerting) - }) - - Convey("settings with alertOnNoData, alertOnExecError should contain both", func() { - json := ` - { - "integrationKey": "abcdefgh0123456789", - "alertOnNoData": true, "alertOnExecError": true }` @@ -96,9 +47,7 @@ func TestPagerdutyNotifier(t *testing.T) { So(pagerdutyNotifier.Name, ShouldEqual, "pagerduty_testing") So(pagerdutyNotifier.Type, ShouldEqual, "pagerduty") So(pagerdutyNotifier.Key, ShouldEqual, "abcdefgh0123456789") - So(pagerdutyNotifier.AlertingStates, ShouldContain, m.AlertStateNoData) - So(pagerdutyNotifier.AlertingStates, ShouldContain, m.AlertStateAlerting) - So(pagerdutyNotifier.AlertingStates, ShouldContain, m.AlertStateExecError) + So(pagerdutyNotifier.AlertOnExecError, ShouldContain, true) }) }) diff --git a/public/app/features/alerting/partials/notification_edit.html b/public/app/features/alerting/partials/notification_edit.html index 379eca2e168..904fd9df0e5 100644 --- a/public/app/features/alerting/partials/notification_edit.html +++ b/public/app/features/alerting/partials/notification_edit.html @@ -103,22 +103,13 @@ Integration Key
-
- - -
+ tooltip="Trigger incident on Exec Error">
From 4b53ea0a56c3bb9be67b679a8996927389279b43 Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Wed, 2 Nov 2016 13:55:39 -0700 Subject: [PATCH 06/15] Fixed pagerduty tests --- pkg/services/alerting/notifiers/pagerduty_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/alerting/notifiers/pagerduty_test.go b/pkg/services/alerting/notifiers/pagerduty_test.go index fb20450d930..76ae3ef963f 100644 --- a/pkg/services/alerting/notifiers/pagerduty_test.go +++ b/pkg/services/alerting/notifiers/pagerduty_test.go @@ -47,7 +47,7 @@ func TestPagerdutyNotifier(t *testing.T) { So(pagerdutyNotifier.Name, ShouldEqual, "pagerduty_testing") So(pagerdutyNotifier.Type, ShouldEqual, "pagerduty") So(pagerdutyNotifier.Key, ShouldEqual, "abcdefgh0123456789") - So(pagerdutyNotifier.AlertOnExecError, ShouldContain, true) + So(pagerdutyNotifier.AlertOnExecError, ShouldEqual, true) }) }) From f8d1eb11a9db7244fb87dd31fa61eb44569523bd Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Mon, 7 Nov 2016 07:12:43 -0800 Subject: [PATCH 07/15] Removed ExecError state --- pkg/services/alerting/notifiers/pagerduty.go | 5 +---- pkg/services/alerting/notifiers/pagerduty_test.go | 6 ++---- .../features/alerting/partials/notification_edit.html | 9 --------- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/pkg/services/alerting/notifiers/pagerduty.go b/pkg/services/alerting/notifiers/pagerduty.go index f9b0af39602..198fe744018 100644 --- a/pkg/services/alerting/notifiers/pagerduty.go +++ b/pkg/services/alerting/notifiers/pagerduty.go @@ -22,7 +22,6 @@ func NewPagerdutyNotifier(model *m.AlertNotification) (alerting.Notifier, error) return &PagerdutyNotifier{ NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), Key: key, - AlertOnExecError: model.Settings.Get("alertOnExecError").MustBool(), log: log.New("alerting.notifier.pagerduty"), }, nil } @@ -30,7 +29,6 @@ func NewPagerdutyNotifier(model *m.AlertNotification) (alerting.Notifier, error) type PagerdutyNotifier struct { NotifierBase Key string - AlertOnExecError bool log log.Logger } @@ -38,8 +36,7 @@ func (this *PagerdutyNotifier) Notify(evalContext *alerting.EvalContext) error { this.log.Info("Notifying Pagerduty") metrics.M_Alerting_Notification_Sent_PagerDuty.Inc(1) - if (evalContext.Rule.State == m.AlertStateAlerting) || - ((this.AlertOnExecError) && (evalContext.Rule.State == m.AlertStateExecError)) { + if evalContext.Rule.State == m.AlertStateAlerting { // Pagerduty Events API URL pgEventsUrl := "https://events.pagerduty.com/generic/2010-04-15/create_event.json" diff --git a/pkg/services/alerting/notifiers/pagerduty_test.go b/pkg/services/alerting/notifiers/pagerduty_test.go index 76ae3ef963f..522bb133d77 100644 --- a/pkg/services/alerting/notifiers/pagerduty_test.go +++ b/pkg/services/alerting/notifiers/pagerduty_test.go @@ -26,11 +26,10 @@ func TestPagerdutyNotifier(t *testing.T) { So(err, ShouldNotBeNil) }) - Convey("settings with alertOnExecError should trigger incident", func() { + Convey("settings should trigger incident", func() { json := ` { - "integrationKey": "abcdefgh0123456789", - "alertOnExecError": true + "integrationKey": "abcdefgh0123456789" }` settingsJSON, _ := simplejson.NewJson([]byte(json)) @@ -47,7 +46,6 @@ func TestPagerdutyNotifier(t *testing.T) { So(pagerdutyNotifier.Name, ShouldEqual, "pagerduty_testing") So(pagerdutyNotifier.Type, ShouldEqual, "pagerduty") So(pagerdutyNotifier.Key, ShouldEqual, "abcdefgh0123456789") - So(pagerdutyNotifier.AlertOnExecError, ShouldEqual, true) }) }) diff --git a/public/app/features/alerting/partials/notification_edit.html b/public/app/features/alerting/partials/notification_edit.html index 904fd9df0e5..7ee96e60c8a 100644 --- a/public/app/features/alerting/partials/notification_edit.html +++ b/public/app/features/alerting/partials/notification_edit.html @@ -103,15 +103,6 @@ Integration Key -
- - -
From 5549d8658a4f7143e75ba3819c923bea79e28193 Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Mon, 7 Nov 2016 07:27:31 -0800 Subject: [PATCH 08/15] Fixed description message --- pkg/services/alerting/notifiers/pagerduty.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/alerting/notifiers/pagerduty.go b/pkg/services/alerting/notifiers/pagerduty.go index 198fe744018..8b8b2df1af4 100644 --- a/pkg/services/alerting/notifiers/pagerduty.go +++ b/pkg/services/alerting/notifiers/pagerduty.go @@ -43,7 +43,7 @@ func (this *PagerdutyNotifier) Notify(evalContext *alerting.EvalContext) error { bodyJSON := simplejson.New() bodyJSON.Set("service_key", this.Key) - bodyJSON.Set("description", evalContext.Rule.Name+"-"+evalContext.Rule.Message) + bodyJSON.Set("description", evalContext.Rule.Name + " - " + evalContext.Rule.Message) bodyJSON.Set("client", "Grafana") bodyJSON.Set("event_type", "trigger") From 69ff13adce8a3fcc78a27a8b76535b8ed037e8ad Mon Sep 17 00:00:00 2001 From: Roger Swingle Date: Mon, 7 Nov 2016 13:53:35 -0500 Subject: [PATCH 09/15] add govcloud --- pkg/api/cloudwatch/metrics.go | 2 +- public/app/plugins/datasource/cloudwatch/partials/config.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/api/cloudwatch/metrics.go b/pkg/api/cloudwatch/metrics.go index 5f87eccc87b..68843ba5774 100644 --- a/pkg/api/cloudwatch/metrics.go +++ b/pkg/api/cloudwatch/metrics.go @@ -140,7 +140,7 @@ func init() { func handleGetRegions(req *cwRequest, c *middleware.Context) { regions := []string{ "ap-northeast-1", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "cn-north-1", - "eu-central-1", "eu-west-1", "sa-east-1", "us-east-1", "us-west-1", "us-west-2", + "eu-central-1", "eu-west-1", "sa-east-1", "us-east-1", "us-west-1", "us-west-2", "us-gov-west-1", } result := []interface{}{} diff --git a/public/app/plugins/datasource/cloudwatch/partials/config.html b/public/app/plugins/datasource/cloudwatch/partials/config.html index 6f119964512..89e52e76ace 100644 --- a/public/app/plugins/datasource/cloudwatch/partials/config.html +++ b/public/app/plugins/datasource/cloudwatch/partials/config.html @@ -11,7 +11,7 @@
- + Specify the region, such as for US West (Oregon) use ` us-west-2 ` as the region. From a7e67f3bdd3bacdb1aade041eb070a47fd34cb1a Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Mon, 7 Nov 2016 17:43:13 -0800 Subject: [PATCH 10/15] Removed invalid alerting state --- public/app/features/alerting/alert_list_ctrl.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/public/app/features/alerting/alert_list_ctrl.ts b/public/app/features/alerting/alert_list_ctrl.ts index b2287759a9b..5e3cce35c6e 100644 --- a/public/app/features/alerting/alert_list_ctrl.ts +++ b/public/app/features/alerting/alert_list_ctrl.ts @@ -15,7 +15,6 @@ export class AlertListCtrl { {text: 'OK', value: 'ok'}, {text: 'Alerting', value: 'alerting'}, {text: 'No Data', value: 'no_data'}, - {text: 'Execution Error', value: 'execution_error'}, ]; filters = { From 7bc80d0374ee257b4599fd4c25de67b910033864 Mon Sep 17 00:00:00 2001 From: bergquist Date: Tue, 8 Nov 2016 07:50:58 +0100 Subject: [PATCH 11/15] tech(pagerduty): declare url as constant --- pkg/services/alerting/notifiers/pagerduty.go | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/pkg/services/alerting/notifiers/pagerduty.go b/pkg/services/alerting/notifiers/pagerduty.go index 8b8b2df1af4..559276231f7 100644 --- a/pkg/services/alerting/notifiers/pagerduty.go +++ b/pkg/services/alerting/notifiers/pagerduty.go @@ -13,6 +13,10 @@ func init() { alerting.RegisterNotifier("pagerduty", NewPagerdutyNotifier) } +var ( + pagerdutyEventApiUrl string = "https://events.pagerduty.com/generic/2010-04-15/create_event.json" +) + func NewPagerdutyNotifier(model *m.AlertNotification) (alerting.Notifier, error) { key := model.Settings.Get("integrationKey").MustString() if key == "" { @@ -20,16 +24,16 @@ func NewPagerdutyNotifier(model *m.AlertNotification) (alerting.Notifier, error) } return &PagerdutyNotifier{ - NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), - Key: key, - log: log.New("alerting.notifier.pagerduty"), + NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), + Key: key, + log: log.New("alerting.notifier.pagerduty"), }, nil } type PagerdutyNotifier struct { NotifierBase - Key string - log log.Logger + Key string + log log.Logger } func (this *PagerdutyNotifier) Notify(evalContext *alerting.EvalContext) error { @@ -37,13 +41,9 @@ func (this *PagerdutyNotifier) Notify(evalContext *alerting.EvalContext) error { metrics.M_Alerting_Notification_Sent_PagerDuty.Inc(1) if evalContext.Rule.State == m.AlertStateAlerting { - - // Pagerduty Events API URL - pgEventsUrl := "https://events.pagerduty.com/generic/2010-04-15/create_event.json" - bodyJSON := simplejson.New() bodyJSON.Set("service_key", this.Key) - bodyJSON.Set("description", evalContext.Rule.Name + " - " + evalContext.Rule.Message) + bodyJSON.Set("description", evalContext.Rule.Name+" - "+evalContext.Rule.Message) bodyJSON.Set("client", "Grafana") bodyJSON.Set("event_type", "trigger") @@ -66,7 +66,7 @@ func (this *PagerdutyNotifier) Notify(evalContext *alerting.EvalContext) error { body, _ := bodyJSON.MarshalJSON() cmd := &m.SendWebhook{ - Url: pgEventsUrl, + Url: pagerdutyEventApiUrl, Body: string(body), HttpMethod: "POST", } From 66f257e38265222e6a7f78faf5f7c004dd6d93d4 Mon Sep 17 00:00:00 2001 From: bergquist Date: Tue, 8 Nov 2016 07:51:19 +0100 Subject: [PATCH 12/15] tech(pagerduty): make api call sync --- pkg/services/alerting/notifiers/pagerduty.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/alerting/notifiers/pagerduty.go b/pkg/services/alerting/notifiers/pagerduty.go index 559276231f7..1de34e07e5a 100644 --- a/pkg/services/alerting/notifiers/pagerduty.go +++ b/pkg/services/alerting/notifiers/pagerduty.go @@ -65,7 +65,7 @@ func (this *PagerdutyNotifier) Notify(evalContext *alerting.EvalContext) error { body, _ := bodyJSON.MarshalJSON() - cmd := &m.SendWebhook{ + cmd := &m.SendWebhookSync{ Url: pagerdutyEventApiUrl, Body: string(body), HttpMethod: "POST", From 5bbdd99d35e56f503250925c4f38010bcf756077 Mon Sep 17 00:00:00 2001 From: bergquist Date: Tue, 8 Nov 2016 08:06:42 +0100 Subject: [PATCH 13/15] tech(notifications): remove async webhook --- pkg/models/notifications.go | 8 -------- pkg/services/notifications/notifications.go | 13 ------------- 2 files changed, 21 deletions(-) diff --git a/pkg/models/notifications.go b/pkg/models/notifications.go index 80803b3be08..c43024da691 100644 --- a/pkg/models/notifications.go +++ b/pkg/models/notifications.go @@ -16,14 +16,6 @@ type SendEmailCommandSync struct { SendEmailCommand } -type SendWebhook struct { - Url string - User string - Password string - Body string - HttpMethod string -} - type SendWebhookSync struct { Url string User string diff --git a/pkg/services/notifications/notifications.go b/pkg/services/notifications/notifications.go index 8a13eec2dc8..85bda1643d1 100644 --- a/pkg/services/notifications/notifications.go +++ b/pkg/services/notifications/notifications.go @@ -31,7 +31,6 @@ func Init() error { bus.AddCtxHandler("email", sendEmailCommandHandlerSync) - bus.AddHandler("webhook", sendWebhook) bus.AddCtxHandler("webhook", SendWebhookSync) bus.AddEventListener(signUpStartedHandler) @@ -69,18 +68,6 @@ func SendWebhookSync(ctx context.Context, cmd *m.SendWebhookSync) error { }) } -func sendWebhook(cmd *m.SendWebhook) error { - addToWebhookQueue(&Webhook{ - Url: cmd.Url, - User: cmd.User, - Password: cmd.Password, - Body: cmd.Body, - HttpMethod: cmd.HttpMethod, - }) - - return nil -} - func subjectTemplateFunc(obj map[string]interface{}, value string) string { obj["value"] = value return "" From 74632b5e983281424d1fda0a9ca7eeda093a1df9 Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Mon, 7 Nov 2016 17:28:30 -0800 Subject: [PATCH 14/15] Added last function for alerting conditions --- pkg/services/alerting/conditions/reducer.go | 7 +++++++ pkg/services/alerting/conditions/reducer_test.go | 6 ++++++ public/app/features/alerting/alert_def.ts | 1 + 3 files changed, 14 insertions(+) diff --git a/pkg/services/alerting/conditions/reducer.go b/pkg/services/alerting/conditions/reducer.go index a982fa63d33..5fbaeb18326 100644 --- a/pkg/services/alerting/conditions/reducer.go +++ b/pkg/services/alerting/conditions/reducer.go @@ -62,6 +62,13 @@ func (s *SimpleReducer) Reduce(series *tsdb.TimeSeries) null.Float { case "count": value = float64(len(series.Points)) allNull = false + case "last": + for _, point := range series.Points { + if point[0].Valid { + value = point[0].Float64 + allNull = false + } + } } if allNull { diff --git a/pkg/services/alerting/conditions/reducer_test.go b/pkg/services/alerting/conditions/reducer_test.go index 198a52b746a..dfd229e1374 100644 --- a/pkg/services/alerting/conditions/reducer_test.go +++ b/pkg/services/alerting/conditions/reducer_test.go @@ -35,6 +35,12 @@ func TestSimpleReducer(t *testing.T) { result := testReducer("count", 1, 2, 3000) So(result, ShouldEqual, float64(3)) }) + + Convey("last", func() { + result := testReducer("last", 1, 2, 3000) + So(result, ShouldEqual, float64(3000)) + }) + }) } diff --git a/public/app/features/alerting/alert_def.ts b/public/app/features/alerting/alert_def.ts index aaddb9e425f..8ee1981f3d8 100644 --- a/public/app/features/alerting/alert_def.ts +++ b/public/app/features/alerting/alert_def.ts @@ -34,6 +34,7 @@ var reducerTypes = [ {text: 'max()', value: 'max'}, {text: 'sum()' , value: 'sum'}, {text: 'count()', value: 'count'}, + {text: 'last()', value: 'last'}, ]; var noDataModes = [ From 841fb74b39736e85987389389c10a550543cc0fb Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Mon, 7 Nov 2016 23:15:47 -0800 Subject: [PATCH 15/15] Reversed loop for last function --- pkg/services/alerting/conditions/reducer.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/services/alerting/conditions/reducer.go b/pkg/services/alerting/conditions/reducer.go index 5fbaeb18326..988a640591d 100644 --- a/pkg/services/alerting/conditions/reducer.go +++ b/pkg/services/alerting/conditions/reducer.go @@ -63,10 +63,12 @@ func (s *SimpleReducer) Reduce(series *tsdb.TimeSeries) null.Float { value = float64(len(series.Points)) allNull = false case "last": - for _, point := range series.Points { - if point[0].Valid { - value = point[0].Float64 + points := series.Points + for i := len(points) - 1; i >= 0; i-- { + if points[i][0].Valid { + value = points[i][0].Float64 allNull = false + break } } }