Commit 11a4ff0f by bergquist

feat(alerting): add basic UI for history in alert tab

ref #5850
parent 650a87dc
......@@ -215,8 +215,13 @@ func DeleteAlertNotification(c *middleware.Context) Response {
}
func GetAlertHistory(c *middleware.Context) Response {
alertId, err := getAlertIdForRequest(c)
if err != nil {
return ApiError(400, "Invalid request", err)
}
query := &annotations.ItemQuery{
AlertId: c.ParamsInt64("alertId"),
AlertId: alertId,
Type: annotations.AlertType,
OrgId: c.OrgId,
Limit: c.QueryInt64("limit"),
......@@ -244,3 +249,34 @@ func GetAlertHistory(c *middleware.Context) Response {
return Json(200, result)
}
func getAlertIdForRequest(c *middleware.Context) (int64, error) {
alertId := c.QueryInt64("alertId")
panelId := c.QueryInt64("panelId")
dashboardId := c.QueryInt64("dashboardId")
if alertId == 0 && dashboardId == 0 && panelId == 0 {
return 0, fmt.Errorf("Missing alertId or dashboardId and panelId")
}
if alertId == 0 {
//fetch alertId
query := models.GetAlertsQuery{
OrgId: c.OrgId,
DashboardId: dashboardId,
PanelId: panelId,
}
if err := bus.Dispatch(&query); err != nil {
return 0, err
}
if len(query.Result) != 1 {
return 0, fmt.Errorf("PanelId is not unique on dashboard")
}
alertId = query.Result[0].Id
}
return alertId, nil
}
......@@ -254,7 +254,7 @@ func Register(r *macaron.Macaron) {
r.Get("/", wrap(GetAlerts))
})
r.Get("/alert-history/:alertId", ValidateOrgAlert, wrap(GetAlertHistory))
r.Get("/alert-history", wrap(GetAlertHistory))
r.Get("/alert-notifications", wrap(GetAlertNotifications))
......
......@@ -55,7 +55,7 @@ type EvalMatch struct {
type AlertHistory struct {
AlertId int64 `json:"alertId"`
NewState string `json:"netState"`
NewState string `json:"newState"`
Timestamp time.Time `json:"timestamp"`
Title string `json:"title"`
Text string `json:"text"`
......
......@@ -4,6 +4,7 @@ import (
"time"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/metrics"
m "github.com/grafana/grafana/pkg/models"
......@@ -65,6 +66,7 @@ func (handler *DefaultResultHandler) Handle(ctx *EvalContext) {
NewState: string(ctx.Rule.State),
PrevState: string(oldState),
Timestamp: time.Now(),
Data: simplejson.NewFromAny(ctx.EvalMatches),
}
annotationRepo := annotations.GetRepository()
......
......@@ -5,6 +5,7 @@ import {ThresholdMapper} from './threshold_mapper';
import {QueryPart} from 'app/core/components/query_part/query_part';
import alertDef from './alert_def';
import config from 'app/core/config';
import moment from 'moment';
export class AlertTabCtrl {
panel: any;
......@@ -22,6 +23,7 @@ export class AlertTabCtrl {
alertNotifications;
error: string;
appSubUrl: string;
alertHistory: any;
/** @ngInject */
constructor(private $scope,
......@@ -60,6 +62,7 @@ export class AlertTabCtrl {
// build notification model
this.notifications = [];
this.alertNotifications = [];
this.alertHistory = [];
return this.backendSrv.get('/api/alert-notifications').then(res => {
this.notifications = res;
......@@ -71,6 +74,19 @@ export class AlertTabCtrl {
this.alertNotifications.push(model);
}
});
}).then(() => {
this.backendSrv.get(`/api/alert-history?dashboardId=${this.panelCtrl.dashboard.id}&panelId=${this.panel.id}`).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);
ah.metrics = _.map(ah.data, (ev) => {
return ev.Metric + "=" + ev.Value;
}).join(', ');
return ah;
});
});
});
}
......
......@@ -122,6 +122,28 @@
<textarea class="gf-form-input width-20" rows="10" ng-model="ctrl.alert.message" placeholder="Notification message details..."></textarea>
</div>
</div>
<div class="gf-form-group" style="width: 60%; margin-left: 8rem;" ng-if="ctrl.subTabIndex === 2">
<h5 class="section-heading">Alert history</h5>
<section class="card-section card-list-layout-list">
<ol class="card-list" >
<li class="card-item-wrapper" ng-repeat="ah in ctrl.alertHistory">
<div class="card-item card-item--alert">
<div class="card-item-body">
<div class="card-item-details">
<div class="card-item-sub-name">
<span class="alert-list-item-state {{ah.stateModel.stateClass}}">
<i class="{{ah.stateModel.iconClass}}"></i>
{{ah.text}}
</span> at {{ah.time}} {{ah.metrics}}
</div>
</div>
</div>
</div>
</li>
</ol>
</section>
</div>
</div>
</div>
......
......@@ -5,7 +5,7 @@
}
.edit-sidemenu-aside {
width: 14rem;
width: 16rem;
}
.edit-sidemenu {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment