Triggers query mode, allow to get active triggers count, #141

This commit is contained in:
Alexander Zobnin
2017-10-22 14:30:54 +03:00
parent dacc3f3576
commit 6c64f21b1a
26 changed files with 458 additions and 88 deletions

View File

@@ -3,6 +3,7 @@ export const MODE_METRICS = 0;
export const MODE_ITSERVICE = 1;
export const MODE_TEXT = 2;
export const MODE_ITEMID = 3;
export const MODE_TRIGGERS = 4;
// Triggers severity
export const SEV_NOT_CLASSIFIED = 0;

View File

@@ -136,6 +136,10 @@ class ZabbixAPIDatasource {
} else if (target.mode === c.MODE_ITSERVICE) {
// IT services mode
return this.queryITServiceData(target, timeRange, options);
} else if (target.mode === c.MODE_TRIGGERS) {
return this.queryTriggersData(target, timeRange);
} else {
return [];
}
});
@@ -350,6 +354,24 @@ class ZabbixAPIDatasource {
});
}
queryTriggersData(target, timeRange) {
let [timeFrom, timeTo] = timeRange;
return this.zabbix.getHostsFromTarget(target)
.then((results) => {
let [hosts, apps] = results;
if (hosts.length) {
let hostids = _.map(hosts, 'hostid');
let appids = _.map(apps, 'applicationid');
return this.zabbix.getHostAlerts(hostids, appids, target.minSeverity, target.options.countTriggers, timeFrom, timeTo)
.then((triggers) => {
return responseHandler.handleTriggersResponse(triggers, timeRange);
});
} else {
return Promise.resolve([]);
}
});
}
/**
* Test connection to Zabbix API
* @return {object} Connection status and Zabbix API version

View File

@@ -48,7 +48,7 @@
</div>
</div>
<div class="gf-form-inline" ng-show="ctrl.target.mode == editorMode.METRICS || ctrl.target.mode == editorMode.TEXT">
<div class="gf-form-inline" ng-show="ctrl.target.mode == editorMode.METRICS || ctrl.target.mode == editorMode.TEXT || ctrl.target.mode == editorMode.TRIGGERS">
<!-- Select Group -->
<div class="gf-form max-width-20">
<label class="gf-form-label query-keyword width-7">Group</label>
@@ -66,7 +66,7 @@
</div>
<!-- Select Host -->
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">Host</label>
<label class="gf-form-label query-keyword width-8">Host</label>
<input type="text"
ng-model="ctrl.target.host.filter"
bs-typeahead="ctrl.getHostNames"
@@ -85,7 +85,7 @@
</div>
</div>
<div class="gf-form-inline" ng-show="ctrl.target.mode == editorMode.METRICS || ctrl.target.mode == editorMode.TEXT">
<div class="gf-form-inline" ng-show="ctrl.target.mode == editorMode.METRICS || ctrl.target.mode == editorMode.TEXT || ctrl.target.mode == editorMode.TRIGGERS">
<!-- Select Application -->
<div class="gf-form max-width-20">
<label class="gf-form-label query-keyword width-7">Application</label>
@@ -103,8 +103,8 @@
</div>
<!-- Select Item -->
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">Item</label>
<div class="gf-form" ng-show="ctrl.target.mode == editorMode.METRICS || ctrl.target.mode == editorMode.TEXT">
<label class="gf-form-label query-keyword width-8">Item</label>
<input type="text"
ng-model="ctrl.target.item.filter"
bs-typeahead="ctrl.getItemNames"
@@ -117,6 +117,18 @@
'zbx-regex': ctrl.isRegex(ctrl.target.item.filter)
}">
</div>
<div class="gf-form max-width-20" ng-show="ctrl.target.mode == editorMode.TRIGGERS">
<label class="gf-form-label query-keyword width-8">Min Severity</label>
<div class="gf-form-select-wrapper width-20">
<select class="gf-form-input"
ng-change="ctrl.onTargetBlur()"
ng-model="ctrl.target.minSeverity"
ng-options="s.val as s.text for s in ctrl.triggerSeverity">
</select>
</div>
</div>
<div class="gf-form gf-form--grow">
<label class="gf-form-label gf-form-label--grow">
<a ng-click="ctrl.toggleQueryOptions()">
@@ -130,13 +142,20 @@
<!-- Query options -->
<div class="gf-form-group" ng-if="ctrl.showQueryOptions">
<div class="gf-form offset-width-7">
<div class="gf-form offset-width-7" ng-hide="ctrl.target.mode == editorMode.TRIGGERS">
<gf-form-switch class="gf-form"
label="Show disabled items"
checked="ctrl.target.options.showDisabledItems"
on-change="ctrl.onQueryOptionChange()">
</gf-form-switch>
</div>
<div class="gf-form offset-width-7" ng-show="ctrl.target.mode == editorMode.TRIGGERS">
<gf-form-switch class="gf-form"
label="Count triggers"
checked="ctrl.target.options.countTriggers"
on-change="ctrl.onQueryOptionChange()">
</gf-form-switch>
</div>
</div>
<!-- Item IDs editor mode -->

View File

@@ -25,14 +25,16 @@ export class ZabbixQueryController extends QueryCtrl {
{value: 'num', text: 'Metrics', mode: c.MODE_METRICS},
{value: 'text', text: 'Text', mode: c.MODE_TEXT},
{value: 'itservice', text: 'IT Services', mode: c.MODE_ITSERVICE},
{value: 'itemid', text: 'Item ID', mode: c.MODE_ITEMID}
{value: 'itemid', text: 'Item ID', mode: c.MODE_ITEMID},
{value: 'triggers', text: 'Triggers', mode: c.MODE_TRIGGERS}
];
this.$scope.editorMode = {
METRICS: c.MODE_METRICS,
TEXT: c.MODE_TEXT,
ITSERVICE: c.MODE_ITSERVICE,
ITEMID: c.MODE_ITEMID
ITEMID: c.MODE_ITEMID,
TRIGGERS: c.MODE_TRIGGERS
};
this.slaPropertyList = [
@@ -43,6 +45,12 @@ export class ZabbixQueryController extends QueryCtrl {
{name: "Down time", property: "downtimeTime"}
];
this.triggerSeverity = [
{val: 0, text: 'Not classified'}, {val: 1, text:'Information'},
{val: 2, text: 'Warning'}, {val: 3, text: 'Average'},
{val: 4, text: 'High'}, {val: 5, text: 'Disaster'}
];
// Map functions for bs-typeahead
this.getGroupNames = _.bind(this.getMetricNames, this, 'groupList');
this.getHostNames = _.bind(this.getMetricNames, this, 'hostList', true);
@@ -80,8 +88,10 @@ export class ZabbixQueryController extends QueryCtrl {
'application': { 'filter': "" },
'item': { 'filter': "" },
'functions': [],
'minSeverity': 3,
'options': {
'showDisabledItems': false
'showDisabledItems': false,
'countTriggers': true
}
};
_.defaults(target, targetDefaults);
@@ -92,8 +102,8 @@ export class ZabbixQueryController extends QueryCtrl {
});
if (target.mode === c.MODE_METRICS ||
target.mode === c.MODE_TEXT) {
target.mode === c.MODE_TEXT ||
target.mode === c.MODE_TRIGGERS) {
this.initFilters();
}
else if (target.mode === c.MODE_ITSERVICE) {
@@ -103,6 +113,7 @@ export class ZabbixQueryController extends QueryCtrl {
};
this.init();
this.queryOptionsText = this.renderQueryOptionsText();
}
initFilters() {
@@ -282,7 +293,8 @@ export class ZabbixQueryController extends QueryCtrl {
renderQueryOptionsText() {
var optionsMap = {
showDisabledItems: "Show disabled items"
showDisabledItems: "Show disabled items",
countTriggers: "Count Triggers"
};
var options = [];
_.forOwn(this.target.options, (value, key) => {

View File

@@ -100,6 +100,19 @@ function handleSLAResponse(itservice, slaProperty, slaObject) {
}
}
function handleTriggersResponse(triggers, timeRange) {
if (_.isNumber(triggers)) {
return {
target: "triggers count",
datapoints: [
[triggers, timeRange[1]]
]
};
} else {
return triggers;
}
}
function convertHistoryPoint(point) {
// Value must be a number for properly work
return [
@@ -141,7 +154,8 @@ export default {
convertHistory: convertHistory,
handleTrends: handleTrends,
handleText: handleText,
handleSLAResponse: handleSLAResponse
handleSLAResponse: handleSLAResponse,
handleTriggersResponse: handleTriggersResponse
};
// Fix for backward compatibility with lodash 2.4

View File

@@ -46,6 +46,7 @@ function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy, ZabbixDBConnector)
this.getTrend = this.zabbixAPI.getTrend.bind(this.zabbixAPI);
this.getEvents = this.zabbixAPI.getEvents.bind(this.zabbixAPI);
this.getAlerts = this.zabbixAPI.getAlerts.bind(this.zabbixAPI);
this.getHostAlerts = this.zabbixAPI.getHostAlerts.bind(this.zabbixAPI);
this.getAcknowledges = this.zabbixAPI.getAcknowledges.bind(this.zabbixAPI);
this.getITService = this.zabbixAPI.getITService.bind(this.zabbixAPI);
this.getSLA = this.zabbixAPI.getSLA.bind(this.zabbixAPI);
@@ -59,6 +60,21 @@ function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy, ZabbixDBConnector)
return this.getItems(...filters, options);
}
getHostsFromTarget(target) {
let parts = ['group', 'host', 'application'];
let filters = _.map(parts, p => target[p].filter);
return Promise.all([
this.getHosts(...filters),
this.getApps(...filters),
]).then((results) => {
let [hosts, apps] = results;
if (apps.appFilterEmpty) {
apps = [];
}
return [hosts, apps];
});
}
getAllGroups() {
return this.cachingProxy.getGroups();
}

View File

@@ -433,6 +433,36 @@ function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) {
return this.request('trigger.get', params);
}
getHostAlerts(hostids, applicationids, minSeverity, count, timeFrom, timeTo) {
var params = {
output: 'extend',
hostids: hostids,
min_severity: minSeverity,
filter: { value: 1 },
expandDescription: true,
expandData: true,
expandComment: true,
monitored: true,
skipDependent: true,
selectLastEvent: 'extend'
};
if (count) {
params.countOutput = true;
}
if (applicationids && applicationids.length) {
params.applicationids = applicationids;
}
if (timeFrom || timeTo) {
params.lastChangeSince = timeFrom;
params.lastChangeTill = timeTo;
}
return this.request('trigger.get', params);
}
}
return ZabbixAPI;