Merge branch 'develop'

This commit is contained in:
Alexander Zobnin
2015-09-09 14:29:19 +03:00
7 changed files with 699 additions and 384 deletions

View File

@@ -72,6 +72,12 @@ function (angular, _, kbn) {
};
}
});
}, function(error) {
return {
status: "error",
title: "Connection failed",
message: "Could not connect to " + error.config.url
};
});
};
@@ -94,6 +100,7 @@ function (angular, _, kbn) {
// Create request for each target
var promises = _.map(options.targets, function(target) {
if (target.mode !== 1) {
// Don't show undefined and hidden targets
if (target.hide || !target.group || !target.host
|| !target.application || !target.item) {
@@ -101,10 +108,10 @@ function (angular, _, kbn) {
}
// Replace templated variables
var groupname = templateSrv.replace(target.group.name);
var hostname = templateSrv.replace(target.host.name);
var appname = templateSrv.replace(target.application.name);
var itemname = templateSrv.replace(target.item.name);
var groupname = templateSrv.replace(target.group.name, options.scopedVars);
var hostname = templateSrv.replace(target.host.name, options.scopedVars);
var appname = templateSrv.replace(target.application.name, options.scopedVars);
var itemname = templateSrv.replace(target.item.name, options.scopedVars);
// Extract zabbix groups, hosts and apps from string:
// "{host1,host2,...,hostN}" --> [host1, host2, ..., hostN]
@@ -115,11 +122,15 @@ function (angular, _, kbn) {
// Remove hostnames from item names and then
// extract item names
// "hostname: itemname" --> "itemname"
var delete_hostname_pattern = /(?:\[[\w\.]+\]\:\s)/g;
var delete_hostname_pattern = /(?:\[[\w\.]+]:\s)/g;
var itemnames = zabbixHelperSrv.splitMetrics(itemname.replace(delete_hostname_pattern, ''));
// Find items by item names and perform queries
var self = this;
// Query numeric data
if (!target.mode) {
// Find items by item names and perform queries
return this.zabbixAPI.itemFindQuery(groups, hosts, apps)
.then(function (items) {
@@ -128,7 +139,7 @@ function (angular, _, kbn) {
if (target.hostFilter && _.every(items, _.identity.hosts)) {
// Use templated variables in filter
var host_pattern = new RegExp(templateSrv.replace(target.hostFilter));
var host_pattern = new RegExp(templateSrv.replace(target.hostFilter, options.scopedVars));
items = _.filter(items, function (item) {
return _.some(item.hosts, function (host) {
return host_pattern.test(host.name);
@@ -143,7 +154,7 @@ function (angular, _, kbn) {
if (target.itemFilter) {
// Use templated variables in filter
var item_pattern = new RegExp(templateSrv.replace(target.itemFilter));
var item_pattern = new RegExp(templateSrv.replace(target.itemFilter, options.scopedVars));
return _.filter(items, function (item) {
return item_pattern.test(zabbixHelperSrv.expandItemName(item));
});
@@ -170,31 +181,72 @@ function (angular, _, kbn) {
items = _.flatten(items);
// Use alias only for single metric, otherwise use item names
var alias = target.item.name === 'All' || itemnames.length > 1 ? undefined : templateSrv.replace(target.alias);
var alias = target.item.name === 'All' || itemnames.length > 1 ?
undefined : templateSrv.replace(target.alias, options.scopedVars);
var history;
if ((from < useTrendsFrom) && self.trends) {
return self.zabbixAPI.getTrends(items, from, to)
.then(_.bind(zabbixHelperSrv.handleTrendResponse, zabbixHelperSrv, items, alias, target.scale));
var points = target.downsampleFunction ? target.downsampleFunction.value : "avg";
history = self.zabbixAPI.getTrends(items, from, to)
.then(_.bind(zabbixHelperSrv.handleTrendResponse, zabbixHelperSrv, items, alias, target.scale, points));
} else {
return self.zabbixAPI.getHistory(items, from, to)
history = self.zabbixAPI.getHistory(items, from, to)
.then(_.bind(zabbixHelperSrv.handleHistoryResponse, zabbixHelperSrv, items, alias, target.scale));
}
}
});
}, this);
return $q.all(_.flatten(promises)).then(function (results) {
var timeseries_data = _.flatten(results);
var data = _.map(timeseries_data, function (timeseries) {
return history.then(function (timeseries) {
var timeseries_data = _.flatten(timeseries);
return _.map(timeseries_data, function (timeseries) {
// Series downsampling
if (timeseries.datapoints.length > options.maxDataPoints) {
var ms_interval = Math.floor((to - from) / options.maxDataPoints) * 1000;
timeseries.datapoints = zabbixHelperSrv.downsampleSeries(timeseries.datapoints, to, ms_interval);
var downsampleFunc = target.downsampleFunction ? target.downsampleFunction.value : "avg";
timeseries.datapoints = zabbixHelperSrv.downsampleSeries(timeseries.datapoints, to, ms_interval, downsampleFunc);
}
return timeseries;
});
return { data: data };
});
}
});
}
// Query text data
else if (target.mode === 2) {
// Find items by item names and perform queries
return this.zabbixAPI.itemFindQuery(groups, hosts, apps, "text")
.then(function (items) {
items = _.filter(items, function (item) {
return _.contains(itemnames, zabbixHelperSrv.expandItemName(item));
});
return self.zabbixAPI.getHistory(items, from, to).then(function(history) {
return {
target: target.item.name,
datapoints: _.map(history, function (p) {
return [p.value, p.clock * 1000];
})
};
});
});
}
}
// IT services mode
else if (target.mode === 1) {
// Don't show undefined and hidden targets
if (target.hide || !target.itservice || !target.slaProperty) {
return [];
} else {
return this.zabbixAPI.getSLA(target.itservice.serviceid, from, to)
.then(_.bind(zabbixHelperSrv.handleSLAResponse, zabbixHelperSrv, target.itservice, target.slaProperty));
}
}
}, this);
return $q.all(_.flatten(promises)).then(function (results) {
var timeseries_data = _.flatten(results);
return { data: timeseries_data };
});
};
@@ -291,11 +343,17 @@ function (angular, _, kbn) {
var params = {
output: ['triggerid', 'description'],
search: {
'description': annotation.query
'description': annotation.trigger
},
searchWildcardsEnabled: true,
expandDescription: true
};
if (annotation.host) {
params.host = templateSrv.replace(annotation.host);
}
else if (annotation.group) {
params.group = templateSrv.replace(annotation.group);
}
return this.zabbixAPI.performZabbixAPIRequest('trigger.get', params)
.then(function (result) {
@@ -323,7 +381,7 @@ function (angular, _, kbn) {
annotation: annotation,
time: e.clock * 1000,
title: Number(e.value) ? 'Problem' : 'OK',
text: objects[e.objectid].description + formatted_acknowledges,
text: objects[e.objectid].description + formatted_acknowledges
});
});
return events;

View File

@@ -14,6 +14,8 @@ function (angular, _) {
* Convert Zabbix API history.get response to Grafana format
*
* @param {Array} items Array of Zabbix Items
* @param alias
* @param scale
* @param {Array} history Array of Zabbix History
*
* @return {Array} Array of timeseries in Grafana format
@@ -44,7 +46,7 @@ function (angular, _) {
var self = this;
return $q.when(_.map(grouped_history, function (history, itemid) {
var item = indexed_items[itemid];
var series = {
return {
target: (item.hosts ? item.hosts[0].name+': ' : '')
+ (alias ? alias : self.expandItemName(item)),
datapoints: _.map(history, function (p) {
@@ -59,7 +61,6 @@ function (angular, _) {
return [value, p.clock * 1000];
})
};
return series;
})).then(function (result) {
return _.sortBy(result, 'target');
});
@@ -69,6 +70,9 @@ function (angular, _) {
* Convert Zabbix API trends.get response to Grafana format
*
* @param {Array} items Array of Zabbix Items
* @param alias
* @param scale
* @param {string} points Point value to return: min, max or avg
* @param {Array} trends Array of Zabbix Trends
*
* @return {Array} Array of timeseries in Grafana format
@@ -77,7 +81,7 @@ function (angular, _) {
* datapoints: [[<value>, <unixtime>], ...]
* }
*/
this.handleTrendResponse = function (items, alias, scale, trends) {
this.handleTrendResponse = function (items, alias, scale, points, trends) {
// Group items and trends by itemid
var indexed_items = _.indexBy(items, 'itemid');
@@ -86,13 +90,22 @@ function (angular, _) {
var self = this;
return $q.when(_.map(grouped_trends, function (trends, itemid) {
var item = indexed_items[itemid];
var series = {
return {
target: (item.hosts ? item.hosts[0].name+': ' : '')
+ (alias ? alias : self.expandItemName(item)),
datapoints: _.map(trends, function (p) {
// Value must be a number for properly work
var value = Number(p.value_avg);
var value;
if (points === "min") {
value = Number(p.value_min);
}
else if (points === "max") {
value = Number(p.value_max);
}
else {
value = Number(p.value_avg);
}
// Apply scale
if (scale) {
@@ -101,18 +114,46 @@ function (angular, _) {
return [value, p.clock * 1000];
})
};
return series;
})).then(function (result) {
return _.sortBy(result, 'target');
});
};
/**
* Convert Zabbix API service.getsla response to Grafana format
*
* @param itservice
* @param slaProperty
* @param slaObject
* @returns {{target: *, datapoints: *[]}}
*/
this.handleSLAResponse = function (itservice, slaProperty, slaObject) {
var targetSLA = slaObject[itservice.serviceid].sla[0];
if (slaProperty.property === 'status') {
var targetStatus = slaObject[itservice.serviceid].status;
return {
target: itservice.name + ' ' + slaProperty.name,
datapoints: [
[targetStatus, targetSLA.to * 1000]
]
};
} else {
return {
target: itservice.name + ' ' + slaProperty.name,
datapoints: [
[targetSLA[slaProperty.property], targetSLA.from * 1000],
[targetSLA[slaProperty.property], targetSLA.to * 1000]
]
};
}
};
/**
* Expand item parameters, for example:
* CPU $2 time ($3) --> CPU system time (avg1)
*
* @param item: zabbix api item object
* @return: expanded item name (string)
* @return {string} expanded item name (string)
*/
this.expandItemName = function(item) {
var name = item.name;
@@ -185,12 +226,13 @@ function (angular, _) {
/**
* Downsample datapoints series
*
* @param {array} datapoints [[<value>, <unixtime>], ...]
* @param {Object[]} datapoints [[<value>, <unixtime>], ...]
* @param {integer} time_to Panel time to
* @param {integer} ms_interval Interval in milliseconds for grouping datapoints
* @return {array} [[<value>, <unixtime>], ...]
* @param {string} func Value to return: min, max or avg
* @return {Object[]} [[<value>, <unixtime>], ...]
*/
this.downsampleSeries = function(datapoints, time_to, ms_interval) {
this.downsampleSeries = function(datapoints, time_to, ms_interval, func) {
var downsampledSeries = [];
var timeWindow = {
from: time_to * 1000 - ms_interval,
@@ -200,14 +242,28 @@ function (angular, _) {
var points_sum = 0;
var points_num = 0;
var value_avg = 0;
var frame = [];
for (var i = datapoints.length - 1; i >= 0; i -= 1) {
if (timeWindow.from < datapoints[i][1] && datapoints[i][1] <= timeWindow.to) {
points_sum += datapoints[i][0];
points_num++;
frame.push(datapoints[i][0]);
}
else {
value_avg = points_num ? points_sum / points_num : 0;
if (func === "max") {
downsampledSeries.push([_.max(frame), timeWindow.to]);
}
else if (func === "min") {
downsampledSeries.push([_.min(frame), timeWindow.to]);
}
// avg by default
else {
downsampledSeries.push([value_avg, timeWindow.to]);
}
// Shift time window
timeWindow.to = timeWindow.from;
@@ -215,6 +271,7 @@ function (angular, _) {
points_sum = 0;
points_num = 0;
frame = [];
// Process point again
i++;

View File

@@ -1,16 +1,36 @@
<div class="editor-row">
<div class="section">
<h5>Zabbix trigger <tip>Example: Lack of free swap space</tip></h5>
<div class="editor-option">
<input type="text" class="span10" ng-model="currentAnnotation.query" placeholder="Lack of free swap space"></input>
<h5>Zabbix trigger
</h5>
</div>
</div>
<div class="editor-row">
<div class="editor-option">
<label class="small">Group</label>
<input type="text" class="input-medium" ng-model='currentAnnotation.group'></input>
</div>
<div class="editor-option">
<label class="small">Host</label>
<input type="text" class="input-medium" ng-model='currentAnnotation.host'></input>
</div>
<div class="editor-option">
<label class="small">Trigger
<tip>Trigger name for search. Wildcards are supports. Examples: Lack of free swap space, Lack of*.
</tip>
</label>
<input type="text" style="width: 25em" ng-model='currentAnnotation.trigger' placeholder="Trigger name"></input>
</div>
</div>
<div class="editor-row">
<div class="section">
<h5>Options</h5>
<input type="checkbox" class="cr1" id="currentAnnotation.showOkEvents" ng-model="currentAnnotation.showOkEvents" ng-checked="currentAnnotation.showOkEvents">
<label for="currentAnnotation.showOkEvents" class="cr1">Show OK events <tip>Show events, generated when trigger release to OK state</tip></label>
<input type="checkbox" class="cr1" id="currentAnnotation.showOkEvents"
ng-model="currentAnnotation.showOkEvents"
ng-checked="currentAnnotation.showOkEvents">
<label for="currentAnnotation.showOkEvents" class="cr1">Show OK events
<tip>Show events, generated when trigger release to OK state</tip>
</label>
</div>
</div>

View File

@@ -10,13 +10,17 @@
User
</li>
<li>
<input type="text" class="tight-form-input input-large" ng-model='current.jsonData.username' placeholder=""></input>
<input type="text" class="tight-form-input input-large"
ng-model='current.jsonData.username'
placeholder="">
</li>
<li class="tight-form-item">
Password
</li>
<li>
<input type="password" class="tight-form-input input-large" ng-model='current.jsonData.password' placeholder=""></input>
<input type="password" class="tight-form-input input-large"
ng-model='current.jsonData.password'
placeholder="">
</li>
</ul>
<div class="clearfix"></div>
@@ -28,14 +32,18 @@
</li>
<li class="tight-form-item">
Enable&nbsp;
<input class="cr1" id="current.jsonData.trends" type="checkbox" ng-model="current.jsonData.trends" ng-checked="current.jsonData.trends">
<input class="cr1" id="current.jsonData.trends" type="checkbox"
ng-model="current.jsonData.trends"
ng-checked="current.jsonData.trends">
<label for="current.jsonData.trends" class="cr1"></label>
</li>
<li class="tight-form-item" ng-if="current.jsonData.trends">
Use trends from
</li>
<li ng-if="current.jsonData.trends">
<input type="text" class="tight-form-input input-small" ng-model='current.basicAuthUser' placeholder="7d"></input>
<input type="text" class="tight-form-input input-small"
ng-model='current.jsonData.trendsFrom'
placeholder="7d">
</li>
</ul>
<div class="clearfix"></div>
@@ -46,7 +54,9 @@
Metrics limit
</li>
<li>
<input type="text" class="tight-form-input input-small" ng-model='current.jsonData.limitMetrics' placeholder="100"></input>
<input type="text" class="tight-form-input input-small"
ng-model='current.jsonData.limitMetrics'
placeholder="100">
</li>
</ul>
<div class="clearfix"></div>

View File

@@ -16,6 +16,20 @@
<i class="fa fa-bars"></i>
</a>
<ul class="dropdown-menu pull-right" role="menu">
<!-- Switch editor mode -->
<li role="menuitem" ng-show="target.mode">
<a class="pointer" tabindex="1"
ng-click="switchEditorMode(0)">Numeric metrics</a>
</li>
<li role="menuitem" ng-show="target.mode != 1">
<a class="pointer" tabindex="1"
ng-click="switchEditorMode(1)">IT services</a>
</li>
<li role="menuitem" ng-show="target.mode != 2">
<a class="pointer" tabindex="1"
ng-click="switchEditorMode(2)">Text metrics</a>
</li>
<li class="divider" role="menuitem"></li>
<li role="menuitem"><a tabindex="1" ng-click="duplicate()">Duplicate</a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveMetricQuery($index, $index-1)">Move up</a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveMetricQuery($index, $index+1)">Move down</a></li>
@@ -42,7 +56,30 @@
</li>
</ul>
<ul class="tight-form-list" role="menu">
<!-- IT Service editor -->
<ul class="tight-form-list" role="menu" ng-show="target.mode == 1">
<li class="tight-form-item input-small">IT Service</li>
<li>
<select class="tight-form-input input-large"
ng-change="selectITService()"
ng-model="target.itservice"
bs-tooltip="target.itservice.name.length > 25 ? target.itservice.name : ''"
ng-options="itservice.name for itservice in itserviceList track by itservice.name">
<option value="">-- Select IT service --</option>
</select>
</li>
<li class="tight-form-item input-medium">IT service property</li>
<li>
<select class="tight-form-input input-medium"
ng-change="selectITService()"
ng-model="target.slaProperty"
ng-options="slaProperty.name for slaProperty in slaPropertyList track by slaProperty.name">
<option value="">-- Property --</option>
</select>
</li>
</ul>
<ul class="tight-form-list" role="menu" ng-hide="target.mode == 1">
<!-- Alias -->
<li>
<input type="text"
@@ -59,7 +96,7 @@
ng-change="selectHostGroup()"
ng-model="target.group"
bs-tooltip="target.group.name.length > 25 ? target.group.name : ''"
ng-options="group.visible_name ? group.visible_name : group.name for group in metric.groupList track by group.name" >
ng-options="group.visible_name ? group.visible_name : group.name for group in metric.groupList track by group.name">
<option value="">-- Select host group --</option>
</select>
<a bs-tooltip="target.errors.metric"
@@ -75,7 +112,7 @@
ng-change="selectHost()"
ng-model="target.host"
bs-tooltip="target.host.name.length > 25 ? target.host.name : ''"
ng-options="host.visible_name ? host.visible_name : host.name for host in metric.hostList track by host.name" >
ng-options="host.visible_name ? host.visible_name : host.name for host in metric.hostList track by host.name">
<option value="">-- Select host --</option>
</select>
<a bs-tooltip="target.errors.metric"
@@ -85,11 +122,12 @@
</a>
</li>
<!-- Host filter -->
<li class="tight-form-item">
<li class="tight-form-item" ng-hide="target.mode == 2">
Filter
<i class="fa fa-question-circle" bs-tooltip="'Filtering hosts by regex. Select All in items and specify regex for host names.'"></i>
<i class="fa fa-question-circle"
bs-tooltip="'Filtering hosts by regex. Select All in items and specify regex for host names.'"></i>
</li>
<li>
<li ng-hide="target.mode == 2">
<input type="text"
class="tight-form-input input-large"
ng-model="target.hostFilter"
@@ -97,12 +135,29 @@
placeholder="Host filter (regex)"
ng-blur="targetBlur()">
</li>
<!-- Downsampling function -->
<li class="tight-form-item input-medium" ng-hide="target.mode == 2">
Downsampling
</li>
<li ng-hide="target.mode == 2">
<select class="tight-form-input input-small"
ng-change="targetBlur()"
ng-model="target.downsampleFunction"
bs-tooltip="'Downsampling function'"
ng-options="func.name for func in downsampleFunctionList track by func.name">
</select>
<a bs-tooltip="target.errors.metric"
style="color: rgb(229, 189, 28)"
ng-show="target.errors.metric">
<i class="icon-warning-sign"></i>
</a>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form">
<div class="tight-form" ng-hide="target.mode == 1">
<ul class="tight-form-list" role="menu">
<li class="tight-form-item" style="min-width: 15px; text-align: center">&nbsp</li>
<li class="tight-form-item">
@@ -117,7 +172,7 @@
ng-change="selectApplication()"
ng-model="target.application"
bs-tooltip="target.application.name.length > 15 ? target.application.name : ''"
ng-options="app.visible_name ? app.visible_name : app.name for app in metric.applicationList track by app.name" >
ng-options="app.visible_name ? app.visible_name : app.name for app in metric.applicationList track by app.name">
<option value="">-- Select application --</option>
</select>
<a bs-tooltip="target.errors.metric"
@@ -133,7 +188,7 @@
ng-change="selectItem()"
ng-model="target.item"
bs-tooltip="target.item.name.length > 25 ? target.item.name : ''"
ng-options="item.name for item in metric.itemList track by item.name" >
ng-options="item.name for item in metric.itemList track by item.name">
<option value="">-- Select item --</option>
</select>
<a bs-tooltip="target.errors.metric"
@@ -143,11 +198,12 @@
</a>
</li>
<!-- Item filter -->
<li class="tight-form-item">
<li class="tight-form-item" ng-hide="target.mode == 2">
Filter
<i class="fa fa-question-circle" bs-tooltip="'Filtering items by regex. Select All in items and specify regex for item names.'"></i>
<i class="fa fa-question-circle"
bs-tooltip="'Filtering items by regex. Select All in items and specify regex for item names.'"></i>
</li>
<li>
<li ng-hide="target.mode == 2">
<input type="text"
class="tight-form-input input-large"
ng-model="target.itemFilter"
@@ -156,11 +212,12 @@
ng-blur="targetBlur()">
</li>
<!-- Scale -->
<li class="tight-form-item">
<li class="tight-form-item" ng-hide="target.mode == 2">
Scale
<i class="fa fa-question-circle" bs-tooltip="'Set a custom multiplier for series values, for example -1 to invert series'"></i>
<i class="fa fa-question-circle"
bs-tooltip="'Set a custom multiplier for series values, for example -1 to invert series'"></i>
</li>
<li>
<li ng-hide="target.mode == 2">
<input type="text"
class="tight-form-input input-small"
ng-model="target.scale"
@@ -169,6 +226,7 @@
ng-blur="targetBlur()">
</li>
</ul>
<div class="clearfix"></div>
</div>
@@ -204,7 +262,17 @@
</li>
<li class="tight-form-item">
<a ng-click="toggleEditorHelp(1)" bs-tooltip="'click to show helpful info'" data-placement="bottom">
max data points
Max data points
</a>
</li>
<li class="tight-form-item">
<a ng-click="toggleEditorHelp(2)" bs-tooltip="'click to show helpful info'" data-placement="bottom">
IT services
</a>
</li>
<li class="tight-form-item">
<a ng-click="toggleEditorHelp(3)" bs-tooltip="'click to show helpful info'" data-placement="bottom">
IT service property
</a>
</li>
</ul>
@@ -218,7 +286,9 @@
<div class="grafana-info-box span6" ng-if="editorHelpIndex === 1">
<h5>Max data points</h5>
<ul>
<li>Grafana-Zabbix plugin uses maxDataPoints parameter to consolidate the real number of values down to this number</li>
<li>Grafana-Zabbix plugin uses maxDataPoints parameter to consolidate the real number of values down to this
number
</li>
<li>If there are more real values, then by default they will be consolidated using averages</li>
<li>This could hide real peaks and max values in your series</li>
<li>Point consolidation will effect series legend values (min,max,total,current)</li>
@@ -226,5 +296,23 @@
</ul>
</div>
<div class="grafana-info-box span6" ng-if="editorHelpIndex === 2">
<h5>IT services</h5>
<p>
Select "IT services" in targets menu to activate IT services mode.
</p>
</div>
<div class="grafana-info-box span6" ng-if="editorHelpIndex === 3">
<h5>IT service property</h5>
<ul>
<li>Zabbix returns the following availability information about IT service</li>
<li>Status - current status of the IT service</li>
<li>SLA - SLA for the given time interval</li>
<li>OK time - time the service was in OK state, in seconds</li>
<li>Problem time - time the service was in problem state, in seconds</li>
<li>Down time - time the service was in scheduled downtime, in seconds</li>
</ul>
</div>
</div>
</div>

View File

@@ -2,23 +2,36 @@ define([
'angular',
'lodash',
'./helperFunctions'
],
function (angular, _) {
],
function (angular, _) {
'use strict';
var module = angular.module('grafana.controllers');
var targetLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
module.controller('ZabbixAPIQueryCtrl', function($scope, $sce, templateSrv, zabbixHelperSrv) {
module.controller('ZabbixAPIQueryCtrl', function ($scope, $sce, templateSrv, zabbixHelperSrv) {
$scope.init = function() {
$scope.init = function () {
$scope.targetLetters = targetLetters;
if (!$scope.target.mode || $scope.target.mode !== 1) {
$scope.downsampleFunctionList = [
{name: "avg", value: "avg"},
{name: "min", value: "min"},
{name: "max", value: "max"}
];
// Set avg by default
if (!$scope.target.downsampleFunction) {
$scope.target.downsampleFunction = $scope.downsampleFunctionList[0];
}
if (!$scope.metric) {
$scope.metric = {
hostGroupList: [],
hostList: [{name: '*', visible_name: 'All'}],
applicationList: [{name: '*', visible_name: 'All'}],
itemList: [{name: 'All'}]
};
}
// Update host group, host, application and item lists
$scope.updateGroupList();
@@ -27,10 +40,33 @@ function (angular, _) {
$scope.updateItemList();
setItemAlias();
}
else if ($scope.target.mode === 1) {
$scope.slaPropertyList = [
{name: "Status", property: "status"},
{name: "SLA", property: "sla"},
{name: "OK time", property: "okTime"},
{name: "Problem time", property: "problemTime"},
{name: "Down time", property: "downtimeTime"}
];
$scope.itserviceList = [{name: "test"}];
$scope.updateITServiceList();
}
$scope.target.errors = validateTarget($scope.target);
};
/**
* Switch query editor to specified mode.
* Modes:
* 0 - items
* 1 - IT services
*/
$scope.switchEditorMode = function (mode) {
$scope.target.mode = mode;
$scope.init();
};
/**
* Take alias from item name by default
*/
@@ -40,7 +76,7 @@ function (angular, _) {
}
}
$scope.targetBlur = function() {
$scope.targetBlur = function () {
setItemAlias();
$scope.target.errors = validateTarget($scope.target);
if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
@@ -49,10 +85,21 @@ function (angular, _) {
}
};
/**
* Call when IT service is selected.
*/
$scope.selectITService = function () {
$scope.target.errors = validateTarget($scope.target);
if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
$scope.oldTarget = angular.copy($scope.target);
$scope.get_data();
}
};
/**
* Call when host group selected
*/
$scope.selectHostGroup = function() {
$scope.selectHostGroup = function () {
$scope.updateHostList();
$scope.updateAppList();
$scope.updateItemList();
@@ -67,7 +114,7 @@ function (angular, _) {
/**
* Call when host selected
*/
$scope.selectHost = function() {
$scope.selectHost = function () {
$scope.updateAppList();
$scope.updateItemList();
@@ -81,7 +128,7 @@ function (angular, _) {
/**
* Call when application selected
*/
$scope.selectApplication = function() {
$scope.selectApplication = function () {
$scope.updateItemList();
$scope.target.errors = validateTarget($scope.target);
@@ -94,7 +141,7 @@ function (angular, _) {
/**
* Call when item selected
*/
$scope.selectItem = function() {
$scope.selectItem = function () {
setItemAlias();
$scope.target.errors = validateTarget($scope.target);
if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
@@ -103,12 +150,12 @@ function (angular, _) {
}
};
$scope.duplicate = function() {
$scope.duplicate = function () {
var clone = angular.copy($scope.target);
$scope.panel.targets.push(clone);
};
$scope.moveMetricQuery = function(fromIndex, toIndex) {
$scope.moveMetricQuery = function (fromIndex, toIndex) {
_.move($scope.panel.targets, fromIndex, toIndex);
};
@@ -116,10 +163,20 @@ function (angular, _) {
// SUGGESTION QUERIES
//////////////////////////////
/**
* Update list of IT services
*/
$scope.updateITServiceList = function () {
$scope.datasource.zabbixAPI.getITService().then(function (iteservices) {
$scope.itserviceList = [];
$scope.itserviceList = $scope.itserviceList.concat(iteservices);
});
};
/**
* Update list of host groups
*/
$scope.updateGroupList = function() {
$scope.updateGroupList = function () {
$scope.datasource.zabbixAPI.performHostGroupSuggestQuery().then(function (groups) {
$scope.metric.groupList = [{name: '*', visible_name: 'All'}];
addTemplatedVariables($scope.metric.groupList);
@@ -130,7 +187,7 @@ function (angular, _) {
/**
* Update list of hosts
*/
$scope.updateHostList = function() {
$scope.updateHostList = function () {
var groups = $scope.target.group ? zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.group.name)) : undefined;
if (groups) {
$scope.datasource.zabbixAPI.hostFindQuery(groups).then(function (hosts) {
@@ -144,7 +201,7 @@ function (angular, _) {
/**
* Update list of host applications
*/
$scope.updateAppList = function() {
$scope.updateAppList = function () {
var groups = $scope.target.group ? zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.group.name)) : undefined;
var hosts = $scope.target.host ? zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.host.name)) : undefined;
if (groups && hosts) {
@@ -162,12 +219,14 @@ function (angular, _) {
/**
* Update list of items
*/
$scope.updateItemList = function() {
$scope.updateItemList = function () {
var groups = $scope.target.group ? zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.group.name)) : undefined;
var hosts = $scope.target.host ? zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.host.name)) : undefined;
var apps = $scope.target.application ? zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.application.name)) : undefined;
var apps = $scope.target.application ?
zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.application.name)) : undefined;
var itemtype = $scope.target.mode === 2 ? "text" : "numeric";
if (groups && hosts && apps) {
$scope.datasource.zabbixAPI.itemFindQuery(groups, hosts, apps).then(function (items) {
$scope.datasource.zabbixAPI.itemFindQuery(groups, hosts, apps, itemtype).then(function (items) {
// Show only unique item names
var uniq_items = _.map(_.uniq(items, function (item) {
return zabbixHelperSrv.expandItemName(item);
@@ -187,7 +246,7 @@ function (angular, _) {
* @param {Array} metricList List of metrics which variables add to
*/
function addTemplatedVariables(metricList) {
_.each(templateSrv.variables, function(variable) {
_.each(templateSrv.variables, function (variable) {
metricList.push({
name: '$' + variable.name,
templated: true
@@ -209,4 +268,4 @@ function (angular, _) {
});
});
});

View File

@@ -1,7 +1,7 @@
define([
'angular',
'lodash',
],
'lodash'
],
function (angular, _) {
'use strict';
@@ -94,7 +94,7 @@ function (angular, _) {
},
auth: null,
id: 1
},
}
};
if (this.basicAuth || this.withCredentials) {
@@ -245,8 +245,8 @@ function (angular, _) {
/**
* Get the list of hosts
*
* @param {array} groupids
* @return {array} array of Zabbix host objects
* @param {string|string[]} groupids
* @return {Object} array of Zabbix host objects
*/
p.performHostSuggestQuery = function(groupids) {
var params = {
@@ -269,7 +269,7 @@ function (angular, _) {
*
* @param {array} hostids
* @param {array} groupids
* @return {array} array of Zabbix application objects
* @return {Object} array of Zabbix application objects
*/
p.performAppSuggestQuery = function(hostids, /* optional */ groupids) {
var params = {
@@ -289,12 +289,12 @@ function (angular, _) {
/**
* Items request
*
* @param {string or Array} hostids ///////////////////////////
* @param {string or Array} applicationids // Zabbix API parameters //
* @param {string or Array} groupids ///////////////////////////
* @return {string or Array} Array of Zabbix API item objects
* @param {string|string[]} hostids ///////////////////////////
* @param {string|string[]} applicationids // Zabbix API parameters //
* @param {string|string[]} groupids ///////////////////////////
* @return {string|string[]} Array of Zabbix API item objects
*/
p.performItemSuggestQuery = function(hostids, applicationids, /* optional */ groupids) {
p.performItemSuggestQuery = function(hostids, applicationids, groupids, itemtype) {
var params = {
output: ['name', 'key_', 'value_type', 'delay'],
sortfield: 'name',
@@ -302,13 +302,17 @@ function (angular, _) {
webitems: true,
// Return only numeric items
filter: {
value_type: [0,3]
value_type: [0, 3]
},
// Return only enabled items
monitored: true,
searchByAny: true
};
if (itemtype === "text") {
params.filter.value_type = [1, 2, 4];
}
// Filter by hosts or by groups
if (hostids) {
params.hostids = hostids;
@@ -409,7 +413,7 @@ function (angular, _) {
* @param {string or array} apps
* @return {array} array of Zabbix API item objects
*/
p.itemFindQuery = function(groups, hosts, apps) {
p.itemFindQuery = function(groups, hosts, apps, itemtype) {
var promises = [];
// Get hostids from names
@@ -447,7 +451,7 @@ function (angular, _) {
}), 'applicationid');
}
return self.performItemSuggestQuery(hostids, applicationids, groupids);
return self.performItemSuggestQuery(hostids, applicationids, groupids, itemtype);
});
};
@@ -508,6 +512,25 @@ function (angular, _) {
});
};
p.getITService = function(/* optional */ serviceids) {
var params = {
output: 'extend',
serviceids: serviceids
};
return this.performZabbixAPIRequest('service.get', params);
};
p.getSLA = function(serviceids, from, to) {
var params = {
serviceids: serviceids,
intervals: [{
from: from,
to: to
}]
};
return this.performZabbixAPIRequest('service.getsla', params);
};
return ZabbixAPI;
});