Iss #152 - fixed trigger panel (used new plugin API).

This commit is contained in:
Alexander Zobnin
2016-02-14 18:04:30 +03:00
parent f2201f9461
commit 637cf4c63d
4 changed files with 496 additions and 470 deletions

View File

@@ -8,28 +8,28 @@
</li> </li>
<li> <li>
<input type="text" <input type="text"
ng-model="panel.triggers.group.filter" ng-model="editor.panel.triggers.group.filter"
bs-typeahead="getGroupNames" bs-typeahead="editor.getGroupNames"
ng-change="onTargetPartChange(panel.triggers.group)" ng-change="editor.onTargetPartChange(editor.panel.triggers.group)"
ng-blur="parseTarget()" ng-blur="editor.parseTarget()"
data-min-length=0 data-min-length=0
data-items=100 data-items=100
class="input-large tight-form-input" class="input-large tight-form-input"
ng-style="panel.triggers.group.style"> ng-style="editor.panel.triggers.group.style">
</li> </li>
<li class="tight-form-item" style="width: 50px"> <li class="tight-form-item" style="width: 50px">
Host Host
</li> </li>
<li> <li>
<input type="text" <input type="text"
ng-model="panel.triggers.host.filter" ng-model="editor.panel.triggers.host.filter"
bs-typeahead="getHostNames" bs-typeahead="editor.getHostNames"
ng-change="onTargetPartChange(panel.triggers.host)" ng-change="editor.onTargetPartChange(editor.panel.triggers.host)"
ng-blur="parseTarget()" ng-blur="editor.parseTarget()"
data-min-length=0 data-min-length=0
data-items=100 data-items=100
class="input-large tight-form-input last" class="input-large tight-form-input last"
ng-style="panel.triggers.host.style"> ng-style="editor.panel.triggers.host.style">
</li> </li>
</ul> </ul>
<div class="clearfix"></div> <div class="clearfix"></div>
@@ -41,26 +41,26 @@
</li> </li>
<li> <li>
<input type="text" <input type="text"
ng-model="panel.triggers.application.filter" ng-model="editor.panel.triggers.application.filter"
bs-typeahead="getApplicationNames" bs-typeahead="editor.getApplicationNames"
ng-change="onTargetPartChange(panel.triggers.application)" ng-change="editor.onTargetPartChange(editor.panel.triggers.application)"
ng-blur="parseTarget()" ng-blur="editor.parseTarget()"
data-min-length=0 data-min-length=0
data-items=100 data-items=100
class="input-large tight-form-input" class="input-large tight-form-input"
ng-style="panel.triggers.application.style"> ng-style="editor.panel.triggers.application.style">
</li> </li>
<li class="tight-form-item" style="width: 50px"> <li class="tight-form-item" style="width: 50px">
Trigger Trigger
</li> </li>
<li> <li>
<input type="text" <input type="text"
ng-model="panel.triggers.trigger.filter" ng-model="editor.panel.triggers.trigger.filter"
ng-change="onTargetPartChange(panel.triggers.trigger)" ng-change="editor.onTargetPartChange(editor.panel.triggers.trigger)"
ng-blur="parseTarget()" ng-blur="editor.parseTarget()"
placeholder="trigger name" placeholder="trigger name"
class="input-large tight-form-input last" class="input-large tight-form-input last"
ng-style="panel.triggers.trigger.style" ng-style="editor.panel.triggers.trigger.style"
empty-to-null> empty-to-null>
</li> </li>
</ul> </ul>
@@ -74,9 +74,9 @@
<ul class="tight-form-list"> <ul class="tight-form-list">
<li> <li>
<select class="tight-form-input input-large last" <select class="tight-form-input input-large last"
ng-model="panel.datasource" ng-model="editor.panel.datasource"
ng-options="ds for ds in datasources" ng-options="ds for ds in editor.datasources"
ng-change="datasourceChanged()"> ng-change="editor.datasourceChanged()">
</select> </select>
</li> </li>
</ul> </ul>
@@ -96,9 +96,9 @@
</li> </li>
<li> <li>
<select class="input-medium tight-form-input" <select class="input-medium tight-form-input"
ng-model="panel.showTriggers" ng-model="editor.panel.showTriggers"
ng-options="f for f in ackFilters" ng-options="f for f in editor.ackFilters"
ng-change="get_data()"> ng-change="editor.panelCtrl.refreshData()">
</select> </select>
</li> </li>
<li class="tight-form-item" style="width: 13em"> <li class="tight-form-item" style="width: 13em">
@@ -107,9 +107,9 @@
<li> <li>
<input class="input-small tight-form-input" <input class="input-small tight-form-input"
type="number" type="number"
ng-model="panel.limit" ng-model="editor.panel.limit"
ng-model-onblur ng-model-onblur
ng-change="get_data()"> ng-change="editor.panelCtrl.refreshData()">
</li> </li>
</ul> </ul>
<div class="clearfix"></div> <div class="clearfix"></div>
@@ -121,9 +121,9 @@
</li> </li>
<li> <li>
<select class="input-medium tight-form-input" <select class="input-medium tight-form-input"
ng-model="panel.sortTriggersBy" ng-model="editor.panel.sortTriggersBy"
ng-options="f.text for f in sortByFields track by f.value" ng-options="f.text for f in editor.sortByFields track by f.value"
ng-change="get_data()"> ng-change="editor.panelCtrl.refreshData()">
</select> </select>
</li> </li>
<li class="tight-form-item" style="width: 13em"> <li class="tight-form-item" style="width: 13em">
@@ -131,9 +131,9 @@
</li> </li>
<li> <li>
<select class="tight-form-input input-medium" <select class="tight-form-input input-medium"
ng-model="panel.showEvents" ng-model="editor.panel.showEvents"
ng-options="f.text for f in showEventsFields track by f.value" ng-options="f.text for f in editor.showEventsFields track by f.value"
ng-change="get_data()"> ng-change="editor.panelCtrl.refreshData()">
</select> </select>
</li> </li>
</ul> </ul>
@@ -145,58 +145,58 @@
<strong>Show fields</strong> <strong>Show fields</strong>
</li> </li>
<li class="tight-form-item"> <li class="tight-form-item">
<label class="checkbox-label" for="panel.hostField">Host</label> <label class="checkbox-label" for="hostField">Host</label>
<input class="cr1" <input class="cr1"
id="panel.hostField" id="hostField"
type="checkbox" type="checkbox"
ng-model="panel.hostField" ng-model="editor.panel.hostField"
ng-checked="panel.hostField"> ng-checked="editor.panel.hostField">
<label for="panel.hostField" class="cr1"></label> <label for="hostField" class="cr1"></label>
</li> </li>
<li class="tight-form-item"> <li class="tight-form-item">
<label class="checkbox-label" for="panel.severityField">Status</label> <label class="checkbox-label" for="statusField">Status</label>
<input class="cr1" <input class="cr1"
id="panel.statusField" id="statusField"
type="checkbox" type="checkbox"
ng-model="panel.statusField" ng-model="editor.panel.statusField"
ng-checked="panel.statusField"> ng-checked="editor.panel.statusField">
<label for="panel.statusField" class="cr1"></label> <label for="statusField" class="cr1"></label>
</li> </li>
<li class="tight-form-item"> <li class="tight-form-item">
<label class="checkbox-label" for="panel.severityField">Severity</label> <label class="checkbox-label" for="severityField">Severity</label>
<input class="cr1" <input class="cr1"
id="panel.severityField" id="severityField"
type="checkbox" type="checkbox"
ng-model="panel.severityField" ng-model="editor.panel.severityField"
ng-checked="panel.severityField"> ng-checked="editor.panel.severityField">
<label for="panel.severityField" class="cr1"></label> <label for="severityField" class="cr1"></label>
</li> </li>
<li class="tight-form-item"> <li class="tight-form-item">
<label class="checkbox-label" for="panel.lastChangeField">Last change</label> <label class="checkbox-label" for="lastChangeField">Last change</label>
<input class="cr1" <input class="cr1"
id="panel.lastChangeField" id="lastChangeField"
type="checkbox" type="checkbox"
ng-model="panel.lastChangeField" ng-model="editor.panel.lastChangeField"
ng-checked="panel.lastChangeField"> ng-checked="editor.panel.lastChangeField">
<label for="panel.lastChangeField" class="cr1"></label> <label for="lastChangeField" class="cr1"></label>
</li> </li>
<li class="tight-form-item"> <li class="tight-form-item">
<label class="checkbox-label" for="panel.ageField">Age</label> <label class="checkbox-label" for="ageField">Age</label>
<input class="cr1" <input class="cr1"
id="panel.ageField" id="ageField"
type="checkbox" type="checkbox"
ng-model="panel.ageField" ng-model="editor.panel.ageField"
ng-checked="panel.ageField"> ng-checked="editor.panel.ageField">
<label for="panel.ageField" class="cr1"></label> <label for="ageField" class="cr1"></label>
</li> </li>
<li class="tight-form-item last"> <li class="tight-form-item last">
<label class="checkbox-label" for="panel.infoField">Info</label> <label class="checkbox-label" for="infoField">Info</label>
<input class="cr1" <input class="cr1"
id="panel.infoField" id="infoField"
type="checkbox" type="checkbox"
ng-model="panel.infoField" ng-model="editor.panel.infoField"
ng-checked="panel.infoField"> ng-checked="editor.panel.infoField">
<label for="panel.infoField" class="cr1"></label> <label for="infoField" class="cr1"></label>
</li> </li>
</ul> </ul>
<div class="clearfix"></div> <div class="clearfix"></div>
@@ -205,25 +205,25 @@
<ul class="tight-form-list"> <ul class="tight-form-list">
<li class="tight-form-item"> <li class="tight-form-item">
<strong>Custom Last change format</strong> <strong>Custom Last change format</strong>
<label class="checkbox-label" for="panel.customLastChangeFormat">&nbsp;</label> <label class="checkbox-label" for="customLastChangeFormat">&nbsp;</label>
<input class="cr1" <input class="cr1"
id="panel.customLastChangeFormat" id="customLastChangeFormat"
type="checkbox" type="checkbox"
ng-change="get_data()" ng-change="editor.panelCtrl.refreshData()"
ng-model="panel.customLastChangeFormat" ng-model="editor.panel.customLastChangeFormat"
ng-checked="panel.customLastChangeFormat"> ng-checked="editor.panel.customLastChangeFormat">
<label for="panel.customLastChangeFormat" class="cr1"></label> <label for="customLastChangeFormat" class="cr1"></label>
</li> </li>
<li ng-if="panel.customLastChangeFormat"> <li ng-if="editor.panel.customLastChangeFormat">
<input type="text" <input type="text"
ng-model="panel.lastChangeFormat" ng-model="editor.panel.lastChangeFormat"
ng-blur="get_data()" ng-blur="editor.panelCtrl.refreshData()"
placeholder="dddd, MMMM Do YYYY, h:mm:ss a" placeholder="dddd, MMMM Do YYYY, h:mm:ss a"
class="tight-form-input" class="tight-form-input"
style="width: 300px" style="width: 300px"
empty-to-null> empty-to-null>
</li> </li>
<li class="tight-form-item last" ng-if="panel.customLastChangeFormat"> <li class="tight-form-item last" ng-if="editor.panel.customLastChangeFormat">
<a href="http://momentjs.com/docs/#/displaying/format/" target="_blank"> <a href="http://momentjs.com/docs/#/displaying/format/" target="_blank">
<i class="fa fa-question-circle" <i class="fa fa-question-circle"
bs-tooltip="'See moment.js dosc for time format.'"> bs-tooltip="'See moment.js dosc for time format.'">
@@ -237,8 +237,7 @@
</div> </div>
<div class="section"> <div class="section">
<h5>Customize triggers severity and colors</h5> <h5>Customize triggers severity and colors</h5>
<div class="tight-form" <div class="tight-form" ng-repeat="trigger in editor.panel.triggerSeverity">
ng-repeat="trigger in panel.triggerSeverity">
<ul class="tight-form-list"> <ul class="tight-form-list">
<li class="tight-form-item" style="width: 10px"> <li class="tight-form-item" style="width: 10px">
{{ trigger.priority }} {{ trigger.priority }}
@@ -251,10 +250,10 @@
style="color: white" style="color: white"
ng-style="{background: trigger.color}" ng-style="{background: trigger.color}"
ng-model-onblur ng-model-onblur
ng-change="get_data()"> ng-change="editor.panelCtrl.refreshData()">
</li> </li>
<li class="tight-form-item"> <li class="tight-form-item">
<spectrum-picker ng-model="trigger.color" ng-change="get_data()"></spectrum-picker> <spectrum-picker ng-model="trigger.color" ng-change="editor.panelCtrl.refreshData()"></spectrum-picker>
</li> </li>
<li class="tight-form-item last" style="width: 28px"> <li class="tight-form-item last" style="width: 28px">
<label class="checkbox-label" for="{{ 'trigger-show-' + $index }}"></label> <label class="checkbox-label" for="{{ 'trigger-show-' + $index }}"></label>
@@ -263,7 +262,7 @@
type="checkbox" type="checkbox"
ng-model="trigger.show" ng-model="trigger.show"
ng-checked="trigger.show" ng-checked="trigger.show"
ng-change="get_data()"> ng-change="editor.panelCtrl.refreshData()">
<label for="{{ 'trigger-show-' + $index }}" class="cr1"></label> <label for="{{ 'trigger-show-' + $index }}" class="cr1"></label>
</li> </li>
</ul> </ul>
@@ -272,12 +271,15 @@
<div class="tight-form last"> <div class="tight-form last">
<ul class="tight-form-list"> <ul class="tight-form-list">
<li class="tight-form-item" <li class="tight-form-item"
ng-style="{background:panel.okEventColor}" ng-style="{background:editor.panel.okEventColor}"
style="width: 160px; color: white"> style="width: 160px; color: white">
<span style="padding-left: 25px"> OK event color </span> <span style="padding-left: 25px"> OK event color </span>
</li> </li>
<li class="tight-form-item"> <li class="tight-form-item">
<spectrum-picker ng-model="panel.okEventColor" ng-change="get_data()"></spectrum-picker> <spectrum-picker
ng-model="editor.panel.okEventColor"
ng-change="editor.panelCtrl.refreshData()">
</spectrum-picker>
</li> </li>
</ul> </ul>
<div class="clearfix"></div> <div class="clearfix"></div>

View File

@@ -0,0 +1,205 @@
/**
* Grafana-Zabbix
* Zabbix plugin for Grafana.
* http://github.com/alexanderzobnin/grafana-zabbix
*
* Trigger panel.
* This feature sponsored by CORE IT
* http://www.coreit.fr
*
* Copyright 2015 Alexander Zobnin alexanderzobnin@gmail.com
* Licensed under the Apache License, Version 2.0
*/
define([
'angular',
'lodash',
'jquery'
],
function (angular, _, $) {
'use strict';
function TriggerPanelEditorCtrl($scope, $q, uiSegmentSrv, datasourceSrv, templateSrv, popoverSrv) {
$scope.editor = this;
this.panelCtrl = $scope.ctrl;
this.panel = this.panelCtrl.panel;
this.datasourceSrv = datasourceSrv;
this.templateSrv = templateSrv;
this.popoverSrv = popoverSrv;
// Map functions for bs-typeahead
this.getGroupNames = _.partial(getMetricNames, this, 'groupList');
this.getHostNames = _.partial(getMetricNames, this, 'filteredHosts');
this.getApplicationNames = _.partial(getMetricNames, this, 'filteredApplications');
this.getItemNames = _.partial(getMetricNames, this, 'filteredItems');
this.ackFilters = [
'all triggers',
'unacknowledged',
'acknowledged'
];
this.sortByFields = [
{ text: 'last change', value: 'lastchange' },
{ text: 'severity', value: 'priority' }
];
this.showEventsFields = [
{ text: 'all events', value: [0,1] },
{ text: 'Ok events', value: 0 },
{ text: 'Problem events', value: 1 }
];
// Load scope defaults
var scopeDefaults = {
metric: {},
inputStyles: {},
oldTarget: _.cloneDeep(this.panel.triggers),
defaultTimeFormat: "DD MMM YYYY HH:mm:ss"
};
_.defaults(this, scopeDefaults);
var self = this;
// Get zabbix data sources
var datasources = _.filter(this.datasourceSrv.getMetricSources(), function(datasource) {
return datasource.meta.id === 'zabbix';
});
this.datasources = _.map(datasources, 'name');
// Set default datasource
if (!this.panel.datasource) {
this.panel.datasource = this.datasources[0];
}
// Load datasource
this.datasourceSrv.get(this.panel.datasource).then(function (datasource) {
self.datasource = datasource;
self.initFilters();
self.panelCtrl.refreshData();
});
}
var p = TriggerPanelEditorCtrl.prototype;
// Get list of metric names for bs-typeahead directive
function getMetricNames(scope, metricList) {
return _.uniq(_.map(scope.metric[metricList], 'name'));
}
p.initFilters = function () {
this.filterGroups();
this.filterHosts();
this.filterApplications();
};
p.filterGroups = function() {
var self = this;
this.datasource.queryProcessor.filterGroups().then(function(groups) {
self.metric.groupList = groups;
});
};
p.filterHosts = function() {
var self = this;
var groupFilter = this.templateSrv.replace(this.panel.triggers.group.filter);
this.datasource.queryProcessor.filterHosts(groupFilter).then(function(hosts) {
self.metric.filteredHosts = hosts;
});
};
p.filterApplications = function() {
var self = this;
var groupFilter = this.templateSrv.replace(this.panel.triggers.group.filter);
var hostFilter = this.templateSrv.replace(this.panel.triggers.host.filter);
this.datasource.queryProcessor.filterApplications(groupFilter, hostFilter)
.then(function(apps) {
self.metric.filteredApplications = apps;
});
};
p.onTargetPartChange = function(targetPart) {
var regexStyle = {'color': '#CCA300'};
targetPart.isRegex = isRegex(targetPart.filter);
targetPart.style = targetPart.isRegex ? regexStyle : {};
};
function isRegex(str) {
// Pattern for testing regex
var regexPattern = /^\/(.*)\/([gmi]*)$/m;
return regexPattern.test(str);
}
p.parseTarget = function() {
this.initFilters();
var newTarget = _.cloneDeep(this.panel.triggers);
if (!_.isEqual(this.oldTarget, this.panel.triggers)) {
this.oldTarget = newTarget;
this.panelCtrl.refreshData();
}
};
p.refreshTriggerSeverity = function() {
_.each(this.triggerList, function(trigger) {
trigger.color = this.panel.triggerSeverity[trigger.priority].color;
trigger.severity = this.panel.triggerSeverity[trigger.priority].severity;
});
this.panelCtrl.refreshData();
};
p.datasourceChanged = function() {
this.panelCtrl.refreshData();
};
p.changeTriggerSeverityColor = function(trigger, color) {
this.panel.triggerSeverity[trigger.priority].color = color;
this.refreshTriggerSeverity();
};
function getTriggerIndexForElement(el) {
return el.parents('[data-trigger-index]').data('trigger-index');
}
p.openTriggerColorSelector = function(event) {
var el = $(event.currentTarget);
var index = getTriggerIndexForElement(el);
var popoverScope = this.$new();
popoverScope.trigger = this.panel.triggerSeverity[index];
popoverScope.changeTriggerSeverityColor = this.changeTriggerSeverityColor;
this.popoverSrv.show({
element: el,
placement: 'top',
templateUrl: 'public/plugins/triggers/trigger.colorpicker.html',
scope: popoverScope
});
};
p.openOkEventColorSelector = function(event) {
var el = $(event.currentTarget);
var popoverScope = this.$new();
popoverScope.trigger = {color: this.panel.okEventColor};
popoverScope.changeTriggerSeverityColor = function(trigger, color) {
this.panel.okEventColor = color;
this.refreshTriggerSeverity();
};
this.popoverSrv.show({
element: el,
placement: 'top',
templateUrl: 'public/plugins/triggers/trigger.colorpicker.html',
scope: popoverScope
});
};
var triggerPanelEditor = function() {
return {
restrict: 'E',
scope: true,
templateUrl: 'public/plugins/triggers/editor.html',
controller: TriggerPanelEditorCtrl,
};
};
return triggerPanelEditor;
});

View File

@@ -1,49 +1,47 @@
<div class="table-panel-wrapper">
<grafana-panel>
<div class="table-panel-container"> <div class="table-panel-container">
<div class="table-panel-header-bg"></div> <div class="table-panel-header-bg"></div>
<div class="table-panel-scroll"> <div class="table-panel-scroll">
<table class="table-panel-table"> <table class="table-panel-table">
<thead> <thead>
<tr> <tr>
<th ng-if="panel.hostField" style="width: 15%"> <th ng-if="ctrl.panel.hostField" style="width: 15%">
<div class="table-panel-table-header-inner pointer"> <div class="table-panel-table-header-inner pointer">
Host Host
</div> </div>
</th> </th>
<th ng-if="panel.statusField" style="width: 85px"> <th ng-if="ctrl.panel.statusField" style="width: 85px">
<div class="table-panel-table-header-inner pointer">Status</div> <div class="table-panel-table-header-inner pointer">Status</div>
</th> </th>
<th ng-if="panel.severityField" style="width: 120px"> <th ng-if="ctrl.panel.severityField" style="width: 120px">
<div class="table-panel-table-header-inner pointer">Severity</div> <div class="table-panel-table-header-inner pointer">Severity</div>
</th> </th>
<th> <th>
<div class="table-panel-table-header-inner pointer">Issue</div> <div class="table-panel-table-header-inner pointer">Issue</div>
</th> </th>
<th ng-if="panel.lastChangeField" style="width: 220px"> <th ng-if="ctrl.panel.lastChangeField" style="width: 220px">
<div class="table-panel-table-header-inner pointer">Last change</div> <div class="table-panel-table-header-inner pointer">Last change</div>
</th> </th>
<th ng-if="panel.ageField" style="width: 180px"> <th ng-if="ctrl.panel.ageField" style="width: 180px">
<div class="table-panel-table-header-inner pointer">Age</div> <div class="table-panel-table-header-inner pointer">Age</div>
</th> </th>
<th ng-if="panel.infoField" style="width: 100px"> <th ng-if="ctrl.panel.infoField" style="width: 100px">
<div class="table-panel-table-header-inner pointer">Info</div> <div class="table-panel-table-header-inner pointer">Info</div>
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="trigger in triggerList"> <tr ng-repeat="trigger in ctrl.triggerList">
<td ng-if="panel.hostField"> <td ng-if="ctrl.panel.hostField">
<div> <div>
<span><strong>{{trigger.host}}</strong></span> <span><strong>{{trigger.host}}</strong></span>
</div> </div>
</td> </td>
<td ng-if="panel.statusField" style="background-color: {{trigger.color}}; color: white"> <td ng-if="ctrl.panel.statusField" style="background-color: {{trigger.color}}; color: white">
<div> <div>
{{triggerStatusMap[trigger.value]}} {{ctrl.triggerStatusMap[trigger.value]}}
</div> </div>
</td> </td>
<td ng-if="panel.severityField" style="background-color: {{trigger.color}}; color: white"> <td ng-if="ctrl.panel.severityField" style="background-color: {{trigger.color}}; color: white">
<div> <div>
{{trigger.severity}} {{trigger.severity}}
</div> </div>
@@ -101,13 +99,13 @@
</div> </div>
</div> </div>
</td> </td>
<td ng-if="panel.lastChangeField"> <td ng-if="ctrl.panel.lastChangeField">
{{trigger.lastchange}} {{trigger.lastchange}}
</td> </td>
<td ng-if="panel.ageField"> <td ng-if="ctrl.panel.ageField">
{{trigger.age}} {{trigger.age}}
</td> </td>
<td ng-if="panel.infoField"> <td ng-if="ctrl.panel.infoField">
<!-- Trigger Url --> <!-- Trigger Url -->
<a ng-if="trigger.url" <a ng-if="trigger.url"
@@ -136,5 +134,3 @@
</div> </div>
</div> </div>
<div class="table-panel-footer"></div> <div class="table-panel-footer"></div>
</grafana-panel>
</div>

View File

@@ -12,54 +12,17 @@
*/ */
define([ define([
'app/plugins/sdk',
'angular', 'angular',
'app/app',
'lodash', 'lodash',
'jquery', 'jquery',
'moment', 'moment',
'app/core/config', './editor'
'app/features/panel/panel_meta'
], ],
function (angular, app, _, $, moment, config, PanelMeta) { function (sdk, angular, _, $, moment, triggerPanelEditor) {
'use strict'; 'use strict';
var module = angular.module('grafana.panels.triggers', []); var defaultSeverity = [
app.useModule(module);
/** @ngInject */
function TriggerPanelCtrl($q, $scope, $element, datasourceSrv, panelSrv, templateSrv, popoverSrv) {
$scope.panelMeta = new PanelMeta({
panelName: 'Zabbix triggers',
editIcon: "fa fa-lightbulb-o",
fullscreen: true,
});
$scope.panelMeta.addEditorTab('Options', 'public/plugins/triggers/editor.html');
$scope.ackFilters = [
'all triggers',
'unacknowledged',
'acknowledged'
];
$scope.sortByFields = [
{ text: 'last change', value: 'lastchange' },
{ text: 'severity', value: 'priority' }
];
$scope.showEventsFields = [
{ text: 'all events', value: [0,1] },
{ text: 'Ok events', value: 0 },
{ text: 'Problem events', value: 1 }
];
$scope.triggerStatusMap = {
'0': 'OK',
'1': 'Problem'
};
var grafanaDefaultSeverity = [
{ priority: 0, severity: 'Not classified', color: '#B7DBAB', show: true }, { priority: 0, severity: 'Not classified', color: '#B7DBAB', show: true },
{ priority: 1, severity: 'Information', color: '#82B5D8', show: true }, { priority: 1, severity: 'Information', color: '#82B5D8', show: true },
{ priority: 2, severity: 'Warning', color: '#E5AC0E', show: true }, { priority: 2, severity: 'Warning', color: '#E5AC0E', show: true },
@@ -86,53 +49,51 @@ function (angular, app, _, $, moment, config, PanelMeta) {
showTriggers: 'all triggers', showTriggers: 'all triggers',
sortTriggersBy: { text: 'last change', value: 'lastchange' }, sortTriggersBy: { text: 'last change', value: 'lastchange' },
showEvents: { text: 'Problem events', value: '1' }, showEvents: { text: 'Problem events', value: '1' },
triggerSeverity: grafanaDefaultSeverity, triggerSeverity: defaultSeverity,
okEventColor: '#890F02', okEventColor: '#890F02',
}; };
_.defaults($scope.panel, panelDefaults); var triggerStatusMap = {
$scope.triggerList = []; '0': 'OK',
'1': 'Problem'
$scope.init = function() {
panelSrv.init($scope);
if ($scope.isNewPanel()) {
$scope.panel.title = "Zabbix Triggers";
}
// Load scope defaults
var scopeDefaults = {
metric: {},
inputStyles: {},
oldTarget: _.cloneDeep($scope.panel.triggers),
defaultTimeFormat: "DD MMM YYYY HH:mm:ss"
};
_.defaults($scope, scopeDefaults);
// Get zabbix data sources
var datasources = _.filter(datasourceSrv.getMetricSources(), function(datasource) {
return datasource.meta.id === 'zabbix';
});
$scope.datasources = _.map(datasources, 'name');
// Set default datasource
if (!$scope.panel.datasource) {
$scope.panel.datasource = $scope.datasources[0];
}
// Load datasource
datasourceSrv.get($scope.panel.datasource).then(function (datasource) {
$scope.datasource = datasource;
$scope.initFilters();
});
}; };
$scope.refreshData = function() { var TriggerPanelCtrl = (function(_super) {
/** @ngInject */
function TriggerPanelCtrl($scope, $injector, $q, $element, datasourceSrv) {
_super.call(this, $scope, $injector);
this.datasourceSrv = datasourceSrv;
this.triggerStatusMap = triggerStatusMap;
// Load panel defaults
_.defaults(this.panel, panelDefaults);
this.triggerList = [];
this.refreshData();
}
TriggerPanelCtrl.templateUrl = 'module.html';
TriggerPanelCtrl.prototype = Object.create(_super.prototype);
TriggerPanelCtrl.prototype.constructor = TriggerPanelCtrl;
// Add panel editor
TriggerPanelCtrl.prototype.initEditMode = function() {
_super.prototype.initEditMode();
this.icon = "fa fa-lightbulb-o";
this.addEditorTab('Options', triggerPanelEditor, 2);
};
TriggerPanelCtrl.prototype.refreshData = function() {
var self = this;
// Load datasource // Load datasource
return datasourceSrv.get($scope.panel.datasource).then(function (datasource) { return this.datasourceSrv.get(this.panel.datasource).then(function (datasource) {
var zabbix = datasource.zabbixAPI; var zabbix = datasource.zabbixAPI;
var queryProcessor = datasource.queryProcessor; var queryProcessor = datasource.queryProcessor;
var triggerFilter = $scope.panel.triggers; var triggerFilter = self.panel.triggers;
var showEvents = $scope.panel.showEvents.value; var showEvents = self.panel.showEvents.value;
var buildQuery = queryProcessor.buildTriggerQuery(triggerFilter.group.filter, var buildQuery = queryProcessor.buildTriggerQuery(triggerFilter.group.filter,
triggerFilter.host.filter, triggerFilter.host.filter,
triggerFilter.application.filter); triggerFilter.application.filter);
@@ -148,22 +109,22 @@ function (angular, app, _, $, moment, config, PanelMeta) {
// Format last change and age // Format last change and age
trigger.lastchangeUnix = Number(trigger.lastchange); trigger.lastchangeUnix = Number(trigger.lastchange);
var timestamp = moment.unix(trigger.lastchangeUnix); var timestamp = moment.unix(trigger.lastchangeUnix);
if ($scope.panel.customLastChangeFormat) { if (self.panel.customLastChangeFormat) {
// User defined format // User defined format
triggerObj.lastchange = timestamp.format($scope.panel.lastChangeFormat); triggerObj.lastchange = timestamp.format(self.panel.lastChangeFormat);
} else { } else {
triggerObj.lastchange = timestamp.format($scope.defaultTimeFormat); triggerObj.lastchange = timestamp.format(self.defaultTimeFormat);
} }
triggerObj.age = timestamp.fromNow(true); triggerObj.age = timestamp.fromNow(true);
// Set color // Set color
if (trigger.value === '1') { if (trigger.value === '1') {
triggerObj.color = $scope.panel.triggerSeverity[trigger.priority].color; triggerObj.color = self.panel.triggerSeverity[trigger.priority].color;
} else { } else {
triggerObj.color = $scope.panel.okEventColor; triggerObj.color = self.panel.okEventColor;
} }
triggerObj.severity = $scope.panel.triggerSeverity[trigger.priority].severity; triggerObj.severity = self.panel.triggerSeverity[trigger.priority].severity;
return triggerObj; return triggerObj;
}); });
}) })
@@ -173,6 +134,7 @@ function (angular, app, _, $, moment, config, PanelMeta) {
var eventids = _.map(triggerList, function(trigger) { var eventids = _.map(triggerList, function(trigger) {
return trigger.lastEvent.eventid; return trigger.lastEvent.eventid;
}); });
return zabbix.getAcknowledges(eventids) return zabbix.getAcknowledges(eventids)
.then(function (events) { .then(function (events) {
@@ -193,17 +155,17 @@ function (angular, app, _, $, moment, config, PanelMeta) {
}); });
// Filter triggers by description // Filter triggers by description
var triggerFilter = $scope.panel.triggers.trigger.filter; var triggerFilter = self.panel.triggers.trigger.filter;
if (triggerFilter) { if (triggerFilter) {
triggerList = filterTriggers(triggerList, triggerFilter); triggerList = filterTriggers(triggerList, triggerFilter);
} }
// Filter acknowledged triggers // Filter acknowledged triggers
if ($scope.panel.showTriggers === 'unacknowledged') { if (self.panel.showTriggers === 'unacknowledged') {
triggerList = _.filter(triggerList, function (trigger) { triggerList = _.filter(triggerList, function (trigger) {
return !trigger.acknowledges; return !trigger.acknowledges;
}); });
} else if ($scope.panel.showTriggers === 'acknowledged') { } else if (self.panel.showTriggers === 'acknowledged') {
triggerList = _.filter(triggerList, 'acknowledges'); triggerList = _.filter(triggerList, 'acknowledges');
} else { } else {
triggerList = triggerList; triggerList = triggerList;
@@ -211,65 +173,26 @@ function (angular, app, _, $, moment, config, PanelMeta) {
// Filter triggers by severity // Filter triggers by severity
triggerList = _.filter(triggerList, function (trigger) { triggerList = _.filter(triggerList, function (trigger) {
return $scope.panel.triggerSeverity[trigger.priority].show; return self.panel.triggerSeverity[trigger.priority].show;
}); });
// Sort triggers // Sort triggers
if ($scope.panel.sortTriggersBy.value === 'priority') { if (self.panel.sortTriggersBy.value === 'priority') {
triggerList = _.sortBy(triggerList, 'priority').reverse(); triggerList = _.sortBy(triggerList, 'priority').reverse();
} else { } else {
triggerList = _.sortBy(triggerList, 'lastchangeUnix').reverse(); triggerList = _.sortBy(triggerList, 'lastchangeUnix').reverse();
} }
// Limit triggers number // Limit triggers number
$scope.triggerList = _.first(triggerList, $scope.panel.limit); self.triggerList = _.first(triggerList, self.panel.limit);
$scope.panelRenderingComplete(); self.renderingCompleted();
}); });
}); });
}); });
}); });
}; };
$scope.initFilters = function () {
$scope.filterGroups();
$scope.filterHosts();
$scope.filterApplications();
};
// Get list of metric names for bs-typeahead directive
function getMetricNames(scope, metricList) {
return _.uniq(_.map(scope.metric[metricList], 'name'));
}
// Map functions for bs-typeahead
$scope.getGroupNames = _.partial(getMetricNames, $scope, 'groupList');
$scope.getHostNames = _.partial(getMetricNames, $scope, 'filteredHosts');
$scope.getApplicationNames = _.partial(getMetricNames, $scope, 'filteredApplications');
$scope.getItemNames = _.partial(getMetricNames, $scope, 'filteredItems');
$scope.filterGroups = function() {
$scope.datasource.queryProcessor.filterGroups().then(function(groups) {
$scope.metric.groupList = groups;
});
};
$scope.filterHosts = function() {
var groupFilter = templateSrv.replace($scope.panel.triggers.group.filter);
$scope.datasource.queryProcessor.filterHosts(groupFilter).then(function(hosts) {
$scope.metric.filteredHosts = hosts;
});
};
$scope.filterApplications = function() {
var groupFilter = templateSrv.replace($scope.panel.triggers.group.filter);
var hostFilter = templateSrv.replace($scope.panel.triggers.host.filter);
$scope.datasource.queryProcessor.filterApplications(groupFilter, hostFilter)
.then(function(apps) {
$scope.metric.filteredApplications = apps;
});
};
function filterTriggers(triggers, triggerFilter) { function filterTriggers(triggers, triggerFilter) {
if (isRegex(triggerFilter)) { if (isRegex(triggerFilter)) {
return _.filter(triggers, function(trigger) { return _.filter(triggers, function(trigger) {
@@ -282,12 +205,6 @@ function (angular, app, _, $, moment, config, PanelMeta) {
} }
} }
$scope.onTargetPartChange = function(targetPart) {
var regexStyle = {'color': '#CCA300'};
targetPart.isRegex = isRegex(targetPart.filter);
targetPart.style = targetPart.isRegex ? regexStyle : {};
};
function isRegex(str) { function isRegex(str) {
// Pattern for testing regex // Pattern for testing regex
var regexPattern = /^\/(.*)\/([gmi]*)$/m; var regexPattern = /^\/(.*)\/([gmi]*)$/m;
@@ -302,106 +219,12 @@ function (angular, app, _, $, moment, config, PanelMeta) {
return new RegExp(pattern, flags); return new RegExp(pattern, flags);
} }
$scope.parseTarget = function() { return TriggerPanelCtrl;
$scope.initFilters();
var newTarget = _.cloneDeep($scope.panel.triggers);
if (!_.isEqual($scope.oldTarget, $scope.panel.triggers)) {
$scope.oldTarget = newTarget;
$scope.get_data();
}
};
$scope.refreshTriggerSeverity = function() { })(sdk.PanelCtrl);
_.each($scope.triggerList, function(trigger) {
trigger.color = $scope.panel.triggerSeverity[trigger.priority].color;
trigger.severity = $scope.panel.triggerSeverity[trigger.priority].severity;
});
};
$scope.datasourceChanged = function() {
$scope.refreshData();
};
$scope.changeTriggerSeverityColor = function(trigger, color) {
$scope.panel.triggerSeverity[trigger.priority].color = color;
$scope.refreshTriggerSeverity();
};
function getTriggerIndexForElement(el) {
return el.parents('[data-trigger-index]').data('trigger-index');
}
$scope.openTriggerColorSelector = function(event) {
var el = $(event.currentTarget);
var index = getTriggerIndexForElement(el);
var popoverScope = $scope.$new();
popoverScope.trigger = $scope.panel.triggerSeverity[index];
popoverScope.changeTriggerSeverityColor = $scope.changeTriggerSeverityColor;
popoverSrv.show({
element: el,
placement: 'top',
templateUrl: 'public/plugins/triggers/trigger.colorpicker.html',
scope: popoverScope
});
};
$scope.openOkEventColorSelector = function(event) {
var el = $(event.currentTarget);
var popoverScope = $scope.$new();
popoverScope.trigger = {color: $scope.panel.okEventColor};
popoverScope.changeTriggerSeverityColor = function(trigger, color) {
$scope.panel.okEventColor = color;
$scope.refreshTriggerSeverity();
};
popoverSrv.show({
element: el,
placement: 'top',
templateUrl: 'public/plugins/triggers/trigger.colorpicker.html',
scope: popoverScope
});
};
/**
* Convert event age from Unix format (milliseconds sins 1970)
* to Zabbix format (like at Last 20 issues panel).
* @param {Date} AgeUnix time in Unix format
* @return {string} Formatted time
*/
function toZabbixAgeFormat(ageUnix) {
var age = new Date(+ageUnix);
var ageZabbix = age.getSeconds() + 's';
if (age.getMinutes()) {
ageZabbix = age.getMinutes() + 'm ' + ageZabbix;
}
if (age.getHours()) {
ageZabbix = age.getHours() + 'h ' + ageZabbix;
}
if (age.getDate() - 1) {
ageZabbix = age.getDate() - 1 + 'd ' + ageZabbix;
}
if (age.getMonth()) {
ageZabbix = age.getMonth() + 'M ' + ageZabbix;
}
if (age.getYear() - 70) {
ageZabbix = age.getYear() -70 + 'y ' + ageZabbix;
}
return ageZabbix;
}
$scope.init();
}
function triggerPanelDirective() {
return {
controller: TriggerPanelCtrl,
templateUrl: 'public/plugins/triggers/module.html',
};
}
return { return {
panel: triggerPanelDirective PanelCtrl: TriggerPanelCtrl
}; };
}); });