diff --git a/dist/datasource-zabbix/zabbixDBConnector.js b/dist/datasource-zabbix/zabbixDBConnector.js index 0ce7b49..e8ed627 100644 --- a/dist/datasource-zabbix/zabbixDBConnector.js +++ b/dist/datasource-zabbix/zabbixDBConnector.js @@ -69,7 +69,8 @@ System.register(['angular', 'lodash'], function (_export, _context) { 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, ' + aggFunction + '(value) AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY time_sec DIV ' + intervalSec + ', metric\n '; + var time_expression = 'clock DIV ' + intervalSec + ' * ' + intervalSec; + var query = '\n SELECT itemid AS metric, ' + time_expression + ' AS time_sec, ' + aggFunction + '(value) AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY ' + time_expression + ', metric\n '; query = compactSQLQuery(query); return _this.invokeSQLQuery(query); @@ -100,7 +101,8 @@ System.register(['angular', 'lodash'], function (_export, _context) { var valueColumn = _.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg'; valueColumn = consolidateByTrendColumns[valueColumn]; - var query = '\n SELECT itemid AS metric, clock AS time_sec, ' + aggFunction + '(' + valueColumn + ') AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY time_sec DIV ' + intervalSec + ', metric\n '; + var time_expression = 'clock DIV ' + intervalSec + ' * ' + intervalSec; + var query = '\n SELECT itemid AS metric, ' + time_expression + ' AS time_sec, ' + aggFunction + '(' + valueColumn + ') AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY ' + time_expression + ', metric\n '; query = compactSQLQuery(query); return _this2.invokeSQLQuery(query); diff --git a/dist/datasource-zabbix/zabbixDBConnector.js.map b/dist/datasource-zabbix/zabbixDBConnector.js.map index 1f1db02..59d13cf 100644 --- a/dist/datasource-zabbix/zabbixDBConnector.js.map +++ b/dist/datasource-zabbix/zabbixDBConnector.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/datasource-zabbix/zabbixDBConnector.js"],"names":["ZabbixDBConnectorFactory","datasourceSrv","backendSrv","ZabbixDBConnector","sqlDataSourceId","options","limit","DEFAULT_QUERY_LIMIT","datasourceId","ds","_","find","getAll","loadDatasource","name","then","console","log","Promise","reject","testQuery","invokeSQLQuery","items","timeFrom","timeTill","intervalMs","consolidateBy","intervalSec","Math","ceil","aggFunction","consolidateByFunc","grouped_items","groupBy","promises","map","value_type","itemids","join","table","HISTORY_TO_TABLE_MAP","query","compactSQLQuery","all","flatten","results","TREND_TO_TABLE_MAP","valueColumn","includes","consolidateByTrendColumns","history","addHostName","convertGrafanaTSResponse","queryDef","refId","format","rawSql","maxDataPoints","datasourceRequest","url","method","data","queries","response","series","time_series","hosts","uniqBy","grafanaSeries","itemid","item","alias","keys","length","host","hostid","datapoints","cloneDeep","points","target","sortBy","replace","angular","module","factory"],"mappings":"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","file":"zabbixDBConnector.js","sourcesContent":["import angular from 'angular';\nimport _ from 'lodash';\n\nconst DEFAULT_QUERY_LIMIT = 10000;\nconst HISTORY_TO_TABLE_MAP = {\n '0': 'history',\n '1': 'history_str',\n '2': 'history_log',\n '3': 'history_uint',\n '4': 'history_text'\n};\n\nconst TREND_TO_TABLE_MAP = {\n '0': 'trends',\n '3': 'trends_uint'\n};\n\nconst consolidateByFunc = {\n 'avg': 'AVG',\n 'min': 'MIN',\n 'max': 'MAX',\n 'sum': 'SUM',\n 'count': 'COUNT'\n};\n\nconst consolidateByTrendColumns = {\n 'avg': 'value_avg',\n 'min': 'value_min',\n 'max': 'value_max'\n};\n\n/** @ngInject */\nfunction ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {\n\n class ZabbixDBConnector {\n\n constructor(sqlDataSourceId, options = {}) {\n let {limit} = options;\n\n this.sqlDataSourceId = sqlDataSourceId;\n this.limit = limit || DEFAULT_QUERY_LIMIT;\n }\n\n /**\n * Try to load DS with given id to check it's exist.\n * @param {*} datasourceId ID of SQL data source\n */\n loadSQLDataSource(datasourceId) {\n let ds = _.find(datasourceSrv.getAll(), {'id': datasourceId});\n if (ds) {\n return datasourceSrv.loadDatasource(ds.name)\n .then(ds => {\n console.log('SQL data source loaded', ds);\n });\n } else {\n return Promise.reject(`SQL Data Source with ID ${datasourceId} not found`);\n }\n }\n\n /**\n * Try to invoke test query for one of Zabbix database tables.\n */\n testSQLDataSource() {\n let testQuery = `SELECT itemid AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1`;\n return this.invokeSQLQuery(testQuery);\n }\n\n getHistory(items, timeFrom, timeTill, options) {\n let {intervalMs, consolidateBy} = options;\n let intervalSec = Math.ceil(intervalMs / 1000);\n\n consolidateBy = consolidateBy || 'avg';\n let aggFunction = consolidateByFunc[consolidateBy];\n\n // Group items by value type and perform request for each value type\n let grouped_items = _.groupBy(items, 'value_type');\n let promises = _.map(grouped_items, (items, value_type) => {\n let itemids = _.map(items, 'itemid').join(', ');\n let table = HISTORY_TO_TABLE_MAP[value_type];\n\n let query = `\n SELECT itemid AS metric, clock AS time_sec, ${aggFunction}(value) AS value\n FROM ${table}\n WHERE itemid IN (${itemids})\n AND clock > ${timeFrom} AND clock < ${timeTill}\n GROUP BY time_sec DIV ${intervalSec}, metric\n `;\n\n query = compactSQLQuery(query);\n return this.invokeSQLQuery(query);\n });\n\n return Promise.all(promises).then(results => {\n return _.flatten(results);\n });\n }\n\n getTrends(items, timeFrom, timeTill, options) {\n let {intervalMs, consolidateBy} = options;\n let intervalSec = Math.ceil(intervalMs / 1000);\n\n consolidateBy = consolidateBy || 'avg';\n let aggFunction = consolidateByFunc[consolidateBy];\n\n // Group items by value type and perform request for each value type\n let grouped_items = _.groupBy(items, 'value_type');\n let promises = _.map(grouped_items, (items, value_type) => {\n let itemids = _.map(items, 'itemid').join(', ');\n let table = TREND_TO_TABLE_MAP[value_type];\n let valueColumn = _.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg';\n valueColumn = consolidateByTrendColumns[valueColumn];\n\n let query = `\n SELECT itemid AS metric, clock AS time_sec, ${aggFunction}(${valueColumn}) AS value\n FROM ${table}\n WHERE itemid IN (${itemids})\n AND clock > ${timeFrom} AND clock < ${timeTill}\n GROUP BY time_sec DIV ${intervalSec}, metric\n `;\n\n query = compactSQLQuery(query);\n return this.invokeSQLQuery(query);\n });\n\n return Promise.all(promises).then(results => {\n return _.flatten(results);\n });\n }\n\n handleGrafanaTSResponse(history, items, addHostName = true) {\n return convertGrafanaTSResponse(history, items, addHostName);\n }\n\n invokeSQLQuery(query) {\n let queryDef = {\n refId: 'A',\n format: 'time_series',\n datasourceId: this.sqlDataSourceId,\n rawSql: query,\n maxDataPoints: this.limit\n };\n\n return backendSrv.datasourceRequest({\n url: '/api/tsdb/query',\n method: 'POST',\n data: {\n queries: [queryDef],\n }\n })\n .then(response => {\n let results = response.data.results;\n if (results['A']) {\n return results['A'].series;\n } else {\n return null;\n }\n });\n }\n }\n\n return ZabbixDBConnector;\n}\n\nangular\n .module('grafana.services')\n .factory('ZabbixDBConnector', ZabbixDBConnectorFactory);\n\n///////////////////////////////////////////////////////////////////////////////\n\nfunction convertGrafanaTSResponse(time_series, items, addHostName) {\n var hosts = _.uniqBy(_.flatten(_.map(items, 'hosts')), 'hostid'); //uniqBy is needed to deduplicate\n let grafanaSeries = _.map(time_series, series => {\n let itemid = series.name;\n var item = _.find(items, {'itemid': itemid});\n var alias = item.name;\n if (_.keys(hosts).length > 1 && addHostName) { //only when actual multi hosts selected\n var host = _.find(hosts, {'hostid': item.hostid});\n alias = host.name + \": \" + alias;\n }\n // zabbixCachingProxy deduplicates requests and returns one time series for equal queries.\n // Clone is needed to prevent changing of series object shared between all targets.\n let datapoints = _.cloneDeep(series.points);\n return {\n target: alias,\n datapoints: datapoints\n };\n });\n\n return _.sortBy(grafanaSeries, 'target');\n}\n\nfunction compactSQLQuery(query) {\n return query.replace(/\\s+/g, ' ');\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/datasource-zabbix/zabbixDBConnector.js"],"names":["ZabbixDBConnectorFactory","datasourceSrv","backendSrv","ZabbixDBConnector","sqlDataSourceId","options","limit","DEFAULT_QUERY_LIMIT","datasourceId","ds","_","find","getAll","loadDatasource","name","then","console","log","Promise","reject","testQuery","invokeSQLQuery","items","timeFrom","timeTill","intervalMs","consolidateBy","intervalSec","Math","ceil","aggFunction","consolidateByFunc","grouped_items","groupBy","promises","map","value_type","itemids","join","table","HISTORY_TO_TABLE_MAP","time_expression","query","compactSQLQuery","all","flatten","results","TREND_TO_TABLE_MAP","valueColumn","includes","consolidateByTrendColumns","history","addHostName","convertGrafanaTSResponse","queryDef","refId","format","rawSql","maxDataPoints","datasourceRequest","url","method","data","queries","response","series","time_series","hosts","uniqBy","grafanaSeries","itemid","item","alias","keys","length","host","hostid","datapoints","cloneDeep","points","target","sortBy","replace","angular","module","factory"],"mappings":"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","file":"zabbixDBConnector.js","sourcesContent":["import angular from 'angular';\nimport _ from 'lodash';\n\nconst DEFAULT_QUERY_LIMIT = 10000;\nconst HISTORY_TO_TABLE_MAP = {\n '0': 'history',\n '1': 'history_str',\n '2': 'history_log',\n '3': 'history_uint',\n '4': 'history_text'\n};\n\nconst TREND_TO_TABLE_MAP = {\n '0': 'trends',\n '3': 'trends_uint'\n};\n\nconst consolidateByFunc = {\n 'avg': 'AVG',\n 'min': 'MIN',\n 'max': 'MAX',\n 'sum': 'SUM',\n 'count': 'COUNT'\n};\n\nconst consolidateByTrendColumns = {\n 'avg': 'value_avg',\n 'min': 'value_min',\n 'max': 'value_max'\n};\n\n/** @ngInject */\nfunction ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {\n\n class ZabbixDBConnector {\n\n constructor(sqlDataSourceId, options = {}) {\n let {limit} = options;\n\n this.sqlDataSourceId = sqlDataSourceId;\n this.limit = limit || DEFAULT_QUERY_LIMIT;\n }\n\n /**\n * Try to load DS with given id to check it's exist.\n * @param {*} datasourceId ID of SQL data source\n */\n loadSQLDataSource(datasourceId) {\n let ds = _.find(datasourceSrv.getAll(), {'id': datasourceId});\n if (ds) {\n return datasourceSrv.loadDatasource(ds.name)\n .then(ds => {\n console.log('SQL data source loaded', ds);\n });\n } else {\n return Promise.reject(`SQL Data Source with ID ${datasourceId} not found`);\n }\n }\n\n /**\n * Try to invoke test query for one of Zabbix database tables.\n */\n testSQLDataSource() {\n let testQuery = `SELECT itemid AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1`;\n return this.invokeSQLQuery(testQuery);\n }\n\n getHistory(items, timeFrom, timeTill, options) {\n let {intervalMs, consolidateBy} = options;\n let intervalSec = Math.ceil(intervalMs / 1000);\n\n consolidateBy = consolidateBy || 'avg';\n let aggFunction = consolidateByFunc[consolidateBy];\n\n // Group items by value type and perform request for each value type\n let grouped_items = _.groupBy(items, 'value_type');\n let promises = _.map(grouped_items, (items, value_type) => {\n let itemids = _.map(items, 'itemid').join(', ');\n let table = HISTORY_TO_TABLE_MAP[value_type];\n\n let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`;\n let query = `\n SELECT itemid AS metric, ${time_expression} AS time_sec, ${aggFunction}(value) AS value\n FROM ${table}\n WHERE itemid IN (${itemids})\n AND clock > ${timeFrom} AND clock < ${timeTill}\n GROUP BY ${time_expression}, metric\n `;\n\n query = compactSQLQuery(query);\n return this.invokeSQLQuery(query);\n });\n\n return Promise.all(promises).then(results => {\n return _.flatten(results);\n });\n }\n\n getTrends(items, timeFrom, timeTill, options) {\n let {intervalMs, consolidateBy} = options;\n let intervalSec = Math.ceil(intervalMs / 1000);\n\n consolidateBy = consolidateBy || 'avg';\n let aggFunction = consolidateByFunc[consolidateBy];\n\n // Group items by value type and perform request for each value type\n let grouped_items = _.groupBy(items, 'value_type');\n let promises = _.map(grouped_items, (items, value_type) => {\n let itemids = _.map(items, 'itemid').join(', ');\n let table = TREND_TO_TABLE_MAP[value_type];\n let valueColumn = _.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg';\n valueColumn = consolidateByTrendColumns[valueColumn];\n\n let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`;\n let query = `\n SELECT itemid AS metric, ${time_expression} AS time_sec, ${aggFunction}(${valueColumn}) AS value\n FROM ${table}\n WHERE itemid IN (${itemids})\n AND clock > ${timeFrom} AND clock < ${timeTill}\n GROUP BY ${time_expression}, metric\n `;\n\n query = compactSQLQuery(query);\n return this.invokeSQLQuery(query);\n });\n\n return Promise.all(promises).then(results => {\n return _.flatten(results);\n });\n }\n\n handleGrafanaTSResponse(history, items, addHostName = true) {\n return convertGrafanaTSResponse(history, items, addHostName);\n }\n\n invokeSQLQuery(query) {\n let queryDef = {\n refId: 'A',\n format: 'time_series',\n datasourceId: this.sqlDataSourceId,\n rawSql: query,\n maxDataPoints: this.limit\n };\n\n return backendSrv.datasourceRequest({\n url: '/api/tsdb/query',\n method: 'POST',\n data: {\n queries: [queryDef],\n }\n })\n .then(response => {\n let results = response.data.results;\n if (results['A']) {\n return results['A'].series;\n } else {\n return null;\n }\n });\n }\n }\n\n return ZabbixDBConnector;\n}\n\nangular\n .module('grafana.services')\n .factory('ZabbixDBConnector', ZabbixDBConnectorFactory);\n\n///////////////////////////////////////////////////////////////////////////////\n\nfunction convertGrafanaTSResponse(time_series, items, addHostName) {\n var hosts = _.uniqBy(_.flatten(_.map(items, 'hosts')), 'hostid'); //uniqBy is needed to deduplicate\n let grafanaSeries = _.map(time_series, series => {\n let itemid = series.name;\n var item = _.find(items, {'itemid': itemid});\n var alias = item.name;\n if (_.keys(hosts).length > 1 && addHostName) { //only when actual multi hosts selected\n var host = _.find(hosts, {'hostid': item.hostid});\n alias = host.name + \": \" + alias;\n }\n // zabbixCachingProxy deduplicates requests and returns one time series for equal queries.\n // Clone is needed to prevent changing of series object shared between all targets.\n let datapoints = _.cloneDeep(series.points);\n return {\n target: alias,\n datapoints: datapoints\n };\n });\n\n return _.sortBy(grafanaSeries, 'target');\n}\n\nfunction compactSQLQuery(query) {\n return query.replace(/\\s+/g, ' ');\n}\n"]} \ No newline at end of file diff --git a/dist/test/datasource-zabbix/zabbixDBConnector.js b/dist/test/datasource-zabbix/zabbixDBConnector.js index e684201..285a2d1 100644 --- a/dist/test/datasource-zabbix/zabbixDBConnector.js +++ b/dist/test/datasource-zabbix/zabbixDBConnector.js @@ -105,7 +105,8 @@ function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) { 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, ' + aggFunction + '(value) AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY time_sec DIV ' + intervalSec + ', metric\n '; + var time_expression = 'clock DIV ' + intervalSec + ' * ' + intervalSec; + var query = '\n SELECT itemid AS metric, ' + time_expression + ' AS time_sec, ' + aggFunction + '(value) AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY ' + time_expression + ', metric\n '; query = compactSQLQuery(query); return _this.invokeSQLQuery(query); @@ -136,7 +137,8 @@ function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) { var valueColumn = _lodash2.default.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg'; valueColumn = consolidateByTrendColumns[valueColumn]; - var query = '\n SELECT itemid AS metric, clock AS time_sec, ' + aggFunction + '(' + valueColumn + ') AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY time_sec DIV ' + intervalSec + ', metric\n '; + var time_expression = 'clock DIV ' + intervalSec + ' * ' + intervalSec; + var query = '\n SELECT itemid AS metric, ' + time_expression + ' AS time_sec, ' + aggFunction + '(' + valueColumn + ') AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY ' + time_expression + ', metric\n '; query = compactSQLQuery(query); return _this2.invokeSQLQuery(query); diff --git a/src/datasource-zabbix/zabbixDBConnector.js b/src/datasource-zabbix/zabbixDBConnector.js index a3ec58e..84f6c60 100644 --- a/src/datasource-zabbix/zabbixDBConnector.js +++ b/src/datasource-zabbix/zabbixDBConnector.js @@ -78,12 +78,13 @@ function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) { let itemids = _.map(items, 'itemid').join(', '); let table = HISTORY_TO_TABLE_MAP[value_type]; + let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`; let query = ` - SELECT itemid AS metric, clock AS time_sec, ${aggFunction}(value) AS value + SELECT itemid AS metric, ${time_expression} AS time_sec, ${aggFunction}(value) AS value FROM ${table} WHERE itemid IN (${itemids}) AND clock > ${timeFrom} AND clock < ${timeTill} - GROUP BY time_sec DIV ${intervalSec}, metric + GROUP BY ${time_expression}, metric `; query = compactSQLQuery(query); @@ -110,12 +111,13 @@ function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) { let valueColumn = _.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg'; valueColumn = consolidateByTrendColumns[valueColumn]; + let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`; let query = ` - SELECT itemid AS metric, clock AS time_sec, ${aggFunction}(${valueColumn}) AS value + SELECT itemid AS metric, ${time_expression} AS time_sec, ${aggFunction}(${valueColumn}) AS value FROM ${table} WHERE itemid IN (${itemids}) AND clock > ${timeFrom} AND clock < ${timeTill} - GROUP BY time_sec DIV ${intervalSec}, metric + GROUP BY ${time_expression}, metric `; query = compactSQLQuery(query);