diff --git a/pkg/services/alerting/dashboard_parser.go b/pkg/services/alerting/dashboard_parser.go index 7517db5b14c..01914e2b39a 100644 --- a/pkg/services/alerting/dashboard_parser.go +++ b/pkg/services/alerting/dashboard_parser.go @@ -30,8 +30,8 @@ func ParseAlertsFromDashboard(cmd *m.SaveDashboardCommand) []*m.AlertRuleDAO { log.Info("Alertrule: %v", alert.Name) - valueQuery := alerting.Get("valueQuery") - valueQueryRef := valueQuery.Get("queryRefId").MustString() + valueQuery := alerting.Get("query") + valueQueryRef := valueQuery.Get("refId").MustString() for _, targetsObj := range panel.Get("targets").MustArray() { target := simplejson.NewFromAny(targetsObj) @@ -48,7 +48,7 @@ func ParseAlertsFromDashboard(cmd *m.SaveDashboardCommand) []*m.AlertRuleDAO { if err := bus.Dispatch(query); err == nil { for _, ds := range query.Result { if ds.IsDefault { - alerting.SetPath([]string{"valueQuery", "datasourceId"}, ds.Id) + alerting.SetPath([]string{"query", "datasourceId"}, ds.Id) } } } @@ -58,12 +58,12 @@ func ParseAlertsFromDashboard(cmd *m.SaveDashboardCommand) []*m.AlertRuleDAO { OrgId: cmd.OrgId, } bus.Dispatch(query) - alerting.SetPath([]string{"valueQuery", "datasourceId"}, query.Result.Id) + alerting.SetPath([]string{"query", "datasourceId"}, query.Result.Id) } targetQuery := target.Get("target").MustString() if targetQuery != "" { - alerting.SetPath([]string{"valueQuery", "query"}, targetQuery) + alerting.SetPath([]string{"query", "query"}, targetQuery) } } } @@ -105,23 +105,24 @@ func ParseAlertRulesFromAlertModel(ruleDef *m.AlertRuleDAO) (*AlertRule, error) } model.Frequency = ruleDef.Expression.Get("frequency").MustInt64() + model.Transform = ruleDef.Expression.Get("transform").Get("type").MustString() + model.TransformParams = *ruleDef.Expression.Get("transform") - valueQuery := ruleDef.Expression.Get("valueQuery") - - model.ValueQuery = AlertQuery{ - Query: valueQuery.Get("query").MustString(), - DatasourceId: valueQuery.Get("datasourceId").MustInt64(), - From: valueQuery.Get("from").MustString(), - To: valueQuery.Get("to").MustString(), - Aggregator: valueQuery.Get("agg").MustString(), + query := ruleDef.Expression.Get("query") + model.Query = AlertQuery{ + Query: query.Get("query").MustString(), + DatasourceId: query.Get("datasourceId").MustInt64(), + From: query.Get("from").MustString(), + To: query.Get("to").MustString(), + Aggregator: query.Get("agg").MustString(), } - if model.ValueQuery.Query == "" { - return nil, fmt.Errorf("missing valueQuery query") + if model.Query.Query == "" { + return nil, fmt.Errorf("missing query.query") } - if model.ValueQuery.DatasourceId == 0 { - return nil, fmt.Errorf("missing valueQuery datasourceId") + if model.Query.DatasourceId == 0 { + return nil, fmt.Errorf("missing query.datasourceId") } return model, nil diff --git a/pkg/services/alerting/executor.go b/pkg/services/alerting/executor.go index ea460a64798..cfdc18edb2c 100644 --- a/pkg/services/alerting/executor.go +++ b/pkg/services/alerting/executor.go @@ -100,7 +100,7 @@ func (e *ExecutorImpl) Execute(job *AlertJob, resultQueue chan *AlertResult) { func (e *ExecutorImpl) executeQuery(job *AlertJob) (tsdb.TimeSeriesSlice, error) { getDsInfo := &m.GetDataSourceByIdQuery{ - Id: job.Rule.ValueQuery.DatasourceId, + Id: job.Rule.Query.DatasourceId, OrgId: job.Rule.OrgId, } @@ -128,16 +128,16 @@ func (e *ExecutorImpl) executeQuery(job *AlertJob) (tsdb.TimeSeriesSlice, error) } func (e *ExecutorImpl) GetRequestForAlertRule(rule *AlertRule, datasource *m.DataSource) *tsdb.Request { - log.Debug2("GetRequest", "query", rule.ValueQuery.Query, "from", rule.ValueQuery.From, "datasourceId", datasource.Id) + log.Debug2("GetRequest", "query", rule.Query.Query, "from", rule.Query.From, "datasourceId", datasource.Id) req := &tsdb.Request{ TimeRange: tsdb.TimeRange{ - From: "-" + rule.ValueQuery.From, - To: rule.ValueQuery.To, + From: "-" + rule.Query.From, + To: rule.Query.To, }, Queries: []*tsdb.Query{ { RefId: "A", - Query: rule.ValueQuery.Query, + Query: rule.Query.Query, DataSource: &tsdb.DataSourceInfo{ Id: datasource.Id, Name: datasource.Name, diff --git a/pkg/services/alerting/models.go b/pkg/services/alerting/models.go index 88dc22feaf7..4f3796d69ec 100644 --- a/pkg/services/alerting/models.go +++ b/pkg/services/alerting/models.go @@ -1,5 +1,10 @@ package alerting +import ( + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/tsdb" +) + type AlertJob struct { Offset int64 Delay bool @@ -18,26 +23,23 @@ type AlertResult struct { } type AlertRule struct { - Id int64 - OrgId int64 - DashboardId int64 - PanelId int64 - //WarnLevel float64 - //CritLevel float64 - //WarnOperator string - //CritOperator string - Frequency int64 - Name string - Description string - State string + Id int64 + OrgId int64 + DashboardId int64 + PanelId int64 + Frequency int64 + Name string + Description string + State string + Warning Level + Critical Level + Query AlertQuery + Transform string + TransformParams simplejson.Json +} - Warning Level - Critical Level - - ValueQuery AlertQuery - EvalFunc string - EvalQuery AlertQuery - EvalParam string +type Transformer interface { + Transform(tsdb tsdb.TimeSeriesSlice) float64 } type Level struct { diff --git a/pkg/services/sqlstore/alert_rule_parser_test.go b/pkg/services/sqlstore/alert_rule_parser_test.go index 03dec377710..6028fba98f4 100644 --- a/pkg/services/sqlstore/alert_rule_parser_test.go +++ b/pkg/services/sqlstore/alert_rule_parser_test.go @@ -15,58 +15,37 @@ func TestAlertRuleModelParsing(t *testing.T) { alertRuleDAO := &m.AlertRuleDAO{} json, _ := simplejson.NewJson([]byte(` { - "critical": { - "level": 20, - "op": ">" - }, - "description": "Alerting Panel Title alert", - "evalQuery": { - "agg": "avg", - "from": "5m", - "params": [ - "#A", - "5m", - "now", - "avg" - ], - "queryRefId": "A", - "to": "now" - }, - "evalStringParam1": "", "frequency": 10, - "function": "static", - "name": "Alerting Panel Title alert", - "queryRef": "- select query -", - "valueQuery": { - "agg": "avg", - "datasourceId": 1, - "from": "5m", - "params": [ - "#A", - "5m", - "now", - "avg" - ], - "query": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)", - "queryRefId": "A", - "to": "now" - }, "warning": { - "level": 10, - "op": ">" - } - }`)) + "op": ">", + "level": 10 + }, + "critical": { + "op": ">", + "level": 20 + }, + "query": { + "queryRefId": "A", + "from": "5m", + "to": "now", + "datasourceId": 1, + "query": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + }, + "transform": { + "name": "aggregation", + "method": "avg" + }`)) alertRuleDAO.Name = "Test" alertRuleDAO.Expression = json rule, _ := alerting.ParseAlertRulesFromAlertModel(alertRuleDAO) Convey("Confirm that all properties are set", func() { - So(rule.ValueQuery.Query, ShouldEqual, "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)") - So(rule.ValueQuery.From, ShouldEqual, "5m") - So(rule.ValueQuery.To, ShouldEqual, "now") - So(rule.ValueQuery.DatasourceId, ShouldEqual, 1) - So(rule.ValueQuery.Aggregator, ShouldEqual, "avg") + So(rule.Query.Query, ShouldEqual, "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)") + So(rule.Query.From, ShouldEqual, "5m") + So(rule.Query.To, ShouldEqual, "now") + So(rule.Query.DatasourceId, ShouldEqual, 1) + //So(rule.ValueQuery.Aggregator, ShouldEqual, "avg") So(rule.Warning.Level, ShouldEqual, 10) So(rule.Warning.Operator, ShouldEqual, ">") So(rule.Critical.Level, ShouldEqual, 20) diff --git a/public/app/plugins/panel/graph/alert_tab_ctrl.ts b/public/app/plugins/panel/graph/alert_tab_ctrl.ts index 0f5f8b58be3..40e8a32926c 100644 --- a/public/app/plugins/panel/graph/alert_tab_ctrl.ts +++ b/public/app/plugins/panel/graph/alert_tab_ctrl.ts @@ -51,20 +51,15 @@ export class AlertTabCtrl { frequency: 10, warning: { op: '>', level: 10 }, critical: { op: '>', level: 20 }, - function: 'static', - valueQuery: { - queryRefId: 'A', - from: '600s', + query: { + refId: 'A', + from: '5m', to: 'now', - agg: 'avg', }, - evalQuery: { - queryRefId: 'A', - from: '600s', - to: 'now', - agg: 'avg', - }, - evalStringParam1: '', + transform: { + type: 'aggregation', + method: 'avg' + } }; /** @ngInject */