Simplify alert UI

This commit is contained in:
Fabian Reinartz 2015-11-09 11:09:32 +01:00
parent 8f2aaff1db
commit 152df94088
7 changed files with 65 additions and 39 deletions

4
api.go
View File

@ -38,7 +38,7 @@ type API struct {
config string
uptime time.Time
groups func() []*UIGroup
groups func() []*UIGroups
// context is an indirection for testing.
context func(r *http.Request) context.Context
@ -46,7 +46,7 @@ type API struct {
}
// NewAPI returns a new API.
func NewAPI(alerts provider.Alerts, silences provider.Silences, gf func() []*UIGroup) *API {
func NewAPI(alerts provider.Alerts, silences provider.Silences, gf func() []*UIGroups) *API {
return &API{
context: route.Context,
alerts: alerts,

View File

@ -59,14 +59,19 @@ func (d *Dispatcher) Run() {
// UIGroup is the representation of a group of alerts as provided by
// the API.
type UIGroup struct {
Matchers types.Matchers `json:"matchers"`
RouteOpts *RouteOpts `json:"routeOpts"`
Labels model.LabelSet `json:"labels"`
Alerts model.Alerts `json:"alerts"`
RouteOpts *RouteOpts `json:"routeOpts"`
Alerts model.Alerts `json:"alerts"`
}
func (d *Dispatcher) Groups() []*UIGroup {
var groups []*UIGroup
type UIGroups struct {
Labels model.LabelSet `json:"labels"`
Groups []*UIGroup `json:"groups"`
}
func (d *Dispatcher) Groups() []*UIGroups {
var groups []*UIGroups
seen := map[model.Fingerprint]*UIGroups{}
for route, ags := range d.aggrGroups {
for _, ag := range ags {
@ -75,14 +80,18 @@ func (d *Dispatcher) Groups() []*UIGroup {
alerts = append(alerts, a)
}
uig := &UIGroup{
Matchers: route.SquashMatchers(),
Labels: ag.labels,
RouteOpts: &route.RouteOpts,
Alerts: types.Alerts(alerts...),
uig, ok := seen[ag.labels.Fingerprint()]
if !ok {
uig = &UIGroups{Labels: ag.labels}
seen[ag.labels.Fingerprint()] = uig
groups = append(groups, uig)
}
groups = append(groups, uig)
uig.Groups = append(uig.Groups, &UIGroup{
RouteOpts: &route.RouteOpts,
Alerts: types.Alerts(alerts...),
})
}
}

View File

@ -66,7 +66,7 @@ func main() {
)
defer disp.Stop()
api := NewAPI(alerts, silences, func() []*UIGroup {
api := NewAPI(alerts, silences, func() []*UIGroups {
return disp.Groups()
})

View File

@ -24,7 +24,8 @@ angular.module('am.directives').directive('alert',
return {
restrict: 'E',
scope: {
a: '='
alert: '=',
hiddenLabels: '='
},
templateUrl: '/app/partials/alert.html'
};
@ -202,11 +203,11 @@ angular.module('am.controllers').controller('AlertCtrl',
$scope.silence = {
matchers: []
}
angular.forEach($scope.a.labels, function(value, key) {
angular.forEach($scope.alert.labels, function(value, key) {
this.push({
name: key,
value: value,
isRegex: false,
isRegex: false
});
}, $scope.silence.matchers);
@ -219,11 +220,25 @@ angular.module('am.controllers').controller('AlertCtrl',
angular.module('am.controllers').controller('AlertsCtrl',
function($scope, AlertGroups) {
$scope.groups = null;
$scope.allDestinations = [];
$scope.refresh = function() {
AlertGroups.query({},
function(data) {
$scope.groups = data.data;
$scope.allDestinations = [];
angular.forEach($scope.groups, function(group) {
angular.forEach(group.groups, function(g) {
if ($scope.allDestinations.indexOf(g.routeOpts.sendTo) < 0) {
$scope.allDestinations.push(g.routeOpts.sendTo);
}
})
});
if (!$scope.destinations) {
$scope.destinations = angular.copy($scope.allDestinations);
}
},
function(data) {
$scope.error = data.data;

View File

@ -1,8 +1,8 @@
<div class="alert-item" ng-controller="AlertCtrl">
<div class="overview group">
<div class="labels left" ng-click="toggleDetails()">
<span ng-repeat="(name, value) in a.labels | orderBy:name">
<span class="lbl {{ name == 'alertname' ? 'lbl-highlight' : '' }}" outline>
<span ng-repeat="(name, value) in alert.labels | orderBy:name">
<span ng-hide="hiddenLabels.indexOf(name) >= 0" class="lbl {{ name == 'alertname' ? 'lbl-highlight' : '' }}" outline>
{{ name }} = '{{ value }}'
</span>
</span>
@ -23,12 +23,12 @@
<tr>
<td>active</td>
<td>
<span>{{ a.startsAt | date:'yyyy-MM-dd HH:mm' }}</span>
<span>{{ alert.startsAt | date:'yyyy-MM-dd HH:mm' }}</span>
<span ng-hide="a.endsAt == '0001-01-01T00:00:00Z'">
<span class="date">{{ a.endsAt | date:'yyyy-MM-dd' }},</span> <span class="time">{{ a.endsAt | date:'HH:mm' }}</span>
<span class="date">{{ alert.endsAt | date:'yyyy-MM-dd' }},</span> <span class="time">{{ alert.endsAt | date:'HH:mm' }}</span>
</span>
<span ng-show="a.endsAt == '0001-01-01T00:00:00Z'">
<span ng-show="alert.endsAt == '0001-01-01T00:00:00Z'">
<span class="time">now</span>
</span>
</td>
@ -38,7 +38,7 @@
<td>
<table class="table-flat">
<tbody>
<tr ng-repeat="(name, val) in a.annotations | orderBy:name">
<tr ng-repeat="(name, val) in alert.annotations | orderBy:name">
<td style="padding-right: 3em"><em>{{ name }}</em></td>
<td style="white-space: pre-line;">{{ val }}</td>
</tr>

View File

@ -1,21 +1,23 @@
<div>
<select class="select" ng-model="destinations" multiple>
<option ng-repeat="dest in allDestinations" value="{{ dest }}">{{ dest }}</option>
</select>
</div>
<div id="alert-groups" ng-controller="AlertsCtrl">
<div ng-repeat="group in groups">
<div class="alert-group" ng-show"group.alerts">
<div class="route-header group">
<div class="route-matchers left">
<span ng-repeat="m in group.matchers" class="lbl lbl-outline">
{{ m.name }} =<span ng-show="m.isRegex">~</span> '{{ m.value }}'
</span>
<div class="alert-group-header group">
<span ng-repeat="(ln, lv) in group.labels" class="lbl lbl-outline">
{{ ln }} = '{{ lv }}'
</span>
</div>
<div ng-repeat="g in group.groups">
<div ng-show="destinations.indexOf(g.routeOpts.sendTo) >= 0" class="alert-group" ng-show"g.alerts">
<div ng-repeat="a in g.alerts">
<alert class="list-item" alert="a" hiddenLabels="Object.keys(group.labels)"></alert>
</div>
</div>
<div class="alert-group-header group">
<span ng-repeat="(ln, lv) in group.labels" class="lbl lbl-outline">
{{ ln }} = '{{ lv }}'
</span>
</div>
<div ng-repeat="a in group.alerts">
<alert class="list-item" a="a"></alert>
</div>
</div>
</div>
</div>

View File

@ -34,7 +34,7 @@
<row>
<column cols="2">
<label>Creator</label>
<input ng-model="silence.createdBy" type="email" required>
<input ng-model="silence.createdBy" type="email" ng-required>
</column>
<column cols="4">
<label>Comment</label>