Handle history response in query builder.

This commit is contained in:
Alexander Zobnin
2016-01-23 22:12:03 +03:00
parent 6b71f42c48
commit fa220cc45a
4 changed files with 233 additions and 132 deletions

View File

@@ -9,12 +9,12 @@ define([
'./zabbixCache', './zabbixCache',
'./queryCtrl' './queryCtrl'
], ],
function (angular, _, dateMath, QueryBuilder) { function (angular, _, dateMath) {
'use strict'; 'use strict';
/** @ngInject */ /** @ngInject */
function ZabbixAPIDatasource(instanceSettings, $q, templateSrv, alertSrv, function ZabbixAPIDatasource(instanceSettings, $q, templateSrv, alertSrv,
ZabbixAPI, zabbixHelperSrv, ZabbixCache) { ZabbixAPI, zabbixHelperSrv, ZabbixCache, QueryBuilder) {
// General data source settings // General data source settings
this.name = instanceSettings.name; this.name = instanceSettings.name;
@@ -39,6 +39,8 @@ function (angular, _, dateMath, QueryBuilder) {
// Initialize query builder // Initialize query builder
this.queryBuilder = new QueryBuilder(this.zabbixCache); this.queryBuilder = new QueryBuilder(this.zabbixCache);
console.log(this.zabbixCache);
//////////////////////// ////////////////////////
// Datasource methods // // Datasource methods //
//////////////////////// ////////////////////////
@@ -128,19 +130,26 @@ function (angular, _, dateMath, QueryBuilder) {
alias = templateSrv.replace(target.alias, options.scopedVars); alias = templateSrv.replace(target.alias, options.scopedVars);
} }
var history; // Add hostname for items from multiple hosts
var addHostName = target.host.isRegex;
var getHistory;
if ((from < useTrendsFrom) && self.trends) { if ((from < useTrendsFrom) && self.trends) {
// Use trends // Use trends
var points = target.downsampleFunction ? target.downsampleFunction.value : "avg"; var valueType = target.downsampleFunction ? target.downsampleFunction.value : "avg";
history = self.zabbixAPI.getTrends(items, from, to) getHistory = self.zabbixAPI.getTrends(items, from, to).then(function(history) {
.then(_.bind(zabbixHelperSrv.handleTrendResponse, zabbixHelperSrv, items, alias, target.scale, points)); return self.queryBuilder.handleTrends(history, addHostName, valueType);
});
} else { } else {
// Use history // Use history
history = self.zabbixAPI.getHistory(items, from, to) getHistory = self.zabbixAPI.getHistory(items, from, to).then(function(history) {
.then(_.bind(zabbixHelperSrv.handleHistoryResponse, zabbixHelperSrv, items, alias, target.scale)); return self.queryBuilder.handleHistory(history, addHostName);
});
} }
return history.then(function (timeseries) { return getHistory.then(function (timeseries) {
var timeseries_data = _.flatten(timeseries); var timeseries_data = _.flatten(timeseries);
return _.map(timeseries_data, function (timeseries) { return _.map(timeseries_data, function (timeseries) {

View File

@@ -6,122 +6,206 @@ define([
function (angular, _, utils) { function (angular, _, utils) {
'use strict'; 'use strict';
function QueryBuilder(zabbixCacheInstance) { var module = angular.module('grafana.services');
this.cache = zabbixCacheInstance; module.factory('QueryBuilder', function() {
this.build = function (groupFilter, hostFilter, appFilter, itemFilter) { function QueryBuilder(zabbixCacheInstance) {
var self = this;
// Find items by item names and perform queries this.cache = zabbixCacheInstance;
var groups = [];
var hosts = [];
var apps = [];
var items = [];
if (utils.isRegex(hostFilter)) { /**
* Build query - convert target filters to array of Zabbix items
*/
this.build = function (groupFilter, hostFilter, appFilter, itemFilter) {
// Filter groups // Find items by item names and perform queries
if (utils.isRegex(groupFilter)) { var groups = [];
var groupPattern = utils.buildRegex(groupFilter); var hosts = [];
groups = _.filter(this.cache.getGroups(), function (groupObj) { var apps = [];
return groupPattern.test(groupObj.name); var items = [];
});
} else { if (utils.isRegex(hostFilter)) {
var findedGroup = _.find(this.cache.getGroups(), {'name': groupFilter});
if (findedGroup) { // Filter groups
groups.push(findedGroup); if (utils.isRegex(groupFilter)) {
var groupPattern = utils.buildRegex(groupFilter);
groups = _.filter(this.cache.getGroups(), function (groupObj) {
return groupPattern.test(groupObj.name);
});
} else { } else {
groups = undefined; var findedGroup = _.find(this.cache.getGroups(), {'name': groupFilter});
if (findedGroup) {
groups.push(findedGroup);
} else {
groups = undefined;
}
} }
} if (groups) {
if (groups) { var groupids = _.map(groups, 'groupid');
var groupids = _.map(groups, 'groupid'); hosts = _.filter(this.cache.getHosts(), function (hostObj) {
hosts = _.filter(this.cache.getHosts(), function (hostObj) { return _.intersection(groupids, hostObj.groups).length;
return _.intersection(groupids, hostObj.groups).length; });
});
} else {
// No groups finded
return [];
}
// Filter hosts
var hostPattern = utils.buildRegex(hostFilter);
hosts = _.filter(hosts, function (hostObj) {
return hostPattern.test(hostObj.name);
});
} else {
var findedHost = _.find(this.cache.getHosts(), {'name': hostFilter});
if (findedHost) {
hosts.push(findedHost);
} else {
// No hosts finded
return [];
}
}
// Find items belongs to selected hosts
items = _.filter(this.cache.getItems(), function (itemObj) {
return _.contains(_.map(hosts, 'hostid'), itemObj.hostid);
});
if (utils.isRegex(itemFilter)) {
// Filter applications
if (utils.isRegex(appFilter)) {
var appPattern = utils.buildRegex(appFilter);
apps = _.filter(this.cache.getApplications(), function (appObj) {
return appPattern.test(appObj.name);
});
}
// Don't use application filter if it empty
else if (appFilter === "") {
apps = undefined;
}
else {
var findedApp = _.find(this.cache.getApplications(), {'name': appFilter});
if (findedApp) {
apps.push(findedApp);
} else { } else {
// No applications finded // No groups finded
return [];
}
// Filter hosts
var hostPattern = utils.buildRegex(hostFilter);
hosts = _.filter(hosts, function (hostObj) {
return hostPattern.test(hostObj.name);
});
} else {
var findedHost = _.find(this.cache.getHosts(), {'name': hostFilter});
if (findedHost) {
hosts.push(findedHost);
} else {
// No hosts finded
return []; return [];
} }
} }
// Find items belongs to selected applications // Find items belongs to selected hosts
if (apps) { items = _.filter(this.cache.getItems(), function (itemObj) {
var appids = _.flatten(_.map(apps, 'applicationids')); return _.contains(_.map(hosts, 'hostid'), itemObj.hostid);
items = _.filter(items, function (itemObj) { });
return _.intersection(appids, itemObj.applications).length;
}); if (utils.isRegex(itemFilter)) {
// Filter applications
if (utils.isRegex(appFilter)) {
var appPattern = utils.buildRegex(appFilter);
apps = _.filter(this.cache.getApplications(), function (appObj) {
return appPattern.test(appObj.name);
});
}
// Don't use application filter if it empty
else if (appFilter === "") {
apps = undefined;
}
else {
var findedApp = _.find(this.cache.getApplications(), {'name': appFilter});
if (findedApp) {
apps.push(findedApp);
} else {
// No applications finded
return [];
}
}
// Find items belongs to selected applications
if (apps) {
var appids = _.flatten(_.map(apps, 'applicationids'));
items = _.filter(items, function (itemObj) {
return _.intersection(appids, itemObj.applications).length;
});
}
if (items) {
var itemPattern = utils.buildRegex(itemFilter);
items = _.filter(items, function (itemObj) {
return itemPattern.test(itemObj.name);
});
} else {
// No items finded
return [];
}
} else {
items = _.filter(items, {'name': hostFilter});
if (!items.length) {
// No items finded
return [];
}
} }
if (items) { // Set host as host name for each item
var itemPattern = utils.buildRegex(itemFilter); items = _.each(items, function (itemObj) {
items = _.filter(items, function (itemObj) { itemObj.host = _.find(hosts, {'hostid': itemObj.hostid}).name;
return itemPattern.test(itemObj.name); });
});
} else { return items;
// No items finded };
return [];
} /**
} else { * Convert Zabbix API history.get response to Grafana format
items = _.filter(items, {'name': hostFilter}); *
if (!items.length) { * @return {Array} Array of timeseries in Grafana format
// No items finded * {
return []; * target: "Metric name",
} * datapoints: [[<value>, <unixtime>], ...]
* }
*/
this.convertHistory = function(history, addHostName, convertPointCallback) {
/**
* Response should be in the format:
* data: [
* {
* target: "Metric name",
* datapoints: [[<value>, <unixtime>], ...]
* }, ...
* ]
*/
// Group history by itemid
var grouped_history = _.groupBy(history, 'itemid');
return _.map(grouped_history, function(hist, itemid) {
var item = self.cache.getItem(itemid);
var alias = item.name;
if (addHostName) {
var host = self.cache.getHost(item.hostid);
alias = host.name + ": " + alias;
}
return {
target: alias,
datapoints: _.map(hist, convertPointCallback)
};
});
};
this.handleHistory = function(history, addHostName) {
return this.convertHistory(history, addHostName, convertHistoryPoint);
};
this.handleTrends = function(history, addHostName, valueType) {
var convertPointCallback = _.partial(convertTrendPoint, valueType);
return this.convertHistory(history, addHostName, convertPointCallback);
};
function convertHistoryPoint(point) {
// Value must be a number for properly work
return [
Number(point.value),
point.clock * 1000
];
} }
// Set host as host name for each item function convertTrendPoint(valueType, point) {
items = _.each(items, function (itemObj) { var value;
itemObj.host = _.find(hosts, {'hostid': itemObj.hostid}).name; switch (valueType) {
}); case "min":
value = point.value_min;
break;
case "max":
value = point.value_max;
break;
case "avg":
value = point.value_avg;
break;
default:
value = point.value_avg;
}
return items; return [
}; Number(value),
point.clock * 1000
];
}
}
} return QueryBuilder;
});
return QueryBuilder;
}); });

View File

@@ -118,12 +118,14 @@ function (angular, _) {
/** /**
* Perform history query from Zabbix API * Perform history query from Zabbix API
* *
* @param {Array} items Array of Zabbix item objects * @param {Array} items Array of Zabbix item objects
* @param {Number} start Time in seconds * @param {Number} time_from Time in seconds
* @param {Number} end Time in seconds * @param {Number} time_till Time in seconds
* @return {Array} Array of Zabbix history objects * @return {Array} Array of Zabbix history objects
*/ */
p.getHistory = function(items, start, end) { p.getHistory = function(items, time_from, time_till) {
var self = this;
// Group items by value type // Group items by value type
var grouped_items = _.groupBy(items, 'value_type'); var grouped_items = _.groupBy(items, 'value_type');
@@ -136,30 +138,30 @@ function (angular, _) {
itemids: itemids, itemids: itemids,
sortfield: 'clock', sortfield: 'clock',
sortorder: 'ASC', sortorder: 'ASC',
time_from: start time_from: time_from
}; };
// Relative queries (e.g. last hour) don't include an end time // Relative queries (e.g. last hour) don't include an end time
if (end) { if (time_till) {
params.time_till = end; params.time_till = time_till;
} }
return this.request('history.get', params); return self.request('history.get', params);
}, this)).then(function (results) { })).then(_.flatten);
return _.flatten(results);
});
}; };
/** /**
* Perform trends query from Zabbix API * Perform trends query from Zabbix API
* Use trends api extension from ZBXNEXT-1193 patch. * Use trends api extension from ZBXNEXT-1193 patch.
* *
* @param {Array} items Array of Zabbix item objects * @param {Array} items Array of Zabbix item objects
* @param {Number} start Time in seconds * @param {Number} time_from Time in seconds
* @param {Number} end Time in seconds * @param {Number} time_till Time in seconds
* @return {Array} Array of Zabbix trend objects * @return {Array} Array of Zabbix trend objects
*/ */
p.getTrends = function(items, start, end) { p.getTrends = function(items, time_from, time_till) {
var self = this;
// Group items by value type // Group items by value type
var grouped_items = _.groupBy(items, 'value_type'); var grouped_items = _.groupBy(items, 'value_type');
@@ -172,18 +174,16 @@ function (angular, _) {
itemids: itemids, itemids: itemids,
sortfield: 'clock', sortfield: 'clock',
sortorder: 'ASC', sortorder: 'ASC',
time_from: start time_from: time_from
}; };
// Relative queries (e.g. last hour) don't include an end time // Relative queries (e.g. last hour) don't include an end time
if (end) { if (time_till) {
params.time_till = end; params.time_till = time_till;
} }
return this.request('trend.get', params); return self.request('trend.get', params);
}, this)).then(function (results) { })).then(_.flatten);
return _.flatten(results);
});
}; };
p.getITService = function(/* optional */ serviceids) { p.getITService = function(/* optional */ serviceids) {

View File

@@ -70,6 +70,14 @@ function (angular, _, utils) {
return this._items; return this._items;
}; };
p.getHost = function(hostid) {
return _.find(this._hosts, {'hostid': hostid});
};
p.getItem = function(itemid) {
return _.find(this._items, {'itemid': itemid});
};
/** /**
* Convert host.get response to cache format * Convert host.get response to cache format
* host.groups - array of group ids * host.groups - array of group ids