mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(alerting): progress on notifications
This commit is contained in:
parent
8df558dece
commit
6cb1dafb1d
@ -65,7 +65,6 @@ func addAlertMigrations(mg *Migrator) {
|
||||
{Name: "org_id", Type: DB_BigInt, Nullable: false},
|
||||
{Name: "name", Type: DB_NVarchar, Length: 255, Nullable: false},
|
||||
{Name: "type", Type: DB_NVarchar, Length: 255, Nullable: false},
|
||||
{Name: "always_execute", Type: DB_Bool, Nullable: false},
|
||||
{Name: "settings", Type: DB_Text, Nullable: false},
|
||||
{Name: "created", Type: DB_DateTime, Nullable: false},
|
||||
{Name: "updated", Type: DB_DateTime, Nullable: false},
|
||||
|
@ -211,7 +211,7 @@ function setupAngularRoutes($routeProvider, $locationProvider) {
|
||||
controllerAs: 'ctrl',
|
||||
resolve: loadAlertingBundle,
|
||||
})
|
||||
.when('/alerting/notification/:notificationId/edit', {
|
||||
.when('/alerting/notification/:id/edit', {
|
||||
templateUrl: 'public/app/features/alerting/partials/notification_edit.html',
|
||||
controller: 'AlertNotificationEditCtrl',
|
||||
controllerAs: 'ctrl',
|
||||
|
@ -27,7 +27,6 @@ export class AlertListCtrl {
|
||||
|
||||
updateFilter() {
|
||||
var stats = [];
|
||||
|
||||
this.filter.ok && stats.push('OK');
|
||||
this.filter.warn && stats.push('Warn');
|
||||
this.filter.critical && stats.push('critical');
|
||||
|
@ -6,49 +6,39 @@ import coreModule from '../../core/core_module';
|
||||
import config from 'app/core/config';
|
||||
|
||||
export class AlertNotificationEditCtrl {
|
||||
|
||||
notification: any;
|
||||
model: any;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private $routeParams, private backendSrv, private $scope) {
|
||||
if ($routeParams.notificationId) {
|
||||
this.loadNotification($routeParams.notificationId);
|
||||
constructor(private $routeParams, private backendSrv, private $scope, private $location) {
|
||||
if ($routeParams.id) {
|
||||
this.loadNotification($routeParams.id);
|
||||
} else {
|
||||
this.notification = {
|
||||
this.model = {
|
||||
type: 'email',
|
||||
settings: {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
loadNotification(notificationId) {
|
||||
this.backendSrv.get(`/api/alert-notifications/${notificationId}`).then(result => {
|
||||
console.log(result);
|
||||
this.notification = result;
|
||||
loadNotification(id) {
|
||||
this.backendSrv.get(`/api/alert-notifications/${id}`).then(result => {
|
||||
this.model = result;
|
||||
});
|
||||
}
|
||||
|
||||
isNew() {
|
||||
return this.notification === undefined || this.notification.id === undefined;
|
||||
return this.model.id === undefined;
|
||||
}
|
||||
|
||||
save() {
|
||||
if (this.notification.id) {
|
||||
console.log('this.notification: ', this.notification);
|
||||
this.backendSrv.put(`/api/alert-notifications/${this.notification.id}`, this.notification)
|
||||
.then(result => {
|
||||
this.notification = result;
|
||||
this.$scope.appEvent('alert-success', ['Notification created!', '']);
|
||||
}, () => {
|
||||
this.$scope.appEvent('alert-error', ['Unable to create notification.', '']);
|
||||
});
|
||||
if (this.model.id) {
|
||||
this.backendSrv.put(`/api/alert-notifications/${this.model.id}`, this.model).then(res => {
|
||||
this.model = res;
|
||||
});
|
||||
} else {
|
||||
this.backendSrv.post(`/api/alert-notifications`, this.notification)
|
||||
.then(result => {
|
||||
this.notification = result;
|
||||
this.$scope.appEvent('alert-success', ['Notification updated!', '']);
|
||||
}, () => {
|
||||
this.$scope.appEvent('alert-error', ['Unable to update notification.', '']);
|
||||
});
|
||||
this.backendSrv.post(`/api/alert-notifications`, this.model).then(res => {
|
||||
this.$location.path('alerting/notification/' + res.id + '/edit');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,16 +20,12 @@ export class AlertNotificationsListCtrl {
|
||||
});
|
||||
}
|
||||
|
||||
deleteNotification(notificationId) {
|
||||
this.backendSrv.delete(`/api/alerts-notification/${notificationId}`)
|
||||
.then(() => {
|
||||
this.notifications = this.notifications.filter(notification => {
|
||||
return notification.id !== notificationId;
|
||||
});
|
||||
this.$scope.appEvent('alert-success', ['Notification deleted', '']);
|
||||
}, () => {
|
||||
this.$scope.appEvent('alert-error', ['Unable to delete notification', '']);
|
||||
deleteNotification(id) {
|
||||
this.backendSrv.delete(`/api/alert-notifications/${id}`).then(() => {
|
||||
this.notifications = this.notifications.filter(notification => {
|
||||
return notification.id !== notificationId;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<navbar icon="fa fa-fw fa-list" title="Alerting" title-url="alerting">
|
||||
<navbar icon="icon-gf icon-gf-monitoring" title="Alerting" title-url="alerting">
|
||||
</navbar>
|
||||
|
||||
<div class="page-container" >
|
||||
|
@ -1,4 +1,8 @@
|
||||
<navbar icon="fa fa-fw fa-list" title="Alerting" title-url="alerting">
|
||||
<navbar icon="icon-gf icon-gf-monitoring" title="Alerting" title-url="alerting">
|
||||
<a href="alerting/notifications" class="navbar-page-btn">
|
||||
<i class="fa fa-fw fa-envelope-o"></i>
|
||||
Notifications
|
||||
</a>
|
||||
</navbar>
|
||||
|
||||
<div class="page-container" >
|
||||
@ -9,13 +13,13 @@
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-8">Name</span>
|
||||
<input type="text" class="gf-form-input max-width-15" ng-model="ctrl.notification.name" required></input>
|
||||
<input type="text" class="gf-form-input max-width-15" ng-model="ctrl.model.name" required></input>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-8">Type</span>
|
||||
<div class="gf-form-select-wrapper width-15">
|
||||
<select class="gf-form-input"
|
||||
ng-model="ctrl.notification.type"
|
||||
ng-model="ctrl.model.type"
|
||||
ng-options="t for t in ['webhook', 'email']"
|
||||
ng-change="ctrl.typeChanged(notification, $index)">
|
||||
</select>
|
||||
@ -23,27 +27,28 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-group" ng-show="ctrl.notification.type === 'webhook'">
|
||||
<div class="gf-form-group" ng-show="ctrl.model.type === 'webhook'">
|
||||
<h3 class="page-heading">Webhook settings</h3>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-6">Url</span>
|
||||
<input type="text" class="gf-form-input max-width-26" ng-model="ctrl.notification.settings.url"></input>
|
||||
<input type="text" class="gf-form-input max-width-26" ng-model="ctrl.model.settings.url"></input>
|
||||
</div>
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-6">Username</span>
|
||||
<input type="text" class="gf-form-input max-width-10" ng-model="ctrl.notification.settings.username"></input>
|
||||
<input type="text" class="gf-form-input max-width-10" ng-model="ctrl.model.settings.username"></input>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-6">Password</span>
|
||||
<input type="text" class="gf-form-input max-width-10" ng-model="ctrl.notification.settings.password"></input>
|
||||
<input type="text" class="gf-form-input max-width-10" ng-model="ctrl.model.settings.password"></input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form-group section" ng-show="ctrl.notification.type === 'email'">
|
||||
|
||||
<div class="gf-form-group section" ng-show="ctrl.model.type === 'email'">
|
||||
<h3 class="page-heading">Email addresses</h3>
|
||||
<div class="gf-form">
|
||||
<textarea rows="7" class="gf-form-input width-25" ng-ctrl="ctrl.notification.settings.addresses"></textarea>
|
||||
<textarea rows="7" class="gf-form-input width-25" ng-model="ctrl.model.settings.addresses"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -1,4 +1,8 @@
|
||||
<navbar icon="fa fa-fw fa-list" title="Alerting" title-url="alerting">
|
||||
<navbar icon="icon-gf icon-gf-monitoring" title="Alerting" title-url="alerting">
|
||||
<a href="alerting/notifications" class="navbar-page-btn">
|
||||
<i class="fa fa-fw fa-envelope-o"></i>
|
||||
Notifications
|
||||
</a>
|
||||
</navbar>
|
||||
|
||||
<div class="page-container" >
|
||||
|
@ -49,14 +49,17 @@ export class AlertTabCtrl {
|
||||
{text: 'Critical', value: 'critical'},
|
||||
{text: 'Warning', value: 'warning'},
|
||||
];
|
||||
addNotificationSegment;
|
||||
|
||||
/** @ngInject */
|
||||
constructor($scope, private $timeout, private backendSrv, private dashboardSrv) {
|
||||
constructor($scope, private $timeout, private backendSrv, private dashboardSrv, private uiSegmentSrv) {
|
||||
this.panelCtrl = $scope.ctrl;
|
||||
this.panel = this.panelCtrl.panel;
|
||||
$scope.ctrl = this;
|
||||
|
||||
this.metricTargets = this.panel.targets.map(val => val);
|
||||
this.addNotificationSegment = uiSegmentSrv.newPlusButton();
|
||||
|
||||
this.initModel();
|
||||
|
||||
// set panel alert edit mode
|
||||
@ -66,6 +69,28 @@ export class AlertTabCtrl {
|
||||
});
|
||||
}
|
||||
|
||||
getNotifications() {
|
||||
return this.backendSrv.get('/api/alert-notifications').then(res => {
|
||||
return res.map(item => {
|
||||
return this.uiSegmentSrv.newSegment(item.name);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
notificationAdded() {
|
||||
this.alert.notifications.push({
|
||||
name: this.addNotificationSegment.value
|
||||
});
|
||||
|
||||
// reset plus button
|
||||
this.addNotificationSegment.value = this.uiSegmentSrv.newPlusButton().value;
|
||||
this.addNotificationSegment.html = this.uiSegmentSrv.newPlusButton().html;
|
||||
}
|
||||
|
||||
removeNotification(index) {
|
||||
this.alert.notifications.splice(index, 1);
|
||||
}
|
||||
|
||||
initModel() {
|
||||
var alert = this.alert = this.panel.alert = this.panel.alert || {};
|
||||
|
||||
|
@ -24,53 +24,33 @@
|
||||
<!-- </div> -->
|
||||
|
||||
<div ng-if="ctrl.alert.enabled">
|
||||
<div class="gf-form-group">
|
||||
<h5 class="section-heading">Alert Rule</h5>
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form max-width-30">
|
||||
<span class="gf-form-label width-8">Name</span>
|
||||
<input type="text" class="gf-form-input width-22" ng-model="ctrl.alert.name">
|
||||
</div>
|
||||
<!-- <div class="gf-form"> -->
|
||||
<!-- <span class="gf-form-label width-6">Handler</span> -->
|
||||
<!-- <div class="gf-form-select-wrapper"> -->
|
||||
<!-- <select class="gf-form-input" -->
|
||||
<!-- ng-model="ctrl.alert.handler" -->
|
||||
<!-- ng-options="f.value as f.text for f in ctrl.handlers"> -->
|
||||
<!-- </select> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-8">Evaluate every</span>
|
||||
<input class="gf-form-input max-width-7" type="text" ng-model="ctrl.alert.frequency"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form max-width-30">
|
||||
<span class="gf-form-label width-8">Notifications</span>
|
||||
<input class="gf-form-input max-width-22" type="text" ng-model="ctrl.alert.notifications"></input>
|
||||
</div>
|
||||
<!--
|
||||
<bootstrap-tagsinput ng-model="ctrl.alert.notify" tagclass="label label-tag" placeholder="add tags">
|
||||
</bootstrap-tagsinput>
|
||||
-->
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-8">Severity</span>
|
||||
<div class="gf-form-select-wrapper">
|
||||
<select class="gf-form-input"
|
||||
ng-model="ctrl.alert.severity"
|
||||
ng-options="f.value as f.text for f in ctrl.severityLevels">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form-group">
|
||||
<h5 class="section-heading">Alert Rule</h5>
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label">Name</span>
|
||||
<input type="text" class="gf-form-input width-22" ng-model="ctrl.alert.name">
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label">Evaluate every</span>
|
||||
<input class="gf-form-input max-width-7" type="text" ng-model="ctrl.alert.frequency"></input>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label">Severity</span>
|
||||
<div class="gf-form-select-wrapper">
|
||||
<select class="gf-form-input" ng-model="ctrl.alert.severity" ng-options="f.value as f.text for f in ctrl.severityLevels">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-group">
|
||||
<h5 class="section-heading">Conditions</h5>
|
||||
<div class="gf-form-inline" ng-repeat="conditionModel in ctrl.conditionModels">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label query-keyword">AND</span>
|
||||
<span class="gf-form-label query-keyword width-5" ng-if="$index">AND</span>
|
||||
<span class="gf-form-label query-keyword width-5" ng-if="$index===0">WHEN</span>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<query-part-editor
|
||||
@ -88,7 +68,7 @@
|
||||
</query-part-editor>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label">When Value</span>
|
||||
<span class="gf-form-label">Value</span>
|
||||
<metric-segment-model property="conditionModel.evaluator.type" options="ctrl.evalFunctions" custom="false" css-class="query-segment-operator" on-change="ctrl.thresholdUpdated()"></metric-segment-model>
|
||||
<input class="gf-form-input max-width-7" type="number" ng-model="conditionModel.evaluator.params[0]" ng-change="ctrl.thresholdsUpdated()"></input>
|
||||
</div>
|
||||
@ -98,48 +78,63 @@
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-button-row">
|
||||
<div class="dropdown pull-left" ng-if="ctrl.alert.enabled" >
|
||||
<button class="btn btn-inverse dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="fa fa-plus"></i> Add Condition
|
||||
</button>
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label dropdown">
|
||||
<a class="pointer dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="fa fa-plus"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li ng-repeat="ct in ctrl.conditionTypes" role="menuitem">
|
||||
<a ng-click="ctrl.addCondition(ct.value);">{{ct.text}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li ng-repeat="ct in ctrl.conditionTypes" role="menuitem">
|
||||
<a ng-click="ctrl.addCondition(ct.value);">{{ct.text}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="gf-form-group">
|
||||
<h5 class="section-heading">Notifications</h5>
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form max-width-30">
|
||||
<span class="gf-form-label" ng-repeat="nc in ctrl.alert.notifications">
|
||||
{{nc.name}}
|
||||
<i class="fa fa-remove pointer" ng-click="ctrl.removeNotification($index)"></i>
|
||||
</span>
|
||||
<metric-segment segment="ctrl.addNotificationSegment" get-options="ctrl.getNotifications()" on-change="ctrl.notificationAdded()"></metric-segment>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-inverse" ng-click="ctrl.test()">
|
||||
Test Rule
|
||||
</button>
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-button-row">
|
||||
<button class="btn btn-inverse" ng-click="ctrl.test()">
|
||||
Test Rule
|
||||
</button>
|
||||
|
||||
<button class="btn btn-inverse" ng-click="ctrl.delete()">
|
||||
Delete Alert
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-inverse" ng-click="ctrl.delete()">
|
||||
Delete Alert
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-group" ng-if="ctrl.testing">
|
||||
Evaluating rule <i class="fa fa-spinner fa-spin"></i>
|
||||
Evaluating rule <i class="fa fa-spinner fa-spin"></i>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-group" ng-if="ctrl.testResult">
|
||||
<json-tree root-name="result" object="ctrl.testResult" start-expanded="true"></json-tree>
|
||||
<json-tree root-name="result" object="ctrl.testResult" start-expanded="true"></json-tree>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-group" ng-if="!ctrl.alert.enabled">
|
||||
<div class="gf-form-button-row">
|
||||
<button class="btn btn-inverse" ng-click="ctrl.enable()">
|
||||
<i class="icon-gf icon-gf-alert"></i>
|
||||
Create Alert
|
||||
</button>
|
||||
</div>
|
||||
<div class="gf-form-button-row">
|
||||
<button class="btn btn-inverse" ng-click="ctrl.enable()">
|
||||
<i class="icon-gf icon-gf-alert"></i>
|
||||
Create Alert
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user