Browse Source

(feature) add LINE notify to notifier

huydx 9 years ago
parent
commit
376d2d56bf

+ 2 - 0
pkg/metrics/metrics.go

@@ -45,6 +45,7 @@ var (
 	M_Alerting_Notification_Sent_Email     Counter
 	M_Alerting_Notification_Sent_Email     Counter
 	M_Alerting_Notification_Sent_Webhook   Counter
 	M_Alerting_Notification_Sent_Webhook   Counter
 	M_Alerting_Notification_Sent_PagerDuty Counter
 	M_Alerting_Notification_Sent_PagerDuty Counter
+	M_Alerting_Notification_Sent_LINE      Counter
 	M_Alerting_Notification_Sent_Victorops Counter
 	M_Alerting_Notification_Sent_Victorops Counter
 	M_Alerting_Notification_Sent_OpsGenie  Counter
 	M_Alerting_Notification_Sent_OpsGenie  Counter
 	M_Alerting_Notification_Sent_Telegram  Counter
 	M_Alerting_Notification_Sent_Telegram  Counter
@@ -118,6 +119,7 @@ func initMetricVars(settings *MetricSettings) {
 	M_Alerting_Notification_Sent_OpsGenie = RegCounter("alerting.notifications_sent", "type", "opsgenie")
 	M_Alerting_Notification_Sent_OpsGenie = RegCounter("alerting.notifications_sent", "type", "opsgenie")
 	M_Alerting_Notification_Sent_Telegram = RegCounter("alerting.notifications_sent", "type", "telegram")
 	M_Alerting_Notification_Sent_Telegram = RegCounter("alerting.notifications_sent", "type", "telegram")
 	M_Alerting_Notification_Sent_Sensu = RegCounter("alerting.notifications_sent", "type", "sensu")
 	M_Alerting_Notification_Sent_Sensu = RegCounter("alerting.notifications_sent", "type", "sensu")
+	M_Alerting_Notification_Sent_LINE = RegCounter("alerting.notifications_sent", "type", "LINE")
 
 
 	M_Aws_CloudWatch_GetMetricStatistics = RegCounter("aws.cloudwatch.get_metric_statistics")
 	M_Aws_CloudWatch_GetMetricStatistics = RegCounter("aws.cloudwatch.get_metric_statistics")
 	M_Aws_CloudWatch_ListMetrics = RegCounter("aws.cloudwatch.list_metrics")
 	M_Aws_CloudWatch_ListMetrics = RegCounter("aws.cloudwatch.list_metrics")

+ 1 - 0
pkg/models/notifications.go

@@ -23,6 +23,7 @@ type SendWebhookSync struct {
 	Password   string
 	Password   string
 	Body       string
 	Body       string
 	HttpMethod string
 	HttpMethod string
+	HttpHeader map[string]string
 }
 }
 
 
 type SendResetPasswordEmailCommand struct {
 type SendResetPasswordEmailCommand struct {

+ 94 - 0
pkg/services/alerting/notifiers/line.go

@@ -0,0 +1,94 @@
+package notifiers
+
+import (
+	"github.com/grafana/grafana/pkg/log"
+	"github.com/grafana/grafana/pkg/services/alerting"
+	m "github.com/grafana/grafana/pkg/models"
+	"github.com/grafana/grafana/pkg/metrics"
+	"net/url"
+	"fmt"
+	"github.com/grafana/grafana/pkg/bus"
+)
+
+func init() {
+	alerting.RegisterNotifier(&alerting.NotifierPlugin{
+		Type: "LINE",
+		Name: "LINE",
+		Description: "Send notifications to LINE notify",
+		Factory: NewLINENotifier,
+		OptionsTemplate: `
+    <div class="gf-form-group">
+      <h3 class="page-heading">LINE notify settings</h3>
+      <div class="gf-form">
+        <span class="gf-form-label width-14">Token</span>
+        <input type="text" required class="gf-form-input max-width-22" ng-model="ctrl.model.settings.token" placeholder="LINE notify token key"></input>
+      </div>
+    </div>
+`,
+	})
+}
+
+const (
+	lineNotifyUrl string = "https://notify-api.line.me/api/notify"
+)
+
+func NewLINENotifier(model *m.AlertNotification) (alerting.Notifier, error) {
+	token := model.Settings.Get("token").MustString()
+	if token == "" {
+		return nil, alerting.ValidationError{Reason: "Could not find token in settings"}
+	}
+
+	return &LineNotifier{
+		NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
+		Token:        token,
+		log:          log.New("alerting.notifier.line"),
+	}, nil
+}
+
+type LineNotifier struct {
+	NotifierBase
+	Token string
+	log   log.Logger
+}
+
+func (this *LineNotifier) Notify(evalContext *alerting.EvalContext) error {
+	this.log.Info("Executing line notification", "ruleId", evalContext.Rule.Id, "notification", this.Name)
+	metrics.M_Alerting_Notification_Sent_LINE.Inc(1)
+
+	var err error
+	switch evalContext.Rule.State {
+	case m.AlertStateAlerting:
+		err = this.createAlert(evalContext)
+	}
+	return err
+}
+
+func (this *LineNotifier) createAlert(evalContext *alerting.EvalContext) error {
+	this.log.Info("Creating Line notify", "ruleId", evalContext.Rule.Id, "notification", this.Name)
+	ruleUrl, err := evalContext.GetRuleUrl()
+	if err != nil {
+		this.log.Error("Failed get rule link", "error", err)
+		return err
+	}
+
+	form := url.Values{}
+	body := fmt.Sprintf("%s - %s\n%s", evalContext.Rule.Name, ruleUrl, evalContext.Rule.Message)
+	form.Add("message", body)
+
+	cmd := &m.SendWebhookSync{
+		Url:        lineNotifyUrl,
+		HttpMethod: "POST",
+		HttpHeader: map[string]string{
+			"Authorization": fmt.Sprintf("Bearer %s", this.Token),
+			"Content-Type":  "application/x-www-form-urlencoded",
+		},
+		Body: form.Encode(),
+	}
+
+	if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
+		this.log.Error("Failed to send notification to LINE", "error", err, "body", string(body))
+		return err
+	}
+
+	return nil
+}

+ 50 - 0
pkg/services/alerting/notifiers/line_test.go

@@ -0,0 +1,50 @@
+
+package notifiers
+
+import (
+	"testing"
+
+	"github.com/grafana/grafana/pkg/components/simplejson"
+	m "github.com/grafana/grafana/pkg/models"
+	. "github.com/smartystreets/goconvey/convey"
+)
+
+func TestLineNotifier(t *testing.T) {
+	Convey("Line notifier tests", t, func() {
+		Convey("empty settings should return error", func() {
+			json := `{ }`
+
+			settingsJSON, _ := simplejson.NewJson([]byte(json))
+			model := &m.AlertNotification{
+				Name:     "line_testing",
+				Type:     "line",
+				Settings: settingsJSON,
+			}
+
+			_, err := NewLINENotifier(model)
+			So(err, ShouldNotBeNil)
+
+		})
+		Convey("settings should trigger incident", func() {
+			json := `
+			{
+  "token": "abcdefgh0123456789"
+			}`
+			settingsJSON, _ := simplejson.NewJson([]byte(json))
+			model := &m.AlertNotification{
+				Name:     "line_testing",
+				Type:     "line",
+				Settings: settingsJSON,
+			}
+
+			not, err := NewLINENotifier(model)
+			lineNotifier := not.(*LineNotifier)
+
+			So(err, ShouldBeNil)
+			So(lineNotifier.Name, ShouldEqual, "line_testing")
+			So(lineNotifier.Type, ShouldEqual, "line")
+			So(lineNotifier.Token, ShouldEqual, "abcdefgh0123456789")
+		})
+
+	})
+}

+ 1 - 0
pkg/services/notifications/notifications.go

@@ -65,6 +65,7 @@ func SendWebhookSync(ctx context.Context, cmd *m.SendWebhookSync) error {
 		Password:   cmd.Password,
 		Password:   cmd.Password,
 		Body:       cmd.Body,
 		Body:       cmd.Body,
 		HttpMethod: cmd.HttpMethod,
 		HttpMethod: cmd.HttpMethod,
+		HttpHeader: cmd.HttpHeader,
 	})
 	})
 }
 }
 
 

+ 7 - 0
pkg/services/notifications/webhook.go

@@ -19,6 +19,7 @@ type Webhook struct {
 	Password   string
 	Password   string
 	Body       string
 	Body       string
 	HttpMethod string
 	HttpMethod string
+	HttpHeader map[string]string
 }
 }
 
 
 var (
 var (
@@ -63,6 +64,12 @@ func sendWebRequestSync(ctx context.Context, webhook *Webhook) error {
 		request.Header.Add("Authorization", util.GetBasicAuthHeader(webhook.User, webhook.Password))
 		request.Header.Add("Authorization", util.GetBasicAuthHeader(webhook.User, webhook.Password))
 	}
 	}
 
 
+	if len(webhook.HttpHeader) != 0 {
+		for k, v := range webhook.HttpHeader {
+			request.Header.Set(k, v)
+		}
+	}
+
 	resp, err := ctxhttp.Do(ctx, http.DefaultClient, request)
 	resp, err := ctxhttp.Do(ctx, http.DefaultClient, request)
 	if err != nil {
 	if err != nil {
 		return err
 		return err