diff --git a/pkg/services/alerting/notifier.go b/pkg/services/alerting/notifier.go
index 32bece31820..c4c4dc45f50 100644
--- a/pkg/services/alerting/notifier.go
+++ b/pkg/services/alerting/notifier.go
@@ -65,7 +65,7 @@ func (n *notificationService) sendNotifications(context *EvalContext, notifiers
for _, notifier := range notifiers {
not := notifier //avoid updating scope variable in go routine
- n.log.Info("Sending notification", "type", not.GetType(), "id", not.GetNotifierId(), "isDefault", not.GetIsDefault())
+ n.log.Debug("Sending notification", "type", not.GetType(), "id", not.GetNotifierId(), "isDefault", not.GetIsDefault())
metrics.M_Alerting_Notification_Sent.WithLabelValues(not.GetType()).Inc()
g.Go(func() error { return not.Notify(context) })
}
diff --git a/pkg/services/alerting/notifiers/alertmanager.go b/pkg/services/alerting/notifiers/alertmanager.go
new file mode 100644
index 00000000000..08f8e8be29c
--- /dev/null
+++ b/pkg/services/alerting/notifiers/alertmanager.go
@@ -0,0 +1,96 @@
+package notifiers
+
+import (
+ "time"
+
+ "github.com/grafana/grafana/pkg/bus"
+ "github.com/grafana/grafana/pkg/components/simplejson"
+ "github.com/grafana/grafana/pkg/log"
+ m "github.com/grafana/grafana/pkg/models"
+ "github.com/grafana/grafana/pkg/services/alerting"
+)
+
+func init() {
+ alerting.RegisterNotifier(&alerting.NotifierPlugin{
+ Type: "prometheus-alertmanager",
+ Name: "Prometheus Alertmanager",
+ Description: "Sends alert to Prometheus Alertmanager",
+ Factory: NewAlertmanagerNotifier,
+ OptionsTemplate: `
+
Alertmanager settings
+
+ Url
+
+
+ `,
+ })
+}
+
+func NewAlertmanagerNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
+ url := model.Settings.Get("url").MustString()
+ if url == "" {
+ return nil, alerting.ValidationError{Reason: "Could not find url property in settings"}
+ }
+
+ return &AlertmanagerNotifier{
+ NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
+ Url: url,
+ log: log.New("alerting.notifier.prometheus-alertmanager"),
+ }, nil
+}
+
+type AlertmanagerNotifier struct {
+ NotifierBase
+ Url string
+ log log.Logger
+}
+
+func (this *AlertmanagerNotifier) ShouldNotify(evalContext *alerting.EvalContext) bool {
+ return evalContext.Rule.State == m.AlertStateAlerting
+}
+
+func (this *AlertmanagerNotifier) Notify(evalContext *alerting.EvalContext) error {
+
+ alerts := make([]interface{}, 0)
+ for _, match := range evalContext.EvalMatches {
+ alertJSON := simplejson.New()
+ alertJSON.Set("startsAt", evalContext.StartTime.UTC().Format(time.RFC3339))
+
+ if ruleUrl, err := evalContext.GetRuleUrl(); err == nil {
+ alertJSON.Set("generatorURL", ruleUrl)
+ }
+
+ if evalContext.Rule.Message != "" {
+ alertJSON.SetPath([]string{"annotations", "description"}, evalContext.Rule.Message)
+ }
+
+ tags := make(map[string]string)
+ if len(match.Tags) == 0 {
+ tags["metric"] = match.Metric
+ } else {
+ for k, v := range match.Tags {
+ tags[k] = v
+ }
+ }
+ tags["alertname"] = evalContext.Rule.Name
+ alertJSON.Set("labels", tags)
+
+ alerts = append(alerts, alertJSON)
+ }
+
+ bodyJSON := simplejson.NewFromAny(alerts)
+ body, _ := bodyJSON.MarshalJSON()
+
+ cmd := &m.SendWebhookSync{
+ Url: this.Url + "/api/v1/alerts",
+ HttpMethod: "POST",
+ Body: string(body),
+ }
+
+ if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
+ this.log.Error("Failed to send alertmanager", "error", err, "alertmanager", this.Name)
+ return err
+ }
+
+ return nil
+}
diff --git a/pkg/services/alerting/notifiers/alertmanager_test.go b/pkg/services/alerting/notifiers/alertmanager_test.go
new file mode 100644
index 00000000000..3549b536e48
--- /dev/null
+++ b/pkg/services/alerting/notifiers/alertmanager_test.go
@@ -0,0 +1,47 @@
+package notifiers
+
+import (
+ "testing"
+
+ "github.com/grafana/grafana/pkg/components/simplejson"
+ m "github.com/grafana/grafana/pkg/models"
+ . "github.com/smartystreets/goconvey/convey"
+)
+
+func TestAlertmanagerNotifier(t *testing.T) {
+ Convey("Alertmanager 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: "alertmanager",
+ Type: "alertmanager",
+ Settings: settingsJSON,
+ }
+
+ _, err := NewAlertmanagerNotifier(model)
+ So(err, ShouldNotBeNil)
+ })
+
+ Convey("from settings", func() {
+ json := `{ "url": "http://127.0.0.1:9093/" }`
+
+ settingsJSON, _ := simplejson.NewJson([]byte(json))
+ model := &m.AlertNotification{
+ Name: "alertmanager",
+ Type: "alertmanager",
+ Settings: settingsJSON,
+ }
+
+ not, err := NewAlertmanagerNotifier(model)
+ alertmanagerNotifier := not.(*AlertmanagerNotifier)
+
+ So(err, ShouldBeNil)
+ So(alertmanagerNotifier.Url, ShouldEqual, "http://127.0.0.1:9093/")
+ })
+ })
+ })
+}
diff --git a/pkg/services/alerting/notifiers/base.go b/pkg/services/alerting/notifiers/base.go
index 2308a5943d6..601f8fc24b1 100644
--- a/pkg/services/alerting/notifiers/base.go
+++ b/pkg/services/alerting/notifiers/base.go
@@ -15,7 +15,7 @@ type NotifierBase struct {
}
func NewNotifierBase(id int64, isDefault bool, name, notifierType string, model *simplejson.Json) NotifierBase {
- uploadImage := model.Get("uploadImage").MustBool(true)
+ uploadImage := model.Get("uploadImage").MustBool(false)
return NotifierBase{
Id: id,
diff --git a/pkg/services/alerting/notifiers/dingding_test.go b/pkg/services/alerting/notifiers/dingding_test.go
index b21815f95af..f89bf6382ce 100644
--- a/pkg/services/alerting/notifiers/dingding_test.go
+++ b/pkg/services/alerting/notifiers/dingding_test.go
@@ -25,10 +25,8 @@ func TestDingDingNotifier(t *testing.T) {
})
Convey("settings should trigger incident", func() {
- json := `
- {
- "url": "https://www.google.com"
- }`
+ json := `{ "url": "https://www.google.com" }`
+
settingsJSON, _ := simplejson.NewJson([]byte(json))
model := &m.AlertNotification{
Name: "dingding_testing",