diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go
index 06302484cda..1020f28f874 100644
--- a/pkg/metrics/metrics.go
+++ b/pkg/metrics/metrics.go
@@ -45,6 +45,7 @@ var (
M_Alerting_Notification_Sent_Email Counter
M_Alerting_Notification_Sent_Webhook Counter
M_Alerting_Notification_Sent_PagerDuty Counter
+ M_Alerting_Notification_Sent_LINE Counter
M_Alerting_Notification_Sent_Victorops Counter
M_Alerting_Notification_Sent_OpsGenie 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_Telegram = RegCounter("alerting.notifications_sent", "type", "telegram")
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_ListMetrics = RegCounter("aws.cloudwatch.list_metrics")
diff --git a/pkg/models/notifications.go b/pkg/models/notifications.go
index 42ebda9ea44..ad7aed3bc50 100644
--- a/pkg/models/notifications.go
+++ b/pkg/models/notifications.go
@@ -23,6 +23,7 @@ type SendWebhookSync struct {
Password string
Body string
HttpMethod string
+ HttpHeader map[string]string
}
type SendResetPasswordEmailCommand struct {
diff --git a/pkg/services/alerting/notifiers/line.go b/pkg/services/alerting/notifiers/line.go
new file mode 100644
index 00000000000..bf15c497f2c
--- /dev/null
+++ b/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: `
+
+`,
+ })
+}
+
+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
+}
diff --git a/pkg/services/alerting/notifiers/line_test.go b/pkg/services/alerting/notifiers/line_test.go
new file mode 100644
index 00000000000..8d11cc6e1bf
--- /dev/null
+++ b/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")
+ })
+
+ })
+}
diff --git a/pkg/services/notifications/notifications.go b/pkg/services/notifications/notifications.go
index c1ed9ac9e74..095ce15ef32 100644
--- a/pkg/services/notifications/notifications.go
+++ b/pkg/services/notifications/notifications.go
@@ -65,6 +65,7 @@ func SendWebhookSync(ctx context.Context, cmd *m.SendWebhookSync) error {
Password: cmd.Password,
Body: cmd.Body,
HttpMethod: cmd.HttpMethod,
+ HttpHeader: cmd.HttpHeader,
})
}
diff --git a/pkg/services/notifications/webhook.go b/pkg/services/notifications/webhook.go
index ac46a43f294..584d22e8b1b 100644
--- a/pkg/services/notifications/webhook.go
+++ b/pkg/services/notifications/webhook.go
@@ -19,6 +19,7 @@ type Webhook struct {
Password string
Body string
HttpMethod string
+ HttpHeader map[string]string
}
var (
@@ -63,6 +64,12 @@ func sendWebRequestSync(ctx context.Context, webhook *Webhook) error {
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)
if err != nil {
return err