mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(alerting): add support for alert page filter
This commit is contained in:
parent
3e462f2914
commit
1be513fabd
@ -47,6 +47,7 @@ func GetAlertChanges(c *middleware.Context) Response {
|
||||
func GetAlerts(c *middleware.Context) Response {
|
||||
query := models.GetAlertsQuery{
|
||||
OrgId: c.OrgId,
|
||||
State: c.QueryStrings("state"),
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
@ -78,8 +79,10 @@ func GetAlerts(c *middleware.Context) Response {
|
||||
DashboardIds: dashboardIds,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&dashboardsQuery); err != nil {
|
||||
return ApiError(500, "List alerts failed", err)
|
||||
if len(alertDTOs) > 0 {
|
||||
if err := bus.Dispatch(&dashboardsQuery); err != nil {
|
||||
return ApiError(500, "List alerts failed", err)
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: should be possible to speed this up with lookup table
|
||||
@ -128,7 +131,7 @@ func DelAlert(c *middleware.Context) Response {
|
||||
func GetAlertStates(c *middleware.Context) Response {
|
||||
alertId := c.ParamsInt64(":alertId")
|
||||
|
||||
query := models.GetAlertsStateCommand{
|
||||
query := models.GetAlertsStateQuery{
|
||||
AlertId: alertId,
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,7 @@ type DeleteAlertCommand struct {
|
||||
//Queries
|
||||
type GetAlertsQuery struct {
|
||||
OrgId int64
|
||||
State []string
|
||||
|
||||
Result []AlertRule
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ type UpdateAlertStateCommand struct {
|
||||
|
||||
// Queries
|
||||
|
||||
type GetAlertsStateCommand struct {
|
||||
type GetAlertsStateQuery struct {
|
||||
OrgId int64 `json:"orgId" binding:"Required"`
|
||||
AlertId int64 `json:"alertId" binding:"Required"`
|
||||
|
||||
|
@ -1,15 +1,17 @@
|
||||
package sqlstore
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/go-xorm/xorm"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
bus.AddHandler("sql", SaveAlerts)
|
||||
bus.AddHandler("sql", GetAllAlertsForOrg)
|
||||
bus.AddHandler("sql", HandleAlertsQuery)
|
||||
bus.AddHandler("sql", GetAlertById)
|
||||
bus.AddHandler("sql", GetAlertsByDashboardId)
|
||||
bus.AddHandler("sql", GetAlertsByDashboardAndPanelId)
|
||||
@ -41,9 +43,33 @@ func DeleteAlertById(cmd *m.DeleteAlertCommand) error {
|
||||
})
|
||||
}
|
||||
|
||||
func GetAllAlertsForOrg(query *m.GetAlertsQuery) error {
|
||||
func HandleAlertsQuery(query *m.GetAlertsQuery) error {
|
||||
var sql bytes.Buffer
|
||||
params := make([]interface{}, 0)
|
||||
|
||||
sql.WriteString(`SELECT *
|
||||
from alert_rule
|
||||
`)
|
||||
|
||||
sql.WriteString(`WHERE org_id = ?`)
|
||||
params = append(params, query.OrgId)
|
||||
|
||||
if len(query.State) > 0 {
|
||||
|
||||
sql.WriteString(` AND (`)
|
||||
for i, v := range query.State {
|
||||
if i > 0 {
|
||||
sql.WriteString(" OR ")
|
||||
}
|
||||
sql.WriteString("state = ? ")
|
||||
params = append(params, strings.ToUpper(v))
|
||||
}
|
||||
sql.WriteString(")")
|
||||
|
||||
}
|
||||
|
||||
alerts := make([]m.AlertRule, 0)
|
||||
if err := x.Where("org_id = ?", query.OrgId).Find(&alerts); err != nil {
|
||||
if err := x.Sql(sql.String(), params...).Find(&alerts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -127,6 +153,7 @@ func upsertAlerts(alerts []m.AlertRule, posted *[]m.AlertRule, sess *xorm.Sessio
|
||||
}
|
||||
|
||||
} else {
|
||||
alert.State = "OK"
|
||||
_, err := sess.Insert(&alert)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -30,7 +30,6 @@ func TestAlertingDataAccess(t *testing.T) {
|
||||
Description: "Alerting description",
|
||||
QueryRange: "5m",
|
||||
Aggregator: "avg",
|
||||
State: "OK",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ func SetNewAlertState(cmd *m.UpdateAlertStateCommand) error {
|
||||
})
|
||||
}
|
||||
|
||||
func GetAlertStateLogByAlertId(cmd *m.GetAlertsStateCommand) error {
|
||||
func GetAlertStateLogByAlertId(cmd *m.GetAlertsStateQuery) error {
|
||||
alertLogs := make([]m.AlertState, 0)
|
||||
|
||||
if err := x.Where("alert_id = ?", cmd.AlertId).Desc("created").Find(&alertLogs); err != nil {
|
||||
|
@ -82,7 +82,7 @@ func TestAlertingStateAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("should have two event state logs", func() {
|
||||
query := &m.GetAlertsStateCommand{
|
||||
query := &m.GetAlertsStateQuery{
|
||||
AlertId: 1,
|
||||
OrgId: 1,
|
||||
}
|
||||
@ -92,6 +92,17 @@ func TestAlertingStateAccess(t *testing.T) {
|
||||
|
||||
So(len(*query.Result), ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("should not get any alerts with critical state", func() {
|
||||
query := &m.GetAlertsQuery{
|
||||
OrgId: 1,
|
||||
State: []string{"Critical"},
|
||||
}
|
||||
|
||||
err := HandleAlertsQuery(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(query.Result), ShouldEqual, 0)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -9,6 +9,8 @@ import alertDef from './alert_def';
|
||||
export class AlertPageCtrl {
|
||||
|
||||
alerts: any;
|
||||
stateFilters = [ 'Ok', 'Warn', 'Critical', 'Acknowledged' ];
|
||||
stateFilter = 'Warn';
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private backendSrv) {
|
||||
@ -16,7 +18,11 @@ export class AlertPageCtrl {
|
||||
}
|
||||
|
||||
loadAlerts() {
|
||||
this.backendSrv.get('/api/alerts/rules').then(result => {
|
||||
var params = {
|
||||
state: this.stateFilter
|
||||
};
|
||||
|
||||
this.backendSrv.get('/api/alerts/rules', params).then(result => {
|
||||
this.alerts = _.map(result, alert => {
|
||||
alert.iconCss = alertDef.getCssForState(alert.state);
|
||||
return alert;
|
||||
|
@ -3,34 +3,37 @@
|
||||
|
||||
<div class="page-container" >
|
||||
<div class="page-header">
|
||||
<h1>Alerts</h1>
|
||||
</div>
|
||||
<h1>Alerts</h1>
|
||||
<div class="gf-form-select-wrapper max-width-10">
|
||||
<select class="gf-form-input" ng-model="ctrl.stateFilter" ng-change="ctrl.loadAlerts()" ng-options="filter as filter for filter in ctrl.stateFilters"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="grafana-options-table">
|
||||
<thead>
|
||||
<th style="min-width: 200px"><strong>Name</strong></th>
|
||||
<th style="width: 1%">State</th>
|
||||
<th style="width: 1%"></th>
|
||||
</thead>
|
||||
<tr ng-repeat="alert in ctrl.alerts">
|
||||
<td>
|
||||
<table class="grafana-options-table">
|
||||
<thead>
|
||||
<th style="min-width: 200px"><strong>Name</strong></th>
|
||||
<th style="width: 1%">State</th>
|
||||
<th style="width: 1%"></th>
|
||||
</thead>
|
||||
<tr ng-repeat="alert in ctrl.alerts">
|
||||
<td>
|
||||
<a href="/alerts/events/{{alert.id}}">
|
||||
{{alert.title}}
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{{alert.title}}
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a href="/alerts/events/{{alert.id}}">
|
||||
<i class="icon-gf {{alert.iconCss}}"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<i class="icon-gf {{alert.iconCss}}"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a href="/dashboard/{{alert.dashboardUri}}?panelId={{alert.panelId}}&fullscreen&edit" class="btn btn-inverse btn-small">
|
||||
<i class="fa fa-edit"></i>
|
||||
edit
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<i class="fa fa-edit"></i>
|
||||
edit
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user