mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* Alerting NG: prototype v2 (WIP) * Separate eval package * Modify eval alert definition endpoint * Disable migration if ngalert is not enabled * Remove premature test * Fix lint issues * Delete obsolete struct * Apply suggestions from code review * Update pkg/services/ngalert/ngalert.go Co-authored-by: Kyle Brandt <kyle@grafana.com> * Add API endpoint for listing alert definitions * Introduce index for alert_definition table * make ds object for expression to avoid panic * wrap error * Update pkg/services/ngalert/eval/eval.go * Swith to backend.DataQuery * Export TransformWrapper callback * Fix lint issues * Update pkg/services/ngalert/ngalert.go Co-authored-by: Kyle Brandt <kyle@grafana.com> * Validate alert definitions before storing them * Introduce AlertQuery * Add test * Add QueryType in AlertQuery * Accept only float64 (seconds) durations * Apply suggestions from code review * Get rid of bus * Do not export symbols * Fix failing test * Fix failure due to service initialization order Introduce MediumHigh service priority and assign it to backendplugin service * Fix test * Apply suggestions from code review * Fix renamed reference Co-authored-by: Kyle Brandt <kyle@grafana.com>
182 lines
4.4 KiB
Go
182 lines
4.4 KiB
Go
// +build integration
|
|
|
|
package ngalert
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/grafana/grafana/pkg/services/ngalert/eval"
|
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestCreatingAlertDefinition(t *testing.T) {
|
|
t.Run("should fail gracefully when creating alert definition with invalid relative time range", func(t *testing.T) {
|
|
ng := setupTestEnv(t)
|
|
q := saveAlertDefinitionCommand{
|
|
OrgID: 1,
|
|
Name: "something completely different",
|
|
Condition: condition{
|
|
RefID: "B",
|
|
QueriesAndExpressions: []eval.AlertQuery{
|
|
{
|
|
Model: json.RawMessage(`{
|
|
"datasource": "__expr__",
|
|
"type":"math",
|
|
"expression":"2 + 3 > 1"
|
|
}`),
|
|
RefID: "B",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
err := ng.saveAlertDefinition(&q)
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
}
|
|
|
|
func TestUpdatingAlertDefinition(t *testing.T) {
|
|
t.Run("zero rows affected when updating unknown alert", func(t *testing.T) {
|
|
ng := setupTestEnv(t)
|
|
|
|
q := updateAlertDefinitionCommand{
|
|
ID: 1,
|
|
OrgID: 1,
|
|
Name: "something completely different",
|
|
Condition: condition{
|
|
RefID: "A",
|
|
QueriesAndExpressions: []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),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
err := ng.updateAlertDefinition(&q)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(0), q.RowsAffected)
|
|
})
|
|
|
|
t.Run("updating successfully existing alert", func(t *testing.T) {
|
|
ng := setupTestEnv(t)
|
|
alertDefinition := createTestAlertDefinition(t, ng)
|
|
|
|
q := updateAlertDefinitionCommand{
|
|
ID: (*alertDefinition).Id,
|
|
OrgID: 1,
|
|
Name: "something completely different",
|
|
Condition: condition{
|
|
RefID: "B",
|
|
QueriesAndExpressions: []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),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
err := ng.updateAlertDefinition(&q)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(1), q.RowsAffected)
|
|
assert.Equal(t, int64(1), q.Result.Id)
|
|
|
|
getAlertDefinitionByIDQuery := getAlertDefinitionByIDQuery{ID: (*alertDefinition).Id}
|
|
err = ng.getAlertDefinitionByID(&getAlertDefinitionByIDQuery)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "something completely different", getAlertDefinitionByIDQuery.Result.Name)
|
|
assert.Equal(t, "B", getAlertDefinitionByIDQuery.Result.Condition)
|
|
assert.Equal(t, 1, len(getAlertDefinitionByIDQuery.Result.Data))
|
|
})
|
|
}
|
|
|
|
func TestDeletingAlertDefinition(t *testing.T) {
|
|
t.Run("zero rows affected when deleting unknown alert", func(t *testing.T) {
|
|
ng := setupTestEnv(t)
|
|
|
|
q := deleteAlertDefinitionByIDQuery{
|
|
ID: 1,
|
|
OrgID: 1,
|
|
}
|
|
|
|
err := ng.deleteAlertDefinitionByID(&q)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(0), q.RowsAffected)
|
|
})
|
|
|
|
t.Run("deleting successfully existing alert", func(t *testing.T) {
|
|
ng := setupTestEnv(t)
|
|
alertDefinition := createTestAlertDefinition(t, ng)
|
|
|
|
q := deleteAlertDefinitionByIDQuery{
|
|
ID: (*alertDefinition).Id,
|
|
OrgID: 1,
|
|
}
|
|
|
|
err := ng.deleteAlertDefinitionByID(&q)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(1), q.RowsAffected)
|
|
})
|
|
}
|
|
|
|
func setupTestEnv(t *testing.T) AlertNG {
|
|
sqlStore := sqlstore.InitTestDB(t)
|
|
cfg := setting.Cfg{}
|
|
cfg.FeatureToggles = map[string]bool{"ngalert": true}
|
|
ng := AlertNG{
|
|
SQLStore: sqlStore,
|
|
Cfg: &cfg,
|
|
}
|
|
return ng
|
|
}
|
|
|
|
func createTestAlertDefinition(t *testing.T, ng AlertNG) *AlertDefinition {
|
|
cmd := saveAlertDefinitionCommand{
|
|
OrgID: 1,
|
|
Name: "an alert definition",
|
|
Condition: condition{
|
|
RefID: "A",
|
|
QueriesAndExpressions: []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",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
err := ng.saveAlertDefinition(&cmd)
|
|
require.NoError(t, err)
|
|
return cmd.Result
|
|
}
|