2016-06-11 03:13:33 -05:00
|
|
|
package alerting
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
|
|
|
|
"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"
|
|
|
|
)
|
|
|
|
|
2016-06-11 03:54:24 -05:00
|
|
|
type DashAlertExtractor struct {
|
2016-06-11 03:13:33 -05:00
|
|
|
Dash *m.Dashboard
|
|
|
|
OrgId int64
|
|
|
|
log log.Logger
|
|
|
|
}
|
|
|
|
|
2016-06-11 03:54:24 -05:00
|
|
|
func NewDashAlertExtractor(dash *m.Dashboard, orgId int64) *DashAlertExtractor {
|
|
|
|
return &DashAlertExtractor{
|
2016-06-11 03:13:33 -05:00
|
|
|
Dash: dash,
|
|
|
|
OrgId: orgId,
|
|
|
|
log: log.New("alerting.extractor"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-20 04:44:06 -05:00
|
|
|
func (e *DashAlertExtractor) lookupDatasourceId(dsName string) (*m.DataSource, error) {
|
2016-06-11 03:13:33 -05:00
|
|
|
if dsName == "" {
|
|
|
|
query := &m.GetDataSourcesQuery{OrgId: e.OrgId}
|
|
|
|
if err := bus.Dispatch(query); err != nil {
|
2016-06-20 04:44:06 -05:00
|
|
|
return nil, err
|
2016-06-11 03:13:33 -05:00
|
|
|
} else {
|
|
|
|
for _, ds := range query.Result {
|
|
|
|
if ds.IsDefault {
|
2016-06-20 04:44:06 -05:00
|
|
|
return ds, nil
|
2016-06-11 03:13:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
query := &m.GetDataSourceByNameQuery{Name: dsName, OrgId: e.OrgId}
|
|
|
|
if err := bus.Dispatch(query); err != nil {
|
2016-06-20 04:44:06 -05:00
|
|
|
return nil, err
|
2016-06-11 03:13:33 -05:00
|
|
|
} else {
|
2016-06-20 04:44:06 -05:00
|
|
|
return query.Result, nil
|
2016-06-11 03:13:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-20 04:44:06 -05:00
|
|
|
return nil, errors.New("Could not find datasource id for " + dsName)
|
2016-06-11 03:13:33 -05:00
|
|
|
}
|
|
|
|
|
2016-07-19 14:00:41 -05:00
|
|
|
func findPanelQueryByRefId(panel *simplejson.Json, refId string) *simplejson.Json {
|
|
|
|
for _, targetsObj := range panel.Get("targets").MustArray() {
|
|
|
|
target := simplejson.NewFromAny(targetsObj)
|
|
|
|
|
|
|
|
if target.Get("refId").MustString() == refId {
|
|
|
|
return target
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-06-11 04:54:46 -05:00
|
|
|
func (e *DashAlertExtractor) GetAlerts() ([]*m.Alert, error) {
|
|
|
|
e.log.Debug("GetAlerts")
|
2016-06-11 03:13:33 -05:00
|
|
|
|
2016-06-11 03:54:24 -05:00
|
|
|
alerts := make([]*m.Alert, 0)
|
2016-06-11 03:13:33 -05:00
|
|
|
|
|
|
|
for _, rowObj := range e.Dash.Data.Get("rows").MustArray() {
|
|
|
|
row := simplejson.NewFromAny(rowObj)
|
|
|
|
|
|
|
|
for _, panelObj := range row.Get("panels").MustArray() {
|
|
|
|
panel := simplejson.NewFromAny(panelObj)
|
2016-06-12 04:43:18 -05:00
|
|
|
jsonAlert, hasAlert := panel.CheckGet("alert")
|
2016-06-11 03:13:33 -05:00
|
|
|
|
2016-06-12 04:43:18 -05:00
|
|
|
if !hasAlert {
|
2016-06-11 03:13:33 -05:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2016-09-30 10:37:47 -05:00
|
|
|
// backward compatability check, can be removed later
|
2016-06-15 04:39:25 -05:00
|
|
|
enabled, hasEnabled := jsonAlert.CheckGet("enabled")
|
2016-09-30 10:37:47 -05:00
|
|
|
if hasEnabled && enabled.MustBool() == false {
|
2016-06-15 04:39:25 -05:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2016-06-11 03:54:24 -05:00
|
|
|
alert := &m.Alert{
|
2016-06-11 03:13:33 -05:00
|
|
|
DashboardId: e.Dash.Id,
|
|
|
|
OrgId: e.OrgId,
|
|
|
|
PanelId: panel.Get("id").MustInt64(),
|
2016-06-11 03:54:24 -05:00
|
|
|
Id: jsonAlert.Get("id").MustInt64(),
|
|
|
|
Name: jsonAlert.Get("name").MustString(),
|
2016-06-13 08:58:22 -05:00
|
|
|
Handler: jsonAlert.Get("handler").MustInt64(),
|
2016-08-12 03:12:04 -05:00
|
|
|
Message: jsonAlert.Get("message").MustString(),
|
2016-06-17 01:27:38 -05:00
|
|
|
Frequency: getTimeDurationStringToSeconds(jsonAlert.Get("frequency").MustString()),
|
2016-06-11 03:13:33 -05:00
|
|
|
}
|
|
|
|
|
2016-07-19 14:00:41 -05:00
|
|
|
for _, condition := range jsonAlert.Get("conditions").MustArray() {
|
|
|
|
jsonCondition := simplejson.NewFromAny(condition)
|
|
|
|
|
|
|
|
jsonQuery := jsonCondition.Get("query")
|
|
|
|
queryRefId := jsonQuery.Get("params").MustArray()[0].(string)
|
|
|
|
panelQuery := findPanelQueryByRefId(panel, queryRefId)
|
|
|
|
|
|
|
|
if panelQuery == nil {
|
2016-07-27 09:29:28 -05:00
|
|
|
return nil, ValidationError{Reason: "Alert refes to query that cannot be found"}
|
2016-06-11 03:13:33 -05:00
|
|
|
}
|
2016-07-19 14:00:41 -05:00
|
|
|
|
|
|
|
dsName := ""
|
|
|
|
if panelQuery.Get("datasource").MustString() != "" {
|
|
|
|
dsName = panelQuery.Get("datasource").MustString()
|
|
|
|
} else if panel.Get("datasource").MustString() != "" {
|
|
|
|
dsName = panel.Get("datasource").MustString()
|
|
|
|
}
|
|
|
|
|
|
|
|
if datasource, err := e.lookupDatasourceId(dsName); err != nil {
|
|
|
|
return nil, err
|
|
|
|
} else {
|
|
|
|
jsonQuery.SetPath([]string{"datasourceId"}, datasource.Id)
|
|
|
|
}
|
|
|
|
|
|
|
|
jsonQuery.Set("model", panelQuery.Interface())
|
2016-06-11 03:13:33 -05:00
|
|
|
}
|
|
|
|
|
2016-06-13 08:18:19 -05:00
|
|
|
alert.Settings = jsonAlert
|
2016-06-11 03:13:33 -05:00
|
|
|
|
|
|
|
// validate
|
2016-07-27 09:29:28 -05:00
|
|
|
_, err := NewRuleFromDBAlert(alert)
|
2016-06-11 03:54:24 -05:00
|
|
|
if err == nil && alert.ValidToSave() {
|
|
|
|
alerts = append(alerts, alert)
|
2016-06-11 03:13:33 -05:00
|
|
|
} else {
|
2016-06-11 03:54:24 -05:00
|
|
|
e.log.Error("Failed to extract alerts from dashboard", "error", err)
|
2016-07-21 06:09:12 -05:00
|
|
|
return nil, err
|
2016-06-11 03:13:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-11 04:54:46 -05:00
|
|
|
e.log.Debug("Extracted alerts from dashboard", "alertCount", len(alerts))
|
2016-06-11 03:54:24 -05:00
|
|
|
return alerts, nil
|
2016-06-11 03:13:33 -05:00
|
|
|
}
|