Skip to content

Commit

Permalink
AlertingNG: Edit Alert Definition (grafana#30676)
Browse files Browse the repository at this point in the history
* break out new and edit

* changed model to match new model in backend

* AlertingNG: API modifications (grafana#30683)

* Fix API consistency

* Change eval alert definition to POST request

* Fix eval endpoint to accept custom now parameter

* Change JSON input property for create/update endpoints

* model adjustments

* set mixed datasource, fix put url

* update snapshots

* remove edit and add landing page

* remove snapshot tests ans snapshots

* wrap linkbutton in array

Co-authored-by: Sofia Papagiannaki <papagian@users.noreply.github.com>
Co-authored-by: Sofia Papagiannaki <sofia@grafana.com>
  • Loading branch information
3 people authored Feb 4, 2021
1 parent 2181705 commit aaf5710
Show file tree
Hide file tree
Showing 16 changed files with 287 additions and 471 deletions.
10 changes: 0 additions & 10 deletions pkg/api/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,16 +196,6 @@ func (hs *HTTPServer) getNavTree(c *models.ReqContext, hasEditPerm bool) ([]*dto
})
}

if hs.Cfg.IsNgAlertEnabled() {
navTree = append(navTree, &dtos.NavLink{
Text: "NgAlerting",
Id: "ngalerting",
SubTitle: "Next generation alerting",
Icon: "bell",
Url: setting.AppSubUrl + "/ngalerting",
})
}

if c.IsSignedIn {
navTree = append(navTree, getProfileNode(c))
}
Expand Down
33 changes: 27 additions & 6 deletions pkg/services/ngalert/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,24 @@ func (ng *AlertNG) registerAPIEndpoints() {
}

// conditionEvalEndpoint handles POST /api/alert-definitions/eval.
func (ng *AlertNG) conditionEvalEndpoint(c *models.ReqContext, dto evalAlertConditionCommand) response.Response {
if err := ng.validateCondition(dto.Condition, c.SignedInUser, c.SkipCache); err != nil {
func (ng *AlertNG) conditionEvalEndpoint(c *models.ReqContext, cmd evalAlertConditionCommand) response.Response {
evalCond := eval.Condition{
RefID: cmd.Condition,
OrgID: c.SignedInUser.OrgId,
QueriesAndExpressions: cmd.Data,
}
if err := ng.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: ng.Cfg}
evalResults, err := evaluator.ConditionEval(&dto.Condition, timeNow())

evalResults, err := evaluator.ConditionEval(&evalCond, now)
if err != nil {
return response.Error(400, "Failed to evaluate conditions", err)
}
Expand All @@ -61,7 +72,7 @@ func (ng *AlertNG) conditionEvalEndpoint(c *models.ReqContext, dto evalAlertCond
})
}

// alertDefinitionEvalEndpoint handles GET /api/alert-definitions/eval/:alertDefinitionUID.
// alertDefinitionEvalEndpoint handles POST /api/alert-definitions/eval/:alertDefinitionUID.
func (ng *AlertNG) alertDefinitionEvalEndpoint(c *models.ReqContext) response.Response {
alertDefinitionUID := c.Params(":alertDefinitionUID")

Expand Down Expand Up @@ -132,7 +143,12 @@ func (ng *AlertNG) updateAlertDefinitionEndpoint(c *models.ReqContext, cmd updat
cmd.UID = c.Params(":alertDefinitionUID")
cmd.OrgID = c.SignedInUser.OrgId

if err := ng.validateCondition(cmd.Condition, c.SignedInUser, c.SkipCache); err != nil {
evalCond := eval.Condition{
RefID: cmd.Condition,
OrgID: c.SignedInUser.OrgId,
QueriesAndExpressions: cmd.Data,
}
if err := ng.validateCondition(evalCond, c.SignedInUser, c.SkipCache); err != nil {
return response.Error(400, "invalid condition", err)
}

Expand All @@ -147,7 +163,12 @@ func (ng *AlertNG) updateAlertDefinitionEndpoint(c *models.ReqContext, cmd updat
func (ng *AlertNG) createAlertDefinitionEndpoint(c *models.ReqContext, cmd saveAlertDefinitionCommand) response.Response {
cmd.OrgID = c.SignedInUser.OrgId

if err := ng.validateCondition(cmd.Condition, c.SignedInUser, c.SkipCache); err != nil {
evalCond := eval.Condition{
RefID: cmd.Condition,
OrgID: c.SignedInUser.OrgId,
QueriesAndExpressions: cmd.Data,
}
if err := ng.validateCondition(evalCond, c.SignedInUser, c.SkipCache); err != nil {
return response.Error(400, "invalid condition", err)
}

Expand Down
22 changes: 10 additions & 12 deletions pkg/services/ngalert/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,21 @@ func overrideAlertNGInRegistry(cfg *setting.Cfg) AlertNG {

func createTestAlertDefinition(t *testing.T, ng *AlertNG, intervalSeconds int64) *AlertDefinition {
cmd := saveAlertDefinitionCommand{
OrgID: 1,
Title: fmt.Sprintf("an alert definition %d", rand.Intn(1000)),
Condition: eval.Condition{
RefID: "A",
QueriesAndExpressions: []eval.AlertQuery{
{
Model: json.RawMessage(`{
OrgID: 1,
Title: fmt.Sprintf("an alert definition %d", rand.Intn(1000)),
Condition: "A",
Data: []eval.AlertQuery{
{
Model: json.RawMessage(`{
"datasource": "__expr__",
"type":"math",
"expression":"2 + 2 > 1"
}`),
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(5 * time.Hour),
To: eval.Duration(3 * time.Hour),
},
RefID: "A",
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(5 * time.Hour),
To: eval.Duration(3 * time.Hour),
},
RefID: "A",
},
},
IntervalSeconds: &intervalSeconds,
Expand Down
8 changes: 4 additions & 4 deletions pkg/services/ngalert/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ func (ng *AlertNG) saveAlertDefinition(cmd *saveAlertDefinitionCommand) error {
alertDefinition := &AlertDefinition{
OrgID: cmd.OrgID,
Title: cmd.Title,
Condition: cmd.Condition.RefID,
Data: cmd.Condition.QueriesAndExpressions,
Condition: cmd.Condition,
Data: cmd.Data,
IntervalSeconds: intervalSeconds,
Version: initialVersion,
UID: uid,
Expand Down Expand Up @@ -133,11 +133,11 @@ func (ng *AlertNG) updateAlertDefinition(cmd *updateAlertDefinitionCommand) erro
if title == "" {
title = existingAlertDefinition.Title
}
condition := cmd.Condition.RefID
condition := cmd.Condition
if condition == "" {
condition = existingAlertDefinition.Condition
}
data := cmd.Condition.QueriesAndExpressions
data := cmd.Data
if data == nil {
data = existingAlertDefinition.Data
}
Expand Down
110 changes: 50 additions & 60 deletions pkg/services/ngalert/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,22 +74,20 @@ func TestCreatingAlertDefinition(t *testing.T) {
t.Cleanup(registry.ClearOverrides)

q := saveAlertDefinitionCommand{
OrgID: 1,
Title: tc.inputTitle,
Condition: eval.Condition{
RefID: "B",
QueriesAndExpressions: []eval.AlertQuery{
{
Model: json.RawMessage(`{
OrgID: 1,
Title: tc.inputTitle,
Condition: "B",
Data: []eval.AlertQuery{
{
Model: json.RawMessage(`{
"datasource": "__expr__",
"type":"math",
"expression":"2 + 3 > 1"
}`),
RefID: "B",
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(time.Duration(5) * time.Hour),
To: eval.Duration(time.Duration(3) * time.Hour),
},
RefID: "B",
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(time.Duration(5) * time.Hour),
To: eval.Duration(time.Duration(3) * time.Hour),
},
},
},
Expand Down Expand Up @@ -117,22 +115,20 @@ func TestCreatingConflictionAlertDefinition(t *testing.T) {
t.Cleanup(registry.ClearOverrides)

q := saveAlertDefinitionCommand{
OrgID: 1,
Title: "title",
Condition: eval.Condition{
RefID: "B",
QueriesAndExpressions: []eval.AlertQuery{
{
Model: json.RawMessage(`{
OrgID: 1,
Title: "title",
Condition: "B",
Data: []eval.AlertQuery{
{
Model: json.RawMessage(`{
"datasource": "__expr__",
"type":"math",
"expression":"2 + 3 > 1"
}`),
RefID: "B",
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(time.Duration(5) * time.Hour),
To: eval.Duration(time.Duration(3) * time.Hour),
},
RefID: "B",
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(time.Duration(5) * time.Hour),
To: eval.Duration(time.Duration(3) * time.Hour),
},
},
},
Expand All @@ -156,23 +152,21 @@ func TestUpdatingAlertDefinition(t *testing.T) {
t.Cleanup(registry.ClearOverrides)

q := updateAlertDefinitionCommand{
UID: "unknown",
OrgID: 1,
Title: "something completely different",
Condition: eval.Condition{
RefID: "A",
QueriesAndExpressions: []eval.AlertQuery{
{
Model: json.RawMessage(`{
UID: "unknown",
OrgID: 1,
Title: "something completely different",
Condition: "A",
Data: []eval.AlertQuery{
{
Model: json.RawMessage(`{
"datasource": "__expr__",
"type":"math",
"expression":"2 + 2 > 1"
}`),
RefID: "A",
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(time.Duration(5) * time.Hour),
To: eval.Duration(time.Duration(3) * time.Hour),
},
RefID: "A",
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(time.Duration(5) * time.Hour),
To: eval.Duration(time.Duration(3) * time.Hour),
},
},
},
Expand Down Expand Up @@ -250,21 +244,19 @@ func TestUpdatingAlertDefinition(t *testing.T) {
}

q := updateAlertDefinitionCommand{
UID: (*alertDefinition).UID,
Condition: eval.Condition{
RefID: "B",
QueriesAndExpressions: []eval.AlertQuery{
{
Model: json.RawMessage(`{
UID: (*alertDefinition).UID,
Condition: "B",
Data: []eval.AlertQuery{
{
Model: json.RawMessage(`{
"datasource": "__expr__",
"type":"math",
"expression":"2 + 3 > 1"
}`),
RefID: "B",
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(5 * time.Hour),
To: eval.Duration(3 * time.Hour),
},
RefID: "B",
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(5 * time.Hour),
To: eval.Duration(3 * time.Hour),
},
},
},
Expand Down Expand Up @@ -335,22 +327,20 @@ func TestUpdatingConflictingAlertDefinition(t *testing.T) {
alertDef2 := createTestAlertDefinition(t, ng, initialInterval)

q := updateAlertDefinitionCommand{
UID: (*alertDef2).UID,
Title: alertDef1.Title,
Condition: eval.Condition{
RefID: "B",
QueriesAndExpressions: []eval.AlertQuery{
{
Model: json.RawMessage(`{
UID: (*alertDef2).UID,
Title: alertDef1.Title,
Condition: "B",
Data: []eval.AlertQuery{
{
Model: json.RawMessage(`{
"datasource": "__expr__",
"type":"math",
"expression":"2 + 3 > 1"
}`),
RefID: "B",
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(5 * time.Hour),
To: eval.Duration(3 * time.Hour),
},
RefID: "B",
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(5 * time.Hour),
To: eval.Duration(3 * time.Hour),
},
},
},
Expand Down
25 changes: 14 additions & 11 deletions pkg/services/ngalert/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,28 +73,31 @@ type deleteAlertDefinitionByUIDCommand struct {

// saveAlertDefinitionCommand is the query for saving a new alert definition.
type saveAlertDefinitionCommand struct {
Title string `json:"title"`
OrgID int64 `json:"-"`
Condition eval.Condition `json:"condition"`
IntervalSeconds *int64 `json:"interval_seconds"`
Title string `json:"title"`
OrgID int64 `json:"-"`
Condition string `json:"condition"`
Data []eval.AlertQuery `json:"data"`
IntervalSeconds *int64 `json:"intervalSeconds"`

Result *AlertDefinition
}

// updateAlertDefinitionCommand is the query for updating an existing alert definition.
type updateAlertDefinitionCommand struct {
Title string `json:"title"`
OrgID int64 `json:"-"`
Condition eval.Condition `json:"condition"`
IntervalSeconds *int64 `json:"interval_seconds"`
UID string `json:"-"`
Title string `json:"title"`
OrgID int64 `json:"-"`
Condition string `json:"condition"`
Data []eval.AlertQuery `json:"data"`
IntervalSeconds *int64 `json:"intervalSeconds"`
UID string `json:"-"`

Result *AlertDefinition
}

type evalAlertConditionCommand struct {
Condition eval.Condition `json:"condition"`
Now time.Time `json:"now"`
Condition string `json:"condition"`
Data []eval.AlertQuery `json:"data"`
Now time.Time `json:"now"`
}

type listAlertDefinitionsQuery struct {
Expand Down
Loading

0 comments on commit aaf5710

Please sign in to comment.