diff --git a/pkg/api/alerting.go b/pkg/api/alerting.go index 37d247a7c8f..bd40d8d63e9 100644 --- a/pkg/api/alerting.go +++ b/pkg/api/alerting.go @@ -8,7 +8,6 @@ import ( "github.com/grafana/grafana/pkg/middleware" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/alerting" - "github.com/grafana/grafana/pkg/services/annotations" ) func ValidateOrgAlert(c *middleware.Context) { @@ -231,42 +230,6 @@ func NotificationTest(c *middleware.Context, dto dtos.NotificationTestCommand) R return ApiSuccess("Test notification sent") } -func GetAlertHistory(c *middleware.Context) Response { - alertId, err := getAlertIdForRequest(c) - if err != nil { - return ApiError(400, "Invalid request", err) - } - - query := &annotations.ItemQuery{ - AlertId: alertId, - Type: annotations.AlertType, - OrgId: c.OrgId, - Limit: c.QueryInt64("limit"), - } - - repo := annotations.GetRepository() - - items, err := repo.Find(query) - if err != nil { - return ApiError(500, "Failed to get history for alert", err) - } - - var result []dtos.AlertHistory - for _, item := range items { - result = append(result, dtos.AlertHistory{ - AlertId: item.AlertId, - Timestamp: item.Timestamp, - Data: item.Data, - NewState: item.NewState, - Text: item.Text, - Metric: item.Metric, - Title: item.Title, - }) - } - - return Json(200, result) -} - func getAlertIdForRequest(c *middleware.Context) (int64, error) { alertId := c.QueryInt64("alertId") panelId := c.QueryInt64("panelId") diff --git a/pkg/api/annotations.go b/pkg/api/annotations.go new file mode 100644 index 00000000000..4e43a7ea21e --- /dev/null +++ b/pkg/api/annotations.go @@ -0,0 +1,42 @@ +package api + +import ( + "github.com/grafana/grafana/pkg/api/dtos" + "github.com/grafana/grafana/pkg/middleware" + "github.com/grafana/grafana/pkg/services/annotations" +) + +func GetAnnotations(c *middleware.Context) Response { + + query := &annotations.ItemQuery{ + From: c.QueryInt64("from") / 1000, + To: c.QueryInt64("to") / 1000, + Type: annotations.ItemType(c.Query("type")), + OrgId: c.OrgId, + Limit: c.QueryInt64("limit"), + } + + repo := annotations.GetRepository() + + items, err := repo.Find(query) + if err != nil { + return ApiError(500, "Failed to get annotations", err) + } + + result := make([]dtos.Annotation, 0) + + for _, item := range items { + result = append(result, dtos.Annotation{ + AlertId: item.AlertId, + Time: item.Epoch * 1000, + Data: item.Data, + NewState: item.NewState, + PrevState: item.PrevState, + Text: item.Text, + Metric: item.Metric, + Title: item.Title, + }) + } + + return Json(200, result) +} diff --git a/pkg/api/api.go b/pkg/api/api.go index de3a1de8a65..71331acda9f 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -254,8 +254,6 @@ func Register(r *macaron.Macaron) { r.Get("/", wrap(GetAlerts)) }) - r.Get("/alert-history", wrap(GetAlertHistory)) - r.Get("/alert-notifications", wrap(GetAlertNotifications)) r.Group("/alert-notifications", func() { @@ -266,6 +264,8 @@ func Register(r *macaron.Macaron) { r.Delete("/:notificationId", wrap(DeleteAlertNotification)) }, reqOrgAdmin) + r.Get("/annotations", wrap(GetAnnotations)) + // error test r.Get("/metrics/error", wrap(GenerateError)) diff --git a/pkg/api/dtos/alerting.go b/pkg/api/dtos/alerting.go index 83b21757d32..2b91cf0cb5b 100644 --- a/pkg/api/dtos/alerting.go +++ b/pkg/api/dtos/alerting.go @@ -54,17 +54,6 @@ type EvalMatch struct { Value float64 `json:"value"` } -type AlertHistory struct { - AlertId int64 `json:"alertId"` - NewState string `json:"newState"` - Timestamp time.Time `json:"timestamp"` - Title string `json:"title"` - Text string `json:"text"` - Metric string `json:"metric"` - - Data *simplejson.Json `json:"data"` -} - type NotificationTestCommand struct { Name string `json:"name"` Type string `json:"type"` diff --git a/pkg/api/dtos/annotations.go b/pkg/api/dtos/annotations.go new file mode 100644 index 00000000000..2068b6186d2 --- /dev/null +++ b/pkg/api/dtos/annotations.go @@ -0,0 +1,15 @@ +package dtos + +import "github.com/grafana/grafana/pkg/components/simplejson" + +type Annotation struct { + AlertId int64 `json:"alertId"` + NewState string `json:"newState"` + PrevState string `json:"prevState"` + Time int64 `json:"time"` + Title string `json:"title"` + Text string `json:"text"` + Metric string `json:"metric"` + + Data *simplejson.Json `json:"data"` +} diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index 5a84409d2c1..3a019e80c49 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -105,6 +105,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro grafanaDatasourceMeta, _ := plugins.DataSources["grafana"] datasources["-- Grafana --"] = map[string]interface{}{ "type": "grafana", + "name": "-- Grafana --", "meta": grafanaDatasourceMeta, } diff --git a/pkg/services/alerting/eval_context.go b/pkg/services/alerting/eval_context.go index d1ac851daf1..f54a4e212be 100644 --- a/pkg/services/alerting/eval_context.go +++ b/pkg/services/alerting/eval_context.go @@ -66,7 +66,6 @@ func (c *EvalContext) GetStateModel() *StateDescription { default: panic("Unknown rule state " + c.Rule.State) } - } func (a *EvalContext) GetDurationMs() float64 { diff --git a/pkg/services/alerting/result_handler.go b/pkg/services/alerting/result_handler.go index 7932aead4aa..6239a1e58d7 100644 --- a/pkg/services/alerting/result_handler.go +++ b/pkg/services/alerting/result_handler.go @@ -73,7 +73,7 @@ func (handler *DefaultResultHandler) Handle(ctx *EvalContext) { Text: ctx.GetStateModel().Text, NewState: string(ctx.Rule.State), PrevState: string(oldState), - Timestamp: time.Now(), + Epoch: time.Now().Unix(), Data: annotationData, } diff --git a/pkg/services/annotations/annotations.go b/pkg/services/annotations/annotations.go index 06be152ec31..e9ef899eca9 100644 --- a/pkg/services/annotations/annotations.go +++ b/pkg/services/annotations/annotations.go @@ -1,10 +1,6 @@ package annotations -import ( - "time" - - "github.com/grafana/grafana/pkg/components/simplejson" -) +import "github.com/grafana/grafana/pkg/components/simplejson" type Repository interface { Save(item *Item) error @@ -13,6 +9,8 @@ type Repository interface { type ItemQuery struct { OrgId int64 `json:"orgId"` + From int64 `json:"from"` + To int64 `json:"from"` Type ItemType `json:"type"` AlertId int64 `json:"alertId"` @@ -36,17 +34,17 @@ const ( ) type Item struct { - Id int64 `json:"id"` - OrgId int64 `json:"orgId"` - Type ItemType `json:"type"` - Title string `json:"title"` - Text string `json:"text"` - Metric string `json:"metric"` - AlertId int64 `json:"alertId"` - UserId int64 `json:"userId"` - PrevState string `json:"prevState"` - NewState string `json:"newState"` - Timestamp time.Time `json:"timestamp"` + Id int64 `json:"id"` + OrgId int64 `json:"orgId"` + Type ItemType `json:"type"` + Title string `json:"title"` + Text string `json:"text"` + Metric string `json:"metric"` + AlertId int64 `json:"alertId"` + UserId int64 `json:"userId"` + PrevState string `json:"prevState"` + NewState string `json:"newState"` + Epoch int64 `json:"epoch"` Data *simplejson.Json `json:"data"` } diff --git a/pkg/services/sqlstore/annotation.go b/pkg/services/sqlstore/annotation.go index 5cf4461b370..e5a5443c3bf 100644 --- a/pkg/services/sqlstore/annotation.go +++ b/pkg/services/sqlstore/annotation.go @@ -38,6 +38,9 @@ func (r *SqlAnnotationRepo) Find(query *annotations.ItemQuery) ([]*annotations.I params = append(params, query.AlertId) } + sql.WriteString(` AND epoch BETWEEN ? AND ?`) + params = append(params, query.From, query.To) + if query.Type != "" { sql.WriteString(` AND type = ?`) params = append(params, string(query.Type)) @@ -47,7 +50,7 @@ func (r *SqlAnnotationRepo) Find(query *annotations.ItemQuery) ([]*annotations.I query.Limit = 10 } - sql.WriteString(fmt.Sprintf("ORDER BY timestamp DESC LIMIT %v", query.Limit)) + sql.WriteString(fmt.Sprintf("ORDER BY epoch DESC LIMIT %v", query.Limit)) items := make([]*annotations.Item, 0) if err := x.Sql(sql.String(), params...).Find(&items); err != nil { diff --git a/pkg/services/sqlstore/migrations/annotation_mig.go b/pkg/services/sqlstore/migrations/annotation_mig.go index 11b4eeed629..ddb622894ac 100644 --- a/pkg/services/sqlstore/migrations/annotation_mig.go +++ b/pkg/services/sqlstore/migrations/annotation_mig.go @@ -5,6 +5,7 @@ import ( ) func addAnnotationMig(mg *Migrator) { + table := Table{ Name: "annotation", Columns: []*Column{ @@ -19,20 +20,22 @@ func addAnnotationMig(mg *Migrator) { {Name: "prev_state", Type: DB_NVarchar, Length: 25, Nullable: false}, {Name: "new_state", Type: DB_NVarchar, Length: 25, Nullable: false}, {Name: "data", Type: DB_Text, Nullable: false}, - {Name: "timestamp", Type: DB_DateTime, Nullable: false}, + {Name: "epoch", Type: DB_BigInt, Nullable: false}, }, Indices: []*Index{ {Cols: []string{"org_id", "alert_id"}, Type: IndexType}, {Cols: []string{"org_id", "type"}, Type: IndexType}, - {Cols: []string{"timestamp"}, Type: IndexType}, + {Cols: []string{"epoch"}, Type: IndexType}, }, } - mg.AddMigration("create annotation table v1", NewAddTableMigration(table)) + mg.AddMigration("Drop old annotation table v2", NewDropTableMigration("annotation")) + + mg.AddMigration("create annotation table v3", NewAddTableMigration(table)) // create indices - mg.AddMigration("add index annotation org_id & alert_id ", NewAddIndexMigration(table, table.Indices[0])) + mg.AddMigration("add index annotation org_id & alert_id v2", NewAddIndexMigration(table, table.Indices[0])) - mg.AddMigration("add index annotation org_id & type", NewAddIndexMigration(table, table.Indices[1])) - mg.AddMigration("add index annotation timestamp", NewAddIndexMigration(table, table.Indices[2])) + mg.AddMigration("add index annotation org_id & type v2", NewAddIndexMigration(table, table.Indices[1])) + mg.AddMigration("add index annotation epoch", NewAddIndexMigration(table, table.Indices[2])) } diff --git a/public/app/core/directives/plugin_component.ts b/public/app/core/directives/plugin_component.ts index dbe9932d574..60685fae74e 100644 --- a/public/app/core/directives/plugin_component.ts +++ b/public/app/core/directives/plugin_component.ts @@ -136,12 +136,12 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $ } // Annotations case "annotations-query-ctrl": { - return System.import(scope.currentDatasource.meta.module).then(function(dsModule) { + return System.import(scope.ctrl.currentDatasource.meta.module).then(function(dsModule) { return { - baseUrl: scope.currentDatasource.meta.baseUrl, - name: 'annotations-query-ctrl-' + scope.currentDatasource.meta.id, + baseUrl: scope.ctrl.currentDatasource.meta.baseUrl, + name: 'annotations-query-ctrl-' + scope.ctrl.currentDatasource.meta.id, bindings: {annotation: "=", datasource: "="}, - attrs: {"annotation": "currentAnnotation", datasource: "currentDatasource"}, + attrs: {"annotation": "ctrl.currentAnnotation", datasource: "ctrl.currentDatasource"}, Component: dsModule.AnnotationsQueryCtrl, }; }); diff --git a/public/app/features/alerting/alert_tab_ctrl.ts b/public/app/features/alerting/alert_tab_ctrl.ts index f3cc998deaa..d19904eea0d 100644 --- a/public/app/features/alerting/alert_tab_ctrl.ts +++ b/public/app/features/alerting/alert_tab_ctrl.ts @@ -80,7 +80,7 @@ export class AlertTabCtrl { } getAlertHistory() { - this.backendSrv.get(`/api/alert-history?dashboardId=${this.panelCtrl.dashboard.id}&panelId=${this.panel.id}`).then(res => { + this.backendSrv.get(`/api/alert-history?dashboardId=${this.panelCtrl.dashboard.id}&panelId=${this.panel.id}&limit=50`).then(res => { this.alertHistory = _.map(res, ah => { ah.time = moment(ah.timestamp).format('MMM D, YYYY HH:mm:ss'); ah.stateModel = alertDef.getStateDisplayModel(ah.newState); diff --git a/public/app/features/alerting/partials/alert_tab.html b/public/app/features/alerting/partials/alert_tab.html index 770e3a2cb05..c5517990934 100644 --- a/public/app/features/alerting/partials/alert_tab.html +++ b/public/app/features/alerting/partials/alert_tab.html @@ -10,7 +10,7 @@
{{annotation.name}} | -- | + | + | @@ -46,7 +46,7 @@ | - + | @@ -54,43 +54,43 @@