diff --git a/pkg/api/dashboard.go b/pkg/api/dashboard.go index 2f2dfae48f1..d8a6057c401 100644 --- a/pkg/api/dashboard.go +++ b/pkg/api/dashboard.go @@ -11,6 +11,7 @@ import ( "github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/middleware" 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/setting" "github.com/grafana/grafana/pkg/util" @@ -154,7 +155,7 @@ func PostDashboard(c *middleware.Context, cmd m.SaveDashboardCommand) { DashboardId: cmd.Result.Id, OrgId: c.OrgId, UserId: c.UserId, - Alerts: cmd.GetAlertModels(), + Alerts: alerting.ParseAlertsFromDashboard(&cmd), } err = bus.Dispatch(&saveAlertCommand) diff --git a/pkg/models/alerts.go b/pkg/models/alerts.go index 6f4fce87f09..abf003e9d7f 100644 --- a/pkg/models/alerts.go +++ b/pkg/models/alerts.go @@ -2,14 +2,12 @@ package models import ( "time" - - "github.com/grafana/grafana/pkg/components/simplejson" ) type AlertRule struct { - Id int64 `json:"id"` - OrgId int64 `json:"-"` - //DataSourceId int64 `json:"datasourceId"` + Id int64 `json:"id"` + OrgId int64 `json:"-"` + DatasourceId int64 `json:"datasourceId"` DashboardId int64 `json:"dashboardId"` PanelId int64 `json:"panelId"` Query string `json:"query"` @@ -50,54 +48,6 @@ type AlertRuleChange struct { 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 type SaveAlertsCommand struct { DashboardId int64 diff --git a/pkg/services/alerting/dashboard_parser.go b/pkg/services/alerting/dashboard_parser.go new file mode 100644 index 00000000000..fa962fd6397 --- /dev/null +++ b/pkg/services/alerting/dashboard_parser.go @@ -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 +} diff --git a/pkg/services/sqlstore/alert_rule_test.go b/pkg/services/sqlstore/alert_rule_test.go index a91de723f8d..2aa3d53971a 100644 --- a/pkg/services/sqlstore/alert_rule_test.go +++ b/pkg/services/sqlstore/alert_rule_test.go @@ -30,6 +30,7 @@ func TestAlertingDataAccess(t *testing.T) { Description: "Alerting description", QueryRange: "5m", Aggregator: "avg", + DatasourceId: 42, }, } @@ -69,6 +70,7 @@ func TestAlertingDataAccess(t *testing.T) { So(alert.QueryRange, ShouldEqual, "5m") So(alert.Aggregator, ShouldEqual, "avg") So(alert.State, ShouldEqual, "OK") + So(alert.DatasourceId, ShouldEqual, 42) }) Convey("Alerts with same dashboard id and panel id should update", func() { diff --git a/pkg/models/alerts_test.go b/pkg/services/sqlstore/dashboard_parser_test.go similarity index 92% rename from pkg/models/alerts_test.go rename to pkg/services/sqlstore/dashboard_parser_test.go index 704da36066c..c1ad3d38f3e 100644 --- a/pkg/models/alerts_test.go +++ b/pkg/services/sqlstore/dashboard_parser_test.go @@ -1,9 +1,11 @@ -package models +package sqlstore import ( "testing" "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" ) @@ -336,17 +338,38 @@ func TestAlertModel(t *testing.T) { "links": [] }` dashboardJson, _ := simplejson.NewJson([]byte(json)) - cmd := &SaveDashboardCommand{ + cmd := &m.SaveDashboardCommand{ Dashboard: dashboardJson, UserId: 1, OrgId: 1, Overwrite: true, - Result: &Dashboard{ + Result: &m.Dashboard{ 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() { 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[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) + }) }) } diff --git a/pkg/services/sqlstore/migrations/alert_mig.go b/pkg/services/sqlstore/migrations/alert_mig.go index ef120a98791..1de01276622 100644 --- a/pkg/services/sqlstore/migrations/alert_mig.go +++ b/pkg/services/sqlstore/migrations/alert_mig.go @@ -11,7 +11,7 @@ func addAlertMigrations(mg *Migrator) { Columns: []*Column{ {Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true}, {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: "org_id", Type: DB_BigInt, Nullable: false}, {Name: "query", Type: DB_Text, Nullable: false}, diff --git a/pkg/services/sqlstore/migrations/migrations_test.go b/pkg/services/sqlstore/migrations/migrations_test.go index 0278ea6632b..26a6f3c8a95 100644 --- a/pkg/services/sqlstore/migrations/migrations_test.go +++ b/pkg/services/sqlstore/migrations/migrations_test.go @@ -8,6 +8,7 @@ import ( "github.com/grafana/grafana/pkg/services/sqlstore/sqlutil" . "github.com/smartystreets/goconvey/convey" + //"github.com/grafana/grafana/pkg/log" ) var indexTypes = []string{"Unknown", "INDEX", "UNIQUE INDEX"} @@ -28,7 +29,7 @@ func TestMigrations(t *testing.T) { sqlutil.CleanDB(x) mg := NewMigrator(x) - //mg.LogLevel = log.DEBUG + //mg.LogLevel = log.ERROR AddMigrations(mg) err = mg.Start() diff --git a/pkg/services/sqlstore/migrator/migrator.go b/pkg/services/sqlstore/migrator/migrator.go index 48000e34ca2..86af0e59f04 100644 --- a/pkg/services/sqlstore/migrator/migrator.go +++ b/pkg/services/sqlstore/migrator/migrator.go @@ -115,7 +115,7 @@ func (mg *Migrator) Start() error { func (mg *Migrator) exec(m Migration) error { 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 {