diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index 6d6558f5271..5f937a5cbd8 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -47,6 +47,7 @@ var ( M_Alerting_Notification_Sent_PagerDuty Counter M_Alerting_Notification_Sent_Victorops Counter M_Alerting_Notification_Sent_OpsGenie Counter + M_Alerting_Notification_Sent_Telegram Counter M_Aws_CloudWatch_GetMetricStatistics Counter M_Aws_CloudWatch_ListMetrics Counter @@ -114,6 +115,7 @@ func initMetricVars(settings *MetricSettings) { M_Alerting_Notification_Sent_PagerDuty = RegCounter("alerting.notifications_sent", "type", "pagerduty") M_Alerting_Notification_Sent_Victorops = RegCounter("alerting.notifications_sent", "type", "victorops") M_Alerting_Notification_Sent_OpsGenie = RegCounter("alerting.notifications_sent", "type", "opsgenie") + M_Alerting_Notification_Sent_Telegram = RegCounter("alerting.notifications_sent", "type", "telegram") M_Aws_CloudWatch_GetMetricStatistics = RegCounter("aws.cloudwatch.get_metric_statistics") M_Aws_CloudWatch_ListMetrics = RegCounter("aws.cloudwatch.list_metrics") diff --git a/pkg/services/alerting/notifiers/telegram.go b/pkg/services/alerting/notifiers/telegram.go new file mode 100644 index 00000000000..551464733d9 --- /dev/null +++ b/pkg/services/alerting/notifiers/telegram.go @@ -0,0 +1,86 @@ +package notifiers + +import ( + "fmt" + + "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" +) + +var ( + telegeramApiUrl string = "https://api.telegram.org/bot%s/%s" +) + +func init() { + alerting.RegisterNotifier("telegram", NewTelegramNotifier) +} + +type TelegramNotifier struct { + NotifierBase + BotToken string + ChatID string + log log.Logger +} + +func NewTelegramNotifier(model *m.AlertNotification) (alerting.Notifier, error) { + if model.Settings == nil { + return nil, alerting.ValidationError{Reason: "No Settings Supplied"} + } + + botToken := model.Settings.Get("bottoken").MustString() + chatId := model.Settings.Get("chatid").MustString() + + if botToken == "" { + return nil, alerting.ValidationError{Reason: "Could not find Bot Token in settings"} + } + + if chatId == "" { + return nil, alerting.ValidationError{Reason: "Could not find Chat Id in settings"} + } + + return &TelegramNotifier{ + NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), + BotToken: botToken, + ChatID: chatId, + log: log.New("alerting.notifier.telegram"), + }, nil +} + +func (this *TelegramNotifier) Notify(evalContext *alerting.EvalContext) error { + this.log.Info("Sending alert notification to", "bot_token", this.BotToken) + this.log.Info("Sending alert notification to", "chat_id", this.ChatID) + metrics.M_Alerting_Notification_Sent_Telegram.Inc(1) + + bodyJSON := simplejson.New() + + bodyJSON.Set("chat_id", this.ChatID) + bodyJSON.Set("parse_mode", "html") + + message := fmt.Sprintf("%s\nState: %s\nMessage: %s\n", evalContext.GetNotificationTitle(), evalContext.Rule.Name, evalContext.Rule.Message) + + ruleUrl, err := evalContext.GetRuleUrl() + if err == nil { + message = message + fmt.Sprintf("URL: %s\n", ruleUrl) + } + bodyJSON.Set("text", message) + + url := fmt.Sprintf(telegeramApiUrl, this.BotToken, "sendMessage") + body, _ := bodyJSON.MarshalJSON() + + cmd := &m.SendWebhookSync{ + Url: url, + Body: string(body), + HttpMethod: "POST", + } + + if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil { + this.log.Error("Failed to send webhook", "error", err, "webhook", this.Name) + return err + } + + return nil +} diff --git a/pkg/services/alerting/notifiers/telegram_test.go b/pkg/services/alerting/notifiers/telegram_test.go new file mode 100644 index 00000000000..3e8066e273b --- /dev/null +++ b/pkg/services/alerting/notifiers/telegram_test.go @@ -0,0 +1,55 @@ +package notifiers + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestTelegramNotifier(t *testing.T) { + Convey("Telegram 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: "telegram_testing", + Type: "telegram", + Settings: settingsJSON, + } + + _, err := NewTelegramNotifier(model) + So(err, ShouldNotBeNil) + }) + + Convey("settings should trigger incident", func() { + json := ` + { + "bottoken": "abcdefgh0123456789", + "chatid": "-1234567890" + }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "telegram_testing", + Type: "telegram", + Settings: settingsJSON, + } + + not, err := NewTelegramNotifier(model) + telegramNotifier := not.(*TelegramNotifier) + + So(err, ShouldBeNil) + So(telegramNotifier.Name, ShouldEqual, "telegram_testing") + So(telegramNotifier.Type, ShouldEqual, "telegram") + So(telegramNotifier.BotToken, ShouldEqual, "abcdefgh0123456789") + So(telegramNotifier.ChatID, ShouldEqual, "-1234567890") + }) + + }) + }) +} diff --git a/public/app/features/alerting/partials/notification_edit.html b/public/app/features/alerting/partials/notification_edit.html index b5076efd792..33f8e1a0f87 100644 --- a/public/app/features/alerting/partials/notification_edit.html +++ b/public/app/features/alerting/partials/notification_edit.html @@ -19,7 +19,7 @@