ソースを参照

feat(alerting): began work on testing alert rule from UI without having to save it

Torkel Ödegaard 9 年 前
コミット
fb636344a6
4 ファイル変更90 行追加1 行削除
  1. 16 0
      pkg/api/alerting.go
  2. 1 0
      pkg/api/api.go
  3. 10 1
      pkg/api/dtos/alerting.go
  4. 63 0
      pkg/services/alerting/test_rule.go

+ 16 - 0
pkg/api/alerting.go

@@ -5,6 +5,7 @@ import (
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/middleware"
 	"github.com/grafana/grafana/pkg/middleware"
 	"github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/models"
+	"github.com/grafana/grafana/pkg/services/alerting"
 )
 )
 
 
 func ValidateOrgAlert(c *middleware.Context) {
 func ValidateOrgAlert(c *middleware.Context) {
@@ -71,6 +72,21 @@ func GetAlerts(c *middleware.Context) Response {
 	return Json(200, alertDTOs)
 	return Json(200, alertDTOs)
 }
 }
 
 
+// POST /api/alerts/test
+func TestAlertRule(c *middleware.Context, dto dtos.TestAlertRuleCommand) Response {
+	backendCmd := alerting.TestAlertRuleCommand{
+		OrgId:     c.OrgId,
+		Dashboard: dto.Dashboard,
+		PanelId:   dto.PanelId,
+	}
+
+	if err := bus.Dispatch(&backendCmd); err != nil {
+		return ApiError(500, "Failed to test rule", err)
+	}
+
+	return Json(200, backendCmd.Result)
+}
+
 // GET /api/alerts/:id
 // GET /api/alerts/:id
 func GetAlert(c *middleware.Context) Response {
 func GetAlert(c *middleware.Context) Response {
 	id := c.ParamsInt64(":alertId")
 	id := c.ParamsInt64(":alertId")

+ 1 - 0
pkg/api/api.go

@@ -246,6 +246,7 @@ func Register(r *macaron.Macaron) {
 		r.Get("/metrics", wrap(GetInternalMetrics))
 		r.Get("/metrics", wrap(GetInternalMetrics))
 
 
 		r.Group("/alerts", func() {
 		r.Group("/alerts", func() {
+			r.Post("/test", bind(dtos.TestAlertRuleCommand{}), wrap(TestAlertRule))
 			r.Get("/:alertId/states", wrap(GetAlertStates))
 			r.Get("/:alertId/states", wrap(GetAlertStates))
 			//r.Put("/:alertId/state", bind(m.UpdateAlertStateCommand{}), wrap(PutAlertState))
 			//r.Put("/:alertId/state", bind(m.UpdateAlertStateCommand{}), wrap(PutAlertState))
 			r.Get("/:alertId", ValidateOrgAlert, wrap(GetAlert))
 			r.Get("/:alertId", ValidateOrgAlert, wrap(GetAlert))

+ 10 - 1
pkg/api/dtos/alerting.go

@@ -1,6 +1,10 @@
 package dtos
 package dtos
 
 
-import "time"
+import (
+	"time"
+
+	"github.com/grafana/grafana/pkg/components/simplejson"
+)
 
 
 type AlertRuleDTO struct {
 type AlertRuleDTO struct {
 	Id           int64   `json:"id"`
 	Id           int64   `json:"id"`
@@ -29,3 +33,8 @@ type AlertNotificationDTO struct {
 	Created time.Time `json:"created"`
 	Created time.Time `json:"created"`
 	Updated time.Time `json:"updated"`
 	Updated time.Time `json:"updated"`
 }
 }
+
+type TestAlertRuleCommand struct {
+	Dashboard *simplejson.Json `json:"dashboard"`
+	PanelId   int64            `json:"panelId"`
+}

+ 63 - 0
pkg/services/alerting/test_rule.go

@@ -0,0 +1,63 @@
+package alerting
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/grafana/grafana/pkg/bus"
+	"github.com/grafana/grafana/pkg/components/simplejson"
+	m "github.com/grafana/grafana/pkg/models"
+)
+
+type TestAlertRuleCommand struct {
+	Dashboard *simplejson.Json
+	PanelId   int64
+	OrgId     int64
+
+	Result *AlertResultContext
+}
+
+func init() {
+	bus.AddHandler("alerting", handleTestAlertRuleCommand)
+}
+
+func handleTestAlertRuleCommand(cmd *TestAlertRuleCommand) error {
+
+	dash, err := m.NewDashboardFromJson(cmd.Dashboard)
+	if err != nil {
+		return err
+	}
+
+	extractor := NewDashAlertExtractor(cmd.Dashboard)
+	rules, err := extractor.GetAlerts()
+	if err != nil {
+		return err
+	}
+
+	for _, rule := range rules {
+		if rule.PanelId == cmd.PanelId {
+			if res, err := testAlertRule(rule); err != nil {
+				return err
+			} else {
+				cmd.Result = res
+				return nil
+			}
+		}
+	}
+
+	return fmt.Errorf("Could not find alert with panel id %d", cmd.PanelId)
+}
+
+func testAlertRule(rule *AlertRule) (*AlertResultContext, error) {
+	handler := NewHandler()
+
+	resultChan := make(chan *AlertResultContext, 1)
+	handler.Execute(rule, resultChan)
+
+	select {
+	case <-time.After(time.Second * 10):
+		return &AlertResultContext{Error: fmt.Errorf("Timeout")}, nil
+	case result := <-resultChan:
+		return result, nil
+	}
+}