ngalert: add addition temp translation endpoint (#32287)

spits out new sse condition/data json from old alert id to help with generating UI models
also moves this api code into another file
This commit is contained in:
Kyle Brandt
2021-03-24 12:12:34 -04:00
committed by GitHub
parent 6fa53a1ee4
commit 66548878fe
2 changed files with 153 additions and 104 deletions

View File

@@ -10,8 +10,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/expr/translate"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/models"
@@ -78,15 +76,6 @@ func (api *API) RegisterAPIEndpoints() {
alertDefinitions.Post("/unpause", middleware.ReqEditorRole, binding.Bind(ngmodels.UpdateAlertDefinitionPausedCommand{}), routing.Wrap(api.alertDefinitionUnpauseEndpoint))
})
api.RouteRegister.Group("/api/ngalert/", func(schedulerRouter routing.RouteRegister) {
schedulerRouter.Post("/pause", routing.Wrap(api.pauseScheduler))
schedulerRouter.Post("/unpause", routing.Wrap(api.unpauseScheduler))
}, middleware.ReqOrgAdmin)
api.RouteRegister.Group("/api/alert-instances", func(alertInstances routing.RouteRegister) {
alertInstances.Get("", middleware.ReqSignedIn, routing.Wrap(api.listAlertInstancesEndpoint))
})
if api.Cfg.Env == setting.Dev {
api.RouteRegister.Group("/api/alert-definitions", func(alertDefinitions routing.RouteRegister) {
alertDefinitions.Post("/evalOld", middleware.ReqSignedIn, routing.Wrap(api.conditionEvalOldEndpoint))
@@ -94,102 +83,18 @@ func (api *API) RegisterAPIEndpoints() {
api.RouteRegister.Group("/api/alert-definitions", func(alertDefinitions routing.RouteRegister) {
alertDefinitions.Get("/evalOldByID/:id", middleware.ReqSignedIn, routing.Wrap(api.conditionEvalOldEndpointByID))
})
}
}
// conditionEvalEndpoint handles POST /api/alert-definitions/evalOld.
func (api *API) conditionEvalOldEndpoint(c *models.ReqContext) response.Response {
b, err := c.Req.Body().Bytes()
if err != nil {
response.Error(400, "failed to read body", err)
}
evalCond, err := translate.DashboardAlertConditions(b, c.OrgId)
if err != nil {
return response.Error(400, "Failed to translate alert conditions", err)
api.RouteRegister.Group("/api/alert-definitions", func(alertDefinitions routing.RouteRegister) {
alertDefinitions.Get("/oldByID/:id", middleware.ReqSignedIn, routing.Wrap(api.conditionOldEndpointByID))
})
}
if err := api.validateCondition(*evalCond, c.SignedInUser, c.SkipCache); err != nil {
return response.Error(400, "invalid condition", err)
}
api.RouteRegister.Group("/api/ngalert/", func(schedulerRouter routing.RouteRegister) {
schedulerRouter.Post("/pause", routing.Wrap(api.pauseScheduler))
schedulerRouter.Post("/unpause", routing.Wrap(api.unpauseScheduler))
}, middleware.ReqOrgAdmin)
//now := cmd.Now
//if now.IsZero() {
//now := timeNow()
//}
evaluator := eval.Evaluator{Cfg: api.Cfg}
evalResults, err := evaluator.ConditionEval(evalCond, timeNow(), api.DataService)
if err != nil {
return response.Error(400, "Failed to evaluate conditions", err)
}
frame := evalResults.AsDataFrame()
df := plugins.NewDecodedDataFrames([]*data.Frame{&frame})
instances, err := df.Encoded()
if err != nil {
return response.Error(400, "Failed to encode result dataframes", err)
}
return response.JSON(200, util.DynMap{
"instances": instances,
})
}
// conditionEvalEndpoint handles POST /api/alert-definitions/evalOld.
func (api *API) conditionEvalOldEndpointByID(c *models.ReqContext) response.Response {
id := c.ParamsInt64("id")
if id == 0 {
return response.Error(400, "missing id", nil)
}
getAlert := &models.GetAlertByIdQuery{
Id: id,
}
if err := bus.Dispatch(getAlert); err != nil {
return response.Error(400, fmt.Sprintf("could find alert with id %v", id), err)
}
if getAlert.Result.OrgId != c.SignedInUser.OrgId {
return response.Error(403, "alert does not match organization of user", nil)
}
settings := getAlert.Result.Settings
sb, err := settings.ToDB()
if err != nil {
return response.Error(400, "failed to marshal alert settings", err)
}
evalCond, err := translate.DashboardAlertConditions(sb, c.OrgId)
if err != nil {
return response.Error(400, "Failed to translate alert conditions", err)
}
if err := api.validateCondition(*evalCond, c.SignedInUser, c.SkipCache); err != nil {
return response.Error(400, "invalid condition", err)
}
//now := cmd.Now
//if now.IsZero() {
//now := timeNow()
//}
evaluator := eval.Evaluator{Cfg: api.Cfg}
evalResults, err := evaluator.ConditionEval(evalCond, timeNow(), api.DataService)
if err != nil {
return response.Error(400, "Failed to evaluate conditions", err)
}
frame := evalResults.AsDataFrame()
df := plugins.NewDecodedDataFrames([]*data.Frame{&frame})
instances, err := df.Encoded()
if err != nil {
return response.Error(400, "Failed to encode result dataframes", err)
}
return response.JSON(200, util.DynMap{
"instances": instances,
api.RouteRegister.Group("/api/alert-instances", func(alertInstances routing.RouteRegister) {
alertInstances.Get("", middleware.ReqSignedIn, routing.Wrap(api.listAlertInstancesEndpoint))
})
}

View File

@@ -0,0 +1,144 @@
package api
import (
"fmt"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/expr/translate"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/ngalert/eval"
"github.com/grafana/grafana/pkg/util"
)
// conditionEvalEndpoint handles POST /api/alert-definitions/evalOld.
func (api *API) conditionEvalOldEndpoint(c *models.ReqContext) response.Response {
b, err := c.Req.Body().Bytes()
if err != nil {
response.Error(400, "failed to read body", err)
}
evalCond, err := translate.DashboardAlertConditions(b, c.OrgId)
if err != nil {
return response.Error(400, "Failed to translate alert conditions", err)
}
if err := api.validateCondition(*evalCond, c.SignedInUser, c.SkipCache); err != nil {
return response.Error(400, "invalid condition", err)
}
//now := cmd.Now
//if now.IsZero() {
//now := timeNow()
//}
evaluator := eval.Evaluator{Cfg: api.Cfg}
evalResults, err := evaluator.ConditionEval(evalCond, timeNow(), api.DataService)
if err != nil {
return response.Error(400, "Failed to evaluate conditions", err)
}
frame := evalResults.AsDataFrame()
df := plugins.NewDecodedDataFrames([]*data.Frame{&frame})
instances, err := df.Encoded()
if err != nil {
return response.Error(400, "Failed to encode result dataframes", err)
}
return response.JSON(200, util.DynMap{
"instances": instances,
})
}
// conditionEvalEndpoint handles POST /api/alert-definitions/evalOld.
func (api *API) conditionEvalOldEndpointByID(c *models.ReqContext) response.Response {
id := c.ParamsInt64("id")
if id == 0 {
return response.Error(400, "missing id", nil)
}
getAlert := &models.GetAlertByIdQuery{
Id: id,
}
if err := bus.Dispatch(getAlert); err != nil {
return response.Error(400, fmt.Sprintf("could find alert with id %v", id), err)
}
if getAlert.Result.OrgId != c.SignedInUser.OrgId {
return response.Error(403, "alert does not match organization of user", nil)
}
settings := getAlert.Result.Settings
sb, err := settings.ToDB()
if err != nil {
return response.Error(400, "failed to marshal alert settings", err)
}
evalCond, err := translate.DashboardAlertConditions(sb, c.OrgId)
if err != nil {
return response.Error(400, "Failed to translate alert conditions", err)
}
if err := api.validateCondition(*evalCond, c.SignedInUser, c.SkipCache); err != nil {
return response.Error(400, "invalid condition", err)
}
//now := cmd.Now
//if now.IsZero() {
//now := timeNow()
//}
evaluator := eval.Evaluator{Cfg: api.Cfg}
evalResults, err := evaluator.ConditionEval(evalCond, timeNow(), api.DataService)
if err != nil {
return response.Error(400, "Failed to evaluate conditions", err)
}
frame := evalResults.AsDataFrame()
df := plugins.NewDecodedDataFrames([]*data.Frame{&frame})
instances, err := df.Encoded()
if err != nil {
return response.Error(400, "Failed to encode result dataframes", err)
}
return response.JSON(200, util.DynMap{
"instances": instances,
})
}
// conditionEvalEndpoint handles POST /api/alert-definitions/evalOld.
func (api *API) conditionOldEndpointByID(c *models.ReqContext) response.Response {
id := c.ParamsInt64("id")
if id == 0 {
return response.Error(400, "missing id", nil)
}
getAlert := &models.GetAlertByIdQuery{
Id: id,
}
if err := bus.Dispatch(getAlert); err != nil {
return response.Error(400, fmt.Sprintf("could find alert with id %v", id), err)
}
if getAlert.Result.OrgId != c.SignedInUser.OrgId {
return response.Error(403, "alert does not match organization of user", nil)
}
settings := getAlert.Result.Settings
sb, err := settings.ToDB()
if err != nil {
return response.Error(400, "failed to marshal alert settings", err)
}
evalCond, err := translate.DashboardAlertConditions(sb, c.OrgId)
if err != nil {
return response.Error(400, "Failed to translate alert conditions", err)
}
return response.JSON(200, evalCond)
}