mysql-connector: implement getHistory for DB connector

This commit is contained in:
Alexander Zobnin
2017-07-21 19:30:53 +03:00
parent 6d89f36bb2
commit 16256f2778
12 changed files with 233 additions and 24 deletions

View File

@@ -356,9 +356,15 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
}); });
} else { } else {
// Use history // Use history
getHistoryPromise = _this2.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) { if (_this2.enableDirectDBConnection) {
return responseHandler.handleHistory(history, items); getHistoryPromise = _this2.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
}); return _this2.zabbix.dbConnector.handleHistory(history, items);
});
} else {
getHistoryPromise = _this2.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
return responseHandler.handleHistory(history, items);
});
}
} }
return getHistoryPromise; return getHistoryPromise;

File diff suppressed because one or more lines are too long

View File

@@ -67,6 +67,7 @@ System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './za
if (enableDirectDBConnection) { if (enableDirectDBConnection) {
this.dbConnector = new ZabbixDBConnector(sqlDatasourceId); this.dbConnector = new ZabbixDBConnector(sqlDatasourceId);
this.getHistory = this.dbConnector.getHistory.bind(this.dbConnector);
} }
} }

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,7 @@
System.register(['angular', 'lodash'], function (_export, _context) { System.register(['angular', 'lodash'], function (_export, _context) {
"use strict"; "use strict";
var angular, _, _createClass; var angular, _, _createClass, DEFAULT_QUERY_LIMIT, HISTORY_TO_TABLE_MAP;
function _classCallCheck(instance, Constructor) { function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) { if (!(instance instanceof Constructor)) {
@@ -15,9 +15,15 @@ System.register(['angular', 'lodash'], function (_export, _context) {
function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) { function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {
var ZabbixDBConnector = function () { var ZabbixDBConnector = function () {
function ZabbixDBConnector(sqlDataSourceId) { function ZabbixDBConnector(sqlDataSourceId) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classCallCheck(this, ZabbixDBConnector); _classCallCheck(this, ZabbixDBConnector);
var limit = options.limit;
this.sqlDataSourceId = sqlDataSourceId; this.sqlDataSourceId = sqlDataSourceId;
this.limit = limit || DEFAULT_QUERY_LIMIT;
// Try to load DS with given id to check it's exist // Try to load DS with given id to check it's exist
this.loadSQLDataSource(sqlDataSourceId); this.loadSQLDataSource(sqlDataSourceId);
@@ -35,14 +41,42 @@ System.register(['angular', 'lodash'], function (_export, _context) {
return Promise.reject('SQL Data Source with ID ' + datasourceId + ' not found'); return Promise.reject('SQL Data Source with ID ' + datasourceId + ' not found');
} }
} }
}, {
key: 'getHistory',
value: function getHistory(items, timeFrom, timeTill) {
var _this = this;
// Group items by value type and perform request for each value type
var grouped_items = _.groupBy(items, 'value_type');
var promises = _.map(grouped_items, function (items, value_type) {
var itemids = _.map(items, 'itemid').join(', ');
var table = HISTORY_TO_TABLE_MAP[value_type];
var query = '\n SELECT itemid AS metric, clock AS time_sec, ns, value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n ';
return _this.invokeSQLQuery(query);
});
return Promise.all(promises).then(function (results) {
return _.flatten(results);
});
}
}, {
key: 'handleHistory',
value: function handleHistory(history, items) {
var addHostName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
return convertHistory(history, items, addHostName);
}
}, { }, {
key: 'invokeSQLQuery', key: 'invokeSQLQuery',
value: function invokeSQLQuery(query) { value: function invokeSQLQuery(query) {
var queryDef = { var queryDef = {
refId: 'A', refId: 'A',
format: 'table', format: 'time_series',
datasourceId: this.sqlDataSourceId, datasourceId: this.sqlDataSourceId,
rawSql: query rawSql: query,
maxDataPoints: this.limit
}; };
return backendSrv.datasourceRequest({ return backendSrv.datasourceRequest({
@@ -54,7 +88,7 @@ System.register(['angular', 'lodash'], function (_export, _context) {
}).then(function (response) { }).then(function (response) {
var results = response.data.results; var results = response.data.results;
if (results['A']) { if (results['A']) {
return _.head(results['A'].tables); return results['A'].series;
} else { } else {
return null; return null;
} }
@@ -68,6 +102,28 @@ System.register(['angular', 'lodash'], function (_export, _context) {
return ZabbixDBConnector; return ZabbixDBConnector;
} }
///////////////////////////////////////////////////////////////////////////////
function convertHistory(time_series, items, addHostName) {
var hosts = _.uniqBy(_.flatten(_.map(items, 'hosts')), 'hostid'); //uniqBy is needed to deduplicate
var grafanaSeries = _.map(time_series, function (series) {
var itemid = series.name;
var datapoints = series.points;
var item = _.find(items, { 'itemid': itemid });
var alias = item.name;
if (_.keys(hosts).length > 1 && addHostName) {
//only when actual multi hosts selected
var host = _.find(hosts, { 'hostid': item.hostid });
alias = host.name + ": " + alias;
}
return {
target: alias,
datapoints: datapoints
};
});
return _.sortBy(grafanaSeries, 'target');
}
return { return {
setters: [function (_angular) { setters: [function (_angular) {
angular = _angular.default; angular = _angular.default;
@@ -93,6 +149,14 @@ System.register(['angular', 'lodash'], function (_export, _context) {
}; };
}(); }();
DEFAULT_QUERY_LIMIT = 10000;
HISTORY_TO_TABLE_MAP = {
'0': 'history',
'1': 'history_str',
'2': 'history_log',
'3': 'history_uint',
'4': 'history_text'
};
angular.module('grafana.services').factory('ZabbixDBConnector', ZabbixDBConnectorFactory); angular.module('grafana.services').factory('ZabbixDBConnector', ZabbixDBConnectorFactory);
} }
}; };

File diff suppressed because one or more lines are too long

View File

@@ -229,9 +229,15 @@ var ZabbixAPIDatasource = function () {
}); });
} else { } else {
// Use history // Use history
getHistoryPromise = _this2.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) { if (_this2.enableDirectDBConnection) {
return _responseHandler2.default.handleHistory(history, items); getHistoryPromise = _this2.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
}); return _this2.zabbix.dbConnector.handleHistory(history, items);
});
} else {
getHistoryPromise = _this2.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
return _responseHandler2.default.handleHistory(history, items);
});
}
} }
return getHistoryPromise; return getHistoryPromise;

View File

@@ -72,6 +72,7 @@ function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy, ZabbixDBConnector)
if (enableDirectDBConnection) { if (enableDirectDBConnection) {
this.dbConnector = new ZabbixDBConnector(sqlDatasourceId); this.dbConnector = new ZabbixDBConnector(sqlDatasourceId);
this.getHistory = this.dbConnector.getHistory.bind(this.dbConnector);
} }
} }

View File

@@ -14,13 +14,28 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var DEFAULT_QUERY_LIMIT = 10000;
var HISTORY_TO_TABLE_MAP = {
'0': 'history',
'1': 'history_str',
'2': 'history_log',
'3': 'history_uint',
'4': 'history_text'
};
/** @ngInject */ /** @ngInject */
function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) { function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {
var ZabbixDBConnector = function () { var ZabbixDBConnector = function () {
function ZabbixDBConnector(sqlDataSourceId) { function ZabbixDBConnector(sqlDataSourceId) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classCallCheck(this, ZabbixDBConnector); _classCallCheck(this, ZabbixDBConnector);
var limit = options.limit;
this.sqlDataSourceId = sqlDataSourceId; this.sqlDataSourceId = sqlDataSourceId;
this.limit = limit || DEFAULT_QUERY_LIMIT;
// Try to load DS with given id to check it's exist // Try to load DS with given id to check it's exist
this.loadSQLDataSource(sqlDataSourceId); this.loadSQLDataSource(sqlDataSourceId);
@@ -38,14 +53,42 @@ function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {
return Promise.reject('SQL Data Source with ID ' + datasourceId + ' not found'); return Promise.reject('SQL Data Source with ID ' + datasourceId + ' not found');
} }
} }
}, {
key: 'getHistory',
value: function getHistory(items, timeFrom, timeTill) {
var _this = this;
// Group items by value type and perform request for each value type
var grouped_items = _lodash2.default.groupBy(items, 'value_type');
var promises = _lodash2.default.map(grouped_items, function (items, value_type) {
var itemids = _lodash2.default.map(items, 'itemid').join(', ');
var table = HISTORY_TO_TABLE_MAP[value_type];
var query = '\n SELECT itemid AS metric, clock AS time_sec, ns, value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n ';
return _this.invokeSQLQuery(query);
});
return Promise.all(promises).then(function (results) {
return _lodash2.default.flatten(results);
});
}
}, {
key: 'handleHistory',
value: function handleHistory(history, items) {
var addHostName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
return convertHistory(history, items, addHostName);
}
}, { }, {
key: 'invokeSQLQuery', key: 'invokeSQLQuery',
value: function invokeSQLQuery(query) { value: function invokeSQLQuery(query) {
var queryDef = { var queryDef = {
refId: 'A', refId: 'A',
format: 'table', format: 'time_series',
datasourceId: this.sqlDataSourceId, datasourceId: this.sqlDataSourceId,
rawSql: query rawSql: query,
maxDataPoints: this.limit
}; };
return backendSrv.datasourceRequest({ return backendSrv.datasourceRequest({
@@ -57,7 +100,7 @@ function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {
}).then(function (response) { }).then(function (response) {
var results = response.data.results; var results = response.data.results;
if (results['A']) { if (results['A']) {
return _lodash2.default.head(results['A'].tables); return results['A'].series;
} else { } else {
return null; return null;
} }
@@ -72,3 +115,26 @@ function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {
} }
_angular2.default.module('grafana.services').factory('ZabbixDBConnector', ZabbixDBConnectorFactory); _angular2.default.module('grafana.services').factory('ZabbixDBConnector', ZabbixDBConnectorFactory);
///////////////////////////////////////////////////////////////////////////////
function convertHistory(time_series, items, addHostName) {
var hosts = _lodash2.default.uniqBy(_lodash2.default.flatten(_lodash2.default.map(items, 'hosts')), 'hostid'); //uniqBy is needed to deduplicate
var grafanaSeries = _lodash2.default.map(time_series, function (series) {
var itemid = series.name;
var datapoints = series.points;
var item = _lodash2.default.find(items, { 'itemid': itemid });
var alias = item.name;
if (_lodash2.default.keys(hosts).length > 1 && addHostName) {
//only when actual multi hosts selected
var host = _lodash2.default.find(hosts, { 'hostid': item.hostid });
alias = host.name + ": " + alias;
}
return {
target: alias,
datapoints: datapoints
};
});
return _lodash2.default.sortBy(grafanaSeries, 'target');
}

View File

@@ -172,10 +172,13 @@ class ZabbixAPIDatasource {
}); });
} else { } else {
// Use history // Use history
getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo) if (this.enableDirectDBConnection) {
.then(history => { getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo)
return responseHandler.handleHistory(history, items); .then(history => this.zabbix.dbConnector.handleHistory(history, items));
}); } else {
getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo)
.then(history => responseHandler.handleHistory(history, items));
}
} }
return getHistoryPromise; return getHistoryPromise;

View File

@@ -44,6 +44,7 @@ function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy, ZabbixDBConnector)
if (enableDirectDBConnection) { if (enableDirectDBConnection) {
this.dbConnector = new ZabbixDBConnector(sqlDatasourceId); this.dbConnector = new ZabbixDBConnector(sqlDatasourceId);
this.getHistory = this.dbConnector.getHistory.bind(this.dbConnector);
} }
} }

View File

@@ -1,13 +1,25 @@
import angular from 'angular'; import angular from 'angular';
import _ from 'lodash'; import _ from 'lodash';
const DEFAULT_QUERY_LIMIT = 10000;
const HISTORY_TO_TABLE_MAP = {
'0': 'history',
'1': 'history_str',
'2': 'history_log',
'3': 'history_uint',
'4': 'history_text'
};
/** @ngInject */ /** @ngInject */
function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) { function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {
class ZabbixDBConnector { class ZabbixDBConnector {
constructor(sqlDataSourceId) { constructor(sqlDataSourceId, options = {}) {
let {limit} = options;
this.sqlDataSourceId = sqlDataSourceId; this.sqlDataSourceId = sqlDataSourceId;
this.limit = limit || DEFAULT_QUERY_LIMIT;
// Try to load DS with given id to check it's exist // Try to load DS with given id to check it's exist
this.loadSQLDataSource(sqlDataSourceId); this.loadSQLDataSource(sqlDataSourceId);
@@ -25,12 +37,39 @@ function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {
} }
} }
getHistory(items, timeFrom, timeTill) {
// Group items by value type and perform request for each value type
let grouped_items = _.groupBy(items, 'value_type');
let promises = _.map(grouped_items, (items, value_type) => {
let itemids = _.map(items, 'itemid').join(', ');
let table = HISTORY_TO_TABLE_MAP[value_type];
let query = `
SELECT itemid AS metric, clock AS time_sec, ns, value
FROM ${table}
WHERE itemid IN (${itemids})
AND clock > ${timeFrom} AND clock < ${timeTill}
`;
return this.invokeSQLQuery(query);
});
return Promise.all(promises).then(results => {
return _.flatten(results);
});
}
handleHistory(history, items, addHostName = true) {
return convertHistory(history, items, addHostName);
}
invokeSQLQuery(query) { invokeSQLQuery(query) {
let queryDef = { let queryDef = {
refId: 'A', refId: 'A',
format: 'table', format: 'time_series',
datasourceId: this.sqlDataSourceId, datasourceId: this.sqlDataSourceId,
rawSql: query rawSql: query,
maxDataPoints: this.limit
}; };
return backendSrv.datasourceRequest({ return backendSrv.datasourceRequest({
@@ -43,7 +82,7 @@ function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {
.then(response => { .then(response => {
let results = response.data.results; let results = response.data.results;
if (results['A']) { if (results['A']) {
return _.head(results['A'].tables); return results['A'].series;
} else { } else {
return null; return null;
} }
@@ -57,3 +96,25 @@ function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {
angular angular
.module('grafana.services') .module('grafana.services')
.factory('ZabbixDBConnector', ZabbixDBConnectorFactory); .factory('ZabbixDBConnector', ZabbixDBConnectorFactory);
///////////////////////////////////////////////////////////////////////////////
function convertHistory(time_series, items, addHostName) {
var hosts = _.uniqBy(_.flatten(_.map(items, 'hosts')), 'hostid'); //uniqBy is needed to deduplicate
let grafanaSeries = _.map(time_series, series => {
let itemid = series.name;
let datapoints = series.points;
var item = _.find(items, {'itemid': itemid});
var alias = item.name;
if (_.keys(hosts).length > 1 && addHostName) { //only when actual multi hosts selected
var host = _.find(hosts, {'hostid': item.hostid});
alias = host.name + ": " + alias;
}
return {
target: alias,
datapoints: datapoints
};
});
return _.sortBy(grafanaSeries, 'target');
}