diff --git a/pkg/api/alerting.go b/pkg/api/alerting.go index 23e389f5990..f9605312574 100644 --- a/pkg/api/alerting.go +++ b/pkg/api/alerting.go @@ -5,6 +5,7 @@ import ( "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/middleware" "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/alerting" ) func ValidateOrgAlert(c *middleware.Context) { @@ -71,6 +72,21 @@ func GetAlerts(c *middleware.Context) Response { 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 func GetAlert(c *middleware.Context) Response { id := c.ParamsInt64(":alertId") diff --git a/pkg/api/api.go b/pkg/api/api.go index 4d2430a7c35..5e2d457b1e3 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -246,6 +246,7 @@ func Register(r *macaron.Macaron) { r.Get("/metrics", wrap(GetInternalMetrics)) r.Group("/alerts", func() { + r.Post("/test", bind(dtos.TestAlertRuleCommand{}), wrap(TestAlertRule)) r.Get("/:alertId/states", wrap(GetAlertStates)) //r.Put("/:alertId/state", bind(m.UpdateAlertStateCommand{}), wrap(PutAlertState)) r.Get("/:alertId", ValidateOrgAlert, wrap(GetAlert)) diff --git a/pkg/api/dtos/alerting.go b/pkg/api/dtos/alerting.go index b07ea9cd8b2..e9c57b57ce2 100644 --- a/pkg/api/dtos/alerting.go +++ b/pkg/api/dtos/alerting.go @@ -1,6 +1,10 @@ package dtos -import "time" +import ( + "time" + + "github.com/grafana/grafana/pkg/components/simplejson" +) type AlertRuleDTO struct { Id int64 `json:"id"` @@ -29,3 +33,8 @@ type AlertNotificationDTO struct { Created time.Time `json:"created"` Updated time.Time `json:"updated"` } + +type TestAlertRuleCommand struct { + Dashboard *simplejson.Json `json:"dashboard"` + PanelId int64 `json:"panelId"` +} diff --git a/pkg/services/alerting/test_rule.go b/pkg/services/alerting/test_rule.go new file mode 100644 index 00000000000..0d51748a5da --- /dev/null +++ b/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 + } +}