mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(alerting): add datasource ref to alert rule
This commit is contained in:
parent
0f58f8a679
commit
b2a4d8083e
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/metrics"
|
"github.com/grafana/grafana/pkg/metrics"
|
||||||
"github.com/grafana/grafana/pkg/middleware"
|
"github.com/grafana/grafana/pkg/middleware"
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
|
"github.com/grafana/grafana/pkg/services/alerting"
|
||||||
"github.com/grafana/grafana/pkg/services/search"
|
"github.com/grafana/grafana/pkg/services/search"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
"github.com/grafana/grafana/pkg/util"
|
"github.com/grafana/grafana/pkg/util"
|
||||||
@ -154,7 +155,7 @@ func PostDashboard(c *middleware.Context, cmd m.SaveDashboardCommand) {
|
|||||||
DashboardId: cmd.Result.Id,
|
DashboardId: cmd.Result.Id,
|
||||||
OrgId: c.OrgId,
|
OrgId: c.OrgId,
|
||||||
UserId: c.UserId,
|
UserId: c.UserId,
|
||||||
Alerts: cmd.GetAlertModels(),
|
Alerts: alerting.ParseAlertsFromDashboard(&cmd),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = bus.Dispatch(&saveAlertCommand)
|
err = bus.Dispatch(&saveAlertCommand)
|
||||||
|
@ -2,14 +2,12 @@ package models
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AlertRule struct {
|
type AlertRule struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
OrgId int64 `json:"-"`
|
OrgId int64 `json:"-"`
|
||||||
//DataSourceId int64 `json:"datasourceId"`
|
DatasourceId int64 `json:"datasourceId"`
|
||||||
DashboardId int64 `json:"dashboardId"`
|
DashboardId int64 `json:"dashboardId"`
|
||||||
PanelId int64 `json:"panelId"`
|
PanelId int64 `json:"panelId"`
|
||||||
Query string `json:"query"`
|
Query string `json:"query"`
|
||||||
@ -50,54 +48,6 @@ type AlertRuleChange struct {
|
|||||||
Created time.Time `json:"created"`
|
Created time.Time `json:"created"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *SaveDashboardCommand) GetAlertModels() []AlertRule {
|
|
||||||
alerts := make([]AlertRule, 0)
|
|
||||||
|
|
||||||
for _, rowObj := range cmd.Dashboard.Get("rows").MustArray() {
|
|
||||||
row := simplejson.NewFromAny(rowObj)
|
|
||||||
|
|
||||||
for _, panelObj := range row.Get("panels").MustArray() {
|
|
||||||
panel := simplejson.NewFromAny(panelObj)
|
|
||||||
|
|
||||||
alerting := panel.Get("alerting")
|
|
||||||
alert := AlertRule{
|
|
||||||
DashboardId: cmd.Result.Id,
|
|
||||||
OrgId: cmd.Result.OrgId,
|
|
||||||
PanelId: panel.Get("id").MustInt64(),
|
|
||||||
Id: alerting.Get("id").MustInt64(),
|
|
||||||
QueryRefId: alerting.Get("queryRef").MustString(),
|
|
||||||
WarnLevel: alerting.Get("warnLevel").MustInt64(),
|
|
||||||
CritLevel: alerting.Get("critLevel").MustInt64(),
|
|
||||||
WarnOperator: alerting.Get("warnOperator").MustString(),
|
|
||||||
CritOperator: alerting.Get("critOperator").MustString(),
|
|
||||||
Interval: alerting.Get("interval").MustString(),
|
|
||||||
Title: alerting.Get("title").MustString(),
|
|
||||||
Description: alerting.Get("description").MustString(),
|
|
||||||
QueryRange: alerting.Get("queryRange").MustString(),
|
|
||||||
Aggregator: alerting.Get("aggregator").MustString(),
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, targetsObj := range panel.Get("targets").MustArray() {
|
|
||||||
target := simplejson.NewFromAny(targetsObj)
|
|
||||||
|
|
||||||
if target.Get("refId").MustString() == alert.QueryRefId {
|
|
||||||
targetJson, err := target.MarshalJSON()
|
|
||||||
if err == nil {
|
|
||||||
alert.Query = string(targetJson)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if alert.Query != "" {
|
|
||||||
alerts = append(alerts, alert)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return alerts
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
type SaveAlertsCommand struct {
|
type SaveAlertsCommand struct {
|
||||||
DashboardId int64
|
DashboardId int64
|
||||||
|
80
pkg/services/alerting/dashboard_parser.go
Normal file
80
pkg/services/alerting/dashboard_parser.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package alerting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
|
"github.com/grafana/grafana/pkg/log"
|
||||||
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ParseAlertsFromDashboard(cmd *m.SaveDashboardCommand) []m.AlertRule {
|
||||||
|
alerts := make([]m.AlertRule, 0)
|
||||||
|
|
||||||
|
for _, rowObj := range cmd.Dashboard.Get("rows").MustArray() {
|
||||||
|
row := simplejson.NewFromAny(rowObj)
|
||||||
|
|
||||||
|
for _, panelObj := range row.Get("panels").MustArray() {
|
||||||
|
panel := simplejson.NewFromAny(panelObj)
|
||||||
|
|
||||||
|
alerting := panel.Get("alerting")
|
||||||
|
alert := m.AlertRule{
|
||||||
|
DashboardId: cmd.Result.Id,
|
||||||
|
OrgId: cmd.Result.OrgId,
|
||||||
|
PanelId: panel.Get("id").MustInt64(),
|
||||||
|
Id: alerting.Get("id").MustInt64(),
|
||||||
|
QueryRefId: alerting.Get("queryRef").MustString(),
|
||||||
|
WarnLevel: alerting.Get("warnLevel").MustInt64(),
|
||||||
|
CritLevel: alerting.Get("critLevel").MustInt64(),
|
||||||
|
WarnOperator: alerting.Get("warnOperator").MustString(),
|
||||||
|
CritOperator: alerting.Get("critOperator").MustString(),
|
||||||
|
Interval: alerting.Get("interval").MustString(),
|
||||||
|
Title: alerting.Get("title").MustString(),
|
||||||
|
Description: alerting.Get("description").MustString(),
|
||||||
|
QueryRange: alerting.Get("queryRange").MustString(),
|
||||||
|
Aggregator: alerting.Get("aggregator").MustString(),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, targetsObj := range panel.Get("targets").MustArray() {
|
||||||
|
target := simplejson.NewFromAny(targetsObj)
|
||||||
|
|
||||||
|
if target.Get("refId").MustString() == alert.QueryRefId {
|
||||||
|
targetJson, err := target.MarshalJSON()
|
||||||
|
if err == nil {
|
||||||
|
alert.Query = string(targetJson)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("datasource is %s", panel.Get("datasource").MustString())
|
||||||
|
log.Info("is datasource null? %v", panel.Get("datasource").MustString() == "")
|
||||||
|
if panel.Get("datasource").MustString() == "" {
|
||||||
|
|
||||||
|
query := &m.GetDataSourcesQuery{OrgId: cmd.OrgId}
|
||||||
|
if err := bus.Dispatch(query); err == nil {
|
||||||
|
|
||||||
|
for _, ds := range query.Result {
|
||||||
|
log.Info("found datasource %s", ds.Name)
|
||||||
|
if ds.IsDefault {
|
||||||
|
alert.DatasourceId = ds.Id
|
||||||
|
log.Info("setting default datasource! %d", ds.Id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
query := &m.GetDataSourceByNameQuery{
|
||||||
|
Name: panel.Get("datasource").MustString(),
|
||||||
|
OrgId: cmd.OrgId,
|
||||||
|
}
|
||||||
|
bus.Dispatch(query)
|
||||||
|
alert.DatasourceId = query.Result.Id
|
||||||
|
}
|
||||||
|
|
||||||
|
if alert.Query != "" {
|
||||||
|
alerts = append(alerts, alert)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return alerts
|
||||||
|
}
|
@ -30,6 +30,7 @@ func TestAlertingDataAccess(t *testing.T) {
|
|||||||
Description: "Alerting description",
|
Description: "Alerting description",
|
||||||
QueryRange: "5m",
|
QueryRange: "5m",
|
||||||
Aggregator: "avg",
|
Aggregator: "avg",
|
||||||
|
DatasourceId: 42,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +70,7 @@ func TestAlertingDataAccess(t *testing.T) {
|
|||||||
So(alert.QueryRange, ShouldEqual, "5m")
|
So(alert.QueryRange, ShouldEqual, "5m")
|
||||||
So(alert.Aggregator, ShouldEqual, "avg")
|
So(alert.Aggregator, ShouldEqual, "avg")
|
||||||
So(alert.State, ShouldEqual, "OK")
|
So(alert.State, ShouldEqual, "OK")
|
||||||
|
So(alert.DatasourceId, ShouldEqual, 42)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Alerts with same dashboard id and panel id should update", func() {
|
Convey("Alerts with same dashboard id and panel id should update", func() {
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package models
|
package sqlstore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
|
"github.com/grafana/grafana/pkg/services/alerting"
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -336,17 +338,38 @@ func TestAlertModel(t *testing.T) {
|
|||||||
"links": []
|
"links": []
|
||||||
}`
|
}`
|
||||||
dashboardJson, _ := simplejson.NewJson([]byte(json))
|
dashboardJson, _ := simplejson.NewJson([]byte(json))
|
||||||
cmd := &SaveDashboardCommand{
|
cmd := &m.SaveDashboardCommand{
|
||||||
Dashboard: dashboardJson,
|
Dashboard: dashboardJson,
|
||||||
UserId: 1,
|
UserId: 1,
|
||||||
OrgId: 1,
|
OrgId: 1,
|
||||||
Overwrite: true,
|
Overwrite: true,
|
||||||
Result: &Dashboard{
|
Result: &m.Dashboard{
|
||||||
Id: 1,
|
Id: 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
alerts := cmd.GetAlertModels()
|
InitTestDB(t)
|
||||||
|
|
||||||
|
AddDataSource(&m.AddDataSourceCommand{
|
||||||
|
Name: "graphite2",
|
||||||
|
OrgId: 1,
|
||||||
|
Type: m.DS_INFLUXDB,
|
||||||
|
Access: m.DS_ACCESS_DIRECT,
|
||||||
|
Url: "http://test",
|
||||||
|
IsDefault: false,
|
||||||
|
Database: "site",
|
||||||
|
})
|
||||||
|
|
||||||
|
AddDataSource(&m.AddDataSourceCommand{
|
||||||
|
Name: "InfluxDB",
|
||||||
|
OrgId: 1,
|
||||||
|
Type: m.DS_GRAPHITE,
|
||||||
|
Access: m.DS_ACCESS_DIRECT,
|
||||||
|
Url: "http://test",
|
||||||
|
IsDefault: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
alerts := alerting.ParseAlertsFromDashboard(cmd)
|
||||||
|
|
||||||
Convey("all properties have been set", func() {
|
Convey("all properties have been set", func() {
|
||||||
So(alerts, ShouldNotBeEmpty)
|
So(alerts, ShouldNotBeEmpty)
|
||||||
@ -380,6 +403,10 @@ func TestAlertModel(t *testing.T) {
|
|||||||
|
|
||||||
So(alerts[0].Query, ShouldEqual, `{"refId":"A","target":"aliasByNode(statsd.fakesite.counters.session_start.desktop.count, 4)"}`)
|
So(alerts[0].Query, ShouldEqual, `{"refId":"A","target":"aliasByNode(statsd.fakesite.counters.session_start.desktop.count, 4)"}`)
|
||||||
So(alerts[1].Query, ShouldEqual, `{"refId":"A","target":"aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"}`)
|
So(alerts[1].Query, ShouldEqual, `{"refId":"A","target":"aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"}`)
|
||||||
|
|
||||||
|
So(alerts[0].DatasourceId, ShouldEqual, 2)
|
||||||
|
So(alerts[1].DatasourceId, ShouldEqual, 1)
|
||||||
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
@ -11,7 +11,7 @@ func addAlertMigrations(mg *Migrator) {
|
|||||||
Columns: []*Column{
|
Columns: []*Column{
|
||||||
{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
|
{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
|
||||||
{Name: "dashboard_id", Type: DB_BigInt, Nullable: false},
|
{Name: "dashboard_id", Type: DB_BigInt, Nullable: false},
|
||||||
//{Name: "datasource_id", Type: DB_BigInt, Nullable: false},
|
{Name: "datasource_id", Type: DB_BigInt, Nullable: false},
|
||||||
{Name: "panel_id", Type: DB_BigInt, Nullable: false},
|
{Name: "panel_id", Type: DB_BigInt, Nullable: false},
|
||||||
{Name: "org_id", Type: DB_BigInt, Nullable: false},
|
{Name: "org_id", Type: DB_BigInt, Nullable: false},
|
||||||
{Name: "query", Type: DB_Text, Nullable: false},
|
{Name: "query", Type: DB_Text, Nullable: false},
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/sqlstore/sqlutil"
|
"github.com/grafana/grafana/pkg/services/sqlstore/sqlutil"
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
//"github.com/grafana/grafana/pkg/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var indexTypes = []string{"Unknown", "INDEX", "UNIQUE INDEX"}
|
var indexTypes = []string{"Unknown", "INDEX", "UNIQUE INDEX"}
|
||||||
@ -28,7 +29,7 @@ func TestMigrations(t *testing.T) {
|
|||||||
sqlutil.CleanDB(x)
|
sqlutil.CleanDB(x)
|
||||||
|
|
||||||
mg := NewMigrator(x)
|
mg := NewMigrator(x)
|
||||||
//mg.LogLevel = log.DEBUG
|
//mg.LogLevel = log.ERROR
|
||||||
AddMigrations(mg)
|
AddMigrations(mg)
|
||||||
|
|
||||||
err = mg.Start()
|
err = mg.Start()
|
||||||
|
@ -115,7 +115,7 @@ func (mg *Migrator) Start() error {
|
|||||||
|
|
||||||
func (mg *Migrator) exec(m Migration) error {
|
func (mg *Migrator) exec(m Migration) error {
|
||||||
if mg.LogLevel <= log.INFO {
|
if mg.LogLevel <= log.INFO {
|
||||||
log.Info("Migrator: exec migration id: %v", m.Id())
|
//log.Info("Migrator: exec migration id: %v", m.Id())
|
||||||
}
|
}
|
||||||
|
|
||||||
err := mg.inTransaction(func(sess *xorm.Session) error {
|
err := mg.inTransaction(func(sess *xorm.Session) error {
|
||||||
|
Loading…
Reference in New Issue
Block a user