Browse Source

feat(alertlistpanel): support state filter

ref #5981
bergquist 9 years ago
parent
commit
d0f9623037

+ 2 - 1
pkg/api/alerting.go

@@ -25,13 +25,14 @@ func ValidateOrgAlert(c *middleware.Context) {
 	}
 }
 
-// GET /api/alerts/rules/
+// GET /api/alerts
 func GetAlerts(c *middleware.Context) Response {
 	query := models.GetAlertsQuery{
 		OrgId:       c.OrgId,
 		State:       c.QueryStrings("state"),
 		DashboardId: c.QueryInt64("dashboardId"),
 		PanelId:     c.QueryInt64("panelId"),
+		Limit:       c.QueryInt64("limit"),
 	}
 
 	if err := bus.Dispatch(&query); err != nil {

+ 1 - 0
pkg/api/annotations.go

@@ -17,6 +17,7 @@ func GetAnnotations(c *middleware.Context) Response {
 		DashboardId: c.QueryInt64("dashboardId"),
 		PanelId:     c.QueryInt64("panelId"),
 		Limit:       c.QueryInt64("limit"),
+		NewState:    c.QueryStrings("newState"),
 	}
 
 	repo := annotations.GetRepository()

+ 1 - 0
pkg/models/alert.go

@@ -119,6 +119,7 @@ type GetAlertsQuery struct {
 	State       []string
 	DashboardId int64
 	PanelId     int64
+	Limit       int64
 
 	Result []*Alert
 }

+ 1 - 0
pkg/services/annotations/annotations.go

@@ -15,6 +15,7 @@ type ItemQuery struct {
 	AlertId     int64    `json:"alertId"`
 	DashboardId int64    `json:"dashboardId"`
 	PanelId     int64    `json:"panelId"`
+	NewState    []string `json:"newState"`
 
 	Limit int64 `json:"alertId"`
 }

+ 5 - 0
pkg/services/sqlstore/alert.go

@@ -87,6 +87,11 @@ func HandleAlertsQuery(query *m.GetAlertsQuery) error {
 		sql.WriteString(")")
 	}
 
+	if query.Limit != 0 {
+		sql.WriteString(" LIMIT ?")
+		params = append(params, query.Limit)
+	}
+
 	alerts := make([]*m.Alert, 0)
 	if err := x.Sql(sql.String(), params...).Find(&alerts); err != nil {
 		return err

+ 8 - 0
pkg/services/sqlstore/annotation.go

@@ -3,6 +3,7 @@ package sqlstore
 import (
 	"bytes"
 	"fmt"
+	"strings"
 
 	"github.com/go-xorm/xorm"
 	"github.com/grafana/grafana/pkg/services/annotations"
@@ -63,6 +64,13 @@ func (r *SqlAnnotationRepo) Find(query *annotations.ItemQuery) ([]*annotations.I
 		params = append(params, string(query.Type))
 	}
 
+	if len(query.NewState) > 0 {
+		sql.WriteString(` AND new_state IN (?` + strings.Repeat(",?", len(query.NewState)-1) + ")")
+		for _, v := range query.NewState {
+			params = append(params, v)
+		}
+	}
+
 	if query.Limit == 0 {
 		query.Limit = 10
 	}

+ 1 - 1
public/app/features/alerting/alert_tab_ctrl.ts

@@ -88,7 +88,7 @@ export class AlertTabCtrl {
   getAlertHistory() {
     this.backendSrv.get(`/api/annotations?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.time = moment(ah.time).format('MMM D, YYYY HH:mm:ss');
         ah.stateModel = alertDef.getStateDisplayModel(ah.newState);
         ah.metrics = alertDef.joinEvalMatches(ah.data, ', ');
         return ah;

+ 25 - 1
public/app/plugins/panel/alertlist/editor.html

@@ -4,9 +4,33 @@
     <div class="gf-form">
       <span class="gf-form-label width-8">Show</span>
       <div class="gf-form-select-wrapper max-width-15">
-         <select class="gf-form-input" ng-model="ctrl.panel.show" ng-options="f.value as f.text for f in ctrl.showOptions" ng-change="ctrl.onRender()"></select>
+        <select class="gf-form-input" ng-model="ctrl.panel.show" ng-options="f.value as f.text for f in ctrl.showOptions" ng-change="ctrl.onRender()"></select>
       </div>
     </div>
+    <div class="gf-form">
+      <span class="gf-form-label width-8">Max items</span>
+      <input type="text" class="gf-form-input max-width-15" ng-model="ctrl.panel.limit" />
+    </div>
+    <div class="gf-form">
+      <span class="gf-form-label width-8">With state</span>
+      <div class="gf-form-select-wrapper max-width-15">
+        <select class="gf-form-input" ng-model="ctrl.panel.stateFilter" ng-options="f as f for f in ctrl.alertStates" ng-change="ctrl.onRender()"></select>
+      </div>
+    </div>
+
+  </div>
+  <div class="section gf-form-group" ng-if="ctrl.panel.show == 'changes'">
+    <h5 class="section-heading">Search options</h5>
+    <div class="gf-form">
+      <span class="gf-form-label width-8">Timerange from</span>
+      <input type="text" placeholder="6h" class="gf-form-input max-width-4" ng-model="ctrl.panel.since" />
+    </div>
+    <div class="gf-form">
+      <gf-form-switch class="gf-form" label="Setting" label-class="width-8" checked="ctrl.panel.setting" on-change="ctrl.render()"></gf-form-switch>
+    </div>
+  </div>
 
+  <div class="section gf-form-group" ng-if="ctrl.panel.show == 'current'">
+    <h5 class="section-heading">Current state</h5>
   </div>
 </div>

+ 7 - 15
public/app/plugins/panel/alertlist/module.html

@@ -1,19 +1,11 @@
 <div class="panel-alert-list">
   <section class="card-section card-list-layout-list" ng-if="ctrl.panel.show === 'current'">
-
-    <ol class="card-list" >
+    <ol class="card-list">
       <li class="card-item-wrapper" ng-repeat="alert in ctrl.currentAlerts">
         <div class="card-item card-item--alert">
-          <div class="card-item-header">
-            <div class="card-item-type">
-              <a class="card-item-cog" href="dashboard/{{alert.dashboardUri}}?panelId={{alert.panelId}}&fullscreen&edit&tab=alert" bs-tooltip="'Edit alert rule'">
-                <i class="icon-gf icon-gf-settings"></i>
-              </a>
-            </div>
-          </div>
           <div class="card-item-body">
             <div class="card-item-details">
-              <div class="card-item-name">
+              <div class="card-item-notice">
                 <a href="dashboard/{{alert.dashboardUri}}?panelId={{alert.panelId}}&fullscreen&edit&tab=alert">
                   {{alert.name}}
                 </a>
@@ -34,22 +26,22 @@
     </ol>
   </section>
 
-
   <section class="card-section card-list-layout-list" ng-if="ctrl.panel.show === 'changes'">
-    <ol class="card-list" >
+    <ol class="card-list">
       <li class="card-item-wrapper" ng-repeat="al in ctrl.alertHistory">
         <div class="card-item card-item--alert">
+          <div class="card-item-header">
+            <div class="card-item-sub-name">{{al.time}}</div>
+          </div>
           <div class="card-item-body">
             <div class="card-item-details">
+              <div class="card-item-notice">{{al.title}}</div>
               <div class="card-item-sub-name">
                 <span class="alert-list-item-state {{al.stateModel.stateClass}}">
                   <i class="{{al.stateModel.iconClass}}"></i>
                   {{al.stateModel.text}}
                 </span> {{al.metrics}}
               </div>
-              <div class="card-item-sub-name">
-                {{al.time}}
-              </div>
             </div>
           </div>
         </div>

+ 30 - 6
public/app/plugins/panel/alertlist/module.ts

@@ -4,6 +4,7 @@ import _ from 'lodash';
 import moment from 'moment';
 import alertDef from '../../../features/alerting/alert_def';
 import config from 'app/core/config';
+//import * as dateMath from 'app/core/utils/datemath';
 import {PanelCtrl} from 'app/plugins/sdk';
 
 class AlertListPanel extends PanelCtrl {
@@ -11,14 +12,18 @@ class AlertListPanel extends PanelCtrl {
 
   showOptions = [
     {text: 'Current state', value: 'current'},
-    {text: 'State changes', value: 'changes'},
+    {text: 'Recent statechanges', value: 'changes'}
   ];
 
+  alertStates = [ 'all', 'ok', 'alerting', 'paused', 'no_data', 'execution_error' ];
+
   currentAlerts: any = [];
   alertHistory: any = [];
   // Set and populate defaults
   panelDefaults = {
-    show: 'current'
+    show: 'current',
+    limit: 10,
+    stateFilter: 'all'
   };
 
   /** @ngInject */
@@ -37,15 +42,34 @@ class AlertListPanel extends PanelCtrl {
     }
 
     if (this.panel.show === 'changes') {
-      this.getAlertHistory();
+      this.getStateChanges();
     }
   }
 
-  getAlertHistory() {
-    this.backendSrv.get(`/api/alert-history?dashboardId=32&panelId=1`)
+  getStateChanges() {
+    var params: any = {
+      limit: this.panel.limit,
+      type: 'alert',
+    };
+
+    if (this.panel.stateFilter !== "all") {
+      params.newState = this.panel.stateFilter;
+    }
+    /*
+    var since = this.panel.since;
+    if (since !== undefined && since !== "" && since !== null) {
+      var t = this.dashboard.time;
+      var now = (new Date()).getTime();
+      params.to = t.to;
+
+      //this.range = this.timeSrv.timeRange();
+      params.from = dateMath.parseDateMath("1m", t.from, false);
+    }
+    */
+    this.backendSrv.get(`/api/annotations`, params)
       .then(res => {
         this.alertHistory = _.map(res, al => {
-          al.time = moment(al.timestamp).format('MMM D, YYYY HH:mm:ss');
+          al.time = moment(al.time).format('MMM D, YYYY HH:mm:ss');
           al.stateModel = alertDef.getStateDisplayModel(al.newState);
           al.metrics = alertDef.joinEvalMatches(al.data, ', ');
           return al;