Resolved #71 - Text metrics support for singlestat panel.
This commit is contained in:
@@ -94,7 +94,7 @@ function (angular, _, kbn) {
|
|||||||
// Create request for each target
|
// Create request for each target
|
||||||
var promises = _.map(options.targets, function(target) {
|
var promises = _.map(options.targets, function(target) {
|
||||||
|
|
||||||
if (!target.ITService) {
|
if (target.mode !== 1) {
|
||||||
// Don't show undefined and hidden targets
|
// Don't show undefined and hidden targets
|
||||||
if (target.hide || !target.group || !target.host
|
if (target.hide || !target.group || !target.host
|
||||||
|| !target.application || !target.item) {
|
|| !target.application || !target.item) {
|
||||||
@@ -119,87 +119,115 @@ function (angular, _, kbn) {
|
|||||||
var delete_hostname_pattern = /(?:\[[\w\.]+]:\s)/g;
|
var delete_hostname_pattern = /(?:\[[\w\.]+]:\s)/g;
|
||||||
var itemnames = zabbixHelperSrv.splitMetrics(itemname.replace(delete_hostname_pattern, ''));
|
var itemnames = zabbixHelperSrv.splitMetrics(itemname.replace(delete_hostname_pattern, ''));
|
||||||
|
|
||||||
// Find items by item names and perform queries
|
|
||||||
var self = this;
|
var self = this;
|
||||||
return this.zabbixAPI.itemFindQuery(groups, hosts, apps)
|
|
||||||
.then(function (items) {
|
|
||||||
|
|
||||||
// Filter hosts by regex
|
// Query numeric data
|
||||||
if (target.host.visible_name === 'All') {
|
if (!target.mode) {
|
||||||
if (target.hostFilter && _.every(items, _.identity.hosts)) {
|
|
||||||
|
|
||||||
// Use templated variables in filter
|
// Find items by item names and perform queries
|
||||||
var host_pattern = new RegExp(templateSrv.replace(target.hostFilter, options.scopedVars));
|
return this.zabbixAPI.itemFindQuery(groups, hosts, apps)
|
||||||
items = _.filter(items, function (item) {
|
.then(function (items) {
|
||||||
return _.some(item.hosts, function (host) {
|
|
||||||
return host_pattern.test(host.name);
|
// Filter hosts by regex
|
||||||
|
if (target.host.visible_name === 'All') {
|
||||||
|
if (target.hostFilter && _.every(items, _.identity.hosts)) {
|
||||||
|
|
||||||
|
// Use templated variables in filter
|
||||||
|
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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (itemnames[0] === 'All') {
|
if (itemnames[0] === 'All') {
|
||||||
|
|
||||||
// Filter items by regex
|
// Filter items by regex
|
||||||
if (target.itemFilter) {
|
if (target.itemFilter) {
|
||||||
|
|
||||||
// Use templated variables in filter
|
// Use templated variables in filter
|
||||||
var item_pattern = new RegExp(templateSrv.replace(target.itemFilter, options.scopedVars));
|
var item_pattern = new RegExp(templateSrv.replace(target.itemFilter, options.scopedVars));
|
||||||
return _.filter(items, function (item) {
|
return _.filter(items, function (item) {
|
||||||
return item_pattern.test(zabbixHelperSrv.expandItemName(item));
|
return item_pattern.test(zabbixHelperSrv.expandItemName(item));
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return items;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Filtering items
|
// Filtering items
|
||||||
return _.filter(items, function (item) {
|
return _.filter(items, function (item) {
|
||||||
|
return _.contains(itemnames, zabbixHelperSrv.expandItemName(item));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).then(function (items) {
|
||||||
|
|
||||||
|
// Don't perform query for high number of items
|
||||||
|
// to prevent Grafana slowdown
|
||||||
|
if (items.length > self.limitmetrics) {
|
||||||
|
var message = "Try to increase limitmetrics parameter in datasource config.<br>"
|
||||||
|
+ "Current limitmetrics value is " + self.limitmetrics;
|
||||||
|
alertSrv.set("Metrics limit exceeded", message, "warning", 10000);
|
||||||
|
return [];
|
||||||
|
} else {
|
||||||
|
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, options.scopedVars);
|
||||||
|
|
||||||
|
var history;
|
||||||
|
if ((from < useTrendsFrom) && self.trends) {
|
||||||
|
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 {
|
||||||
|
history = self.zabbixAPI.getHistory(items, from, to)
|
||||||
|
.then(_.bind(zabbixHelperSrv.handleHistoryResponse, zabbixHelperSrv, items, alias, target.scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
var downsampleFunc = target.downsampleFunction ? target.downsampleFunction.value : "avg";
|
||||||
|
timeseries.datapoints = zabbixHelperSrv.downsampleSeries(timeseries.datapoints, to, ms_interval, downsampleFunc);
|
||||||
|
}
|
||||||
|
return timeseries;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 _.contains(itemnames, zabbixHelperSrv.expandItemName(item));
|
||||||
});
|
});
|
||||||
}
|
return self.zabbixAPI.getHistory(items, from, to).then(function(history) {
|
||||||
}).then(function (items) {
|
return {
|
||||||
|
target: target.item.name,
|
||||||
|
datapoints: _.map(history, function (p) {
|
||||||
|
return [p.value, p.clock * 1000];
|
||||||
|
})
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Don't perform query for high number of items
|
// IT services mode
|
||||||
// to prevent Grafana slowdown
|
else if (target.mode === 1) {
|
||||||
if (items.length > self.limitmetrics) {
|
|
||||||
var message = "Try to increase limitmetrics parameter in datasource config.<br>"
|
|
||||||
+ "Current limitmetrics value is " + self.limitmetrics;
|
|
||||||
alertSrv.set("Metrics limit exceeded", message, "warning", 10000);
|
|
||||||
return [];
|
|
||||||
} else {
|
|
||||||
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, options.scopedVars);
|
|
||||||
|
|
||||||
var history;
|
|
||||||
if ((from < useTrendsFrom) && self.trends) {
|
|
||||||
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 {
|
|
||||||
history = self.zabbixAPI.getHistory(items, from, to)
|
|
||||||
.then(_.bind(zabbixHelperSrv.handleHistoryResponse, zabbixHelperSrv, items, alias, target.scale));
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
var downsampleFunc = target.downsampleFunction ? target.downsampleFunction.value : "avg";
|
|
||||||
timeseries.datapoints = zabbixHelperSrv.downsampleSeries(timeseries.datapoints, to, ms_interval, downsampleFunc);
|
|
||||||
}
|
|
||||||
return timeseries;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Don't show undefined and hidden targets
|
// Don't show undefined and hidden targets
|
||||||
if (target.hide || !target.itservice || !target.slaProperty) {
|
if (target.hide || !target.itservice || !target.slaProperty) {
|
||||||
return [];
|
return [];
|
||||||
|
|||||||
@@ -16,14 +16,18 @@
|
|||||||
<i class="fa fa-bars"></i>
|
<i class="fa fa-bars"></i>
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu pull-right" role="menu">
|
<ul class="dropdown-menu pull-right" role="menu">
|
||||||
<!-- Switch to IT Services editor -->
|
<!-- Switch editor mode -->
|
||||||
<li role="menuitem" ng-hide="target.mode == 1">
|
<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"
|
<a class="pointer" tabindex="1"
|
||||||
ng-click="switchEditorMode(1)">IT services</a>
|
ng-click="switchEditorMode(1)">IT services</a>
|
||||||
</li>
|
</li>
|
||||||
<li role="menuitem" ng-show="target.mode">
|
<li role="menuitem" ng-show="target.mode != 2">
|
||||||
<a class="pointer" tabindex="1"
|
<a class="pointer" tabindex="1"
|
||||||
ng-click="switchEditorMode(0)">Items</a>
|
ng-click="switchEditorMode(2)">Text metrics</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="divider" role="menuitem"></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="duplicate()">Duplicate</a></li>
|
||||||
@@ -75,7 +79,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul class="tight-form-list" role="menu" ng-hide="target.mode">
|
<ul class="tight-form-list" role="menu" ng-hide="target.mode == 1">
|
||||||
<!-- Alias -->
|
<!-- Alias -->
|
||||||
<li>
|
<li>
|
||||||
<input type="text"
|
<input type="text"
|
||||||
@@ -118,12 +122,12 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<!-- Host filter -->
|
<!-- Host filter -->
|
||||||
<li class="tight-form-item">
|
<li class="tight-form-item" ng-hide="target.mode == 2">
|
||||||
Filter
|
Filter
|
||||||
<i class="fa fa-question-circle"
|
<i class="fa fa-question-circle"
|
||||||
bs-tooltip="'Filtering hosts by regex. Select All in items and specify regex for host names.'"></i>
|
bs-tooltip="'Filtering hosts by regex. Select All in items and specify regex for host names.'"></i>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li ng-hide="target.mode == 2">
|
||||||
<input type="text"
|
<input type="text"
|
||||||
class="tight-form-input input-large"
|
class="tight-form-input input-large"
|
||||||
ng-model="target.hostFilter"
|
ng-model="target.hostFilter"
|
||||||
@@ -132,8 +136,10 @@
|
|||||||
ng-blur="targetBlur()">
|
ng-blur="targetBlur()">
|
||||||
</li>
|
</li>
|
||||||
<!-- Downsampling function -->
|
<!-- Downsampling function -->
|
||||||
<li class="tight-form-item input-medium">Downsampling</li>
|
<li class="tight-form-item input-medium" ng-hide="target.mode == 2">
|
||||||
<li>
|
Downsampling
|
||||||
|
</li>
|
||||||
|
<li ng-hide="target.mode == 2">
|
||||||
<select class="tight-form-input input-small"
|
<select class="tight-form-input input-small"
|
||||||
ng-change="targetBlur()"
|
ng-change="targetBlur()"
|
||||||
ng-model="target.downsampleFunction"
|
ng-model="target.downsampleFunction"
|
||||||
@@ -151,7 +157,7 @@
|
|||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tight-form" ng-hide="target.mode">
|
<div class="tight-form" ng-hide="target.mode == 1">
|
||||||
<ul class="tight-form-list" role="menu">
|
<ul class="tight-form-list" role="menu">
|
||||||
<li class="tight-form-item" style="min-width: 15px; text-align: center"> </li>
|
<li class="tight-form-item" style="min-width: 15px; text-align: center"> </li>
|
||||||
<li class="tight-form-item">
|
<li class="tight-form-item">
|
||||||
@@ -192,12 +198,12 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<!-- Item filter -->
|
<!-- Item filter -->
|
||||||
<li class="tight-form-item">
|
<li class="tight-form-item" ng-hide="target.mode == 2">
|
||||||
Filter
|
Filter
|
||||||
<i class="fa fa-question-circle"
|
<i class="fa fa-question-circle"
|
||||||
bs-tooltip="'Filtering items by regex. Select All in items and specify regex for item names.'"></i>
|
bs-tooltip="'Filtering items by regex. Select All in items and specify regex for item names.'"></i>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li ng-hide="target.mode == 2">
|
||||||
<input type="text"
|
<input type="text"
|
||||||
class="tight-form-input input-large"
|
class="tight-form-input input-large"
|
||||||
ng-model="target.itemFilter"
|
ng-model="target.itemFilter"
|
||||||
@@ -206,12 +212,12 @@
|
|||||||
ng-blur="targetBlur()">
|
ng-blur="targetBlur()">
|
||||||
</li>
|
</li>
|
||||||
<!-- Scale -->
|
<!-- Scale -->
|
||||||
<li class="tight-form-item">
|
<li class="tight-form-item" ng-hide="target.mode == 2">
|
||||||
Scale
|
Scale
|
||||||
<i class="fa fa-question-circle"
|
<i class="fa fa-question-circle"
|
||||||
bs-tooltip="'Set a custom multiplier for series values, for example -1 to invert series'"></i>
|
bs-tooltip="'Set a custom multiplier for series values, for example -1 to invert series'"></i>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li ng-hide="target.mode == 2">
|
||||||
<input type="text"
|
<input type="text"
|
||||||
class="tight-form-input input-small"
|
class="tight-form-input input-small"
|
||||||
ng-model="target.scale"
|
ng-model="target.scale"
|
||||||
|
|||||||
@@ -13,17 +13,7 @@ define([
|
|||||||
|
|
||||||
$scope.init = function () {
|
$scope.init = function () {
|
||||||
$scope.targetLetters = targetLetters;
|
$scope.targetLetters = targetLetters;
|
||||||
if ($scope.target.mode === 1) {
|
if (!$scope.target.mode || $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();
|
|
||||||
} else {
|
|
||||||
$scope.downsampleFunctionList = [
|
$scope.downsampleFunctionList = [
|
||||||
{name: "avg", value: "avg"},
|
{name: "avg", value: "avg"},
|
||||||
{name: "min", value: "min"},
|
{name: "min", value: "min"},
|
||||||
@@ -34,12 +24,14 @@ define([
|
|||||||
if (!$scope.target.downsampleFunction) {
|
if (!$scope.target.downsampleFunction) {
|
||||||
$scope.target.downsampleFunction = $scope.downsampleFunctionList[0];
|
$scope.target.downsampleFunction = $scope.downsampleFunctionList[0];
|
||||||
}
|
}
|
||||||
$scope.metric = {
|
if (!$scope.metric) {
|
||||||
hostGroupList: [],
|
$scope.metric = {
|
||||||
hostList: [{name: '*', visible_name: 'All'}],
|
hostGroupList: [],
|
||||||
applicationList: [{name: '*', visible_name: 'All'}],
|
hostList: [{name: '*', visible_name: 'All'}],
|
||||||
itemList: [{name: 'All'}]
|
applicationList: [{name: '*', visible_name: 'All'}],
|
||||||
};
|
itemList: [{name: 'All'}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Update host group, host, application and item lists
|
// Update host group, host, application and item lists
|
||||||
$scope.updateGroupList();
|
$scope.updateGroupList();
|
||||||
@@ -49,6 +41,17 @@ define([
|
|||||||
|
|
||||||
setItemAlias();
|
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);
|
$scope.target.errors = validateTarget($scope.target);
|
||||||
};
|
};
|
||||||
@@ -221,8 +224,9 @@ define([
|
|||||||
var hosts = $scope.target.host ? zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.host.name)) : undefined;
|
var hosts = $scope.target.host ? zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.host.name)) : undefined;
|
||||||
var apps = $scope.target.application ?
|
var apps = $scope.target.application ?
|
||||||
zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.application.name)) : undefined;
|
zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.application.name)) : undefined;
|
||||||
|
var itemtype = $scope.target.mode === 2 ? "text" : "numeric";
|
||||||
if (groups && hosts && apps) {
|
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
|
// Show only unique item names
|
||||||
var uniq_items = _.map(_.uniq(items, function (item) {
|
var uniq_items = _.map(_.uniq(items, function (item) {
|
||||||
return zabbixHelperSrv.expandItemName(item);
|
return zabbixHelperSrv.expandItemName(item);
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ function (angular, _) {
|
|||||||
* @param {string|string[]} groupids ///////////////////////////
|
* @param {string|string[]} groupids ///////////////////////////
|
||||||
* @return {string|string[]} Array of Zabbix API item objects
|
* @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 = {
|
var params = {
|
||||||
output: ['name', 'key_', 'value_type', 'delay'],
|
output: ['name', 'key_', 'value_type', 'delay'],
|
||||||
sortfield: 'name',
|
sortfield: 'name',
|
||||||
@@ -302,13 +302,17 @@ function (angular, _) {
|
|||||||
webitems: true,
|
webitems: true,
|
||||||
// Return only numeric items
|
// Return only numeric items
|
||||||
filter: {
|
filter: {
|
||||||
value_type: [0,3]
|
value_type: [0, 3]
|
||||||
},
|
},
|
||||||
// Return only enabled items
|
// Return only enabled items
|
||||||
monitored: true,
|
monitored: true,
|
||||||
searchByAny: true
|
searchByAny: true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (itemtype === "text") {
|
||||||
|
params.filter.value_type = [1, 2, 4];
|
||||||
|
}
|
||||||
|
|
||||||
// Filter by hosts or by groups
|
// Filter by hosts or by groups
|
||||||
if (hostids) {
|
if (hostids) {
|
||||||
params.hostids = hostids;
|
params.hostids = hostids;
|
||||||
@@ -409,7 +413,7 @@ function (angular, _) {
|
|||||||
* @param {string or array} apps
|
* @param {string or array} apps
|
||||||
* @return {array} array of Zabbix API item objects
|
* @return {array} array of Zabbix API item objects
|
||||||
*/
|
*/
|
||||||
p.itemFindQuery = function(groups, hosts, apps) {
|
p.itemFindQuery = function(groups, hosts, apps, itemtype) {
|
||||||
var promises = [];
|
var promises = [];
|
||||||
|
|
||||||
// Get hostids from names
|
// Get hostids from names
|
||||||
@@ -447,7 +451,7 @@ function (angular, _) {
|
|||||||
}), 'applicationid');
|
}), 'applicationid');
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.performItemSuggestQuery(hostids, applicationids, groupids);
|
return self.performItemSuggestQuery(hostids, applicationids, groupids, itemtype);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user