Merge branch 'refactor'
This commit is contained in:
@@ -85,7 +85,7 @@ module.exports = function(grunt) {
|
|||||||
cwd: 'src',
|
cwd: 'src',
|
||||||
expand: true,
|
expand: true,
|
||||||
src: [
|
src: [
|
||||||
'datasource-zabbix/*.js',
|
'datasource-zabbix/**/*.js',
|
||||||
'panel-triggers/*.js',
|
'panel-triggers/*.js',
|
||||||
'components/*.js',
|
'components/*.js',
|
||||||
'vendor/*.js',
|
'vendor/*.js',
|
||||||
@@ -172,9 +172,7 @@ module.exports = function(grunt) {
|
|||||||
grunt.registerTask('watchTask', [
|
grunt.registerTask('watchTask', [
|
||||||
'clean:dist',
|
'clean:dist',
|
||||||
'sass',
|
'sass',
|
||||||
'copy:vendor_to_dist',
|
'copy',
|
||||||
'copy:src_to_dist',
|
|
||||||
'copy:pluginDef',
|
|
||||||
'babel:dist',
|
'babel:dist',
|
||||||
'jshint',
|
'jshint',
|
||||||
'jscs'
|
'jscs'
|
||||||
|
|||||||
@@ -1,70 +1,77 @@
|
|||||||
import _ from 'lodash';
|
'use strict';
|
||||||
import ts from '../timeseries';
|
|
||||||
|
|
||||||
let datapoints = [[10.7104, 1498409636085], [10.578, 1498409651011], [10.5985, 1498409666628], [10.6877, 1498409681525], [10.5495, 1498409696586], [10.5981, 1498409711009], [10.5076, 1498409726949], [11.4807, 1498409741853], [11.6165, 1498409756165], [11.8575, 1498409771018], [11.9936, 1498409786056], [10.7566, 1498409801942], [10.7484, 1498409816010], [10.6038, 1498409831018], [10.2932, 1498409846010], [10.4912, 1498409861946], [10.4151, 1498409876871], [10.2401, 1498409891710], [10.4921, 1498409906143], [10.4413, 1498409921477], [10.6318, 1498409936147], [10.5277, 1498409951915], [10.6333, 1498409966052], [10.6417, 1498409981944], [10.4505, 1498409996867], [10.5812, 1498410011770], [10.4934, 1498410026573], [10.5731, 1498410041317], [10.5, 1498410056213], [10.6505, 1498410071013], [9.4035, 1498410086387]];
|
System.register(['lodash', '../timeseries'], function (_export, _context) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
let series_set = [
|
var _, ts, datapoints, series_set, growing_series;
|
||||||
[[1.0247, 1498409631773], [0.9988, 1498409646697], [0.9817, 1498409661239], [0.9569, 1498409676045], [1.0331, 1498409691922], [1.0755, 1498409706546], [1.1862, 1498409721525], [1.2984, 1498409736175], [1.2389, 1498409751817], [1.1452, 1498409766783], [1.102, 1498409781699], [0.9647, 1498409796664], [1.0063, 1498409811627], [1.0318, 1498409826887], [1.065, 1498409841645], [1.0907, 1498409856647], [1.0229, 1498409871521], [1.0654, 1498409886031], [1.0568, 1498409901544], [1.0818, 1498409916194], [1.1335, 1498409931672], [1.057, 1498409946673], [1.0243, 1498409961669], [1.0329, 1498409976637], [1.1428, 1498409991563], [1.2198, 1498410006441], [1.2192, 1498410021230], [1.2615, 1498410036027], [1.1765, 1498410051907], [1.2352, 1498410066109], [1.0557, 1498410081043]],
|
|
||||||
[[10.7104, 1498409636085], [10.578, 1498409651011], [10.5985, 1498409666628], [10.6877, 1498409681525], [10.5495, 1498409696586], [10.5981, 1498409711009], [10.5076, 1498409726949], [11.4807, 1498409741853], [11.6165, 1498409756165], [11.8575, 1498409771018], [11.9936, 1498409786056], [10.7566, 1498409801942], [10.7484, 1498409816010], [10.6038, 1498409831018], [10.2932, 1498409846010], [10.4912, 1498409861946], [10.4151, 1498409876871], [10.2401, 1498409891710], [10.4921, 1498409906143], [10.4413, 1498409921477], [10.6318, 1498409936147], [10.5277, 1498409951915], [10.6333, 1498409966052], [10.6417, 1498409981944], [10.4505, 1498409996867], [10.5812, 1498410011770], [10.4934, 1498410026573], [10.5731, 1498410041317], [10.5, 1498410056213], [10.6505, 1498410071013], [9.4035, 1498410086387]]
|
|
||||||
];
|
|
||||||
|
|
||||||
let growing_series = [[10755200, 1498332216642], [10761200, 1498332276802], [10767200, 1498332336367], [10773200, 1498332396584], [10779200, 1498332456880], [10785200, 1498332516479], [10791200, 1498332576610], [10797200, 1498332636353], [10803200, 1498332696513], [10809200, 1498332756884], [10815200, 1498332816890], [10821200, 1498332876305], [10827200, 1498332936384], [10833200, 1498332996659], [10839200, 1498333056965], [10845200, 1498333116748], [10851200, 1498333176687], [10857200, 1498333236646], [10863200, 1498333297034], [10869200, 1498333356358], [10875200, 1498333416445], [4800, 1498333536686], [17900, 1498333667962], [24000, 1498333729157], [29500, 1498333783662], [34800, 1498333836813], [40700, 1498333896403], [46800, 1498333956953], [52800, 1498334016976], [6000, 1498334136593], [12000, 1498334196567]];
|
return {
|
||||||
|
setters: [function (_lodash) {
|
||||||
|
_ = _lodash.default;
|
||||||
|
}, function (_timeseries) {
|
||||||
|
ts = _timeseries.default;
|
||||||
|
}],
|
||||||
|
execute: function () {
|
||||||
|
datapoints = [[10.7104, 1498409636085], [10.578, 1498409651011], [10.5985, 1498409666628], [10.6877, 1498409681525], [10.5495, 1498409696586], [10.5981, 1498409711009], [10.5076, 1498409726949], [11.4807, 1498409741853], [11.6165, 1498409756165], [11.8575, 1498409771018], [11.9936, 1498409786056], [10.7566, 1498409801942], [10.7484, 1498409816010], [10.6038, 1498409831018], [10.2932, 1498409846010], [10.4912, 1498409861946], [10.4151, 1498409876871], [10.2401, 1498409891710], [10.4921, 1498409906143], [10.4413, 1498409921477], [10.6318, 1498409936147], [10.5277, 1498409951915], [10.6333, 1498409966052], [10.6417, 1498409981944], [10.4505, 1498409996867], [10.5812, 1498410011770], [10.4934, 1498410026573], [10.5731, 1498410041317], [10.5, 1498410056213], [10.6505, 1498410071013], [9.4035, 1498410086387]];
|
||||||
|
series_set = [[[1.0247, 1498409631773], [0.9988, 1498409646697], [0.9817, 1498409661239], [0.9569, 1498409676045], [1.0331, 1498409691922], [1.0755, 1498409706546], [1.1862, 1498409721525], [1.2984, 1498409736175], [1.2389, 1498409751817], [1.1452, 1498409766783], [1.102, 1498409781699], [0.9647, 1498409796664], [1.0063, 1498409811627], [1.0318, 1498409826887], [1.065, 1498409841645], [1.0907, 1498409856647], [1.0229, 1498409871521], [1.0654, 1498409886031], [1.0568, 1498409901544], [1.0818, 1498409916194], [1.1335, 1498409931672], [1.057, 1498409946673], [1.0243, 1498409961669], [1.0329, 1498409976637], [1.1428, 1498409991563], [1.2198, 1498410006441], [1.2192, 1498410021230], [1.2615, 1498410036027], [1.1765, 1498410051907], [1.2352, 1498410066109], [1.0557, 1498410081043]], [[10.7104, 1498409636085], [10.578, 1498409651011], [10.5985, 1498409666628], [10.6877, 1498409681525], [10.5495, 1498409696586], [10.5981, 1498409711009], [10.5076, 1498409726949], [11.4807, 1498409741853], [11.6165, 1498409756165], [11.8575, 1498409771018], [11.9936, 1498409786056], [10.7566, 1498409801942], [10.7484, 1498409816010], [10.6038, 1498409831018], [10.2932, 1498409846010], [10.4912, 1498409861946], [10.4151, 1498409876871], [10.2401, 1498409891710], [10.4921, 1498409906143], [10.4413, 1498409921477], [10.6318, 1498409936147], [10.5277, 1498409951915], [10.6333, 1498409966052], [10.6417, 1498409981944], [10.4505, 1498409996867], [10.5812, 1498410011770], [10.4934, 1498410026573], [10.5731, 1498410041317], [10.5, 1498410056213], [10.6505, 1498410071013], [9.4035, 1498410086387]]];
|
||||||
|
growing_series = [[10755200, 1498332216642], [10761200, 1498332276802], [10767200, 1498332336367], [10773200, 1498332396584], [10779200, 1498332456880], [10785200, 1498332516479], [10791200, 1498332576610], [10797200, 1498332636353], [10803200, 1498332696513], [10809200, 1498332756884], [10815200, 1498332816890], [10821200, 1498332876305], [10827200, 1498332936384], [10833200, 1498332996659], [10839200, 1498333056965], [10845200, 1498333116748], [10851200, 1498333176687], [10857200, 1498333236646], [10863200, 1498333297034], [10869200, 1498333356358], [10875200, 1498333416445], [4800, 1498333536686], [17900, 1498333667962], [24000, 1498333729157], [29500, 1498333783662], [34800, 1498333836813], [40700, 1498333896403], [46800, 1498333956953], [52800, 1498334016976], [6000, 1498334136593], [12000, 1498334196567]];
|
||||||
|
|
||||||
module.exports = [
|
|
||||||
{
|
module.exports = [{
|
||||||
name: 'groupBy',
|
name: 'groupBy',
|
||||||
tests: {
|
tests: {
|
||||||
'groupBy(AVERAGE)': () => {
|
'groupBy(AVERAGE)': function groupByAVERAGE() {
|
||||||
ts.groupBy(datapoints, '5m', ts.AVERAGE);
|
ts.groupBy(datapoints, '5m', ts.AVERAGE);
|
||||||
},
|
},
|
||||||
'groupBy(MAX)': () => {
|
'groupBy(MAX)': function groupByMAX() {
|
||||||
ts.groupBy(datapoints, '5m', ts.COUNT);
|
ts.groupBy(datapoints, '5m', ts.COUNT);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
name: 'sumSeries',
|
||||||
|
tests: {
|
||||||
|
'sumSeries()': function sumSeries() {
|
||||||
|
ts.sumSeries(series_set);
|
||||||
|
},
|
||||||
|
'groupBy(MAX)->sumSeries()': function groupByMAXSumSeries() {
|
||||||
|
var prepeared_series = _.map(series_set, function (datapoints) {
|
||||||
|
return ts.groupBy(datapoints, '5m', ts.MAX);
|
||||||
|
});
|
||||||
|
ts.sumSeries(prepeared_series);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
name: 'delta vs rate',
|
||||||
|
tests: {
|
||||||
|
'delta()': function delta() {
|
||||||
|
ts.delta(growing_series);
|
||||||
|
},
|
||||||
|
'rate()': function rate() {
|
||||||
|
ts.rate(growing_series);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
name: 'scale',
|
||||||
|
tests: {
|
||||||
|
'scale()': function scale() {
|
||||||
|
ts.scale(datapoints, 42);
|
||||||
|
},
|
||||||
|
'scale_perf()': function scale_perf() {
|
||||||
|
ts.scale_perf(datapoints, 42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
name: 'groupBy vs groupBy_perf',
|
||||||
|
tests: {
|
||||||
|
'groupBy()': function groupBy() {
|
||||||
|
ts.groupBy(datapoints, '5m', ts.AVERAGE);
|
||||||
|
},
|
||||||
|
'groupBy_perf()': function groupBy_perf() {
|
||||||
|
ts.groupBy_perf(datapoints, '5m', ts.AVERAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
{
|
});
|
||||||
name: 'sumSeries',
|
//# sourceMappingURL=timeseries_bench.js.map
|
||||||
tests: {
|
|
||||||
'sumSeries()': () => {
|
|
||||||
ts.sumSeries(series_set);
|
|
||||||
},
|
|
||||||
'groupBy(MAX)->sumSeries()': () => {
|
|
||||||
let prepeared_series = _.map(series_set, datapoints => ts.groupBy(datapoints, '5m', ts.MAX));
|
|
||||||
ts.sumSeries(prepeared_series);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'delta vs rate',
|
|
||||||
tests: {
|
|
||||||
'delta()': () => {
|
|
||||||
ts.delta(growing_series);
|
|
||||||
},
|
|
||||||
'rate()': () => {
|
|
||||||
ts.rate(growing_series);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'scale',
|
|
||||||
tests: {
|
|
||||||
'scale()': () => {
|
|
||||||
ts.scale(datapoints, 42);
|
|
||||||
},
|
|
||||||
'scale_perf()': () => {
|
|
||||||
ts.scale_perf(datapoints, 42);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'groupBy vs groupBy_perf',
|
|
||||||
tests: {
|
|
||||||
'groupBy()': () => {
|
|
||||||
ts.groupBy(datapoints, '5m', ts.AVERAGE);
|
|
||||||
},
|
|
||||||
'groupBy_perf()': () => {
|
|
||||||
ts.groupBy_perf(datapoints, '5m', ts.AVERAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|||||||
1
dist/datasource-zabbix/benchmarks/timeseries_bench.js.map
vendored
Normal file
1
dist/datasource-zabbix/benchmarks/timeseries_bench.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
109
dist/datasource-zabbix/datasource.js
vendored
109
dist/datasource-zabbix/datasource.js
vendored
@@ -1,9 +1,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', './metricFunctions', './constants', './dataProcessor', './responseHandler', './zabbix.js', './zabbixAlerting.service.js', './zabbixAPICore.service.js'], function (_export, _context) {
|
System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', './metricFunctions', './constants', './dataProcessor', './responseHandler', './zabbixAlerting.service.js', './zabbix/zabbix', './zabbix/connectors/zabbix_api/zabbixAPICore'], function (_export, _context) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var _, dateMath, utils, migrations, metricFunctions, c, dataProcessor, responseHandler, ZabbixAPIError, _slicedToArray, _createClass, ZabbixAPIDatasource;
|
var _, dateMath, utils, migrations, metricFunctions, c, dataProcessor, responseHandler, Zabbix, ZabbixAPIError, _slicedToArray, _createClass, ZabbixAPIDatasource;
|
||||||
|
|
||||||
function _classCallCheck(instance, Constructor) {
|
function _classCallCheck(instance, Constructor) {
|
||||||
if (!(instance instanceof Constructor)) {
|
if (!(instance instanceof Constructor)) {
|
||||||
@@ -24,7 +24,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getConsolidateBy(target) {
|
function getConsolidateBy(target) {
|
||||||
var consolidateBy = 'avg';
|
var consolidateBy = void 0;
|
||||||
var funcDef = _.find(target.functions, function (func) {
|
var funcDef = _.find(target.functions, function (func) {
|
||||||
return func.def.name === 'consolidateBy';
|
return func.def.name === 'consolidateBy';
|
||||||
});
|
});
|
||||||
@@ -140,8 +140,10 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
|
|||||||
dataProcessor = _dataProcessor.default;
|
dataProcessor = _dataProcessor.default;
|
||||||
}, function (_responseHandler) {
|
}, function (_responseHandler) {
|
||||||
responseHandler = _responseHandler.default;
|
responseHandler = _responseHandler.default;
|
||||||
}, function (_zabbixJs) {}, function (_zabbixAlertingServiceJs) {}, function (_zabbixAPICoreServiceJs) {
|
}, function (_zabbixAlertingServiceJs) {}, function (_zabbixZabbix) {
|
||||||
ZabbixAPIError = _zabbixAPICoreServiceJs.ZabbixAPIError;
|
Zabbix = _zabbixZabbix.Zabbix;
|
||||||
|
}, function (_zabbixConnectorsZabbix_apiZabbixAPICore) {
|
||||||
|
ZabbixAPIError = _zabbixConnectorsZabbix_apiZabbixAPICore.ZabbixAPIError;
|
||||||
}],
|
}],
|
||||||
execute: function () {
|
execute: function () {
|
||||||
_slicedToArray = function () {
|
_slicedToArray = function () {
|
||||||
@@ -203,7 +205,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
|
|||||||
_export('ZabbixAPIDatasource', ZabbixAPIDatasource = function () {
|
_export('ZabbixAPIDatasource', ZabbixAPIDatasource = function () {
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
function ZabbixAPIDatasource(instanceSettings, templateSrv, alertSrv, dashboardSrv, zabbixAlertingSrv, Zabbix) {
|
function ZabbixAPIDatasource(instanceSettings, templateSrv, alertSrv, dashboardSrv, backendSrv, datasourceSrv, zabbixAlertingSrv) {
|
||||||
_classCallCheck(this, ZabbixAPIDatasource);
|
_classCallCheck(this, ZabbixAPIDatasource);
|
||||||
|
|
||||||
this.templateSrv = templateSrv;
|
this.templateSrv = templateSrv;
|
||||||
@@ -246,19 +248,20 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
|
|||||||
// Direct DB Connection options
|
// Direct DB Connection options
|
||||||
var dbConnectionOptions = jsonData.dbConnection || {};
|
var dbConnectionOptions = jsonData.dbConnection || {};
|
||||||
this.enableDirectDBConnection = dbConnectionOptions.enable;
|
this.enableDirectDBConnection = dbConnectionOptions.enable;
|
||||||
this.sqlDatasourceId = dbConnectionOptions.datasourceId;
|
this.datasourceId = dbConnectionOptions.datasourceId;
|
||||||
|
|
||||||
var zabbixOptions = {
|
var zabbixOptions = {
|
||||||
|
url: this.url,
|
||||||
username: this.username,
|
username: this.username,
|
||||||
password: this.password,
|
password: this.password,
|
||||||
basicAuth: this.basicAuth,
|
basicAuth: this.basicAuth,
|
||||||
withCredentials: this.withCredentials,
|
withCredentials: this.withCredentials,
|
||||||
cacheTTL: this.cacheTTL,
|
cacheTTL: this.cacheTTL,
|
||||||
enableDirectDBConnection: this.enableDirectDBConnection,
|
enableDirectDBConnection: this.enableDirectDBConnection,
|
||||||
sqlDatasourceId: this.sqlDatasourceId
|
datasourceId: this.datasourceId
|
||||||
};
|
};
|
||||||
|
|
||||||
this.zabbix = new Zabbix(this.url, zabbixOptions);
|
this.zabbix = new Zabbix(zabbixOptions, backendSrv, datasourceSrv);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
@@ -374,43 +377,14 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
|
|||||||
value: function queryNumericDataForItems(items, target, timeRange, useTrends, options) {
|
value: function queryNumericDataForItems(items, target, timeRange, useTrends, options) {
|
||||||
var _this3 = this;
|
var _this3 = this;
|
||||||
|
|
||||||
var _timeRange = _slicedToArray(timeRange, 2),
|
|
||||||
timeFrom = _timeRange[0],
|
|
||||||
timeTo = _timeRange[1];
|
|
||||||
|
|
||||||
var getHistoryPromise = void 0;
|
var getHistoryPromise = void 0;
|
||||||
options.consolidateBy = getConsolidateBy(target);
|
options.valueType = this.getTrendValueType(target);
|
||||||
|
options.consolidateBy = getConsolidateBy(target) || options.valueType;
|
||||||
|
|
||||||
if (useTrends) {
|
if (useTrends) {
|
||||||
if (this.enableDirectDBConnection) {
|
getHistoryPromise = this.zabbix.getTrends(items, timeRange, options);
|
||||||
getHistoryPromise = this.zabbix.getTrendsDB(items, timeFrom, timeTo, options).then(function (history) {
|
|
||||||
return _this3.zabbix.dbConnector.handleGrafanaTSResponse(history, items);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
var valueType = this.getTrendValueType(target);
|
|
||||||
getHistoryPromise = this.zabbix.getTrend(items, timeFrom, timeTo).then(function (history) {
|
|
||||||
return responseHandler.handleTrends(history, items, valueType);
|
|
||||||
}).then(function (timeseries) {
|
|
||||||
// Sort trend data, issue #202
|
|
||||||
_.forEach(timeseries, function (series) {
|
|
||||||
series.datapoints = _.sortBy(series.datapoints, function (point) {
|
|
||||||
return point[c.DATAPOINT_TS];
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return timeseries;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Use history
|
getHistoryPromise = this.zabbix.getHistoryTS(items, timeRange, options);
|
||||||
if (this.enableDirectDBConnection) {
|
|
||||||
getHistoryPromise = this.zabbix.getHistoryDB(items, timeFrom, timeTo, options).then(function (history) {
|
|
||||||
return _this3.zabbix.dbConnector.handleGrafanaTSResponse(history, items);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
|
|
||||||
return responseHandler.handleHistory(history, items);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return getHistoryPromise.then(function (timeseries) {
|
return getHistoryPromise.then(function (timeseries) {
|
||||||
@@ -492,25 +466,11 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
|
|||||||
value: function queryTextData(target, timeRange) {
|
value: function queryTextData(target, timeRange) {
|
||||||
var _this4 = this;
|
var _this4 = this;
|
||||||
|
|
||||||
var _timeRange2 = _slicedToArray(timeRange, 2),
|
|
||||||
timeFrom = _timeRange2[0],
|
|
||||||
timeTo = _timeRange2[1];
|
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
itemtype: 'text'
|
itemtype: 'text'
|
||||||
};
|
};
|
||||||
return this.zabbix.getItemsFromTarget(target, options).then(function (items) {
|
return this.zabbix.getItemsFromTarget(target, options).then(function (items) {
|
||||||
if (items.length) {
|
return _this4.zabbix.getHistoryText(items, timeRange, target);
|
||||||
return _this4.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
|
|
||||||
if (target.resultFormat === 'table') {
|
|
||||||
return responseHandler.handleHistoryAsTable(history, items, target);
|
|
||||||
} else {
|
|
||||||
return responseHandler.handleText(history, items, target);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Promise.resolve([]);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@@ -542,12 +502,10 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
var itServiceIds = [];
|
|
||||||
var itServices = [];
|
|
||||||
var itServiceFilter = void 0;
|
var itServiceFilter = void 0;
|
||||||
var isOldVersion = target.itservice && !target.itServiceFilter;
|
options.isOldVersion = target.itservice && !target.itServiceFilter;
|
||||||
|
|
||||||
if (isOldVersion) {
|
if (options.isOldVersion) {
|
||||||
// Backward compatibility
|
// Backward compatibility
|
||||||
itServiceFilter = '/.*/';
|
itServiceFilter = '/.*/';
|
||||||
} else {
|
} else {
|
||||||
@@ -555,20 +513,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.zabbix.getITServices(itServiceFilter).then(function (itservices) {
|
return this.zabbix.getITServices(itServiceFilter).then(function (itservices) {
|
||||||
itServices = itservices;
|
return _this6.zabbix.getSLA(itservices, timeRange, target, options);
|
||||||
if (isOldVersion) {
|
|
||||||
itServices = _.filter(itServices, { 'serviceid': target.itservice.serviceid });
|
|
||||||
}
|
|
||||||
|
|
||||||
itServiceIds = _.map(itServices, 'serviceid');
|
|
||||||
return itServiceIds;
|
|
||||||
}).then(function (serviceids) {
|
|
||||||
return _this6.zabbix.getSLA(serviceids, timeRange);
|
|
||||||
}).then(function (slaResponse) {
|
|
||||||
return _.map(itServiceIds, function (serviceid) {
|
|
||||||
var itservice = _.find(itServices, { 'serviceid': serviceid });
|
|
||||||
return responseHandler.handleSLAResponse(itservice, target.slaProperty, slaResponse);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@@ -576,9 +521,9 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
|
|||||||
value: function queryTriggersData(target, timeRange) {
|
value: function queryTriggersData(target, timeRange) {
|
||||||
var _this7 = this;
|
var _this7 = this;
|
||||||
|
|
||||||
var _timeRange3 = _slicedToArray(timeRange, 2),
|
var _timeRange = _slicedToArray(timeRange, 2),
|
||||||
timeFrom = _timeRange3[0],
|
timeFrom = _timeRange[0],
|
||||||
timeTo = _timeRange3[1];
|
timeTo = _timeRange[1];
|
||||||
|
|
||||||
return this.zabbix.getHostsFromTarget(target).then(function (results) {
|
return this.zabbix.getHostsFromTarget(target).then(function (results) {
|
||||||
var _results = _slicedToArray(results, 2),
|
var _results = _slicedToArray(results, 2),
|
||||||
@@ -614,7 +559,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
|
|||||||
return _this8.zabbix.login();
|
return _this8.zabbix.login();
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
if (_this8.enableDirectDBConnection) {
|
if (_this8.enableDirectDBConnection) {
|
||||||
return _this8.zabbix.dbConnector.testSQLDataSource();
|
return _this8.zabbix.dbConnector.testDataSource();
|
||||||
} else {
|
} else {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
@@ -832,9 +777,9 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
|
|||||||
}, {
|
}, {
|
||||||
key: 'isUseTrends',
|
key: 'isUseTrends',
|
||||||
value: function isUseTrends(timeRange) {
|
value: function isUseTrends(timeRange) {
|
||||||
var _timeRange4 = _slicedToArray(timeRange, 2),
|
var _timeRange2 = _slicedToArray(timeRange, 2),
|
||||||
timeFrom = _timeRange4[0],
|
timeFrom = _timeRange2[0],
|
||||||
timeTo = _timeRange4[1];
|
timeTo = _timeRange2[1];
|
||||||
|
|
||||||
var useTrendsFrom = Math.ceil(dateMath.parse('now-' + this.trendsFrom) / 1000);
|
var useTrendsFrom = Math.ceil(dateMath.parse('now-' + this.trendsFrom) / 1000);
|
||||||
var useTrendsRange = Math.ceil(utils.parseInterval(this.trendsRange) / 1000);
|
var useTrendsRange = Math.ceil(utils.parseInterval(this.trendsRange) / 1000);
|
||||||
|
|||||||
2
dist/datasource-zabbix/datasource.js.map
vendored
2
dist/datasource-zabbix/datasource.js.map
vendored
File diff suppressed because one or more lines are too long
57
dist/datasource-zabbix/responseHandler.js
vendored
57
dist/datasource-zabbix/responseHandler.js
vendored
@@ -56,23 +56,33 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleHistory(history, items) {
|
function sortTimeseries(timeseries) {
|
||||||
|
// Sort trend data, issue #202
|
||||||
|
_.forEach(timeseries, function (series) {
|
||||||
|
series.datapoints = _.sortBy(series.datapoints, function (point) {
|
||||||
|
return point[c.DATAPOINT_TS];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return timeseries;
|
||||||
|
}function handleHistory(history, items) {
|
||||||
var addHostName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
var addHostName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
||||||
|
|
||||||
return convertHistory(history, items, addHostName, convertHistoryPoint);
|
return convertHistory(history, items, addHostName, convertHistoryPoint);
|
||||||
}function handleTrends(history, items, valueType) {
|
}
|
||||||
|
|
||||||
|
function handleTrends(history, items, valueType) {
|
||||||
var addHostName = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
|
var addHostName = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
|
||||||
|
|
||||||
var convertPointCallback = _.partial(convertTrendPoint, valueType);
|
var convertPointCallback = _.partial(convertTrendPoint, valueType);
|
||||||
return convertHistory(history, items, addHostName, convertPointCallback);
|
return convertHistory(history, items, addHostName, convertPointCallback);
|
||||||
}
|
}function handleText(history, items, target) {
|
||||||
|
|
||||||
function handleText(history, items, target) {
|
|
||||||
var addHostName = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
|
var addHostName = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
|
||||||
|
|
||||||
var convertTextCallback = _.partial(convertText, target);
|
var convertTextCallback = _.partial(convertText, target);
|
||||||
return convertHistory(history, items, addHostName, convertTextCallback);
|
return convertHistory(history, items, addHostName, convertTextCallback);
|
||||||
}function handleHistoryAsTable(history, items, target) {
|
}
|
||||||
|
|
||||||
|
function handleHistoryAsTable(history, items, target) {
|
||||||
var table = new TableModel();
|
var table = new TableModel();
|
||||||
table.addColumn({ text: 'Host' });
|
table.addColumn({ text: 'Host' });
|
||||||
table.addColumn({ text: 'Item' });
|
table.addColumn({ text: 'Item' });
|
||||||
@@ -101,9 +111,7 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
|||||||
});
|
});
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}function convertText(target, point) {
|
||||||
|
|
||||||
function convertText(target, point) {
|
|
||||||
var value = point.value;
|
var value = point.value;
|
||||||
|
|
||||||
// Regex-based extractor
|
// Regex-based extractor
|
||||||
@@ -112,7 +120,9 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [value, point.clock * 1000 + Math.round(point.ns / 1000000)];
|
return [value, point.clock * 1000 + Math.round(point.ns / 1000000)];
|
||||||
}function extractText(str, pattern, useCaptureGroups) {
|
}
|
||||||
|
|
||||||
|
function extractText(str, pattern, useCaptureGroups) {
|
||||||
var extractPattern = new RegExp(pattern);
|
var extractPattern = new RegExp(pattern);
|
||||||
var extractedValue = extractPattern.exec(str);
|
var extractedValue = extractPattern.exec(str);
|
||||||
if (extractedValue) {
|
if (extractedValue) {
|
||||||
@@ -123,9 +133,7 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return extractedValue;
|
return extractedValue;
|
||||||
}
|
}function handleSLAResponse(itservice, slaProperty, slaObject) {
|
||||||
|
|
||||||
function handleSLAResponse(itservice, slaProperty, slaObject) {
|
|
||||||
var targetSLA = slaObject[itservice.serviceid].sla[0];
|
var targetSLA = slaObject[itservice.serviceid].sla[0];
|
||||||
if (slaProperty.property === 'status') {
|
if (slaProperty.property === 'status') {
|
||||||
var targetStatus = parseInt(slaObject[itservice.serviceid].status);
|
var targetStatus = parseInt(slaObject[itservice.serviceid].status);
|
||||||
@@ -139,7 +147,9 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
|||||||
datapoints: [[targetSLA[slaProperty.property], targetSLA.from * 1000], [targetSLA[slaProperty.property], targetSLA.to * 1000]]
|
datapoints: [[targetSLA[slaProperty.property], targetSLA.from * 1000], [targetSLA[slaProperty.property], targetSLA.to * 1000]]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}function handleTriggersResponse(triggers, timeRange) {
|
}
|
||||||
|
|
||||||
|
function handleTriggersResponse(triggers, timeRange) {
|
||||||
if (_.isNumber(triggers)) {
|
if (_.isNumber(triggers)) {
|
||||||
return {
|
return {
|
||||||
target: "triggers count",
|
target: "triggers count",
|
||||||
@@ -163,9 +173,7 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
|||||||
});
|
});
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
}
|
}function getTriggerStats(triggers) {
|
||||||
|
|
||||||
function getTriggerStats(triggers) {
|
|
||||||
var groups = _.uniq(_.flattenDeep(_.map(triggers, function (trigger) {
|
var groups = _.uniq(_.flattenDeep(_.map(triggers, function (trigger) {
|
||||||
return _.map(trigger.groups, 'name');
|
return _.map(trigger.groups, 'name');
|
||||||
})));
|
})));
|
||||||
@@ -180,12 +188,12 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
return stats;
|
return stats;
|
||||||
}function convertHistoryPoint(point) {
|
|
||||||
// Value must be a number for properly work
|
|
||||||
return [Number(point.value), point.clock * 1000 + Math.round(point.ns / 1000000)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertTrendPoint(valueType, point) {
|
function convertHistoryPoint(point) {
|
||||||
|
// Value must be a number for properly work
|
||||||
|
return [Number(point.value), point.clock * 1000 + Math.round(point.ns / 1000000)];
|
||||||
|
}function convertTrendPoint(valueType, point) {
|
||||||
var value;
|
var value;
|
||||||
switch (valueType) {
|
switch (valueType) {
|
||||||
case "min":
|
case "min":
|
||||||
@@ -208,7 +216,9 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [Number(value), point.clock * 1000];
|
return [Number(value), point.clock * 1000];
|
||||||
}return {
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
setters: [function (_lodash) {
|
setters: [function (_lodash) {
|
||||||
_ = _lodash.default;
|
_ = _lodash.default;
|
||||||
}, function (_appCoreTable_model) {
|
}, function (_appCoreTable_model) {
|
||||||
@@ -224,7 +234,8 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
|||||||
handleText: handleText,
|
handleText: handleText,
|
||||||
handleHistoryAsTable: handleHistoryAsTable,
|
handleHistoryAsTable: handleHistoryAsTable,
|
||||||
handleSLAResponse: handleSLAResponse,
|
handleSLAResponse: handleSLAResponse,
|
||||||
handleTriggersResponse: handleTriggersResponse
|
handleTriggersResponse: handleTriggersResponse,
|
||||||
|
sortTimeseries: sortTimeseries
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fix for backward compatibility with lodash 2.4
|
// Fix for backward compatibility with lodash 2.4
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,51 +1,56 @@
|
|||||||
import _ from 'lodash';
|
'use strict';
|
||||||
import dataProcessor from '../dataProcessor';
|
|
||||||
|
|
||||||
describe('dataProcessor', () => {
|
System.register(['lodash', '../dataProcessor'], function (_export, _context) {
|
||||||
let ctx = {};
|
"use strict";
|
||||||
|
|
||||||
beforeEach(() => {
|
var _, dataProcessor;
|
||||||
ctx.datapoints = [
|
|
||||||
[[10, 1500000000000], [2, 1500000001000], [7, 1500000002000], [1, 1500000003000]],
|
|
||||||
[[9, 1500000000000], [3, 1500000001000], [4, 1500000002000], [8, 1500000003000]],
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('When apply groupBy() functions', () => {
|
return {
|
||||||
it('should return series average', () => {
|
setters: [function (_lodash) {
|
||||||
let aggregateBy = dataProcessor.metricFunctions['groupBy'];
|
_ = _lodash.default;
|
||||||
const avg2s = _.map(ctx.datapoints, (dp) => aggregateBy('2s', 'avg', dp));
|
}, function (_dataProcessor) {
|
||||||
expect(avg2s).toEqual([
|
dataProcessor = _dataProcessor.default;
|
||||||
[[6, 1500000000000], [4, 1500000002000]],
|
}],
|
||||||
[[6, 1500000000000], [6, 1500000002000]],
|
execute: function () {
|
||||||
]);
|
|
||||||
|
|
||||||
const avg10s = _.map(ctx.datapoints, (dp) => aggregateBy('10s', 'avg', dp));
|
describe('dataProcessor', function () {
|
||||||
expect(avg10s).toEqual([
|
var ctx = {};
|
||||||
[[5, 1500000000000]],
|
|
||||||
[[6, 1500000000000]],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// not aligned
|
beforeEach(function () {
|
||||||
const dp = [[10, 1500000001000], [2, 1500000002000], [7, 1500000003000], [1, 1500000004000]];
|
ctx.datapoints = [[[10, 1500000000000], [2, 1500000001000], [7, 1500000002000], [1, 1500000003000]], [[9, 1500000000000], [3, 1500000001000], [4, 1500000002000], [8, 1500000003000]]];
|
||||||
expect(aggregateBy('2s', 'avg', dp)).toEqual([
|
});
|
||||||
[10, 1500000000000], [4.5, 1500000002000], [1, 1500000004000]
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('When apply aggregateBy() functions', () => {
|
describe('When apply groupBy() functions', function () {
|
||||||
it('should return series average', () => {
|
it('should return series average', function () {
|
||||||
let aggregateBy = dataProcessor.metricFunctions['aggregateBy'];
|
var aggregateBy = dataProcessor.metricFunctions['groupBy'];
|
||||||
const avg1s = aggregateBy('1s', 'avg', ctx.datapoints);
|
var avg2s = _.map(ctx.datapoints, function (dp) {
|
||||||
expect(avg1s).toEqual([
|
return aggregateBy('2s', 'avg', dp);
|
||||||
[9.5, 1500000000000], [2.5, 1500000001000], [5.5, 1500000002000], [4.5, 1500000003000]
|
});
|
||||||
]);
|
expect(avg2s).toEqual([[[6, 1500000000000], [4, 1500000002000]], [[6, 1500000000000], [6, 1500000002000]]]);
|
||||||
|
|
||||||
const avg10s = aggregateBy('10s', 'avg', ctx.datapoints);
|
var avg10s = _.map(ctx.datapoints, function (dp) {
|
||||||
expect(avg10s).toEqual([
|
return aggregateBy('10s', 'avg', dp);
|
||||||
[5.5, 1500000000000]
|
});
|
||||||
]);
|
expect(avg10s).toEqual([[[5, 1500000000000]], [[6, 1500000000000]]]);
|
||||||
});
|
|
||||||
});
|
// not aligned
|
||||||
|
var dp = [[10, 1500000001000], [2, 1500000002000], [7, 1500000003000], [1, 1500000004000]];
|
||||||
|
expect(aggregateBy('2s', 'avg', dp)).toEqual([[10, 1500000000000], [4.5, 1500000002000], [1, 1500000004000]]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When apply aggregateBy() functions', function () {
|
||||||
|
it('should return series average', function () {
|
||||||
|
var aggregateBy = dataProcessor.metricFunctions['aggregateBy'];
|
||||||
|
var avg1s = aggregateBy('1s', 'avg', ctx.datapoints);
|
||||||
|
expect(avg1s).toEqual([[9.5, 1500000000000], [2.5, 1500000001000], [5.5, 1500000002000], [4.5, 1500000003000]]);
|
||||||
|
|
||||||
|
var avg10s = aggregateBy('10s', 'avg', ctx.datapoints);
|
||||||
|
expect(avg10s).toEqual([[5.5, 1500000000000]]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
//# sourceMappingURL=dataProcessor.spec.js.map
|
||||||
|
|||||||
1
dist/datasource-zabbix/specs/dataProcessor.spec.js.map
vendored
Normal file
1
dist/datasource-zabbix/specs/dataProcessor.spec.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["../../../src/datasource-zabbix/specs/dataProcessor.spec.js"],"names":["_","dataProcessor","describe","ctx","beforeEach","datapoints","it","aggregateBy","metricFunctions","avg2s","map","dp","expect","toEqual","avg10s","avg1s"],"mappings":";;;;;;;;;AAAOA,O;;AACAC,mB;;;;AAEPC,eAAS,eAAT,EAA0B,YAAM;AAC9B,YAAIC,MAAM,EAAV;;AAEAC,mBAAW,YAAM;AACfD,cAAIE,UAAJ,GAAiB,CACf,CAAC,CAAC,EAAD,EAAK,aAAL,CAAD,EAAsB,CAAC,CAAD,EAAI,aAAJ,CAAtB,EAA0C,CAAC,CAAD,EAAI,aAAJ,CAA1C,EAA8D,CAAC,CAAD,EAAI,aAAJ,CAA9D,CADe,EAEf,CAAC,CAAC,CAAD,EAAI,aAAJ,CAAD,EAAsB,CAAC,CAAD,EAAI,aAAJ,CAAtB,EAA0C,CAAC,CAAD,EAAI,aAAJ,CAA1C,EAA8D,CAAC,CAAD,EAAI,aAAJ,CAA9D,CAFe,CAAjB;AAID,SALD;;AAOAH,iBAAS,gCAAT,EAA2C,YAAM;AAC/CI,aAAG,8BAAH,EAAmC,YAAM;AACvC,gBAAIC,cAAcN,cAAcO,eAAd,CAA8B,SAA9B,CAAlB;AACA,gBAAMC,QAAQT,EAAEU,GAAF,CAAMP,IAAIE,UAAV,EAAsB,UAACM,EAAD;AAAA,qBAAQJ,YAAY,IAAZ,EAAkB,KAAlB,EAAyBI,EAAzB,CAAR;AAAA,aAAtB,CAAd;AACAC,mBAAOH,KAAP,EAAcI,OAAd,CAAsB,CACpB,CAAC,CAAC,CAAD,EAAI,aAAJ,CAAD,EAAqB,CAAC,CAAD,EAAI,aAAJ,CAArB,CADoB,EAEpB,CAAC,CAAC,CAAD,EAAI,aAAJ,CAAD,EAAqB,CAAC,CAAD,EAAI,aAAJ,CAArB,CAFoB,CAAtB;;AAKA,gBAAMC,SAASd,EAAEU,GAAF,CAAMP,IAAIE,UAAV,EAAsB,UAACM,EAAD;AAAA,qBAAQJ,YAAY,KAAZ,EAAmB,KAAnB,EAA0BI,EAA1B,CAAR;AAAA,aAAtB,CAAf;AACAC,mBAAOE,MAAP,EAAeD,OAAf,CAAuB,CACrB,CAAC,CAAC,CAAD,EAAI,aAAJ,CAAD,CADqB,EAErB,CAAC,CAAC,CAAD,EAAI,aAAJ,CAAD,CAFqB,CAAvB;;AAKA;AACA,gBAAMF,KAAK,CAAC,CAAC,EAAD,EAAK,aAAL,CAAD,EAAsB,CAAC,CAAD,EAAI,aAAJ,CAAtB,EAA0C,CAAC,CAAD,EAAI,aAAJ,CAA1C,EAA8D,CAAC,CAAD,EAAI,aAAJ,CAA9D,CAAX;AACAC,mBAAOL,YAAY,IAAZ,EAAkB,KAAlB,EAAyBI,EAAzB,CAAP,EAAqCE,OAArC,CAA6C,CAC3C,CAAC,EAAD,EAAK,aAAL,CAD2C,EACtB,CAAC,GAAD,EAAM,aAAN,CADsB,EACA,CAAC,CAAD,EAAI,aAAJ,CADA,CAA7C;AAGD,WAnBD;AAoBD,SArBD;;AAuBAX,iBAAS,oCAAT,EAA+C,YAAM;AACnDI,aAAG,8BAAH,EAAmC,YAAM;AACvC,gBAAIC,cAAcN,cAAcO,eAAd,CAA8B,aAA9B,CAAlB;AACA,gBAAMO,QAAQR,YAAY,IAAZ,EAAkB,KAAlB,EAAyBJ,IAAIE,UAA7B,CAAd;AACAO,mBAAOG,KAAP,EAAcF,OAAd,CAAsB,CACpB,CAAC,GAAD,EAAM,aAAN,CADoB,EACE,CAAC,GAAD,EAAM,aAAN,CADF,EACwB,CAAC,GAAD,EAAM,aAAN,CADxB,EAC8C,CAAC,GAAD,EAAM,aAAN,CAD9C,CAAtB;;AAIA,gBAAMC,SAASP,YAAY,KAAZ,EAAmB,KAAnB,EAA0BJ,IAAIE,UAA9B,CAAf;AACAO,mBAAOE,MAAP,EAAeD,OAAf,CAAuB,CACrB,CAAC,GAAD,EAAM,aAAN,CADqB,CAAvB;AAGD,WAXD;AAYD,SAbD;AAcD,OA/CD","file":"dataProcessor.spec.js","sourcesContent":["import _ from 'lodash';\nimport dataProcessor from '../dataProcessor';\n\ndescribe('dataProcessor', () => {\n let ctx = {};\n\n beforeEach(() => {\n ctx.datapoints = [\n [[10, 1500000000000], [2, 1500000001000], [7, 1500000002000], [1, 1500000003000]],\n [[9, 1500000000000], [3, 1500000001000], [4, 1500000002000], [8, 1500000003000]],\n ];\n });\n\n describe('When apply groupBy() functions', () => {\n it('should return series average', () => {\n let aggregateBy = dataProcessor.metricFunctions['groupBy'];\n const avg2s = _.map(ctx.datapoints, (dp) => aggregateBy('2s', 'avg', dp));\n expect(avg2s).toEqual([\n [[6, 1500000000000], [4, 1500000002000]],\n [[6, 1500000000000], [6, 1500000002000]],\n ]);\n\n const avg10s = _.map(ctx.datapoints, (dp) => aggregateBy('10s', 'avg', dp));\n expect(avg10s).toEqual([\n [[5, 1500000000000]],\n [[6, 1500000000000]],\n ]);\n\n // not aligned\n const dp = [[10, 1500000001000], [2, 1500000002000], [7, 1500000003000], [1, 1500000004000]];\n expect(aggregateBy('2s', 'avg', dp)).toEqual([\n [10, 1500000000000], [4.5, 1500000002000], [1, 1500000004000]\n ]);\n });\n });\n\n describe('When apply aggregateBy() functions', () => {\n it('should return series average', () => {\n let aggregateBy = dataProcessor.metricFunctions['aggregateBy'];\n const avg1s = aggregateBy('1s', 'avg', ctx.datapoints);\n expect(avg1s).toEqual([\n [9.5, 1500000000000], [2.5, 1500000001000], [5.5, 1500000002000], [4.5, 1500000003000]\n ]);\n\n const avg10s = aggregateBy('10s', 'avg', ctx.datapoints);\n expect(avg10s).toEqual([\n [5.5, 1500000000000]\n ]);\n });\n });\n});\n"]}
|
||||||
914
dist/datasource-zabbix/specs/datasource.spec.js
vendored
914
dist/datasource-zabbix/specs/datasource.spec.js
vendored
@@ -1,429 +1,509 @@
|
|||||||
import _ from 'lodash';
|
"use strict";
|
||||||
import Q, { Promise } from "q";
|
|
||||||
import {Datasource} from "../module";
|
|
||||||
import {zabbixTemplateFormat} from "../datasource";
|
|
||||||
|
|
||||||
describe('ZabbixDatasource', () => {
|
System.register(["lodash", "q", "../module", "../datasource"], function (_export, _context) {
|
||||||
let ctx = {};
|
"use strict";
|
||||||
|
|
||||||
beforeEach(() => {
|
var _, Q, Promise, Datasource, zabbixTemplateFormat;
|
||||||
ctx.instanceSettings = {
|
|
||||||
jsonData: {
|
|
||||||
alerting: true,
|
|
||||||
username: 'zabbix',
|
|
||||||
password: 'zabbix',
|
|
||||||
trends: true,
|
|
||||||
trendsFrom: '14d',
|
|
||||||
trendsRange: '7d',
|
|
||||||
dbConnection: {
|
|
||||||
enabled: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ctx.templateSrv = {};
|
|
||||||
ctx.alertSrv = {};
|
|
||||||
ctx.dashboardSrv = {};
|
|
||||||
ctx.zabbixAlertingSrv = {
|
|
||||||
setPanelAlertState: jest.fn(),
|
|
||||||
removeZabbixThreshold: jest.fn(),
|
|
||||||
};
|
|
||||||
ctx.zabbix = () => {};
|
|
||||||
|
|
||||||
ctx.ds = new Datasource(ctx.instanceSettings, ctx.templateSrv, ctx.alertSrv, ctx.dashboardSrv, ctx.zabbixAlertingSrv, ctx.zabbix);
|
return {
|
||||||
});
|
setters: [function (_lodash) {
|
||||||
|
_ = _lodash.default;
|
||||||
|
}, function (_q) {
|
||||||
|
Q = _q.default;
|
||||||
|
Promise = _q.Promise;
|
||||||
|
}, function (_module) {
|
||||||
|
Datasource = _module.Datasource;
|
||||||
|
}, function (_datasource) {
|
||||||
|
zabbixTemplateFormat = _datasource.zabbixTemplateFormat;
|
||||||
|
}],
|
||||||
|
execute: function () {
|
||||||
|
|
||||||
describe('When querying data', () => {
|
describe('ZabbixDatasource', function () {
|
||||||
beforeEach(() => {
|
var ctx = {};
|
||||||
ctx.ds.replaceTemplateVars = (str) => str;
|
|
||||||
ctx.ds.alertQuery = () => Q.when([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
ctx.options = {
|
beforeEach(function () {
|
||||||
targets: [
|
ctx.instanceSettings = {
|
||||||
{
|
jsonData: {
|
||||||
group: {filter: ""},
|
alerting: true,
|
||||||
host: {filter: ""},
|
username: 'zabbix',
|
||||||
application: {filter: ""},
|
password: 'zabbix',
|
||||||
item: {filter: ""}
|
trends: true,
|
||||||
}
|
trendsFrom: '14d',
|
||||||
],
|
trendsRange: '7d',
|
||||||
range: {from: 'now-7d', to: 'now'}
|
dbConnection: {
|
||||||
};
|
enabled: false
|
||||||
|
}
|
||||||
it('should return an empty array when no targets are set', (done) => {
|
|
||||||
let options = {
|
|
||||||
targets: [],
|
|
||||||
range: {from: 'now-6h', to: 'now'}
|
|
||||||
};
|
|
||||||
ctx.ds.query(options).then(result => {
|
|
||||||
expect(result.data.length).toBe(0);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use trends if it enabled and time more than trendsFrom', (done) => {
|
|
||||||
let ranges = ['now-7d', 'now-168h', 'now-1M', 'now-1y'];
|
|
||||||
|
|
||||||
_.forEach(ranges, range => {
|
|
||||||
ctx.options.range.from = range;
|
|
||||||
ctx.ds.queryNumericData = jest.fn();
|
|
||||||
ctx.ds.query(ctx.options);
|
|
||||||
|
|
||||||
// Check that useTrends options is true
|
|
||||||
let callArgs = ctx.ds.queryNumericData.mock.calls[0];
|
|
||||||
expect(callArgs[2]).toBe(true);
|
|
||||||
ctx.ds.queryNumericData.mockClear();
|
|
||||||
});
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shouldnt use trends if it enabled and time less than trendsFrom', (done) => {
|
|
||||||
let ranges = ['now-6d', 'now-167h', 'now-1h', 'now-30m', 'now-30s'];
|
|
||||||
|
|
||||||
_.forEach(ranges, range => {
|
|
||||||
ctx.options.range.from = range;
|
|
||||||
ctx.ds.queryNumericData = jest.fn();
|
|
||||||
ctx.ds.query(ctx.options);
|
|
||||||
|
|
||||||
// Check that useTrends options is false
|
|
||||||
let callArgs = ctx.ds.queryNumericData.mock.calls[0];
|
|
||||||
expect(callArgs[2]).toBe(false);
|
|
||||||
ctx.ds.queryNumericData.mockClear();
|
|
||||||
});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('When querying text data', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
ctx.ds.replaceTemplateVars = (str) => str;
|
|
||||||
ctx.ds.alertQuery = () => Q.when([]);
|
|
||||||
ctx.ds.zabbix.getHistory = jest.fn().mockReturnValue(Promise.resolve([
|
|
||||||
{clock: "1500010200", itemid:"10100", ns:"900111000", value:"Linux first"},
|
|
||||||
{clock: "1500010300", itemid:"10100", ns:"900111000", value:"Linux 2nd"},
|
|
||||||
{clock: "1500010400", itemid:"10100", ns:"900111000", value:"Linux last"}
|
|
||||||
]));
|
|
||||||
|
|
||||||
ctx.ds.zabbix.getItemsFromTarget = jest.fn().mockReturnValue(Promise.resolve([
|
|
||||||
{
|
|
||||||
hosts: [{hostid: "10001", name: "Zabbix server"}],
|
|
||||||
itemid: "10100",
|
|
||||||
name: "System information",
|
|
||||||
key_: "system.uname",
|
|
||||||
}
|
|
||||||
]));
|
|
||||||
|
|
||||||
ctx.options = {
|
|
||||||
range: {from: 'now-1h', to: 'now'},
|
|
||||||
targets: [
|
|
||||||
{
|
|
||||||
group: {filter: ""},
|
|
||||||
host: {filter: "Zabbix server"},
|
|
||||||
application: {filter: ""},
|
|
||||||
item: {filter: "System information"},
|
|
||||||
textFilter: "",
|
|
||||||
useCaptureGroups: true,
|
|
||||||
mode: 2,
|
|
||||||
resultFormat: "table",
|
|
||||||
options: {
|
|
||||||
skipEmptyValues: false
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
ctx.templateSrv = {};
|
||||||
|
ctx.alertSrv = {};
|
||||||
|
ctx.dashboardSrv = {};
|
||||||
|
ctx.zabbixAlertingSrv = {
|
||||||
|
setPanelAlertState: jest.fn(),
|
||||||
|
removeZabbixThreshold: jest.fn()
|
||||||
|
};
|
||||||
|
ctx.zabbix = function () {};
|
||||||
|
|
||||||
|
ctx.ds = new Datasource(ctx.instanceSettings, ctx.templateSrv, ctx.alertSrv, ctx.dashboardSrv, ctx.zabbixAlertingSrv, ctx.zabbix);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When querying data', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
ctx.ds.replaceTemplateVars = function (str) {
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
ctx.ds.alertQuery = function () {
|
||||||
|
return Q.when([]);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx.options = {
|
||||||
|
targets: [{
|
||||||
|
group: { filter: "" },
|
||||||
|
host: { filter: "" },
|
||||||
|
application: { filter: "" },
|
||||||
|
item: { filter: "" }
|
||||||
|
}],
|
||||||
|
range: { from: 'now-7d', to: 'now' }
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should return an empty array when no targets are set', function (done) {
|
||||||
|
var options = {
|
||||||
|
targets: [],
|
||||||
|
range: { from: 'now-6h', to: 'now' }
|
||||||
|
};
|
||||||
|
ctx.ds.query(options).then(function (result) {
|
||||||
|
expect(result.data.length).toBe(0);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use trends if it enabled and time more than trendsFrom', function (done) {
|
||||||
|
var ranges = ['now-7d', 'now-168h', 'now-1M', 'now-1y'];
|
||||||
|
|
||||||
|
_.forEach(ranges, function (range) {
|
||||||
|
ctx.options.range.from = range;
|
||||||
|
ctx.ds.queryNumericData = jest.fn();
|
||||||
|
ctx.ds.query(ctx.options);
|
||||||
|
|
||||||
|
// Check that useTrends options is true
|
||||||
|
var callArgs = ctx.ds.queryNumericData.mock.calls[0];
|
||||||
|
expect(callArgs[2]).toBe(true);
|
||||||
|
ctx.ds.queryNumericData.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shouldnt use trends if it enabled and time less than trendsFrom', function (done) {
|
||||||
|
var ranges = ['now-6d', 'now-167h', 'now-1h', 'now-30m', 'now-30s'];
|
||||||
|
|
||||||
|
_.forEach(ranges, function (range) {
|
||||||
|
ctx.options.range.from = range;
|
||||||
|
ctx.ds.queryNumericData = jest.fn();
|
||||||
|
ctx.ds.query(ctx.options);
|
||||||
|
|
||||||
|
// Check that useTrends options is false
|
||||||
|
var callArgs = ctx.ds.queryNumericData.mock.calls[0];
|
||||||
|
expect(callArgs[2]).toBe(false);
|
||||||
|
ctx.ds.queryNumericData.mockClear();
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When querying text data', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
ctx.ds.replaceTemplateVars = function (str) {
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
ctx.ds.alertQuery = function () {
|
||||||
|
return Q.when([]);
|
||||||
|
};
|
||||||
|
ctx.ds.zabbix.getHistory = jest.fn().mockReturnValue(Promise.resolve([{ clock: "1500010200", itemid: "10100", ns: "900111000", value: "Linux first" }, { clock: "1500010300", itemid: "10100", ns: "900111000", value: "Linux 2nd" }, { clock: "1500010400", itemid: "10100", ns: "900111000", value: "Linux last" }]));
|
||||||
|
|
||||||
|
ctx.ds.zabbix.getItemsFromTarget = jest.fn().mockReturnValue(Promise.resolve([{
|
||||||
|
hosts: [{ hostid: "10001", name: "Zabbix server" }],
|
||||||
|
itemid: "10100",
|
||||||
|
name: "System information",
|
||||||
|
key_: "system.uname"
|
||||||
|
}]));
|
||||||
|
|
||||||
|
ctx.options = {
|
||||||
|
range: { from: 'now-1h', to: 'now' },
|
||||||
|
targets: [{
|
||||||
|
group: { filter: "" },
|
||||||
|
host: { filter: "Zabbix server" },
|
||||||
|
application: { filter: "" },
|
||||||
|
item: { filter: "System information" },
|
||||||
|
textFilter: "",
|
||||||
|
useCaptureGroups: true,
|
||||||
|
mode: 2,
|
||||||
|
resultFormat: "table",
|
||||||
|
options: {
|
||||||
|
skipEmptyValues: false
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return data in table format', function (done) {
|
||||||
|
ctx.ds.query(ctx.options).then(function (result) {
|
||||||
|
expect(result.data.length).toBe(1);
|
||||||
|
|
||||||
|
var tableData = result.data[0];
|
||||||
|
expect(tableData.columns).toEqual([{ text: 'Host' }, { text: 'Item' }, { text: 'Key' }, { text: 'Last value' }]);
|
||||||
|
expect(tableData.rows).toEqual([['Zabbix server', 'System information', 'system.uname', 'Linux last']]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should extract value if regex with capture group is used', function (done) {
|
||||||
|
ctx.options.targets[0].textFilter = "Linux (.*)";
|
||||||
|
ctx.ds.query(ctx.options).then(function (result) {
|
||||||
|
var tableData = result.data[0];
|
||||||
|
expect(tableData.rows[0][3]).toEqual('last');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should skip item when last value is empty', function () {
|
||||||
|
ctx.ds.zabbix.getItemsFromTarget = jest.fn().mockReturnValue(Promise.resolve([{
|
||||||
|
hosts: [{ hostid: "10001", name: "Zabbix server" }],
|
||||||
|
itemid: "10100", name: "System information", key_: "system.uname"
|
||||||
|
}, {
|
||||||
|
hosts: [{ hostid: "10002", name: "Server02" }],
|
||||||
|
itemid: "90109", name: "System information", key_: "system.uname"
|
||||||
|
}]));
|
||||||
|
|
||||||
|
ctx.options.targets[0].options.skipEmptyValues = true;
|
||||||
|
ctx.ds.zabbix.getHistory = jest.fn().mockReturnValue(Promise.resolve([{ clock: "1500010200", itemid: "10100", ns: "900111000", value: "Linux first" }, { clock: "1500010300", itemid: "10100", ns: "900111000", value: "Linux 2nd" }, { clock: "1500010400", itemid: "10100", ns: "900111000", value: "Linux last" }, { clock: "1500010200", itemid: "90109", ns: "900111000", value: "Non empty value" }, { clock: "1500010500", itemid: "90109", ns: "900111000", value: "" }]));
|
||||||
|
return ctx.ds.query(ctx.options).then(function (result) {
|
||||||
|
var tableData = result.data[0];
|
||||||
|
expect(tableData.rows.length).toBe(1);
|
||||||
|
expect(tableData.rows[0][3]).toEqual('Linux last');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When replacing template variables', function () {
|
||||||
|
|
||||||
|
function testReplacingVariable(target, varValue, expectedResult, done) {
|
||||||
|
ctx.ds.templateSrv.replace = function () {
|
||||||
|
return zabbixTemplateFormat(varValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = ctx.ds.replaceTemplateVars(target);
|
||||||
|
expect(result).toBe(expectedResult);
|
||||||
|
done();
|
||||||
}
|
}
|
||||||
],
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return data in table format', (done) => {
|
/*
|
||||||
ctx.ds.query(ctx.options).then(result => {
|
* Alphanumerics, spaces, dots, dashes and underscores
|
||||||
expect(result.data.length).toBe(1);
|
* are allowed in Zabbix host name.
|
||||||
|
* 'AaBbCc0123 .-_'
|
||||||
|
*/
|
||||||
|
it('should return properly escaped regex', function (done) {
|
||||||
|
var target = '$host';
|
||||||
|
var template_var_value = 'AaBbCc0123 .-_';
|
||||||
|
var expected_result = '/^AaBbCc0123 \\.-_$/';
|
||||||
|
|
||||||
let tableData = result.data[0];
|
testReplacingVariable(target, template_var_value, expected_result, done);
|
||||||
expect(tableData.columns).toEqual([
|
});
|
||||||
{text: 'Host'}, {text: 'Item'}, {text: 'Key'}, {text: 'Last value'}
|
|
||||||
]);
|
/*
|
||||||
expect(tableData.rows).toEqual([
|
* Single-value variable
|
||||||
['Zabbix server', 'System information', 'system.uname', 'Linux last']
|
* $host = backend01
|
||||||
]);
|
* $host => /^backend01|backend01$/
|
||||||
done();
|
*/
|
||||||
|
it('should return proper regex for single value', function (done) {
|
||||||
|
var target = '$host';
|
||||||
|
var template_var_value = 'backend01';
|
||||||
|
var expected_result = '/^backend01$/';
|
||||||
|
|
||||||
|
testReplacingVariable(target, template_var_value, expected_result, done);
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Multi-value variable
|
||||||
|
* $host = [backend01, backend02]
|
||||||
|
* $host => /^(backend01|backend01)$/
|
||||||
|
*/
|
||||||
|
it('should return proper regex for multi-value', function (done) {
|
||||||
|
var target = '$host';
|
||||||
|
var template_var_value = ['backend01', 'backend02'];
|
||||||
|
var expected_result = '/^(backend01|backend02)$/';
|
||||||
|
|
||||||
|
testReplacingVariable(target, template_var_value, expected_result, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When invoking metricFindQuery()', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
ctx.ds.replaceTemplateVars = function (str) {
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
ctx.ds.zabbix = {
|
||||||
|
getGroups: jest.fn().mockReturnValue(Q.when([])),
|
||||||
|
getHosts: jest.fn().mockReturnValue(Q.when([])),
|
||||||
|
getApps: jest.fn().mockReturnValue(Q.when([])),
|
||||||
|
getItems: jest.fn().mockReturnValue(Q.when([]))
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return groups', function (done) {
|
||||||
|
var tests = [{ query: '*', expect: '/.*/' }, { query: '', expect: '' }, { query: 'Backend', expect: 'Backend' }, { query: 'Back*', expect: 'Back*' }];
|
||||||
|
|
||||||
|
var _iteratorNormalCompletion = true;
|
||||||
|
var _didIteratorError = false;
|
||||||
|
var _iteratorError = undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (var _iterator = tests[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||||
|
var test = _step.value;
|
||||||
|
|
||||||
|
ctx.ds.metricFindQuery(test.query);
|
||||||
|
expect(ctx.ds.zabbix.getGroups).toBeCalledWith(test.expect);
|
||||||
|
ctx.ds.zabbix.getGroups.mockClear();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
_didIteratorError = true;
|
||||||
|
_iteratorError = err;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (!_iteratorNormalCompletion && _iterator.return) {
|
||||||
|
_iterator.return();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (_didIteratorError) {
|
||||||
|
throw _iteratorError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return hosts', function (done) {
|
||||||
|
var tests = [{ query: '*.*', expect: ['/.*/', '/.*/'] }, { query: '.', expect: ['', ''] }, { query: 'Backend.*', expect: ['Backend', '/.*/'] }, { query: 'Back*.', expect: ['Back*', ''] }];
|
||||||
|
|
||||||
|
var _iteratorNormalCompletion2 = true;
|
||||||
|
var _didIteratorError2 = false;
|
||||||
|
var _iteratorError2 = undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (var _iterator2 = tests[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
||||||
|
var test = _step2.value;
|
||||||
|
|
||||||
|
ctx.ds.metricFindQuery(test.query);
|
||||||
|
expect(ctx.ds.zabbix.getHosts).toBeCalledWith(test.expect[0], test.expect[1]);
|
||||||
|
ctx.ds.zabbix.getHosts.mockClear();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
_didIteratorError2 = true;
|
||||||
|
_iteratorError2 = err;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (!_iteratorNormalCompletion2 && _iterator2.return) {
|
||||||
|
_iterator2.return();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (_didIteratorError2) {
|
||||||
|
throw _iteratorError2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return applications', function (done) {
|
||||||
|
var tests = [{ query: '*.*.*', expect: ['/.*/', '/.*/', '/.*/'] }, { query: '.*.', expect: ['', '/.*/', ''] }, { query: 'Backend.backend01.*', expect: ['Backend', 'backend01', '/.*/'] }, { query: 'Back*.*.', expect: ['Back*', '/.*/', ''] }];
|
||||||
|
|
||||||
|
var _iteratorNormalCompletion3 = true;
|
||||||
|
var _didIteratorError3 = false;
|
||||||
|
var _iteratorError3 = undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (var _iterator3 = tests[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
|
||||||
|
var test = _step3.value;
|
||||||
|
|
||||||
|
ctx.ds.metricFindQuery(test.query);
|
||||||
|
expect(ctx.ds.zabbix.getApps).toBeCalledWith(test.expect[0], test.expect[1], test.expect[2]);
|
||||||
|
ctx.ds.zabbix.getApps.mockClear();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
_didIteratorError3 = true;
|
||||||
|
_iteratorError3 = err;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (!_iteratorNormalCompletion3 && _iterator3.return) {
|
||||||
|
_iterator3.return();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (_didIteratorError3) {
|
||||||
|
throw _iteratorError3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return items', function (done) {
|
||||||
|
var tests = [{ query: '*.*.*.*', expect: ['/.*/', '/.*/', '', '/.*/'] }, { query: '.*.*.*', expect: ['', '/.*/', '', '/.*/'] }, { query: 'Backend.backend01.*.*', expect: ['Backend', 'backend01', '', '/.*/'] }, { query: 'Back*.*.cpu.*', expect: ['Back*', '/.*/', 'cpu', '/.*/'] }];
|
||||||
|
|
||||||
|
var _iteratorNormalCompletion4 = true;
|
||||||
|
var _didIteratorError4 = false;
|
||||||
|
var _iteratorError4 = undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (var _iterator4 = tests[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
|
||||||
|
var test = _step4.value;
|
||||||
|
|
||||||
|
ctx.ds.metricFindQuery(test.query);
|
||||||
|
expect(ctx.ds.zabbix.getItems).toBeCalledWith(test.expect[0], test.expect[1], test.expect[2], test.expect[3]);
|
||||||
|
ctx.ds.zabbix.getItems.mockClear();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
_didIteratorError4 = true;
|
||||||
|
_iteratorError4 = err;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (!_iteratorNormalCompletion4 && _iterator4.return) {
|
||||||
|
_iterator4.return();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (_didIteratorError4) {
|
||||||
|
throw _iteratorError4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should invoke method with proper arguments', function (done) {
|
||||||
|
var query = '*.*';
|
||||||
|
|
||||||
|
ctx.ds.metricFindQuery(query);
|
||||||
|
expect(ctx.ds.zabbix.getHosts).toBeCalledWith('/.*/', '/.*/');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When querying alerts', function () {
|
||||||
|
var options = {};
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
ctx.ds.replaceTemplateVars = function (str) {
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
|
||||||
|
var targetItems = [{
|
||||||
|
"itemid": "1",
|
||||||
|
"name": "test item",
|
||||||
|
"key_": "test.key",
|
||||||
|
"value_type": "3",
|
||||||
|
"hostid": "10631",
|
||||||
|
"status": "0",
|
||||||
|
"state": "0",
|
||||||
|
"hosts": [{ "hostid": "10631", "name": "Test host" }],
|
||||||
|
"item": "Test item"
|
||||||
|
}];
|
||||||
|
ctx.ds.zabbix.getItemsFromTarget = function () {
|
||||||
|
return Promise.resolve(targetItems);
|
||||||
|
};
|
||||||
|
|
||||||
|
options = {
|
||||||
|
"panelId": 10,
|
||||||
|
"targets": [{
|
||||||
|
"application": { "filter": "" },
|
||||||
|
"group": { "filter": "Test group" },
|
||||||
|
"host": { "filter": "Test host" },
|
||||||
|
"item": { "filter": "Test item" }
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return threshold when comparative symbol is `less than`', function () {
|
||||||
|
|
||||||
|
var itemTriggers = [{
|
||||||
|
"triggerid": "15383",
|
||||||
|
"priority": "4",
|
||||||
|
"expression": "{15915}<100"
|
||||||
|
}];
|
||||||
|
|
||||||
|
ctx.ds.zabbix.getAlerts = function () {
|
||||||
|
return Promise.resolve(itemTriggers);
|
||||||
|
};
|
||||||
|
|
||||||
|
return ctx.ds.alertQuery(options).then(function (resp) {
|
||||||
|
expect(resp.thresholds).toHaveLength(1);
|
||||||
|
expect(resp.thresholds[0]).toBe(100);
|
||||||
|
return resp;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return threshold when comparative symbol is `less than or equal`', function () {
|
||||||
|
|
||||||
|
var itemTriggers = [{
|
||||||
|
"triggerid": "15383",
|
||||||
|
"priority": "4",
|
||||||
|
"expression": "{15915}<=100"
|
||||||
|
}];
|
||||||
|
|
||||||
|
ctx.ds.zabbix.getAlerts = function () {
|
||||||
|
return Promise.resolve(itemTriggers);
|
||||||
|
};
|
||||||
|
|
||||||
|
return ctx.ds.alertQuery(options).then(function (resp) {
|
||||||
|
expect(resp.thresholds.length).toBe(1);
|
||||||
|
expect(resp.thresholds[0]).toBe(100);
|
||||||
|
return resp;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return threshold when comparative symbol is `greater than or equal`', function () {
|
||||||
|
|
||||||
|
var itemTriggers = [{
|
||||||
|
"triggerid": "15383",
|
||||||
|
"priority": "4",
|
||||||
|
"expression": "{15915}>=30"
|
||||||
|
}];
|
||||||
|
|
||||||
|
ctx.ds.zabbix.getAlerts = function () {
|
||||||
|
return Promise.resolve(itemTriggers);
|
||||||
|
};
|
||||||
|
|
||||||
|
return ctx.ds.alertQuery(options).then(function (resp) {
|
||||||
|
expect(resp.thresholds.length).toBe(1);
|
||||||
|
expect(resp.thresholds[0]).toBe(30);
|
||||||
|
return resp;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return threshold when comparative symbol is `equal`', function () {
|
||||||
|
|
||||||
|
var itemTriggers = [{
|
||||||
|
"triggerid": "15383",
|
||||||
|
"priority": "4",
|
||||||
|
"expression": "{15915}=50"
|
||||||
|
}];
|
||||||
|
|
||||||
|
ctx.ds.zabbix.getAlerts = function () {
|
||||||
|
return Promise.resolve(itemTriggers);
|
||||||
|
};
|
||||||
|
|
||||||
|
return ctx.ds.alertQuery(options).then(function (resp) {
|
||||||
|
expect(resp.thresholds.length).toBe(1);
|
||||||
|
expect(resp.thresholds[0]).toBe(50);
|
||||||
|
return resp;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('should extract value if regex with capture group is used', (done) => {
|
|
||||||
ctx.options.targets[0].textFilter = "Linux (.*)";
|
|
||||||
ctx.ds.query(ctx.options).then(result => {
|
|
||||||
let tableData = result.data[0];
|
|
||||||
expect(tableData.rows[0][3]).toEqual('last');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should skip item when last value is empty', () => {
|
|
||||||
ctx.ds.zabbix.getItemsFromTarget = jest.fn().mockReturnValue(Promise.resolve([
|
|
||||||
{
|
|
||||||
hosts: [{hostid: "10001", name: "Zabbix server"}],
|
|
||||||
itemid: "10100", name: "System information", key_: "system.uname"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
hosts: [{hostid: "10002", name: "Server02"}],
|
|
||||||
itemid: "90109", name: "System information", key_: "system.uname"
|
|
||||||
}
|
|
||||||
]));
|
|
||||||
|
|
||||||
ctx.options.targets[0].options.skipEmptyValues = true;
|
|
||||||
ctx.ds.zabbix.getHistory = jest.fn().mockReturnValue(Promise.resolve([
|
|
||||||
{clock: "1500010200", itemid:"10100", ns:"900111000", value:"Linux first"},
|
|
||||||
{clock: "1500010300", itemid:"10100", ns:"900111000", value:"Linux 2nd"},
|
|
||||||
{clock: "1500010400", itemid:"10100", ns:"900111000", value:"Linux last"},
|
|
||||||
{clock: "1500010200", itemid:"90109", ns:"900111000", value:"Non empty value"},
|
|
||||||
{clock: "1500010500", itemid:"90109", ns:"900111000", value:""}
|
|
||||||
]));
|
|
||||||
return ctx.ds.query(ctx.options).then(result => {
|
|
||||||
let tableData = result.data[0];
|
|
||||||
expect(tableData.rows.length).toBe(1);
|
|
||||||
expect(tableData.rows[0][3]).toEqual('Linux last');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('When replacing template variables', () => {
|
|
||||||
|
|
||||||
function testReplacingVariable(target, varValue, expectedResult, done) {
|
|
||||||
ctx.ds.templateSrv.replace = () => {
|
|
||||||
return zabbixTemplateFormat(varValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = ctx.ds.replaceTemplateVars(target);
|
|
||||||
expect(result).toBe(expectedResult);
|
|
||||||
done();
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
/*
|
|
||||||
* Alphanumerics, spaces, dots, dashes and underscores
|
|
||||||
* are allowed in Zabbix host name.
|
|
||||||
* 'AaBbCc0123 .-_'
|
|
||||||
*/
|
|
||||||
it('should return properly escaped regex', (done) => {
|
|
||||||
let target = '$host';
|
|
||||||
let template_var_value = 'AaBbCc0123 .-_';
|
|
||||||
let expected_result = '/^AaBbCc0123 \\.-_$/';
|
|
||||||
|
|
||||||
testReplacingVariable(target, template_var_value, expected_result, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Single-value variable
|
|
||||||
* $host = backend01
|
|
||||||
* $host => /^backend01|backend01$/
|
|
||||||
*/
|
|
||||||
it('should return proper regex for single value', (done) => {
|
|
||||||
let target = '$host';
|
|
||||||
let template_var_value = 'backend01';
|
|
||||||
let expected_result = '/^backend01$/';
|
|
||||||
|
|
||||||
testReplacingVariable(target, template_var_value, expected_result, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Multi-value variable
|
|
||||||
* $host = [backend01, backend02]
|
|
||||||
* $host => /^(backend01|backend01)$/
|
|
||||||
*/
|
|
||||||
it('should return proper regex for multi-value', (done) => {
|
|
||||||
let target = '$host';
|
|
||||||
let template_var_value = ['backend01', 'backend02'];
|
|
||||||
let expected_result = '/^(backend01|backend02)$/';
|
|
||||||
|
|
||||||
testReplacingVariable(target, template_var_value, expected_result, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('When invoking metricFindQuery()', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
ctx.ds.replaceTemplateVars = (str) => str;
|
|
||||||
ctx.ds.zabbix = {
|
|
||||||
getGroups: jest.fn().mockReturnValue(Q.when([])),
|
|
||||||
getHosts: jest.fn().mockReturnValue(Q.when([])),
|
|
||||||
getApps: jest.fn().mockReturnValue(Q.when([])),
|
|
||||||
getItems: jest.fn().mockReturnValue(Q.when([]))
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return groups', (done) => {
|
|
||||||
const tests = [
|
|
||||||
{query: '*', expect: '/.*/'},
|
|
||||||
{query: '', expect: ''},
|
|
||||||
{query: 'Backend', expect: 'Backend'},
|
|
||||||
{query: 'Back*', expect: 'Back*'},
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const test of tests) {
|
|
||||||
ctx.ds.metricFindQuery(test.query);
|
|
||||||
expect(ctx.ds.zabbix.getGroups).toBeCalledWith(test.expect);
|
|
||||||
ctx.ds.zabbix.getGroups.mockClear();
|
|
||||||
}
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return hosts', (done) => {
|
|
||||||
const tests = [
|
|
||||||
{query: '*.*', expect: ['/.*/', '/.*/']},
|
|
||||||
{query: '.', expect: ['', '']},
|
|
||||||
{query: 'Backend.*', expect: ['Backend', '/.*/']},
|
|
||||||
{query: 'Back*.', expect: ['Back*', '']},
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const test of tests) {
|
|
||||||
ctx.ds.metricFindQuery(test.query);
|
|
||||||
expect(ctx.ds.zabbix.getHosts).toBeCalledWith(test.expect[0], test.expect[1]);
|
|
||||||
ctx.ds.zabbix.getHosts.mockClear();
|
|
||||||
}
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return applications', (done) => {
|
|
||||||
const tests = [
|
|
||||||
{query: '*.*.*', expect: ['/.*/', '/.*/', '/.*/']},
|
|
||||||
{query: '.*.', expect: ['', '/.*/', '']},
|
|
||||||
{query: 'Backend.backend01.*', expect: ['Backend', 'backend01', '/.*/']},
|
|
||||||
{query: 'Back*.*.', expect: ['Back*', '/.*/', '']}
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const test of tests) {
|
|
||||||
ctx.ds.metricFindQuery(test.query);
|
|
||||||
expect(ctx.ds.zabbix.getApps).toBeCalledWith(test.expect[0], test.expect[1], test.expect[2]);
|
|
||||||
ctx.ds.zabbix.getApps.mockClear();
|
|
||||||
}
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return items', (done) => {
|
|
||||||
const tests = [
|
|
||||||
{query: '*.*.*.*', expect: ['/.*/', '/.*/', '', '/.*/']},
|
|
||||||
{query: '.*.*.*', expect: ['', '/.*/', '', '/.*/']},
|
|
||||||
{query: 'Backend.backend01.*.*', expect: ['Backend', 'backend01', '', '/.*/']},
|
|
||||||
{query: 'Back*.*.cpu.*', expect: ['Back*', '/.*/', 'cpu', '/.*/']}
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const test of tests) {
|
|
||||||
ctx.ds.metricFindQuery(test.query);
|
|
||||||
expect(ctx.ds.zabbix.getItems)
|
|
||||||
.toBeCalledWith(test.expect[0], test.expect[1], test.expect[2], test.expect[3]);
|
|
||||||
ctx.ds.zabbix.getItems.mockClear();
|
|
||||||
}
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should invoke method with proper arguments', (done) => {
|
|
||||||
let query = '*.*';
|
|
||||||
|
|
||||||
ctx.ds.metricFindQuery(query);
|
|
||||||
expect(ctx.ds.zabbix.getHosts).toBeCalledWith('/.*/', '/.*/');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('When querying alerts', () => {
|
|
||||||
let options = {};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
ctx.ds.replaceTemplateVars = (str) => str;
|
|
||||||
|
|
||||||
let targetItems = [{
|
|
||||||
"itemid": "1",
|
|
||||||
"name": "test item",
|
|
||||||
"key_": "test.key",
|
|
||||||
"value_type": "3",
|
|
||||||
"hostid": "10631",
|
|
||||||
"status": "0",
|
|
||||||
"state": "0",
|
|
||||||
"hosts": [{"hostid": "10631", "name": "Test host"}],
|
|
||||||
"item": "Test item"
|
|
||||||
}];
|
|
||||||
ctx.ds.zabbix.getItemsFromTarget = () => Promise.resolve(targetItems);
|
|
||||||
|
|
||||||
options = {
|
|
||||||
"panelId": 10,
|
|
||||||
"targets": [{
|
|
||||||
"application": {"filter": ""},
|
|
||||||
"group": {"filter": "Test group"},
|
|
||||||
"host": {"filter": "Test host"},
|
|
||||||
"item": {"filter": "Test item"},
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return threshold when comparative symbol is `less than`', () => {
|
|
||||||
|
|
||||||
let itemTriggers = [{
|
|
||||||
"triggerid": "15383",
|
|
||||||
"priority": "4",
|
|
||||||
"expression": "{15915}<100",
|
|
||||||
}];
|
|
||||||
|
|
||||||
ctx.ds.zabbix.getAlerts = () => Promise.resolve(itemTriggers);
|
|
||||||
|
|
||||||
return ctx.ds.alertQuery(options)
|
|
||||||
.then(resp => {
|
|
||||||
expect(resp.thresholds).toHaveLength(1);
|
|
||||||
expect(resp.thresholds[0]).toBe(100);
|
|
||||||
return resp;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return threshold when comparative symbol is `less than or equal`', () => {
|
|
||||||
|
|
||||||
let itemTriggers = [{
|
|
||||||
"triggerid": "15383",
|
|
||||||
"priority": "4",
|
|
||||||
"expression": "{15915}<=100",
|
|
||||||
}];
|
|
||||||
|
|
||||||
ctx.ds.zabbix.getAlerts = () => Promise.resolve(itemTriggers);
|
|
||||||
|
|
||||||
return ctx.ds.alertQuery(options)
|
|
||||||
.then(resp => {
|
|
||||||
expect(resp.thresholds.length).toBe(1);
|
|
||||||
expect(resp.thresholds[0]).toBe(100);
|
|
||||||
return resp;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return threshold when comparative symbol is `greater than or equal`', () => {
|
|
||||||
|
|
||||||
let itemTriggers = [{
|
|
||||||
"triggerid": "15383",
|
|
||||||
"priority": "4",
|
|
||||||
"expression": "{15915}>=30",
|
|
||||||
}];
|
|
||||||
|
|
||||||
ctx.ds.zabbix.getAlerts = () => Promise.resolve(itemTriggers);
|
|
||||||
|
|
||||||
return ctx.ds.alertQuery(options)
|
|
||||||
.then(resp => {
|
|
||||||
expect(resp.thresholds.length).toBe(1);
|
|
||||||
expect(resp.thresholds[0]).toBe(30);
|
|
||||||
return resp;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return threshold when comparative symbol is `equal`', () => {
|
|
||||||
|
|
||||||
let itemTriggers = [{
|
|
||||||
"triggerid": "15383",
|
|
||||||
"priority": "4",
|
|
||||||
"expression": "{15915}=50",
|
|
||||||
}];
|
|
||||||
|
|
||||||
ctx.ds.zabbix.getAlerts = () => Promise.resolve(itemTriggers);
|
|
||||||
|
|
||||||
return ctx.ds.alertQuery(options)
|
|
||||||
.then(resp => {
|
|
||||||
expect(resp.thresholds.length).toBe(1);
|
|
||||||
expect(resp.thresholds[0]).toBe(50);
|
|
||||||
return resp;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
//# sourceMappingURL=datasource.spec.js.map
|
||||||
|
|||||||
1
dist/datasource-zabbix/specs/datasource.spec.js.map
vendored
Normal file
1
dist/datasource-zabbix/specs/datasource.spec.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
59
dist/datasource-zabbix/specs/timeseries.spec.js
vendored
59
dist/datasource-zabbix/specs/timeseries.spec.js
vendored
@@ -1,34 +1,41 @@
|
|||||||
// import _ from 'lodash';
|
'use strict';
|
||||||
import ts from '../timeseries';
|
|
||||||
|
|
||||||
describe('timeseries processing functions', () => {
|
System.register(['../timeseries'], function (_export, _context) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
describe('sumSeries()', () => {
|
var ts;
|
||||||
it('should properly sum series', (done) => {
|
return {
|
||||||
let series = [
|
setters: [function (_timeseries) {
|
||||||
[[0, 1], [1, 2], [1, 3]],
|
ts = _timeseries.default;
|
||||||
[[2, 1], [3, 2], [4, 3]]
|
}],
|
||||||
];
|
execute: function () {
|
||||||
|
|
||||||
let expected = [[2, 1], [4, 2], [5, 3]];
|
describe('timeseries processing functions', function () {
|
||||||
|
|
||||||
let result = ts.sumSeries(series);
|
describe('sumSeries()', function () {
|
||||||
expect(result).toEqual(expected);
|
it('should properly sum series', function (done) {
|
||||||
done();
|
var series = [[[0, 1], [1, 2], [1, 3]], [[2, 1], [3, 2], [4, 3]]];
|
||||||
});
|
|
||||||
|
|
||||||
it('should properly sum series with nulls', (done) => {
|
var expected = [[2, 1], [4, 2], [5, 3]];
|
||||||
// issue #286
|
|
||||||
let series = [
|
|
||||||
[[1, 1], [1, 2], [1, 3]],
|
|
||||||
[[3, 2], [4, 3]]
|
|
||||||
];
|
|
||||||
|
|
||||||
let expected = [[1, 1], [4, 2], [5, 3]];
|
var result = ts.sumSeries(series);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
let result = ts.sumSeries(series);
|
it('should properly sum series with nulls', function (done) {
|
||||||
expect(result).toEqual(expected);
|
// issue #286
|
||||||
done();
|
var series = [[[1, 1], [1, 2], [1, 3]], [[3, 2], [4, 3]]];
|
||||||
});
|
|
||||||
});
|
var expected = [[1, 1], [4, 2], [5, 3]];
|
||||||
|
|
||||||
|
var result = ts.sumSeries(series);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}); // import _ from 'lodash';
|
||||||
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
//# sourceMappingURL=timeseries.spec.js.map
|
||||||
|
|||||||
1
dist/datasource-zabbix/specs/timeseries.spec.js.map
vendored
Normal file
1
dist/datasource-zabbix/specs/timeseries.spec.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["../../../src/datasource-zabbix/specs/timeseries.spec.js"],"names":["ts","describe","it","done","series","expected","result","sumSeries","expect","toEqual"],"mappings":";;;;;;;;AACOA,Q;;;;AAEPC,eAAS,iCAAT,EAA4C,YAAM;;AAEhDA,iBAAS,aAAT,EAAwB,YAAM;AAC5BC,aAAG,4BAAH,EAAiC,UAACC,IAAD,EAAU;AACzC,gBAAIC,SAAS,CACX,CAAC,CAAC,CAAD,EAAI,CAAJ,CAAD,EAAS,CAAC,CAAD,EAAI,CAAJ,CAAT,EAAiB,CAAC,CAAD,EAAI,CAAJ,CAAjB,CADW,EAEX,CAAC,CAAC,CAAD,EAAI,CAAJ,CAAD,EAAS,CAAC,CAAD,EAAI,CAAJ,CAAT,EAAiB,CAAC,CAAD,EAAI,CAAJ,CAAjB,CAFW,CAAb;;AAKA,gBAAIC,WAAW,CAAC,CAAC,CAAD,EAAI,CAAJ,CAAD,EAAS,CAAC,CAAD,EAAI,CAAJ,CAAT,EAAiB,CAAC,CAAD,EAAI,CAAJ,CAAjB,CAAf;;AAEA,gBAAIC,SAASN,GAAGO,SAAH,CAAaH,MAAb,CAAb;AACAI,mBAAOF,MAAP,EAAeG,OAAf,CAAuBJ,QAAvB;AACAF;AACD,WAXD;;AAaAD,aAAG,uCAAH,EAA4C,UAACC,IAAD,EAAU;AACpD;AACA,gBAAIC,SAAS,CACX,CAAC,CAAC,CAAD,EAAI,CAAJ,CAAD,EAAS,CAAC,CAAD,EAAI,CAAJ,CAAT,EAAiB,CAAC,CAAD,EAAI,CAAJ,CAAjB,CADW,EAEX,CAAC,CAAC,CAAD,EAAI,CAAJ,CAAD,EAAS,CAAC,CAAD,EAAI,CAAJ,CAAT,CAFW,CAAb;;AAKA,gBAAIC,WAAW,CAAC,CAAC,CAAD,EAAI,CAAJ,CAAD,EAAS,CAAC,CAAD,EAAI,CAAJ,CAAT,EAAiB,CAAC,CAAD,EAAI,CAAJ,CAAjB,CAAf;;AAEA,gBAAIC,SAASN,GAAGO,SAAH,CAAaH,MAAb,CAAb;AACAI,mBAAOF,MAAP,EAAeG,OAAf,CAAuBJ,QAAvB;AACAF;AACD,WAZD;AAaD,SA3BD;AA4BD,OA9BD,E,CAHA","file":"timeseries.spec.js","sourcesContent":["// import _ from 'lodash';\nimport ts from '../timeseries';\n\ndescribe('timeseries processing functions', () => {\n\n describe('sumSeries()', () => {\n it('should properly sum series', (done) => {\n let series = [\n [[0, 1], [1, 2], [1, 3]],\n [[2, 1], [3, 2], [4, 3]]\n ];\n\n let expected = [[2, 1], [4, 2], [5, 3]];\n\n let result = ts.sumSeries(series);\n expect(result).toEqual(expected);\n done();\n });\n\n it('should properly sum series with nulls', (done) => {\n // issue #286\n let series = [\n [[1, 1], [1, 2], [1, 3]],\n [[3, 2], [4, 3]]\n ];\n\n let expected = [[1, 1], [4, 2], [5, 3]];\n\n let result = ts.sumSeries(series);\n expect(result).toEqual(expected);\n done();\n });\n });\n});\n"]}
|
||||||
265
dist/datasource-zabbix/specs/utils.spec.js
vendored
265
dist/datasource-zabbix/specs/utils.spec.js
vendored
@@ -1,141 +1,136 @@
|
|||||||
import _ from 'lodash';
|
'use strict';
|
||||||
import * as utils from '../utils';
|
|
||||||
|
|
||||||
describe('Utils', () => {
|
System.register(['lodash', '../utils'], function (_export, _context) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
describe('expandItemName()', () => {
|
var _, utils;
|
||||||
|
|
||||||
it('should properly expand unquoted params', (done) => {
|
return {
|
||||||
let test_cases = [
|
setters: [function (_lodash) {
|
||||||
{
|
_ = _lodash.default;
|
||||||
name: `CPU $2 time`,
|
}, function (_utils) {
|
||||||
key: `system.cpu.util[,user,avg1]`,
|
utils = _utils;
|
||||||
expected: "CPU user time"
|
}],
|
||||||
},
|
execute: function () {
|
||||||
{
|
|
||||||
name: `CPU $2 time - $3`,
|
|
||||||
key: `system.cpu.util[,system,avg1]`,
|
|
||||||
expected: "CPU system time - avg1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `CPU - $1 - $2 - $3`,
|
|
||||||
key: `system.cpu.util[,system,avg1]`,
|
|
||||||
expected: "CPU - - system - avg1"
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
_.each(test_cases, test_case => {
|
describe('Utils', function () {
|
||||||
let expandedName = utils.expandItemName(test_case.name, test_case.key);
|
|
||||||
expect(expandedName).toBe(test_case.expected);
|
describe('expandItemName()', function () {
|
||||||
|
|
||||||
|
it('should properly expand unquoted params', function (done) {
|
||||||
|
var test_cases = [{
|
||||||
|
name: 'CPU $2 time',
|
||||||
|
key: 'system.cpu.util[,user,avg1]',
|
||||||
|
expected: "CPU user time"
|
||||||
|
}, {
|
||||||
|
name: 'CPU $2 time - $3',
|
||||||
|
key: 'system.cpu.util[,system,avg1]',
|
||||||
|
expected: "CPU system time - avg1"
|
||||||
|
}, {
|
||||||
|
name: 'CPU - $1 - $2 - $3',
|
||||||
|
key: 'system.cpu.util[,system,avg1]',
|
||||||
|
expected: "CPU - - system - avg1"
|
||||||
|
}];
|
||||||
|
|
||||||
|
_.each(test_cases, function (test_case) {
|
||||||
|
var expandedName = utils.expandItemName(test_case.name, test_case.key);
|
||||||
|
expect(expandedName).toBe(test_case.expected);
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should properly expand quoted params with commas', function (done) {
|
||||||
|
var test_cases = [{
|
||||||
|
name: 'CPU $2 time',
|
||||||
|
key: 'system.cpu.util["type=user,value=avg",user]',
|
||||||
|
expected: "CPU user time"
|
||||||
|
}, {
|
||||||
|
name: 'CPU $1 time',
|
||||||
|
key: 'system.cpu.util["type=user,value=avg","user"]',
|
||||||
|
expected: "CPU type=user,value=avg time"
|
||||||
|
}, {
|
||||||
|
name: 'CPU $1 time $3',
|
||||||
|
key: 'system.cpu.util["type=user,value=avg",,"user"]',
|
||||||
|
expected: "CPU type=user,value=avg time user"
|
||||||
|
}, {
|
||||||
|
name: 'CPU $1 $2 $3',
|
||||||
|
key: 'system.cpu.util["type=user,value=avg",time,"user"]',
|
||||||
|
expected: "CPU type=user,value=avg time user"
|
||||||
|
}];
|
||||||
|
|
||||||
|
_.each(test_cases, function (test_case) {
|
||||||
|
var expandedName = utils.expandItemName(test_case.name, test_case.key);
|
||||||
|
expect(expandedName).toBe(test_case.expected);
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should properly expand array params', function (done) {
|
||||||
|
var test_cases = [{
|
||||||
|
name: 'CPU $2 - $3 time',
|
||||||
|
key: 'system.cpu.util[,[user,system],avg1]',
|
||||||
|
expected: "CPU user,system - avg1 time"
|
||||||
|
}, {
|
||||||
|
name: 'CPU $2 - $3 time',
|
||||||
|
key: 'system.cpu.util[,["user,system",iowait],avg1]',
|
||||||
|
expected: 'CPU "user,system",iowait - avg1 time'
|
||||||
|
}, {
|
||||||
|
name: 'CPU - $2 - $3 - $4',
|
||||||
|
key: 'system.cpu.util[,[],["user,system",iowait],avg1]',
|
||||||
|
expected: 'CPU - - "user,system",iowait - avg1'
|
||||||
|
}];
|
||||||
|
|
||||||
|
_.each(test_cases, function (test_case) {
|
||||||
|
var expandedName = utils.expandItemName(test_case.name, test_case.key);
|
||||||
|
expect(expandedName).toBe(test_case.expected);
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('splitTemplateQuery()', function () {
|
||||||
|
|
||||||
|
// Backward compatibility
|
||||||
|
it('should properly split query in old format', function (done) {
|
||||||
|
var test_cases = [{
|
||||||
|
query: '/alu/./tw-(nyc|que|brx|dwt|brk)-sta_(w|d)*-alu-[0-9{2}/',
|
||||||
|
expected: ['/alu/', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9{2}/']
|
||||||
|
}, {
|
||||||
|
query: 'a.b.c.d',
|
||||||
|
expected: ['a', 'b', 'c', 'd']
|
||||||
|
}];
|
||||||
|
|
||||||
|
_.each(test_cases, function (test_case) {
|
||||||
|
var splitQuery = utils.splitTemplateQuery(test_case.query);
|
||||||
|
expect(splitQuery).toEqual(test_case.expected);
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should properly split query', function (done) {
|
||||||
|
var test_cases = [{
|
||||||
|
query: '{alu}{/tw-(nyc|que|brx|dwt|brk)-sta_(w|d)*-alu-[0-9]*/}',
|
||||||
|
expected: ['alu', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]*/']
|
||||||
|
}, {
|
||||||
|
query: '{alu}{/tw-(nyc|que|brx|dwt|brk)-sta_(w|d)*-alu-[0-9]{2}/}',
|
||||||
|
expected: ['alu', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]{2}/']
|
||||||
|
}, {
|
||||||
|
query: '{a}{b}{c}{d}',
|
||||||
|
expected: ['a', 'b', 'c', 'd']
|
||||||
|
}, {
|
||||||
|
query: '{a}{b.c.d}',
|
||||||
|
expected: ['a', 'b.c.d']
|
||||||
|
}];
|
||||||
|
|
||||||
|
_.each(test_cases, function (test_case) {
|
||||||
|
var splitQuery = utils.splitTemplateQuery(test_case.query);
|
||||||
|
expect(splitQuery).toEqual(test_case.expected);
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
done();
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
it('should properly expand quoted params with commas', (done) => {
|
|
||||||
let test_cases = [
|
|
||||||
{
|
|
||||||
name: `CPU $2 time`,
|
|
||||||
key: `system.cpu.util["type=user,value=avg",user]`,
|
|
||||||
expected: "CPU user time"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `CPU $1 time`,
|
|
||||||
key: `system.cpu.util["type=user,value=avg","user"]`,
|
|
||||||
expected: "CPU type=user,value=avg time"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `CPU $1 time $3`,
|
|
||||||
key: `system.cpu.util["type=user,value=avg",,"user"]`,
|
|
||||||
expected: "CPU type=user,value=avg time user"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `CPU $1 $2 $3`,
|
|
||||||
key: `system.cpu.util["type=user,value=avg",time,"user"]`,
|
|
||||||
expected: "CPU type=user,value=avg time user"
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
_.each(test_cases, test_case => {
|
|
||||||
let expandedName = utils.expandItemName(test_case.name, test_case.key);
|
|
||||||
expect(expandedName).toBe(test_case.expected);
|
|
||||||
});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should properly expand array params', (done) => {
|
|
||||||
let test_cases = [
|
|
||||||
{
|
|
||||||
name: `CPU $2 - $3 time`,
|
|
||||||
key: `system.cpu.util[,[user,system],avg1]`,
|
|
||||||
expected: "CPU user,system - avg1 time"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `CPU $2 - $3 time`,
|
|
||||||
key: `system.cpu.util[,["user,system",iowait],avg1]`,
|
|
||||||
expected: `CPU "user,system",iowait - avg1 time`
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `CPU - $2 - $3 - $4`,
|
|
||||||
key: `system.cpu.util[,[],["user,system",iowait],avg1]`,
|
|
||||||
expected: `CPU - - "user,system",iowait - avg1`
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
_.each(test_cases, test_case => {
|
|
||||||
let expandedName = utils.expandItemName(test_case.name, test_case.key);
|
|
||||||
expect(expandedName).toBe(test_case.expected);
|
|
||||||
});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('splitTemplateQuery()', () => {
|
|
||||||
|
|
||||||
// Backward compatibility
|
|
||||||
it('should properly split query in old format', (done) => {
|
|
||||||
let test_cases = [
|
|
||||||
{
|
|
||||||
query: `/alu/./tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9{2}/`,
|
|
||||||
expected: ['/alu/', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9{2}/']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
query: `a.b.c.d`,
|
|
||||||
expected: ['a', 'b', 'c', 'd']
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
_.each(test_cases, test_case => {
|
|
||||||
let splitQuery = utils.splitTemplateQuery(test_case.query);
|
|
||||||
expect(splitQuery).toEqual(test_case.expected);
|
|
||||||
});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should properly split query', (done) => {
|
|
||||||
let test_cases = [
|
|
||||||
{
|
|
||||||
query: `{alu}{/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]*/}`,
|
|
||||||
expected: ['alu', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]*/']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
query: `{alu}{/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]{2}/}`,
|
|
||||||
expected: ['alu', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]{2}/']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
query: `{a}{b}{c}{d}`,
|
|
||||||
expected: ['a', 'b', 'c', 'd']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
query: `{a}{b.c.d}`,
|
|
||||||
expected: ['a', 'b.c.d']
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
_.each(test_cases, test_case => {
|
|
||||||
let splitQuery = utils.splitTemplateQuery(test_case.query);
|
|
||||||
expect(splitQuery).toEqual(test_case.expected);
|
|
||||||
});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
//# sourceMappingURL=utils.spec.js.map
|
||||||
|
|||||||
1
dist/datasource-zabbix/specs/utils.spec.js.map
vendored
Normal file
1
dist/datasource-zabbix/specs/utils.spec.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
384
dist/datasource-zabbix/zabbix.js
vendored
384
dist/datasource-zabbix/zabbix.js
vendored
@@ -1,384 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './zabbixCachingProxy.service.js', './zabbixDBConnector'], function (_export, _context) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var angular, _, utils, _slicedToArray, _createClass;
|
|
||||||
|
|
||||||
function _toConsumableArray(arr) {
|
|
||||||
if (Array.isArray(arr)) {
|
|
||||||
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
|
|
||||||
arr2[i] = arr[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return arr2;
|
|
||||||
} else {
|
|
||||||
return Array.from(arr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _classCallCheck(instance, Constructor) {
|
|
||||||
if (!(instance instanceof Constructor)) {
|
|
||||||
throw new TypeError("Cannot call a class as a function");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use factory() instead service() for multiple data sources support.
|
|
||||||
// Each Zabbix data source instance should initialize its own API instance.
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy, ZabbixDBConnector) {
|
|
||||||
var Zabbix = function () {
|
|
||||||
function Zabbix(url, options) {
|
|
||||||
_classCallCheck(this, Zabbix);
|
|
||||||
|
|
||||||
var username = options.username,
|
|
||||||
password = options.password,
|
|
||||||
basicAuth = options.basicAuth,
|
|
||||||
withCredentials = options.withCredentials,
|
|
||||||
cacheTTL = options.cacheTTL,
|
|
||||||
enableDirectDBConnection = options.enableDirectDBConnection,
|
|
||||||
sqlDatasourceId = options.sqlDatasourceId;
|
|
||||||
|
|
||||||
|
|
||||||
// Initialize Zabbix API
|
|
||||||
var ZabbixAPI = zabbixAPIService;
|
|
||||||
this.zabbixAPI = new ZabbixAPI(url, username, password, basicAuth, withCredentials);
|
|
||||||
|
|
||||||
if (enableDirectDBConnection) {
|
|
||||||
this.dbConnector = new ZabbixDBConnector(sqlDatasourceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize caching proxy for requests
|
|
||||||
var cacheOptions = {
|
|
||||||
enabled: true,
|
|
||||||
ttl: cacheTTL
|
|
||||||
};
|
|
||||||
this.cachingProxy = new ZabbixCachingProxy(this.zabbixAPI, this.dbConnector, cacheOptions);
|
|
||||||
|
|
||||||
// Proxy methods
|
|
||||||
this.getHistory = this.cachingProxy.getHistory.bind(this.cachingProxy);
|
|
||||||
this.getMacros = this.cachingProxy.getMacros.bind(this.cachingProxy);
|
|
||||||
this.getItemsByIDs = this.cachingProxy.getItemsByIDs.bind(this.cachingProxy);
|
|
||||||
|
|
||||||
if (enableDirectDBConnection) {
|
|
||||||
this.getHistoryDB = this.cachingProxy.getHistoryDB.bind(this.cachingProxy);
|
|
||||||
this.getTrendsDB = this.cachingProxy.getTrendsDB.bind(this.cachingProxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.getTrend = this.zabbixAPI.getTrend.bind(this.zabbixAPI);
|
|
||||||
this.getEvents = this.zabbixAPI.getEvents.bind(this.zabbixAPI);
|
|
||||||
this.getAlerts = this.zabbixAPI.getAlerts.bind(this.zabbixAPI);
|
|
||||||
this.getHostAlerts = this.zabbixAPI.getHostAlerts.bind(this.zabbixAPI);
|
|
||||||
this.getAcknowledges = this.zabbixAPI.getAcknowledges.bind(this.zabbixAPI);
|
|
||||||
this.getITService = this.zabbixAPI.getITService.bind(this.zabbixAPI);
|
|
||||||
this.getSLA = this.zabbixAPI.getSLA.bind(this.zabbixAPI);
|
|
||||||
this.getVersion = this.zabbixAPI.getVersion.bind(this.zabbixAPI);
|
|
||||||
this.login = this.zabbixAPI.login.bind(this.zabbixAPI);
|
|
||||||
}
|
|
||||||
|
|
||||||
_createClass(Zabbix, [{
|
|
||||||
key: 'getItemsFromTarget',
|
|
||||||
value: function getItemsFromTarget(target, options) {
|
|
||||||
var parts = ['group', 'host', 'application', 'item'];
|
|
||||||
var filters = _.map(parts, function (p) {
|
|
||||||
return target[p].filter;
|
|
||||||
});
|
|
||||||
return this.getItems.apply(this, _toConsumableArray(filters).concat([options]));
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getHostsFromTarget',
|
|
||||||
value: function getHostsFromTarget(target) {
|
|
||||||
var parts = ['group', 'host', 'application'];
|
|
||||||
var filters = _.map(parts, function (p) {
|
|
||||||
return target[p].filter;
|
|
||||||
});
|
|
||||||
return Promise.all([this.getHosts.apply(this, _toConsumableArray(filters)), this.getApps.apply(this, _toConsumableArray(filters))]).then(function (results) {
|
|
||||||
var _results = _slicedToArray(results, 2),
|
|
||||||
hosts = _results[0],
|
|
||||||
apps = _results[1];
|
|
||||||
|
|
||||||
if (apps.appFilterEmpty) {
|
|
||||||
apps = [];
|
|
||||||
}
|
|
||||||
return [hosts, apps];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getAllGroups',
|
|
||||||
value: function getAllGroups() {
|
|
||||||
return this.cachingProxy.getGroups();
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getGroups',
|
|
||||||
value: function getGroups(groupFilter) {
|
|
||||||
return this.getAllGroups().then(function (groups) {
|
|
||||||
return findByFilter(groups, groupFilter);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getAllHosts',
|
|
||||||
value: function getAllHosts(groupFilter) {
|
|
||||||
var _this = this;
|
|
||||||
|
|
||||||
return this.getGroups(groupFilter).then(function (groups) {
|
|
||||||
var groupids = _.map(groups, 'groupid');
|
|
||||||
return _this.cachingProxy.getHosts(groupids);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getHosts',
|
|
||||||
value: function getHosts(groupFilter, hostFilter) {
|
|
||||||
return this.getAllHosts(groupFilter).then(function (hosts) {
|
|
||||||
return findByFilter(hosts, hostFilter);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getAllApps',
|
|
||||||
value: function getAllApps(groupFilter, hostFilter) {
|
|
||||||
var _this2 = this;
|
|
||||||
|
|
||||||
return this.getHosts(groupFilter, hostFilter).then(function (hosts) {
|
|
||||||
var hostids = _.map(hosts, 'hostid');
|
|
||||||
return _this2.cachingProxy.getApps(hostids);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getApps',
|
|
||||||
value: function getApps(groupFilter, hostFilter, appFilter) {
|
|
||||||
var _this3 = this;
|
|
||||||
|
|
||||||
return this.getHosts(groupFilter, hostFilter).then(function (hosts) {
|
|
||||||
var hostids = _.map(hosts, 'hostid');
|
|
||||||
if (appFilter) {
|
|
||||||
return _this3.cachingProxy.getApps(hostids).then(function (apps) {
|
|
||||||
return filterByQuery(apps, appFilter);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
appFilterEmpty: true,
|
|
||||||
hostids: hostids
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getAllItems',
|
|
||||||
value: function getAllItems(groupFilter, hostFilter, appFilter) {
|
|
||||||
var _this4 = this;
|
|
||||||
|
|
||||||
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
||||||
|
|
||||||
return this.getApps(groupFilter, hostFilter, appFilter).then(function (apps) {
|
|
||||||
if (apps.appFilterEmpty) {
|
|
||||||
return _this4.cachingProxy.getItems(apps.hostids, undefined, options.itemtype);
|
|
||||||
} else {
|
|
||||||
var appids = _.map(apps, 'applicationid');
|
|
||||||
return _this4.cachingProxy.getItems(undefined, appids, options.itemtype);
|
|
||||||
}
|
|
||||||
}).then(function (items) {
|
|
||||||
if (!options.showDisabledItems) {
|
|
||||||
items = _.filter(items, { 'status': '0' });
|
|
||||||
}
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}).then(this.expandUserMacro.bind(this));
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'expandUserMacro',
|
|
||||||
value: function expandUserMacro(items) {
|
|
||||||
var hostids = getHostIds(items);
|
|
||||||
return this.getMacros(hostids).then(function (macros) {
|
|
||||||
_.forEach(items, function (item) {
|
|
||||||
if (utils.containsMacro(item.name)) {
|
|
||||||
item.name = utils.replaceMacro(item, macros);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return items;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getItems',
|
|
||||||
value: function getItems(groupFilter, hostFilter, appFilter, itemFilter) {
|
|
||||||
var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
|
||||||
|
|
||||||
return this.getAllItems(groupFilter, hostFilter, appFilter, options).then(function (items) {
|
|
||||||
return filterByQuery(items, itemFilter);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getITServices',
|
|
||||||
value: function getITServices(itServiceFilter) {
|
|
||||||
return this.cachingProxy.getITServices().then(function (itServices) {
|
|
||||||
return findByFilter(itServices, itServiceFilter);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getTriggers',
|
|
||||||
value: function getTriggers(groupFilter, hostFilter, appFilter, options) {
|
|
||||||
var _this5 = this;
|
|
||||||
|
|
||||||
var promises = [this.getGroups(groupFilter), this.getHosts(groupFilter, hostFilter), this.getApps(groupFilter, hostFilter, appFilter)];
|
|
||||||
|
|
||||||
return Promise.all(promises).then(function (results) {
|
|
||||||
var filteredGroups = results[0];
|
|
||||||
var filteredHosts = results[1];
|
|
||||||
var filteredApps = results[2];
|
|
||||||
var query = {};
|
|
||||||
|
|
||||||
if (appFilter) {
|
|
||||||
query.applicationids = _.flatten(_.map(filteredApps, 'applicationid'));
|
|
||||||
}
|
|
||||||
if (hostFilter) {
|
|
||||||
query.hostids = _.map(filteredHosts, 'hostid');
|
|
||||||
}
|
|
||||||
if (groupFilter) {
|
|
||||||
query.groupids = _.map(filteredGroups, 'groupid');
|
|
||||||
}
|
|
||||||
|
|
||||||
return query;
|
|
||||||
}).then(function (query) {
|
|
||||||
return _this5.zabbixAPI.getTriggers(query.groupids, query.hostids, query.applicationids, options);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}]);
|
|
||||||
|
|
||||||
return Zabbix;
|
|
||||||
}();
|
|
||||||
|
|
||||||
return Zabbix;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find group, host, app or item by given name.
|
|
||||||
* @param list list of groups, apps or other
|
|
||||||
* @param name visible name
|
|
||||||
* @return array with finded element or empty array
|
|
||||||
*/
|
|
||||||
function findByName(list, name) {
|
|
||||||
var finded = _.find(list, { 'name': name });
|
|
||||||
if (finded) {
|
|
||||||
return [finded];
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Different hosts can contains applications and items with same name.
|
|
||||||
* For this reason use _.filter, which return all elements instead _.find,
|
|
||||||
* which return only first finded.
|
|
||||||
* @param {[type]} list list of elements
|
|
||||||
* @param {[type]} name app name
|
|
||||||
* @return {[type]} array with finded element or empty array
|
|
||||||
*/
|
|
||||||
function filterByName(list, name) {
|
|
||||||
var finded = _.filter(list, { 'name': name });
|
|
||||||
if (finded) {
|
|
||||||
return finded;
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterByRegex(list, regex) {
|
|
||||||
var filterPattern = utils.buildRegex(regex);
|
|
||||||
return _.filter(list, function (zbx_obj) {
|
|
||||||
return filterPattern.test(zbx_obj.name);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function findByFilter(list, filter) {
|
|
||||||
if (utils.isRegex(filter)) {
|
|
||||||
return filterByRegex(list, filter);
|
|
||||||
} else {
|
|
||||||
return findByName(list, filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterByQuery(list, filter) {
|
|
||||||
if (utils.isRegex(filter)) {
|
|
||||||
return filterByRegex(list, filter);
|
|
||||||
} else {
|
|
||||||
return filterByName(list, filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getHostIds(items) {
|
|
||||||
var hostIds = _.map(items, function (item) {
|
|
||||||
return _.map(item.hosts, 'hostid');
|
|
||||||
});
|
|
||||||
return _.uniq(_.flatten(hostIds));
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
setters: [function (_angular) {
|
|
||||||
angular = _angular.default;
|
|
||||||
}, function (_lodash) {
|
|
||||||
_ = _lodash.default;
|
|
||||||
}, function (_utils) {
|
|
||||||
utils = _utils;
|
|
||||||
}, function (_zabbixAPIServiceJs) {}, function (_zabbixCachingProxyServiceJs) {}, function (_zabbixDBConnector) {}],
|
|
||||||
execute: function () {
|
|
||||||
_slicedToArray = function () {
|
|
||||||
function sliceIterator(arr, i) {
|
|
||||||
var _arr = [];
|
|
||||||
var _n = true;
|
|
||||||
var _d = false;
|
|
||||||
var _e = undefined;
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
|
|
||||||
_arr.push(_s.value);
|
|
||||||
|
|
||||||
if (i && _arr.length === i) break;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
_d = true;
|
|
||||||
_e = err;
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (!_n && _i["return"]) _i["return"]();
|
|
||||||
} finally {
|
|
||||||
if (_d) throw _e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return _arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return function (arr, i) {
|
|
||||||
if (Array.isArray(arr)) {
|
|
||||||
return arr;
|
|
||||||
} else if (Symbol.iterator in Object(arr)) {
|
|
||||||
return sliceIterator(arr, i);
|
|
||||||
} else {
|
|
||||||
throw new TypeError("Invalid attempt to destructure non-iterable instance");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}();
|
|
||||||
|
|
||||||
_createClass = function () {
|
|
||||||
function defineProperties(target, props) {
|
|
||||||
for (var i = 0; i < props.length; i++) {
|
|
||||||
var descriptor = props[i];
|
|
||||||
descriptor.enumerable = descriptor.enumerable || false;
|
|
||||||
descriptor.configurable = true;
|
|
||||||
if ("value" in descriptor) descriptor.writable = true;
|
|
||||||
Object.defineProperty(target, descriptor.key, descriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return function (Constructor, protoProps, staticProps) {
|
|
||||||
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
|
||||||
if (staticProps) defineProperties(Constructor, staticProps);
|
|
||||||
return Constructor;
|
|
||||||
};
|
|
||||||
}();
|
|
||||||
|
|
||||||
angular.module('grafana.services').factory('Zabbix', ZabbixFactory);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
//# sourceMappingURL=zabbix.js.map
|
|
||||||
1
dist/datasource-zabbix/zabbix.js.map
vendored
1
dist/datasource-zabbix/zabbix.js.map
vendored
File diff suppressed because one or more lines are too long
89
dist/datasource-zabbix/zabbix/connectors/dbConnector.js
vendored
Normal file
89
dist/datasource-zabbix/zabbix/connectors/dbConnector.js
vendored
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
System.register(['lodash'], function (_export, _context) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var _, _createClass, NOT_IMPLEMENTED, DBConnector;
|
||||||
|
|
||||||
|
function _classCallCheck(instance, Constructor) {
|
||||||
|
if (!(instance instanceof Constructor)) {
|
||||||
|
throw new TypeError("Cannot call a class as a function");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
setters: [function (_lodash) {
|
||||||
|
_ = _lodash.default;
|
||||||
|
}],
|
||||||
|
execute: function () {
|
||||||
|
_createClass = function () {
|
||||||
|
function defineProperties(target, props) {
|
||||||
|
for (var i = 0; i < props.length; i++) {
|
||||||
|
var descriptor = props[i];
|
||||||
|
descriptor.enumerable = descriptor.enumerable || false;
|
||||||
|
descriptor.configurable = true;
|
||||||
|
if ("value" in descriptor) descriptor.writable = true;
|
||||||
|
Object.defineProperty(target, descriptor.key, descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return function (Constructor, protoProps, staticProps) {
|
||||||
|
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
||||||
|
if (staticProps) defineProperties(Constructor, staticProps);
|
||||||
|
return Constructor;
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
NOT_IMPLEMENTED = 'Method should be implemented in subclass of DBConnector';
|
||||||
|
|
||||||
|
DBConnector = function () {
|
||||||
|
function DBConnector(options, backendSrv, datasourceSrv) {
|
||||||
|
_classCallCheck(this, DBConnector);
|
||||||
|
|
||||||
|
this.backendSrv = backendSrv;
|
||||||
|
this.datasourceSrv = datasourceSrv;
|
||||||
|
this.datasourceId = options.datasourceId;
|
||||||
|
this.datasourceName = options.datasourceName;
|
||||||
|
this.datasourceType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_createClass(DBConnector, [{
|
||||||
|
key: 'loadDBDataSource',
|
||||||
|
value: function loadDBDataSource() {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
var ds = _.find(this.datasourceSrv.getAll(), { 'id': this.datasourceId });
|
||||||
|
if (ds) {
|
||||||
|
return this.datasourceSrv.loadDatasource(ds.name).then(function (ds) {
|
||||||
|
_this.datasourceType = ds.meta.id;
|
||||||
|
return ds;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Promise.reject('SQL Data Source with ID ' + this.datasourceId + ' not found');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'testDataSource',
|
||||||
|
value: function testDataSource() {
|
||||||
|
throw NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getHistory',
|
||||||
|
value: function getHistory() {
|
||||||
|
throw NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getTrends',
|
||||||
|
value: function getTrends() {
|
||||||
|
throw NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return DBConnector;
|
||||||
|
}();
|
||||||
|
|
||||||
|
_export('default', DBConnector);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=dbConnector.js.map
|
||||||
1
dist/datasource-zabbix/zabbix/connectors/dbConnector.js.map
vendored
Normal file
1
dist/datasource-zabbix/zabbix/connectors/dbConnector.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["../../../../src/datasource-zabbix/zabbix/connectors/dbConnector.js"],"names":["_","NOT_IMPLEMENTED","DBConnector","options","backendSrv","datasourceSrv","datasourceId","datasourceName","datasourceType","ds","find","getAll","loadDatasource","name","then","meta","id","Promise","reject"],"mappings":";;;;;;;;;;;;;;;AAAOA,O;;;;;;;;;;;;;;;;;;;;;AAEDC,qB,GAAkB,yD;;AAEHC,iB;AACnB,6BAAYC,OAAZ,EAAqBC,UAArB,EAAiCC,aAAjC,EAAgD;AAAA;;AAC9C,eAAKD,UAAL,GAAkBA,UAAlB;AACA,eAAKC,aAAL,GAAqBA,aAArB;AACA,eAAKC,YAAL,GAAoBH,QAAQG,YAA5B;AACA,eAAKC,cAAL,GAAsBJ,QAAQI,cAA9B;AACA,eAAKC,cAAL,GAAsB,IAAtB;AACD;;;;6CAEkB;AAAA;;AACjB,gBAAIC,KAAKT,EAAEU,IAAF,CAAO,KAAKL,aAAL,CAAmBM,MAAnB,EAAP,EAAoC,EAAC,MAAM,KAAKL,YAAZ,EAApC,CAAT;AACA,gBAAIG,EAAJ,EAAQ;AACN,qBAAO,KAAKJ,aAAL,CAAmBO,cAAnB,CAAkCH,GAAGI,IAArC,EACNC,IADM,CACD,cAAM;AACV,sBAAKN,cAAL,GAAsBC,GAAGM,IAAH,CAAQC,EAA9B;AACA,uBAAOP,EAAP;AACD,eAJM,CAAP;AAKD,aAND,MAMO;AACL,qBAAOQ,QAAQC,MAAR,8BAA0C,KAAKZ,YAA/C,gBAAP;AACD;AACF;;;2CAEgB;AACf,kBAAML,eAAN;AACD;;;uCAEY;AACX,kBAAMA,eAAN;AACD;;;sCAEW;AACV,kBAAMA,eAAN;AACD;;;;;;yBAhCkBC,W","file":"dbConnector.js","sourcesContent":["import _ from 'lodash';\n\nconst NOT_IMPLEMENTED = 'Method should be implemented in subclass of DBConnector';\n\nexport default class DBConnector {\n constructor(options, backendSrv, datasourceSrv) {\n this.backendSrv = backendSrv;\n this.datasourceSrv = datasourceSrv;\n this.datasourceId = options.datasourceId;\n this.datasourceName = options.datasourceName;\n this.datasourceType = null;\n }\n\n loadDBDataSource() {\n let ds = _.find(this.datasourceSrv.getAll(), {'id': this.datasourceId});\n if (ds) {\n return this.datasourceSrv.loadDatasource(ds.name)\n .then(ds => {\n this.datasourceType = ds.meta.id;\n return ds;\n });\n } else {\n return Promise.reject(`SQL Data Source with ID ${this.datasourceId} not found`);\n }\n }\n\n testDataSource() {\n throw NOT_IMPLEMENTED;\n }\n\n getHistory() {\n throw NOT_IMPLEMENTED;\n }\n\n getTrends() {\n throw NOT_IMPLEMENTED;\n }\n}\n"]}
|
||||||
41
dist/datasource-zabbix/zabbix/connectors/sql/mysql.js
vendored
Normal file
41
dist/datasource-zabbix/zabbix/connectors/sql/mysql.js
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
System.register([], function (_export, _context) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var TEST_QUERY, mysql;
|
||||||
|
/**
|
||||||
|
* MySQL queries
|
||||||
|
*/
|
||||||
|
|
||||||
|
function historyQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
||||||
|
var time_expression = "clock DIV " + intervalSec + " * " + intervalSec;
|
||||||
|
var query = "\n SELECT CAST(itemid AS CHAR) 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 ORDER BY time_sec ASC\n ";
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
function trendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
||||||
|
var time_expression = "clock DIV " + intervalSec + " * " + intervalSec;
|
||||||
|
var query = "\n SELECT CAST(itemid AS CHAR) 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 ORDER BY time_sec ASC\n ";
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
function testQuery() {
|
||||||
|
return TEST_QUERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
setters: [],
|
||||||
|
execute: function () {
|
||||||
|
TEST_QUERY = "SELECT CAST(itemid AS CHAR) AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1";
|
||||||
|
mysql = {
|
||||||
|
historyQuery: historyQuery,
|
||||||
|
trendsQuery: trendsQuery,
|
||||||
|
testQuery: testQuery
|
||||||
|
};
|
||||||
|
|
||||||
|
_export("default", mysql);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=mysql.js.map
|
||||||
1
dist/datasource-zabbix/zabbix/connectors/sql/mysql.js.map
vendored
Normal file
1
dist/datasource-zabbix/zabbix/connectors/sql/mysql.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["../../../../../src/datasource-zabbix/zabbix/connectors/sql/mysql.js"],"names":["historyQuery","itemids","table","timeFrom","timeTill","intervalSec","aggFunction","time_expression","query","trendsQuery","valueColumn","testQuery","TEST_QUERY","mysql"],"mappings":";;;;;;AAAA;;;;AAIA,WAASA,YAAT,CAAsBC,OAAtB,EAA+BC,KAA/B,EAAsCC,QAAtC,EAAgDC,QAAhD,EAA0DC,WAA1D,EAAuEC,WAAvE,EAAoF;AAClF,QAAIC,iCAA+BF,WAA/B,WAAgDA,WAApD;AACA,QAAIG,0DACuCD,eADvC,sBACuED,WADvE,mCAEKJ,KAFL,+BAGiBD,OAHjB,6BAIcE,QAJd,qBAIsCC,QAJtC,uBAKSG,eALT,4CAAJ;AAQA,WAAOC,KAAP;AACD;;AAED,WAASC,WAAT,CAAqBR,OAArB,EAA8BC,KAA9B,EAAqCC,QAArC,EAA+CC,QAA/C,EAAyDC,WAAzD,EAAsEC,WAAtE,EAAmFI,WAAnF,EAAgG;AAC9F,QAAIH,iCAA+BF,WAA/B,WAAgDA,WAApD;AACA,QAAIG,0DACuCD,eADvC,sBACuED,WADvE,SACsFI,WADtF,6BAEKR,KAFL,+BAGiBD,OAHjB,6BAIcE,QAJd,qBAIsCC,QAJtC,uBAKSG,eALT,4CAAJ;AAQA,WAAOC,KAAP;AACD;;AAID,WAASG,SAAT,GAAqB;AACnB,WAAOC,UAAP;AACD;;;;;AAJKA,gB;AAMAC,W,GAAQ;AACZb,kCADY;AAEZS,gCAFY;AAGZE;AAHY,O;;yBAMCE,K","file":"mysql.js","sourcesContent":["/**\n * MySQL queries\n */\n\nfunction historyQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {\n let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`;\n let query = `\n SELECT CAST(itemid AS CHAR) 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 ORDER BY time_sec ASC\n `;\n return query;\n}\n\nfunction trendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {\n let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`;\n let query = `\n SELECT CAST(itemid AS CHAR) 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 ORDER BY time_sec ASC\n `;\n return query;\n}\n\nconst TEST_QUERY = `SELECT CAST(itemid AS CHAR) AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1`;\n\nfunction testQuery() {\n return TEST_QUERY;\n}\n\nconst mysql = {\n historyQuery,\n trendsQuery,\n testQuery\n};\n\nexport default mysql;\n"]}
|
||||||
40
dist/datasource-zabbix/zabbix/connectors/sql/postgres.js
vendored
Normal file
40
dist/datasource-zabbix/zabbix/connectors/sql/postgres.js
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
System.register([], function (_export, _context) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var ITEMID_FORMAT, TEST_QUERY, postgres;
|
||||||
|
|
||||||
|
|
||||||
|
function historyQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
||||||
|
var time_expression = 'clock / ' + intervalSec + ' * ' + intervalSec;
|
||||||
|
var query = '\n SELECT to_char(itemid, \'' + ITEMID_FORMAT + '\') AS metric, ' + time_expression + ' AS time, ' + aggFunction + '(value) AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY 1, 2\n ORDER BY time ASC\n ';
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
function trendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
||||||
|
var time_expression = 'clock / ' + intervalSec + ' * ' + intervalSec;
|
||||||
|
var query = '\n SELECT to_char(itemid, \'' + ITEMID_FORMAT + '\') AS metric, ' + time_expression + ' AS time, ' + aggFunction + '(' + valueColumn + ') AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY 1, 2\n ORDER BY time ASC\n ';
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
function testQuery() {
|
||||||
|
return TEST_QUERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
setters: [],
|
||||||
|
execute: function () {
|
||||||
|
ITEMID_FORMAT = 'FM99999999999999999999';
|
||||||
|
TEST_QUERY = '\n SELECT to_char(itemid, \'' + ITEMID_FORMAT + '\') AS metric, clock AS time, value_avg AS value\n FROM trends_uint LIMIT 1\n';
|
||||||
|
postgres = {
|
||||||
|
historyQuery: historyQuery,
|
||||||
|
trendsQuery: trendsQuery,
|
||||||
|
testQuery: testQuery
|
||||||
|
};
|
||||||
|
|
||||||
|
_export('default', postgres);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=postgres.js.map
|
||||||
1
dist/datasource-zabbix/zabbix/connectors/sql/postgres.js.map
vendored
Normal file
1
dist/datasource-zabbix/zabbix/connectors/sql/postgres.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["../../../../../src/datasource-zabbix/zabbix/connectors/sql/postgres.js"],"names":["historyQuery","itemids","table","timeFrom","timeTill","intervalSec","aggFunction","time_expression","query","ITEMID_FORMAT","trendsQuery","valueColumn","testQuery","TEST_QUERY","postgres"],"mappings":";;;;;;;;AAMA,WAASA,YAAT,CAAsBC,OAAtB,EAA+BC,KAA/B,EAAsCC,QAAtC,EAAgDC,QAAhD,EAA0DC,WAA1D,EAAuEC,WAAvE,EAAoF;AAClF,QAAIC,+BAA6BF,WAA7B,WAA8CA,WAAlD;AACA,QAAIG,4CACwBC,aADxB,uBACsDF,eADtD,kBACkFD,WADlF,mCAEKJ,KAFL,+BAGiBD,OAHjB,6BAIcE,QAJd,qBAIsCC,QAJtC,mDAAJ;AAQA,WAAOI,KAAP;AACD;;AAED,WAASE,WAAT,CAAqBT,OAArB,EAA8BC,KAA9B,EAAqCC,QAArC,EAA+CC,QAA/C,EAAyDC,WAAzD,EAAsEC,WAAtE,EAAmFK,WAAnF,EAAgG;AAC9F,QAAIJ,+BAA6BF,WAA7B,WAA8CA,WAAlD;AACA,QAAIG,4CACwBC,aADxB,uBACsDF,eADtD,kBACkFD,WADlF,SACiGK,WADjG,6BAEKT,KAFL,+BAGiBD,OAHjB,6BAIcE,QAJd,qBAIsCC,QAJtC,mDAAJ;AAQA,WAAOI,KAAP;AACD;;AAOD,WAASI,SAAT,GAAqB;AACnB,WAAOC,UAAP;AACD;;;;;AAnCKJ,mB,GAAgB,wB;AA4BhBI,gB,qCACsBJ,a;AAQtBK,c,GAAW;AACfd,kCADe;AAEfU,gCAFe;AAGfE;AAHe,O;;yBAMFE,Q","file":"postgres.js","sourcesContent":["/**\n * Postgres queries\n */\n\nconst ITEMID_FORMAT = 'FM99999999999999999999';\n\nfunction historyQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {\n let time_expression = `clock / ${intervalSec} * ${intervalSec}`;\n let query = `\n SELECT to_char(itemid, '${ITEMID_FORMAT}') AS metric, ${time_expression} AS time, ${aggFunction}(value) AS value\n FROM ${table}\n WHERE itemid IN (${itemids})\n AND clock > ${timeFrom} AND clock < ${timeTill}\n GROUP BY 1, 2\n ORDER BY time ASC\n `;\n return query;\n}\n\nfunction trendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {\n let time_expression = `clock / ${intervalSec} * ${intervalSec}`;\n let query = `\n SELECT to_char(itemid, '${ITEMID_FORMAT}') AS metric, ${time_expression} AS time, ${aggFunction}(${valueColumn}) AS value\n FROM ${table}\n WHERE itemid IN (${itemids})\n AND clock > ${timeFrom} AND clock < ${timeTill}\n GROUP BY 1, 2\n ORDER BY time ASC\n `;\n return query;\n}\n\nconst TEST_QUERY = `\n SELECT to_char(itemid, '${ITEMID_FORMAT}') AS metric, clock AS time, value_avg AS value\n FROM trends_uint LIMIT 1\n`;\n\nfunction testQuery() {\n return TEST_QUERY;\n}\n\nconst postgres = {\n historyQuery,\n trendsQuery,\n testQuery\n};\n\nexport default postgres;\n"]}
|
||||||
282
dist/datasource-zabbix/zabbix/connectors/sql/sqlConnector.js
vendored
Normal file
282
dist/datasource-zabbix/zabbix/connectors/sql/sqlConnector.js
vendored
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
System.register(['lodash', './mysql', './postgres', '../dbConnector'], function (_export, _context) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var _, mysql, postgres, DBConnector, _createClass, _get, supportedDatabases, DEFAULT_QUERY_LIMIT, HISTORY_TO_TABLE_MAP, TREND_TO_TABLE_MAP, consolidateByFunc, consolidateByTrendColumns, SQLConnector;
|
||||||
|
|
||||||
|
function _classCallCheck(instance, Constructor) {
|
||||||
|
if (!(instance instanceof Constructor)) {
|
||||||
|
throw new TypeError("Cannot call a class as a function");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _possibleConstructorReturn(self, call) {
|
||||||
|
if (!self) {
|
||||||
|
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
||||||
|
}
|
||||||
|
|
||||||
|
return call && (typeof call === "object" || typeof call === "function") ? call : self;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _inherits(subClass, superClass) {
|
||||||
|
if (typeof superClass !== "function" && superClass !== null) {
|
||||||
|
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
||||||
|
constructor: {
|
||||||
|
value: subClass,
|
||||||
|
enumerable: false,
|
||||||
|
writable: true,
|
||||||
|
configurable: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function convertGrafanaTSResponse(time_series, items, addHostName) {
|
||||||
|
//uniqBy is needed to deduplicate
|
||||||
|
var hosts = _.uniqBy(_.flatten(_.map(items, 'hosts')), 'hostid');
|
||||||
|
var grafanaSeries = _.map(time_series, function (series) {
|
||||||
|
var itemid = series.name;
|
||||||
|
var item = _.find(items, { 'itemid': itemid });
|
||||||
|
var alias = item.name;
|
||||||
|
//only when actual multi hosts selected
|
||||||
|
if (_.keys(hosts).length > 1 && addHostName) {
|
||||||
|
var host = _.find(hosts, { 'hostid': item.hostid });
|
||||||
|
alias = host.name + ": " + alias;
|
||||||
|
}
|
||||||
|
// CachingProxy deduplicates requests and returns one time series for equal queries.
|
||||||
|
// Clone is needed to prevent changing of series object shared between all targets.
|
||||||
|
var datapoints = _.cloneDeep(series.points);
|
||||||
|
return {
|
||||||
|
target: alias,
|
||||||
|
datapoints: datapoints
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return _.sortBy(grafanaSeries, 'target');
|
||||||
|
}
|
||||||
|
|
||||||
|
function compactSQLQuery(query) {
|
||||||
|
return query.replace(/\s+/g, ' ');
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
setters: [function (_lodash) {
|
||||||
|
_ = _lodash.default;
|
||||||
|
}, function (_mysql) {
|
||||||
|
mysql = _mysql.default;
|
||||||
|
}, function (_postgres) {
|
||||||
|
postgres = _postgres.default;
|
||||||
|
}, function (_dbConnector) {
|
||||||
|
DBConnector = _dbConnector.default;
|
||||||
|
}],
|
||||||
|
execute: function () {
|
||||||
|
_createClass = function () {
|
||||||
|
function defineProperties(target, props) {
|
||||||
|
for (var i = 0; i < props.length; i++) {
|
||||||
|
var descriptor = props[i];
|
||||||
|
descriptor.enumerable = descriptor.enumerable || false;
|
||||||
|
descriptor.configurable = true;
|
||||||
|
if ("value" in descriptor) descriptor.writable = true;
|
||||||
|
Object.defineProperty(target, descriptor.key, descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return function (Constructor, protoProps, staticProps) {
|
||||||
|
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
||||||
|
if (staticProps) defineProperties(Constructor, staticProps);
|
||||||
|
return Constructor;
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
_get = function get(object, property, receiver) {
|
||||||
|
if (object === null) object = Function.prototype;
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(object, property);
|
||||||
|
|
||||||
|
if (desc === undefined) {
|
||||||
|
var parent = Object.getPrototypeOf(object);
|
||||||
|
|
||||||
|
if (parent === null) {
|
||||||
|
return undefined;
|
||||||
|
} else {
|
||||||
|
return get(parent, property, receiver);
|
||||||
|
}
|
||||||
|
} else if ("value" in desc) {
|
||||||
|
return desc.value;
|
||||||
|
} else {
|
||||||
|
var getter = desc.get;
|
||||||
|
|
||||||
|
if (getter === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getter.call(receiver);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
supportedDatabases = {
|
||||||
|
mysql: 'mysql',
|
||||||
|
postgres: 'postgres'
|
||||||
|
};
|
||||||
|
DEFAULT_QUERY_LIMIT = 10000;
|
||||||
|
HISTORY_TO_TABLE_MAP = {
|
||||||
|
'0': 'history',
|
||||||
|
'1': 'history_str',
|
||||||
|
'2': 'history_log',
|
||||||
|
'3': 'history_uint',
|
||||||
|
'4': 'history_text'
|
||||||
|
};
|
||||||
|
TREND_TO_TABLE_MAP = {
|
||||||
|
'0': 'trends',
|
||||||
|
'3': 'trends_uint'
|
||||||
|
};
|
||||||
|
consolidateByFunc = {
|
||||||
|
'avg': 'AVG',
|
||||||
|
'min': 'MIN',
|
||||||
|
'max': 'MAX',
|
||||||
|
'sum': 'SUM',
|
||||||
|
'count': 'COUNT'
|
||||||
|
};
|
||||||
|
consolidateByTrendColumns = {
|
||||||
|
'avg': 'value_avg',
|
||||||
|
'min': 'value_min',
|
||||||
|
'max': 'value_max'
|
||||||
|
};
|
||||||
|
|
||||||
|
_export('SQLConnector', SQLConnector = function (_DBConnector) {
|
||||||
|
_inherits(SQLConnector, _DBConnector);
|
||||||
|
|
||||||
|
function SQLConnector(options, backendSrv, datasourceSrv) {
|
||||||
|
_classCallCheck(this, SQLConnector);
|
||||||
|
|
||||||
|
var _this = _possibleConstructorReturn(this, (SQLConnector.__proto__ || Object.getPrototypeOf(SQLConnector)).call(this, options, backendSrv, datasourceSrv));
|
||||||
|
|
||||||
|
_this.limit = options.limit || DEFAULT_QUERY_LIMIT;
|
||||||
|
_this.sqlDialect = null;
|
||||||
|
|
||||||
|
_get(SQLConnector.prototype.__proto__ || Object.getPrototypeOf(SQLConnector.prototype), 'loadDBDataSource', _this).call(_this).then(function () {
|
||||||
|
return _this.loadSQLDialect();
|
||||||
|
});
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
|
||||||
|
_createClass(SQLConnector, [{
|
||||||
|
key: 'loadSQLDialect',
|
||||||
|
value: function loadSQLDialect() {
|
||||||
|
if (this.datasourceType === supportedDatabases.postgres) {
|
||||||
|
this.sqlDialect = postgres;
|
||||||
|
} else {
|
||||||
|
this.sqlDialect = mysql;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'testDataSource',
|
||||||
|
value: function testDataSource() {
|
||||||
|
var testQuery = this.sqlDialect.testQuery();
|
||||||
|
return this.invokeSQLQuery(testQuery);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getHistory',
|
||||||
|
value: function getHistory(items, timeFrom, timeTill, options) {
|
||||||
|
var _this2 = this;
|
||||||
|
|
||||||
|
var intervalMs = options.intervalMs,
|
||||||
|
consolidateBy = options.consolidateBy;
|
||||||
|
|
||||||
|
var intervalSec = Math.ceil(intervalMs / 1000);
|
||||||
|
|
||||||
|
consolidateBy = consolidateBy || 'avg';
|
||||||
|
var aggFunction = consolidateByFunc[consolidateBy];
|
||||||
|
|
||||||
|
// 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 = _this2.sqlDialect.historyQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction);
|
||||||
|
|
||||||
|
query = compactSQLQuery(query);
|
||||||
|
return _this2.invokeSQLQuery(query);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(promises).then(function (results) {
|
||||||
|
return _.flatten(results);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getTrends',
|
||||||
|
value: function getTrends(items, timeFrom, timeTill, options) {
|
||||||
|
var _this3 = this;
|
||||||
|
|
||||||
|
var intervalMs = options.intervalMs,
|
||||||
|
consolidateBy = options.consolidateBy;
|
||||||
|
|
||||||
|
var intervalSec = Math.ceil(intervalMs / 1000);
|
||||||
|
|
||||||
|
consolidateBy = consolidateBy || 'avg';
|
||||||
|
var aggFunction = consolidateByFunc[consolidateBy];
|
||||||
|
|
||||||
|
// 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 = TREND_TO_TABLE_MAP[value_type];
|
||||||
|
var valueColumn = _.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg';
|
||||||
|
valueColumn = consolidateByTrendColumns[valueColumn];
|
||||||
|
var query = _this3.sqlDialect.trendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn);
|
||||||
|
|
||||||
|
query = compactSQLQuery(query);
|
||||||
|
return _this3.invokeSQLQuery(query);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(promises).then(function (results) {
|
||||||
|
return _.flatten(results);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'handleGrafanaTSResponse',
|
||||||
|
value: function handleGrafanaTSResponse(history, items) {
|
||||||
|
var addHostName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
||||||
|
|
||||||
|
return convertGrafanaTSResponse(history, items, addHostName);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'invokeSQLQuery',
|
||||||
|
value: function invokeSQLQuery(query) {
|
||||||
|
var queryDef = {
|
||||||
|
refId: 'A',
|
||||||
|
format: 'time_series',
|
||||||
|
datasourceId: this.datasourceId,
|
||||||
|
rawSql: query,
|
||||||
|
maxDataPoints: this.limit
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.backendSrv.datasourceRequest({
|
||||||
|
url: '/api/tsdb/query',
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
queries: [queryDef]
|
||||||
|
}
|
||||||
|
}).then(function (response) {
|
||||||
|
var results = response.data.results;
|
||||||
|
if (results['A']) {
|
||||||
|
return results['A'].series;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return SQLConnector;
|
||||||
|
}(DBConnector));
|
||||||
|
|
||||||
|
_export('SQLConnector', SQLConnector);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=sqlConnector.js.map
|
||||||
1
dist/datasource-zabbix/zabbix/connectors/sql/sqlConnector.js.map
vendored
Normal file
1
dist/datasource-zabbix/zabbix/connectors/sql/sqlConnector.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
545
dist/datasource-zabbix/zabbix/connectors/zabbix_api/zabbixAPIConnector.js
vendored
Normal file
545
dist/datasource-zabbix/zabbix/connectors/zabbix_api/zabbixAPIConnector.js
vendored
Normal file
@@ -0,0 +1,545 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
System.register(['lodash', '../../../utils', './zabbixAPICore'], function (_export, _context) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var _, utils, ZabbixAPICore, _slicedToArray, _createClass, ZabbixAPIConnector;
|
||||||
|
|
||||||
|
function _classCallCheck(instance, Constructor) {
|
||||||
|
if (!(instance instanceof Constructor)) {
|
||||||
|
throw new TypeError("Cannot call a class as a function");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterTriggersByAcknowledge(triggers, acknowledged) {
|
||||||
|
if (acknowledged === 0) {
|
||||||
|
return _.filter(triggers, function (trigger) {
|
||||||
|
return trigger.lastEvent.acknowledged === "0";
|
||||||
|
});
|
||||||
|
} else if (acknowledged === 1) {
|
||||||
|
return _.filter(triggers, function (trigger) {
|
||||||
|
return trigger.lastEvent.acknowledged === "1";
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return triggers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isNotAuthorized(message) {
|
||||||
|
return message === "Session terminated, re-login, please." || message === "Not authorised." || message === "Not authorized.";
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
setters: [function (_lodash) {
|
||||||
|
_ = _lodash.default;
|
||||||
|
}, function (_utils) {
|
||||||
|
utils = _utils;
|
||||||
|
}, function (_zabbixAPICore) {
|
||||||
|
ZabbixAPICore = _zabbixAPICore.ZabbixAPICore;
|
||||||
|
}],
|
||||||
|
execute: function () {
|
||||||
|
_slicedToArray = function () {
|
||||||
|
function sliceIterator(arr, i) {
|
||||||
|
var _arr = [];
|
||||||
|
var _n = true;
|
||||||
|
var _d = false;
|
||||||
|
var _e = undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
|
||||||
|
_arr.push(_s.value);
|
||||||
|
|
||||||
|
if (i && _arr.length === i) break;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
_d = true;
|
||||||
|
_e = err;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (!_n && _i["return"]) _i["return"]();
|
||||||
|
} finally {
|
||||||
|
if (_d) throw _e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return function (arr, i) {
|
||||||
|
if (Array.isArray(arr)) {
|
||||||
|
return arr;
|
||||||
|
} else if (Symbol.iterator in Object(arr)) {
|
||||||
|
return sliceIterator(arr, i);
|
||||||
|
} else {
|
||||||
|
throw new TypeError("Invalid attempt to destructure non-iterable instance");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
_createClass = function () {
|
||||||
|
function defineProperties(target, props) {
|
||||||
|
for (var i = 0; i < props.length; i++) {
|
||||||
|
var descriptor = props[i];
|
||||||
|
descriptor.enumerable = descriptor.enumerable || false;
|
||||||
|
descriptor.configurable = true;
|
||||||
|
if ("value" in descriptor) descriptor.writable = true;
|
||||||
|
Object.defineProperty(target, descriptor.key, descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return function (Constructor, protoProps, staticProps) {
|
||||||
|
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
||||||
|
if (staticProps) defineProperties(Constructor, staticProps);
|
||||||
|
return Constructor;
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
_export('ZabbixAPIConnector', ZabbixAPIConnector = function () {
|
||||||
|
function ZabbixAPIConnector(api_url, username, password, basicAuth, withCredentials, backendSrv) {
|
||||||
|
_classCallCheck(this, ZabbixAPIConnector);
|
||||||
|
|
||||||
|
this.url = api_url;
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
this.auth = "";
|
||||||
|
|
||||||
|
this.requestOptions = {
|
||||||
|
basicAuth: basicAuth,
|
||||||
|
withCredentials: withCredentials
|
||||||
|
};
|
||||||
|
|
||||||
|
this.loginPromise = null;
|
||||||
|
this.loginErrorCount = 0;
|
||||||
|
this.maxLoginAttempts = 3;
|
||||||
|
|
||||||
|
this.zabbixAPICore = new ZabbixAPICore(backendSrv);
|
||||||
|
|
||||||
|
this.getTrend = this.getTrend_ZBXNEXT1193;
|
||||||
|
//getTrend = getTrend_30;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
// Core method wrappers //
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
_createClass(ZabbixAPIConnector, [{
|
||||||
|
key: 'request',
|
||||||
|
value: function request(method, params) {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
return this.zabbixAPICore.request(this.url, method, params, this.requestOptions, this.auth).catch(function (error) {
|
||||||
|
if (isNotAuthorized(error.data)) {
|
||||||
|
// Handle auth errors
|
||||||
|
_this.loginErrorCount++;
|
||||||
|
if (_this.loginErrorCount > _this.maxLoginAttempts) {
|
||||||
|
_this.loginErrorCount = 0;
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return _this.loginOnce().then(function () {
|
||||||
|
return _this.request(method, params);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Handle API errors
|
||||||
|
var message = error.data ? error.data : error.statusText;
|
||||||
|
return Promise.reject(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'loginOnce',
|
||||||
|
value: function loginOnce() {
|
||||||
|
var _this2 = this;
|
||||||
|
|
||||||
|
if (!this.loginPromise) {
|
||||||
|
this.loginPromise = Promise.resolve(this.login().then(function (auth) {
|
||||||
|
_this2.auth = auth;
|
||||||
|
_this2.loginPromise = null;
|
||||||
|
return auth;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return this.loginPromise;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'login',
|
||||||
|
value: function login() {
|
||||||
|
return this.zabbixAPICore.login(this.url, this.username, this.password, this.requestOptions);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getVersion',
|
||||||
|
value: function getVersion() {
|
||||||
|
return this.zabbixAPICore.getVersion(this.url, this.requestOptions);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'acknowledgeEvent',
|
||||||
|
value: function acknowledgeEvent(eventid, message) {
|
||||||
|
var params = {
|
||||||
|
eventids: eventid,
|
||||||
|
message: message
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('event.acknowledge', params);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getGroups',
|
||||||
|
value: function getGroups() {
|
||||||
|
var params = {
|
||||||
|
output: ['name'],
|
||||||
|
sortfield: 'name',
|
||||||
|
real_hosts: true
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('hostgroup.get', params);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getHosts',
|
||||||
|
value: function getHosts(groupids) {
|
||||||
|
var params = {
|
||||||
|
output: ['name', 'host'],
|
||||||
|
sortfield: 'name'
|
||||||
|
};
|
||||||
|
if (groupids) {
|
||||||
|
params.groupids = groupids;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.request('host.get', params);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getApps',
|
||||||
|
value: function getApps(hostids) {
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
hostids: hostids
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('application.get', params);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getItems',
|
||||||
|
value: function getItems(hostids, appids, itemtype) {
|
||||||
|
var params = {
|
||||||
|
output: ['name', 'key_', 'value_type', 'hostid', 'status', 'state'],
|
||||||
|
sortfield: 'name',
|
||||||
|
webitems: true,
|
||||||
|
filter: {},
|
||||||
|
selectHosts: ['hostid', 'name']
|
||||||
|
};
|
||||||
|
if (hostids) {
|
||||||
|
params.hostids = hostids;
|
||||||
|
}
|
||||||
|
if (appids) {
|
||||||
|
params.applicationids = appids;
|
||||||
|
}
|
||||||
|
if (itemtype === 'num') {
|
||||||
|
// Return only numeric metrics
|
||||||
|
params.filter.value_type = [0, 3];
|
||||||
|
}
|
||||||
|
if (itemtype === 'text') {
|
||||||
|
// Return only text metrics
|
||||||
|
params.filter.value_type = [1, 2, 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.request('item.get', params).then(utils.expandItems);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getItemsByIDs',
|
||||||
|
value: function getItemsByIDs(itemids) {
|
||||||
|
var params = {
|
||||||
|
itemids: itemids,
|
||||||
|
output: ['name', 'key_', 'value_type', 'hostid', 'status', 'state'],
|
||||||
|
webitems: true,
|
||||||
|
selectHosts: ['hostid', 'name']
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('item.get', params).then(utils.expandItems);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getMacros',
|
||||||
|
value: function getMacros(hostids) {
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
hostids: hostids
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('usermacro.get', params);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getGlobalMacros',
|
||||||
|
value: function getGlobalMacros() {
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
globalmacro: true
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('usermacro.get', params);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getLastValue',
|
||||||
|
value: function getLastValue(itemid) {
|
||||||
|
var params = {
|
||||||
|
output: ['lastvalue'],
|
||||||
|
itemids: itemid
|
||||||
|
};
|
||||||
|
return this.request('item.get', params).then(function (items) {
|
||||||
|
return items.length ? items[0].lastvalue : null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getHistory',
|
||||||
|
value: function getHistory(items, timeFrom, timeTill) {
|
||||||
|
var _this3 = 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');
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
history: value_type,
|
||||||
|
itemids: itemids,
|
||||||
|
sortfield: 'clock',
|
||||||
|
sortorder: 'ASC',
|
||||||
|
time_from: timeFrom
|
||||||
|
};
|
||||||
|
|
||||||
|
// Relative queries (e.g. last hour) don't include an end time
|
||||||
|
if (timeTill) {
|
||||||
|
params.time_till = timeTill;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _this3.request('history.get', params);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(promises).then(_.flatten);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getTrend_ZBXNEXT1193',
|
||||||
|
value: function getTrend_ZBXNEXT1193(items, timeFrom, timeTill) {
|
||||||
|
var _this4 = 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');
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
trend: value_type,
|
||||||
|
itemids: itemids,
|
||||||
|
sortfield: 'clock',
|
||||||
|
sortorder: 'ASC',
|
||||||
|
time_from: timeFrom
|
||||||
|
};
|
||||||
|
|
||||||
|
// Relative queries (e.g. last hour) don't include an end time
|
||||||
|
if (timeTill) {
|
||||||
|
params.time_till = timeTill;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _this4.request('trend.get', params);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(promises).then(_.flatten);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getTrend_30',
|
||||||
|
value: function getTrend_30(items, time_from, time_till, value_type) {
|
||||||
|
var self = this;
|
||||||
|
var itemids = _.map(items, 'itemid');
|
||||||
|
|
||||||
|
var params = {
|
||||||
|
output: ["itemid", "clock", value_type],
|
||||||
|
itemids: itemids,
|
||||||
|
time_from: time_from
|
||||||
|
};
|
||||||
|
|
||||||
|
// Relative queries (e.g. last hour) don't include an end time
|
||||||
|
if (time_till) {
|
||||||
|
params.time_till = time_till;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.request('trend.get', params);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getITService',
|
||||||
|
value: function getITService(serviceids) {
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
serviceids: serviceids
|
||||||
|
};
|
||||||
|
return this.request('service.get', params);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getSLA',
|
||||||
|
value: function getSLA(serviceids, timeRange) {
|
||||||
|
var _timeRange = _slicedToArray(timeRange, 2),
|
||||||
|
timeFrom = _timeRange[0],
|
||||||
|
timeTo = _timeRange[1];
|
||||||
|
|
||||||
|
var params = {
|
||||||
|
serviceids: serviceids,
|
||||||
|
intervals: [{
|
||||||
|
from: timeFrom,
|
||||||
|
to: timeTo
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
return this.request('service.getsla', params);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getTriggers',
|
||||||
|
value: function getTriggers(groupids, hostids, applicationids, options) {
|
||||||
|
var showTriggers = options.showTriggers,
|
||||||
|
maintenance = options.maintenance,
|
||||||
|
timeFrom = options.timeFrom,
|
||||||
|
timeTo = options.timeTo;
|
||||||
|
|
||||||
|
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
groupids: groupids,
|
||||||
|
hostids: hostids,
|
||||||
|
applicationids: applicationids,
|
||||||
|
expandDescription: true,
|
||||||
|
expandData: true,
|
||||||
|
expandComment: true,
|
||||||
|
monitored: true,
|
||||||
|
skipDependent: true,
|
||||||
|
//only_true: true,
|
||||||
|
filter: {
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
selectGroups: ['name'],
|
||||||
|
selectHosts: ['name', 'host', 'maintenance_status'],
|
||||||
|
selectItems: ['name', 'key_', 'lastvalue'],
|
||||||
|
selectLastEvent: 'extend',
|
||||||
|
selectTags: 'extend'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (showTriggers) {
|
||||||
|
params.filter.value = showTriggers;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maintenance) {
|
||||||
|
params.maintenance = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeFrom || timeTo) {
|
||||||
|
params.lastChangeSince = timeFrom;
|
||||||
|
params.lastChangeTill = timeTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.request('trigger.get', params);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getEvents',
|
||||||
|
value: function getEvents(objectids, timeFrom, timeTo, showEvents) {
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
time_from: timeFrom,
|
||||||
|
time_till: timeTo,
|
||||||
|
objectids: objectids,
|
||||||
|
select_acknowledges: 'extend',
|
||||||
|
selectHosts: 'extend',
|
||||||
|
value: showEvents
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('event.get', params);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getAcknowledges',
|
||||||
|
value: function getAcknowledges(eventids) {
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
eventids: eventids,
|
||||||
|
preservekeys: true,
|
||||||
|
select_acknowledges: 'extend',
|
||||||
|
sortfield: 'clock',
|
||||||
|
sortorder: 'DESC'
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('event.get', params).then(function (events) {
|
||||||
|
return _.filter(events, function (event) {
|
||||||
|
return event.acknowledges.length;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getAlerts',
|
||||||
|
value: function getAlerts(itemids, timeFrom, timeTo) {
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
itemids: itemids,
|
||||||
|
expandDescription: true,
|
||||||
|
expandData: true,
|
||||||
|
expandComment: true,
|
||||||
|
monitored: true,
|
||||||
|
skipDependent: true,
|
||||||
|
//only_true: true,
|
||||||
|
// filter: {
|
||||||
|
// value: 1
|
||||||
|
// },
|
||||||
|
selectLastEvent: 'extend'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (timeFrom || timeTo) {
|
||||||
|
params.lastChangeSince = timeFrom;
|
||||||
|
params.lastChangeTill = timeTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.request('trigger.get', params);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getHostAlerts',
|
||||||
|
value: function getHostAlerts(hostids, applicationids, options) {
|
||||||
|
var minSeverity = options.minSeverity,
|
||||||
|
acknowledged = options.acknowledged,
|
||||||
|
count = options.count,
|
||||||
|
timeFrom = options.timeFrom,
|
||||||
|
timeTo = options.timeTo;
|
||||||
|
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
hostids: hostids,
|
||||||
|
min_severity: minSeverity,
|
||||||
|
filter: { value: 1 },
|
||||||
|
expandDescription: true,
|
||||||
|
expandData: true,
|
||||||
|
expandComment: true,
|
||||||
|
monitored: true,
|
||||||
|
skipDependent: true,
|
||||||
|
selectLastEvent: 'extend',
|
||||||
|
selectGroups: 'extend',
|
||||||
|
selectHosts: ['host', 'name']
|
||||||
|
};
|
||||||
|
|
||||||
|
if (count && acknowledged !== 0 && acknowledged !== 1) {
|
||||||
|
params.countOutput = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (applicationids && applicationids.length) {
|
||||||
|
params.applicationids = applicationids;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeFrom || timeTo) {
|
||||||
|
params.lastChangeSince = timeFrom;
|
||||||
|
params.lastChangeTill = timeTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.request('trigger.get', params).then(function (triggers) {
|
||||||
|
if (!count || acknowledged === 0 || acknowledged === 1) {
|
||||||
|
triggers = filterTriggersByAcknowledge(triggers, acknowledged);
|
||||||
|
if (count) {
|
||||||
|
triggers = triggers.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return triggers;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return ZabbixAPIConnector;
|
||||||
|
}());
|
||||||
|
|
||||||
|
_export('ZabbixAPIConnector', ZabbixAPIConnector);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=zabbixAPIConnector.js.map
|
||||||
1
dist/datasource-zabbix/zabbix/connectors/zabbix_api/zabbixAPIConnector.js.map
vendored
Normal file
1
dist/datasource-zabbix/zabbix/connectors/zabbix_api/zabbixAPIConnector.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,9 +1,9 @@
|
|||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
System.register(['angular'], function (_export, _context) {
|
System.register([], function (_export, _context) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var angular, _createClass, ZabbixAPICoreService, ZabbixAPIError;
|
var _createClass, ZabbixAPICore, ZabbixAPIError;
|
||||||
|
|
||||||
function _classCallCheck(instance, Constructor) {
|
function _classCallCheck(instance, Constructor) {
|
||||||
if (!(instance instanceof Constructor)) {
|
if (!(instance instanceof Constructor)) {
|
||||||
@@ -12,9 +12,7 @@ System.register(['angular'], function (_export, _context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setters: [function (_angular) {
|
setters: [],
|
||||||
angular = _angular.default;
|
|
||||||
}],
|
|
||||||
execute: function () {
|
execute: function () {
|
||||||
_createClass = function () {
|
_createClass = function () {
|
||||||
function defineProperties(target, props) {
|
function defineProperties(target, props) {
|
||||||
@@ -34,11 +32,11 @@ System.register(['angular'], function (_export, _context) {
|
|||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
|
|
||||||
ZabbixAPICoreService = function () {
|
_export("ZabbixAPICore", ZabbixAPICore = function () {
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
function ZabbixAPICoreService(backendSrv) {
|
function ZabbixAPICore(backendSrv) {
|
||||||
_classCallCheck(this, ZabbixAPICoreService);
|
_classCallCheck(this, ZabbixAPICore);
|
||||||
|
|
||||||
this.backendSrv = backendSrv;
|
this.backendSrv = backendSrv;
|
||||||
}
|
}
|
||||||
@@ -49,8 +47,8 @@ System.register(['angular'], function (_export, _context) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
_createClass(ZabbixAPICoreService, [{
|
_createClass(ZabbixAPICore, [{
|
||||||
key: 'request',
|
key: "request",
|
||||||
value: function request(api_url, method, params, options, auth) {
|
value: function request(api_url, method, params, options, auth) {
|
||||||
var requestData = {
|
var requestData = {
|
||||||
jsonrpc: '2.0',
|
jsonrpc: '2.0',
|
||||||
@@ -87,7 +85,7 @@ System.register(['angular'], function (_export, _context) {
|
|||||||
return this.datasourceRequest(requestOptions);
|
return this.datasourceRequest(requestOptions);
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: 'datasourceRequest',
|
key: "datasourceRequest",
|
||||||
value: function datasourceRequest(requestOptions) {
|
value: function datasourceRequest(requestOptions) {
|
||||||
return this.backendSrv.datasourceRequest(requestOptions).then(function (response) {
|
return this.backendSrv.datasourceRequest(requestOptions).then(function (response) {
|
||||||
if (!response.data) {
|
if (!response.data) {
|
||||||
@@ -103,7 +101,7 @@ System.register(['angular'], function (_export, _context) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: 'login',
|
key: "login",
|
||||||
value: function login(api_url, username, password, options) {
|
value: function login(api_url, username, password, options) {
|
||||||
var params = {
|
var params = {
|
||||||
user: username,
|
user: username,
|
||||||
@@ -112,16 +110,18 @@ System.register(['angular'], function (_export, _context) {
|
|||||||
return this.request(api_url, 'user.login', params, options, null);
|
return this.request(api_url, 'user.login', params, options, null);
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: 'getVersion',
|
key: "getVersion",
|
||||||
value: function getVersion(api_url, options) {
|
value: function getVersion(api_url, options) {
|
||||||
return this.request(api_url, 'apiinfo.version', [], options);
|
return this.request(api_url, 'apiinfo.version', [], options);
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
return ZabbixAPICoreService;
|
return ZabbixAPICore;
|
||||||
}();
|
}());
|
||||||
|
|
||||||
_export('ZabbixAPIError', ZabbixAPIError = function () {
|
_export("ZabbixAPICore", ZabbixAPICore);
|
||||||
|
|
||||||
|
_export("ZabbixAPIError", ZabbixAPIError = function () {
|
||||||
function ZabbixAPIError(error) {
|
function ZabbixAPIError(error) {
|
||||||
_classCallCheck(this, ZabbixAPIError);
|
_classCallCheck(this, ZabbixAPIError);
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ System.register(['angular'], function (_export, _context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createClass(ZabbixAPIError, [{
|
_createClass(ZabbixAPIError, [{
|
||||||
key: 'toString',
|
key: "toString",
|
||||||
value: function toString() {
|
value: function toString() {
|
||||||
return this.name + " " + this.data;
|
return this.name + " " + this.data;
|
||||||
}
|
}
|
||||||
@@ -141,10 +141,8 @@ System.register(['angular'], function (_export, _context) {
|
|||||||
return ZabbixAPIError;
|
return ZabbixAPIError;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
_export('ZabbixAPIError', ZabbixAPIError);
|
_export("ZabbixAPIError", ZabbixAPIError);
|
||||||
|
|
||||||
angular.module('grafana.services').service('zabbixAPICoreService', ZabbixAPICoreService);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
//# sourceMappingURL=zabbixAPICore.service.js.map
|
//# sourceMappingURL=zabbixAPICore.js.map
|
||||||
1
dist/datasource-zabbix/zabbix/connectors/zabbix_api/zabbixAPICore.js.map
vendored
Normal file
1
dist/datasource-zabbix/zabbix/connectors/zabbix_api/zabbixAPICore.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["../../../../../src/datasource-zabbix/zabbix/connectors/zabbix_api/zabbixAPICore.js"],"names":["ZabbixAPICore","backendSrv","api_url","method","params","options","auth","requestData","jsonrpc","id","Promise","reject","ZabbixAPIError","data","requestOptions","url","headers","basicAuth","withCredentials","Authorization","datasourceRequest","then","response","error","result","username","password","user","request","code","name","message"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+BAIaA,a;;AAEX;AACA,+BAAYC,UAAZ,EAAwB;AAAA;;AACtB,eAAKA,UAAL,GAAkBA,UAAlB;AACD;;AAED;;;;;;;;kCAIQC,O,EAASC,M,EAAQC,M,EAAQC,O,EAASC,I,EAAM;AAC9C,gBAAIC,cAAc;AAChBC,uBAAS,KADO;AAEhBL,sBAAQA,MAFQ;AAGhBC,sBAAQA,MAHQ;AAIhBK,kBAAI;AAJY,aAAlB;;AAOA,gBAAIH,SAAS,EAAb,EAAiB;AACf;AACA,qBAAOI,QAAQC,MAAR,CAAe,IAAIC,cAAJ,CAAmB,EAACC,MAAM,iBAAP,EAAnB,CAAf,CAAP;AACD,aAHD,MAGO,IAAIP,IAAJ,EAAU;AACf;AACAC,0BAAYD,IAAZ,GAAmBA,IAAnB;AACD;;AAED,gBAAIQ,iBAAiB;AACnBX,sBAAQ,MADW;AAEnBY,mBAAKb,OAFc;AAGnBW,oBAAMN,WAHa;AAInBS,uBAAS;AACP,gCAAgB;AADT;AAJU,aAArB;;AASA;AACA,gBAAIX,QAAQY,SAAR,IAAqBZ,QAAQa,eAAjC,EAAkD;AAChDJ,6BAAeI,eAAf,GAAiC,IAAjC;AACD;AACD,gBAAIb,QAAQY,SAAZ,EAAuB;AACrBH,6BAAeE,OAAf,CAAuBG,aAAvB,GAAuCd,QAAQY,SAA/C;AACD;;AAED,mBAAO,KAAKG,iBAAL,CAAuBN,cAAvB,CAAP;AACD;;;4CAEiBA,c,EAAgB;AAChC,mBAAO,KAAKb,UAAL,CAAgBmB,iBAAhB,CAAkCN,cAAlC,EACNO,IADM,CACD,UAACC,QAAD,EAAc;AAClB,kBAAI,CAACA,SAAST,IAAd,EAAoB;AAClB,uBAAOH,QAAQC,MAAR,CAAe,IAAIC,cAAJ,CAAmB,EAACC,MAAM,wBAAP,EAAnB,CAAf,CAAP;AACD,eAFD,MAEO,IAAIS,SAAST,IAAT,CAAcU,KAAlB,EAAyB;;AAE9B;AACA,uBAAOb,QAAQC,MAAR,CAAe,IAAIC,cAAJ,CAAmBU,SAAST,IAAT,CAAcU,KAAjC,CAAf,CAAP;AACD;;AAED;AACA,qBAAOD,SAAST,IAAT,CAAcW,MAArB;AACD,aAZM,CAAP;AAaD;;;gCAMKtB,O,EAASuB,Q,EAAUC,Q,EAAUrB,O,EAAS;AAC1C,gBAAID,SAAS;AACXuB,oBAAMF,QADK;AAEXC,wBAAUA;AAFC,aAAb;AAIA,mBAAO,KAAKE,OAAL,CAAa1B,OAAb,EAAsB,YAAtB,EAAoCE,MAApC,EAA4CC,OAA5C,EAAqD,IAArD,CAAP;AACD;;;qCAMUH,O,EAASG,O,EAAS;AAC3B,mBAAO,KAAKuB,OAAL,CAAa1B,OAAb,EAAsB,iBAAtB,EAAyC,EAAzC,EAA6CG,OAA7C,CAAP;AACD;;;;;;;;gCAIUO,c;AACX,gCAAYW,KAAZ,EAAmB;AAAA;;AACjB,eAAKM,IAAL,GAAYN,MAAMM,IAAN,IAAc,IAA1B;AACA,eAAKC,IAAL,GAAYP,MAAMQ,OAAN,IAAiB,EAA7B;AACA,eAAKlB,IAAL,GAAYU,MAAMV,IAAN,IAAc,EAA1B;AACA,eAAKkB,OAAL,GAAe,uBAAuB,KAAKD,IAA5B,GAAmC,GAAnC,GAAyC,KAAKjB,IAA7D;AACD;;;;qCAEU;AACT,mBAAO,KAAKiB,IAAL,GAAY,GAAZ,GAAkB,KAAKjB,IAA9B;AACD","file":"zabbixAPICore.js","sourcesContent":["/**\n * General Zabbix API methods\n */\n\nexport class ZabbixAPICore {\n\n /** @ngInject */\n constructor(backendSrv) {\n this.backendSrv = backendSrv;\n }\n\n /**\n * Request data from Zabbix API\n * @return {object} response.result\n */\n request(api_url, method, params, options, auth) {\n let requestData = {\n jsonrpc: '2.0',\n method: method,\n params: params,\n id: 1\n };\n\n if (auth === \"\") {\n // Reject immediately if not authenticated\n return Promise.reject(new ZabbixAPIError({data: \"Not authorised.\"}));\n } else if (auth) {\n // Set auth parameter only if it needed\n requestData.auth = auth;\n }\n\n let requestOptions = {\n method: 'POST',\n url: api_url,\n data: requestData,\n headers: {\n 'Content-Type': 'application/json'\n }\n };\n\n // Set request options for basic auth\n if (options.basicAuth || options.withCredentials) {\n requestOptions.withCredentials = true;\n }\n if (options.basicAuth) {\n requestOptions.headers.Authorization = options.basicAuth;\n }\n\n return this.datasourceRequest(requestOptions);\n }\n\n datasourceRequest(requestOptions) {\n return this.backendSrv.datasourceRequest(requestOptions)\n .then((response) => {\n if (!response.data) {\n return Promise.reject(new ZabbixAPIError({data: \"General Error, no data\"}));\n } else if (response.data.error) {\n\n // Handle Zabbix API errors\n return Promise.reject(new ZabbixAPIError(response.data.error));\n }\n\n // Success\n return response.data.result;\n });\n }\n\n /**\n * Get authentication token.\n * @return {string} auth token\n */\n login(api_url, username, password, options) {\n let params = {\n user: username,\n password: password\n };\n return this.request(api_url, 'user.login', params, options, null);\n }\n\n /**\n * Get Zabbix API version\n * Matches the version of Zabbix starting from Zabbix 2.0.4\n */\n getVersion(api_url, options) {\n return this.request(api_url, 'apiinfo.version', [], options);\n }\n}\n\n// Define zabbix API exception type\nexport class ZabbixAPIError {\n constructor(error) {\n this.code = error.code || null;\n this.name = error.message || \"\";\n this.data = error.data || \"\";\n this.message = \"Zabbix API Error: \" + this.name + \" \" + this.data;\n }\n\n toString() {\n return this.name + \" \" + this.data;\n }\n}\n"]}
|
||||||
150
dist/datasource-zabbix/zabbix/proxy/cachingProxy.js
vendored
Normal file
150
dist/datasource-zabbix/zabbix/proxy/cachingProxy.js
vendored
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
System.register([], function (_export, _context) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var _createClass, CachingProxy;
|
||||||
|
|
||||||
|
function _classCallCheck(instance, Constructor) {
|
||||||
|
if (!(instance instanceof Constructor)) {
|
||||||
|
throw new TypeError("Cannot call a class as a function");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap request to prevent multiple calls
|
||||||
|
* with same params when waiting for result.
|
||||||
|
*/
|
||||||
|
function callOnce(func, promiseKeeper, funcScope) {
|
||||||
|
return function () {
|
||||||
|
var hash = getRequestHash(arguments);
|
||||||
|
if (!promiseKeeper[hash]) {
|
||||||
|
promiseKeeper[hash] = Promise.resolve(func.apply(funcScope, arguments).then(function (result) {
|
||||||
|
promiseKeeper[hash] = null;
|
||||||
|
return result;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return promiseKeeper[hash];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function _cacheRequest(func, funcName, funcScope, self) {
|
||||||
|
return function () {
|
||||||
|
if (!self.cache[funcName]) {
|
||||||
|
self.cache[funcName] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var cacheObject = self.cache[funcName];
|
||||||
|
var hash = getRequestHash(arguments);
|
||||||
|
if (self.cacheEnabled && !self._isExpired(cacheObject[hash])) {
|
||||||
|
return Promise.resolve(cacheObject[hash].value);
|
||||||
|
} else {
|
||||||
|
return func.apply(funcScope, arguments).then(function (result) {
|
||||||
|
cacheObject[hash] = {
|
||||||
|
value: result,
|
||||||
|
timestamp: Date.now()
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRequestHash(args) {
|
||||||
|
var argsJson = JSON.stringify(args);
|
||||||
|
return argsJson.getHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
setters: [],
|
||||||
|
execute: function () {
|
||||||
|
_createClass = function () {
|
||||||
|
function defineProperties(target, props) {
|
||||||
|
for (var i = 0; i < props.length; i++) {
|
||||||
|
var descriptor = props[i];
|
||||||
|
descriptor.enumerable = descriptor.enumerable || false;
|
||||||
|
descriptor.configurable = true;
|
||||||
|
if ("value" in descriptor) descriptor.writable = true;
|
||||||
|
Object.defineProperty(target, descriptor.key, descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return function (Constructor, protoProps, staticProps) {
|
||||||
|
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
||||||
|
if (staticProps) defineProperties(Constructor, staticProps);
|
||||||
|
return Constructor;
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
_export("CachingProxy", CachingProxy = function () {
|
||||||
|
function CachingProxy(cacheOptions) {
|
||||||
|
_classCallCheck(this, CachingProxy);
|
||||||
|
|
||||||
|
this.cacheEnabled = cacheOptions.enabled;
|
||||||
|
this.ttl = cacheOptions.ttl || 600000; // 10 minutes by default
|
||||||
|
|
||||||
|
// Internal objects for data storing
|
||||||
|
this.cache = {};
|
||||||
|
this.promises = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that result is present in the cache and is up to date or send request otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
_createClass(CachingProxy, [{
|
||||||
|
key: "cacheRequest",
|
||||||
|
value: function cacheRequest(func, funcName, funcScope) {
|
||||||
|
return _cacheRequest(func, funcName, funcScope, this);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "proxyfy",
|
||||||
|
value: function proxyfy(func, funcName, funcScope) {
|
||||||
|
if (!this.promises[funcName]) {
|
||||||
|
this.promises[funcName] = {};
|
||||||
|
}
|
||||||
|
var promiseKeeper = this.promises[funcName];
|
||||||
|
return callOnce(func, promiseKeeper, funcScope);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "proxyfyWithCache",
|
||||||
|
value: function proxyfyWithCache(func, funcName, funcScope) {
|
||||||
|
var proxyfied = this.proxyfy(func, funcName, funcScope);
|
||||||
|
return this.cacheRequest(proxyfied, funcName, funcScope);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "_isExpired",
|
||||||
|
value: function _isExpired(cacheObject) {
|
||||||
|
if (cacheObject) {
|
||||||
|
var object_age = Date.now() - cacheObject.timestamp;
|
||||||
|
return !(cacheObject.timestamp && object_age < this.ttl);
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return CachingProxy;
|
||||||
|
}());
|
||||||
|
|
||||||
|
_export("CachingProxy", CachingProxy);
|
||||||
|
|
||||||
|
String.prototype.getHash = function () {
|
||||||
|
var hash = 0,
|
||||||
|
i,
|
||||||
|
chr,
|
||||||
|
len;
|
||||||
|
if (this.length !== 0) {
|
||||||
|
for (i = 0, len = this.length; i < len; i++) {
|
||||||
|
chr = this.charCodeAt(i);
|
||||||
|
hash = (hash << 5) - hash + chr;
|
||||||
|
hash |= 0; // Convert to 32bit integer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=cachingProxy.js.map
|
||||||
1
dist/datasource-zabbix/zabbix/proxy/cachingProxy.js.map
vendored
Normal file
1
dist/datasource-zabbix/zabbix/proxy/cachingProxy.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
531
dist/datasource-zabbix/zabbix/zabbix.js
vendored
Normal file
531
dist/datasource-zabbix/zabbix/zabbix.js
vendored
Normal file
@@ -0,0 +1,531 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
System.register(['lodash', '../utils', '../responseHandler', './connectors/zabbix_api/zabbixAPIConnector', './connectors/sql/sqlConnector', './proxy/cachingProxy'], function (_export, _context) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var _, utils, responseHandler, ZabbixAPIConnector, SQLConnector, CachingProxy, _slicedToArray, _createClass, REQUESTS_TO_PROXYFY, REQUESTS_TO_CACHE, REQUESTS_TO_BIND, Zabbix;
|
||||||
|
|
||||||
|
function _toConsumableArray(arr) {
|
||||||
|
if (Array.isArray(arr)) {
|
||||||
|
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
|
||||||
|
arr2[i] = arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr2;
|
||||||
|
} else {
|
||||||
|
return Array.from(arr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _classCallCheck(instance, Constructor) {
|
||||||
|
if (!(instance instanceof Constructor)) {
|
||||||
|
throw new TypeError("Cannot call a class as a function");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find group, host, app or item by given name.
|
||||||
|
* @param list list of groups, apps or other
|
||||||
|
* @param name visible name
|
||||||
|
* @return array with finded element or empty array
|
||||||
|
*/
|
||||||
|
function findByName(list, name) {
|
||||||
|
var finded = _.find(list, { 'name': name });
|
||||||
|
if (finded) {
|
||||||
|
return [finded];
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Different hosts can contains applications and items with same name.
|
||||||
|
* For this reason use _.filter, which return all elements instead _.find,
|
||||||
|
* which return only first finded.
|
||||||
|
* @param {[type]} list list of elements
|
||||||
|
* @param {[type]} name app name
|
||||||
|
* @return {[type]} array with finded element or empty array
|
||||||
|
*/
|
||||||
|
function filterByName(list, name) {
|
||||||
|
var finded = _.filter(list, { 'name': name });
|
||||||
|
if (finded) {
|
||||||
|
return finded;
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterByRegex(list, regex) {
|
||||||
|
var filterPattern = utils.buildRegex(regex);
|
||||||
|
return _.filter(list, function (zbx_obj) {
|
||||||
|
return filterPattern.test(zbx_obj.name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function findByFilter(list, filter) {
|
||||||
|
if (utils.isRegex(filter)) {
|
||||||
|
return filterByRegex(list, filter);
|
||||||
|
} else {
|
||||||
|
return findByName(list, filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterByQuery(list, filter) {
|
||||||
|
if (utils.isRegex(filter)) {
|
||||||
|
return filterByRegex(list, filter);
|
||||||
|
} else {
|
||||||
|
return filterByName(list, filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHostIds(items) {
|
||||||
|
var hostIds = _.map(items, function (item) {
|
||||||
|
return _.map(item.hosts, 'hostid');
|
||||||
|
});
|
||||||
|
return _.uniq(_.flatten(hostIds));
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
setters: [function (_lodash) {
|
||||||
|
_ = _lodash.default;
|
||||||
|
}, function (_utils) {
|
||||||
|
utils = _utils;
|
||||||
|
}, function (_responseHandler) {
|
||||||
|
responseHandler = _responseHandler.default;
|
||||||
|
}, function (_connectorsZabbix_apiZabbixAPIConnector) {
|
||||||
|
ZabbixAPIConnector = _connectorsZabbix_apiZabbixAPIConnector.ZabbixAPIConnector;
|
||||||
|
}, function (_connectorsSqlSqlConnector) {
|
||||||
|
SQLConnector = _connectorsSqlSqlConnector.SQLConnector;
|
||||||
|
}, function (_proxyCachingProxy) {
|
||||||
|
CachingProxy = _proxyCachingProxy.CachingProxy;
|
||||||
|
}],
|
||||||
|
execute: function () {
|
||||||
|
_slicedToArray = function () {
|
||||||
|
function sliceIterator(arr, i) {
|
||||||
|
var _arr = [];
|
||||||
|
var _n = true;
|
||||||
|
var _d = false;
|
||||||
|
var _e = undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
|
||||||
|
_arr.push(_s.value);
|
||||||
|
|
||||||
|
if (i && _arr.length === i) break;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
_d = true;
|
||||||
|
_e = err;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (!_n && _i["return"]) _i["return"]();
|
||||||
|
} finally {
|
||||||
|
if (_d) throw _e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return function (arr, i) {
|
||||||
|
if (Array.isArray(arr)) {
|
||||||
|
return arr;
|
||||||
|
} else if (Symbol.iterator in Object(arr)) {
|
||||||
|
return sliceIterator(arr, i);
|
||||||
|
} else {
|
||||||
|
throw new TypeError("Invalid attempt to destructure non-iterable instance");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
_createClass = function () {
|
||||||
|
function defineProperties(target, props) {
|
||||||
|
for (var i = 0; i < props.length; i++) {
|
||||||
|
var descriptor = props[i];
|
||||||
|
descriptor.enumerable = descriptor.enumerable || false;
|
||||||
|
descriptor.configurable = true;
|
||||||
|
if ("value" in descriptor) descriptor.writable = true;
|
||||||
|
Object.defineProperty(target, descriptor.key, descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return function (Constructor, protoProps, staticProps) {
|
||||||
|
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
||||||
|
if (staticProps) defineProperties(Constructor, staticProps);
|
||||||
|
return Constructor;
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
REQUESTS_TO_PROXYFY = ['getHistory', 'getTrend', 'getGroups', 'getHosts', 'getApps', 'getItems', 'getMacros', 'getItemsByIDs', 'getEvents', 'getAlerts', 'getHostAlerts', 'getAcknowledges', 'getITService', 'getSLA', 'getVersion'];
|
||||||
|
REQUESTS_TO_CACHE = ['getGroups', 'getHosts', 'getApps', 'getItems', 'getMacros', 'getItemsByIDs', 'getITService'];
|
||||||
|
REQUESTS_TO_BIND = ['getHistory', 'getTrend', 'getMacros', 'getItemsByIDs', 'getEvents', 'getAlerts', 'getHostAlerts', 'getAcknowledges', 'getITService', 'getVersion', 'login'];
|
||||||
|
|
||||||
|
_export('Zabbix', Zabbix = function () {
|
||||||
|
function Zabbix(options, backendSrv, datasourceSrv) {
|
||||||
|
_classCallCheck(this, Zabbix);
|
||||||
|
|
||||||
|
var url = options.url,
|
||||||
|
username = options.username,
|
||||||
|
password = options.password,
|
||||||
|
basicAuth = options.basicAuth,
|
||||||
|
withCredentials = options.withCredentials,
|
||||||
|
cacheTTL = options.cacheTTL,
|
||||||
|
enableDirectDBConnection = options.enableDirectDBConnection,
|
||||||
|
datasourceId = options.datasourceId;
|
||||||
|
|
||||||
|
|
||||||
|
this.enableDirectDBConnection = enableDirectDBConnection;
|
||||||
|
|
||||||
|
// Initialize caching proxy for requests
|
||||||
|
var cacheOptions = {
|
||||||
|
enabled: true,
|
||||||
|
ttl: cacheTTL
|
||||||
|
};
|
||||||
|
this.cachingProxy = new CachingProxy(cacheOptions);
|
||||||
|
|
||||||
|
this.zabbixAPI = new ZabbixAPIConnector(url, username, password, basicAuth, withCredentials, backendSrv);
|
||||||
|
|
||||||
|
if (enableDirectDBConnection) {
|
||||||
|
var dbConnectorOptions = { datasourceId: datasourceId };
|
||||||
|
this.dbConnector = new SQLConnector(dbConnectorOptions, backendSrv, datasourceSrv);
|
||||||
|
this.getHistoryDB = this.cachingProxy.proxyfyWithCache(this.dbConnector.getHistory, 'getHistory', this.dbConnector);
|
||||||
|
this.getTrendsDB = this.cachingProxy.proxyfyWithCache(this.dbConnector.getTrends, 'getTrends', this.dbConnector);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.proxyfyRequests();
|
||||||
|
this.cacheRequests();
|
||||||
|
this.bindRequests();
|
||||||
|
}
|
||||||
|
|
||||||
|
_createClass(Zabbix, [{
|
||||||
|
key: 'proxyfyRequests',
|
||||||
|
value: function proxyfyRequests() {
|
||||||
|
var _iteratorNormalCompletion = true;
|
||||||
|
var _didIteratorError = false;
|
||||||
|
var _iteratorError = undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (var _iterator = REQUESTS_TO_PROXYFY[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||||
|
var request = _step.value;
|
||||||
|
|
||||||
|
this.zabbixAPI[request] = this.cachingProxy.proxyfy(this.zabbixAPI[request], request, this.zabbixAPI);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
_didIteratorError = true;
|
||||||
|
_iteratorError = err;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (!_iteratorNormalCompletion && _iterator.return) {
|
||||||
|
_iterator.return();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (_didIteratorError) {
|
||||||
|
throw _iteratorError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'cacheRequests',
|
||||||
|
value: function cacheRequests() {
|
||||||
|
var _iteratorNormalCompletion2 = true;
|
||||||
|
var _didIteratorError2 = false;
|
||||||
|
var _iteratorError2 = undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (var _iterator2 = REQUESTS_TO_CACHE[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
||||||
|
var request = _step2.value;
|
||||||
|
|
||||||
|
this.zabbixAPI[request] = this.cachingProxy.cacheRequest(this.zabbixAPI[request], request, this.zabbixAPI);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
_didIteratorError2 = true;
|
||||||
|
_iteratorError2 = err;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (!_iteratorNormalCompletion2 && _iterator2.return) {
|
||||||
|
_iterator2.return();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (_didIteratorError2) {
|
||||||
|
throw _iteratorError2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'bindRequests',
|
||||||
|
value: function bindRequests() {
|
||||||
|
var _iteratorNormalCompletion3 = true;
|
||||||
|
var _didIteratorError3 = false;
|
||||||
|
var _iteratorError3 = undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (var _iterator3 = REQUESTS_TO_BIND[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
|
||||||
|
var request = _step3.value;
|
||||||
|
|
||||||
|
this[request] = this.zabbixAPI[request].bind(this.zabbixAPI);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
_didIteratorError3 = true;
|
||||||
|
_iteratorError3 = err;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (!_iteratorNormalCompletion3 && _iterator3.return) {
|
||||||
|
_iterator3.return();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (_didIteratorError3) {
|
||||||
|
throw _iteratorError3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getItemsFromTarget',
|
||||||
|
value: function getItemsFromTarget(target, options) {
|
||||||
|
var parts = ['group', 'host', 'application', 'item'];
|
||||||
|
var filters = _.map(parts, function (p) {
|
||||||
|
return target[p].filter;
|
||||||
|
});
|
||||||
|
return this.getItems.apply(this, _toConsumableArray(filters).concat([options]));
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getHostsFromTarget',
|
||||||
|
value: function getHostsFromTarget(target) {
|
||||||
|
var parts = ['group', 'host', 'application'];
|
||||||
|
var filters = _.map(parts, function (p) {
|
||||||
|
return target[p].filter;
|
||||||
|
});
|
||||||
|
return Promise.all([this.getHosts.apply(this, _toConsumableArray(filters)), this.getApps.apply(this, _toConsumableArray(filters))]).then(function (results) {
|
||||||
|
var _results = _slicedToArray(results, 2),
|
||||||
|
hosts = _results[0],
|
||||||
|
apps = _results[1];
|
||||||
|
|
||||||
|
if (apps.appFilterEmpty) {
|
||||||
|
apps = [];
|
||||||
|
}
|
||||||
|
return [hosts, apps];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getAllGroups',
|
||||||
|
value: function getAllGroups() {
|
||||||
|
return this.zabbixAPI.getGroups();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getGroups',
|
||||||
|
value: function getGroups(groupFilter) {
|
||||||
|
return this.getAllGroups().then(function (groups) {
|
||||||
|
return findByFilter(groups, groupFilter);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getAllHosts',
|
||||||
|
value: function getAllHosts(groupFilter) {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
return this.getGroups(groupFilter).then(function (groups) {
|
||||||
|
var groupids = _.map(groups, 'groupid');
|
||||||
|
return _this.zabbixAPI.getHosts(groupids);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getHosts',
|
||||||
|
value: function getHosts(groupFilter, hostFilter) {
|
||||||
|
return this.getAllHosts(groupFilter).then(function (hosts) {
|
||||||
|
return findByFilter(hosts, hostFilter);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getAllApps',
|
||||||
|
value: function getAllApps(groupFilter, hostFilter) {
|
||||||
|
var _this2 = this;
|
||||||
|
|
||||||
|
return this.getHosts(groupFilter, hostFilter).then(function (hosts) {
|
||||||
|
var hostids = _.map(hosts, 'hostid');
|
||||||
|
return _this2.zabbixAPI.getApps(hostids);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getApps',
|
||||||
|
value: function getApps(groupFilter, hostFilter, appFilter) {
|
||||||
|
var _this3 = this;
|
||||||
|
|
||||||
|
return this.getHosts(groupFilter, hostFilter).then(function (hosts) {
|
||||||
|
var hostids = _.map(hosts, 'hostid');
|
||||||
|
if (appFilter) {
|
||||||
|
return _this3.zabbixAPI.getApps(hostids).then(function (apps) {
|
||||||
|
return filterByQuery(apps, appFilter);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
appFilterEmpty: true,
|
||||||
|
hostids: hostids
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getAllItems',
|
||||||
|
value: function getAllItems(groupFilter, hostFilter, appFilter) {
|
||||||
|
var _this4 = this;
|
||||||
|
|
||||||
|
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
||||||
|
|
||||||
|
return this.getApps(groupFilter, hostFilter, appFilter).then(function (apps) {
|
||||||
|
if (apps.appFilterEmpty) {
|
||||||
|
return _this4.zabbixAPI.getItems(apps.hostids, undefined, options.itemtype);
|
||||||
|
} else {
|
||||||
|
var appids = _.map(apps, 'applicationid');
|
||||||
|
return _this4.zabbixAPI.getItems(undefined, appids, options.itemtype);
|
||||||
|
}
|
||||||
|
}).then(function (items) {
|
||||||
|
if (!options.showDisabledItems) {
|
||||||
|
items = _.filter(items, { 'status': '0' });
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}).then(this.expandUserMacro.bind(this));
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'expandUserMacro',
|
||||||
|
value: function expandUserMacro(items) {
|
||||||
|
var hostids = getHostIds(items);
|
||||||
|
return this.getMacros(hostids).then(function (macros) {
|
||||||
|
_.forEach(items, function (item) {
|
||||||
|
if (utils.containsMacro(item.name)) {
|
||||||
|
item.name = utils.replaceMacro(item, macros);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return items;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getItems',
|
||||||
|
value: function getItems(groupFilter, hostFilter, appFilter, itemFilter) {
|
||||||
|
var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
||||||
|
|
||||||
|
return this.getAllItems(groupFilter, hostFilter, appFilter, options).then(function (items) {
|
||||||
|
return filterByQuery(items, itemFilter);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getITServices',
|
||||||
|
value: function getITServices(itServiceFilter) {
|
||||||
|
return this.zabbixAPI.getITService().then(function (itServices) {
|
||||||
|
return findByFilter(itServices, itServiceFilter);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getTriggers',
|
||||||
|
value: function getTriggers(groupFilter, hostFilter, appFilter, options) {
|
||||||
|
var _this5 = this;
|
||||||
|
|
||||||
|
var promises = [this.getGroups(groupFilter), this.getHosts(groupFilter, hostFilter), this.getApps(groupFilter, hostFilter, appFilter)];
|
||||||
|
|
||||||
|
return Promise.all(promises).then(function (results) {
|
||||||
|
var filteredGroups = results[0];
|
||||||
|
var filteredHosts = results[1];
|
||||||
|
var filteredApps = results[2];
|
||||||
|
var query = {};
|
||||||
|
|
||||||
|
if (appFilter) {
|
||||||
|
query.applicationids = _.flatten(_.map(filteredApps, 'applicationid'));
|
||||||
|
}
|
||||||
|
if (hostFilter) {
|
||||||
|
query.hostids = _.map(filteredHosts, 'hostid');
|
||||||
|
}
|
||||||
|
if (groupFilter) {
|
||||||
|
query.groupids = _.map(filteredGroups, 'groupid');
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}).then(function (query) {
|
||||||
|
return _this5.zabbixAPI.getTriggers(query.groupids, query.hostids, query.applicationids, options);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getHistoryTS',
|
||||||
|
value: function getHistoryTS(items, timeRange, options) {
|
||||||
|
var _this6 = this;
|
||||||
|
|
||||||
|
var _timeRange = _slicedToArray(timeRange, 2),
|
||||||
|
timeFrom = _timeRange[0],
|
||||||
|
timeTo = _timeRange[1];
|
||||||
|
|
||||||
|
if (this.enableDirectDBConnection) {
|
||||||
|
return this.getHistoryDB(items, timeFrom, timeTo, options).then(function (history) {
|
||||||
|
return _this6.dbConnector.handleGrafanaTSResponse(history, items);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return this.zabbixAPI.getHistory(items, timeFrom, timeTo).then(function (history) {
|
||||||
|
return responseHandler.handleHistory(history, items);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getTrends',
|
||||||
|
value: function getTrends(items, timeRange, options) {
|
||||||
|
var _this7 = this;
|
||||||
|
|
||||||
|
var _timeRange2 = _slicedToArray(timeRange, 2),
|
||||||
|
timeFrom = _timeRange2[0],
|
||||||
|
timeTo = _timeRange2[1];
|
||||||
|
|
||||||
|
if (this.enableDirectDBConnection) {
|
||||||
|
return this.getTrendsDB(items, timeFrom, timeTo, options).then(function (history) {
|
||||||
|
return _this7.dbConnector.handleGrafanaTSResponse(history, items);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var valueType = options.consolidateBy || options.valueType;
|
||||||
|
return this.zabbixAPI.getTrend(items, timeFrom, timeTo).then(function (history) {
|
||||||
|
return responseHandler.handleTrends(history, items, valueType);
|
||||||
|
}).then(responseHandler.sortTimeseries); // Sort trend data, issue #202
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getHistoryText',
|
||||||
|
value: function getHistoryText(items, timeRange, target) {
|
||||||
|
var _timeRange3 = _slicedToArray(timeRange, 2),
|
||||||
|
timeFrom = _timeRange3[0],
|
||||||
|
timeTo = _timeRange3[1];
|
||||||
|
|
||||||
|
if (items.length) {
|
||||||
|
return this.zabbixAPI.getHistory(items, timeFrom, timeTo).then(function (history) {
|
||||||
|
if (target.resultFormat === 'table') {
|
||||||
|
return responseHandler.handleHistoryAsTable(history, items, target);
|
||||||
|
} else {
|
||||||
|
return responseHandler.handleText(history, items, target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getSLA',
|
||||||
|
value: function getSLA(itservices, timeRange, target, options) {
|
||||||
|
var itServices = itservices;
|
||||||
|
if (options.isOldVersion) {
|
||||||
|
itServices = _.filter(itServices, { 'serviceid': target.itservice.serviceid });
|
||||||
|
}
|
||||||
|
var itServiceIds = _.map(itServices, 'serviceid');
|
||||||
|
return this.zabbixAPI.getSLA(itServiceIds, timeRange).then(function (slaResponse) {
|
||||||
|
return _.map(itServiceIds, function (serviceid) {
|
||||||
|
var itservice = _.find(itServices, { 'serviceid': serviceid });
|
||||||
|
return responseHandler.handleSLAResponse(itservice, target.slaProperty, slaResponse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return Zabbix;
|
||||||
|
}());
|
||||||
|
|
||||||
|
_export('Zabbix', Zabbix);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=zabbix.js.map
|
||||||
1
dist/datasource-zabbix/zabbix/zabbix.js.map
vendored
Normal file
1
dist/datasource-zabbix/zabbix/zabbix.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
559
dist/datasource-zabbix/zabbixAPI.service.js
vendored
559
dist/datasource-zabbix/zabbixAPI.service.js
vendored
@@ -1,559 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
System.register(['angular', 'lodash', './utils', './zabbixAPICore.service'], function (_export, _context) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var angular, _, utils, _slicedToArray, _createClass;
|
|
||||||
|
|
||||||
function _classCallCheck(instance, Constructor) {
|
|
||||||
if (!(instance instanceof Constructor)) {
|
|
||||||
throw new TypeError("Cannot call a class as a function");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) {
|
|
||||||
var ZabbixAPI = function () {
|
|
||||||
function ZabbixAPI(api_url, username, password, basicAuth, withCredentials) {
|
|
||||||
_classCallCheck(this, ZabbixAPI);
|
|
||||||
|
|
||||||
this.url = api_url;
|
|
||||||
this.username = username;
|
|
||||||
this.password = password;
|
|
||||||
this.auth = "";
|
|
||||||
|
|
||||||
this.requestOptions = {
|
|
||||||
basicAuth: basicAuth,
|
|
||||||
withCredentials: withCredentials
|
|
||||||
};
|
|
||||||
|
|
||||||
this.loginPromise = null;
|
|
||||||
this.loginErrorCount = 0;
|
|
||||||
this.maxLoginAttempts = 3;
|
|
||||||
|
|
||||||
this.alertSrv = alertSrv;
|
|
||||||
this.zabbixAPICore = zabbixAPICoreService;
|
|
||||||
|
|
||||||
this.getTrend = this.getTrend_ZBXNEXT1193;
|
|
||||||
//getTrend = getTrend_30;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////
|
|
||||||
// Core method wrappers //
|
|
||||||
//////////////////////////
|
|
||||||
|
|
||||||
_createClass(ZabbixAPI, [{
|
|
||||||
key: 'request',
|
|
||||||
value: function request(method, params) {
|
|
||||||
var _this = this;
|
|
||||||
|
|
||||||
return this.zabbixAPICore.request(this.url, method, params, this.requestOptions, this.auth).catch(function (error) {
|
|
||||||
if (isNotAuthorized(error.data)) {
|
|
||||||
// Handle auth errors
|
|
||||||
_this.loginErrorCount++;
|
|
||||||
if (_this.loginErrorCount > _this.maxLoginAttempts) {
|
|
||||||
_this.loginErrorCount = 0;
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return _this.loginOnce().then(function () {
|
|
||||||
return _this.request(method, params);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Handle API errors
|
|
||||||
var message = error.data ? error.data : error.statusText;
|
|
||||||
_this.alertAPIError(message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'alertAPIError',
|
|
||||||
value: function alertAPIError(message) {
|
|
||||||
var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5000;
|
|
||||||
|
|
||||||
this.alertSrv.set("Zabbix API Error", message, 'error', timeout);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'loginOnce',
|
|
||||||
value: function loginOnce() {
|
|
||||||
var _this2 = this;
|
|
||||||
|
|
||||||
if (!this.loginPromise) {
|
|
||||||
this.loginPromise = Promise.resolve(this.login().then(function (auth) {
|
|
||||||
_this2.auth = auth;
|
|
||||||
_this2.loginPromise = null;
|
|
||||||
return auth;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
return this.loginPromise;
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'login',
|
|
||||||
value: function login() {
|
|
||||||
return this.zabbixAPICore.login(this.url, this.username, this.password, this.requestOptions);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getVersion',
|
|
||||||
value: function getVersion() {
|
|
||||||
return this.zabbixAPICore.getVersion(this.url, this.requestOptions);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'acknowledgeEvent',
|
|
||||||
value: function acknowledgeEvent(eventid, message) {
|
|
||||||
var params = {
|
|
||||||
eventids: eventid,
|
|
||||||
message: message
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('event.acknowledge', params);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getGroups',
|
|
||||||
value: function getGroups() {
|
|
||||||
var params = {
|
|
||||||
output: ['name'],
|
|
||||||
sortfield: 'name',
|
|
||||||
real_hosts: true
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('hostgroup.get', params);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getHosts',
|
|
||||||
value: function getHosts(groupids) {
|
|
||||||
var params = {
|
|
||||||
output: ['name', 'host'],
|
|
||||||
sortfield: 'name'
|
|
||||||
};
|
|
||||||
if (groupids) {
|
|
||||||
params.groupids = groupids;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.request('host.get', params);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getApps',
|
|
||||||
value: function getApps(hostids) {
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
hostids: hostids
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('application.get', params);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getItems',
|
|
||||||
value: function getItems(hostids, appids, itemtype) {
|
|
||||||
var params = {
|
|
||||||
output: ['name', 'key_', 'value_type', 'hostid', 'status', 'state'],
|
|
||||||
sortfield: 'name',
|
|
||||||
webitems: true,
|
|
||||||
filter: {},
|
|
||||||
selectHosts: ['hostid', 'name']
|
|
||||||
};
|
|
||||||
if (hostids) {
|
|
||||||
params.hostids = hostids;
|
|
||||||
}
|
|
||||||
if (appids) {
|
|
||||||
params.applicationids = appids;
|
|
||||||
}
|
|
||||||
if (itemtype === 'num') {
|
|
||||||
// Return only numeric metrics
|
|
||||||
params.filter.value_type = [0, 3];
|
|
||||||
}
|
|
||||||
if (itemtype === 'text') {
|
|
||||||
// Return only text metrics
|
|
||||||
params.filter.value_type = [1, 2, 4];
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.request('item.get', params).then(utils.expandItems);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getItemsByIDs',
|
|
||||||
value: function getItemsByIDs(itemids) {
|
|
||||||
var params = {
|
|
||||||
itemids: itemids,
|
|
||||||
output: ['name', 'key_', 'value_type', 'hostid', 'status', 'state'],
|
|
||||||
webitems: true,
|
|
||||||
selectHosts: ['hostid', 'name']
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('item.get', params).then(utils.expandItems);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getMacros',
|
|
||||||
value: function getMacros(hostids) {
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
hostids: hostids
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('usermacro.get', params);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getGlobalMacros',
|
|
||||||
value: function getGlobalMacros() {
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
globalmacro: true
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('usermacro.get', params);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getLastValue',
|
|
||||||
value: function getLastValue(itemid) {
|
|
||||||
var params = {
|
|
||||||
output: ['lastvalue'],
|
|
||||||
itemids: itemid
|
|
||||||
};
|
|
||||||
return this.request('item.get', params).then(function (items) {
|
|
||||||
return items.length ? items[0].lastvalue : null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getHistory',
|
|
||||||
value: function getHistory(items, timeFrom, timeTill) {
|
|
||||||
var _this3 = 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');
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
history: value_type,
|
|
||||||
itemids: itemids,
|
|
||||||
sortfield: 'clock',
|
|
||||||
sortorder: 'ASC',
|
|
||||||
time_from: timeFrom
|
|
||||||
};
|
|
||||||
|
|
||||||
// Relative queries (e.g. last hour) don't include an end time
|
|
||||||
if (timeTill) {
|
|
||||||
params.time_till = timeTill;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _this3.request('history.get', params);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises).then(_.flatten);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getTrend_ZBXNEXT1193',
|
|
||||||
value: function getTrend_ZBXNEXT1193(items, timeFrom, timeTill) {
|
|
||||||
var _this4 = 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');
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
trend: value_type,
|
|
||||||
itemids: itemids,
|
|
||||||
sortfield: 'clock',
|
|
||||||
sortorder: 'ASC',
|
|
||||||
time_from: timeFrom
|
|
||||||
};
|
|
||||||
|
|
||||||
// Relative queries (e.g. last hour) don't include an end time
|
|
||||||
if (timeTill) {
|
|
||||||
params.time_till = timeTill;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _this4.request('trend.get', params);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises).then(_.flatten);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getTrend_30',
|
|
||||||
value: function getTrend_30(items, time_from, time_till, value_type) {
|
|
||||||
var self = this;
|
|
||||||
var itemids = _.map(items, 'itemid');
|
|
||||||
|
|
||||||
var params = {
|
|
||||||
output: ["itemid", "clock", value_type],
|
|
||||||
itemids: itemids,
|
|
||||||
time_from: time_from
|
|
||||||
};
|
|
||||||
|
|
||||||
// Relative queries (e.g. last hour) don't include an end time
|
|
||||||
if (time_till) {
|
|
||||||
params.time_till = time_till;
|
|
||||||
}
|
|
||||||
|
|
||||||
return self.request('trend.get', params);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getITService',
|
|
||||||
value: function getITService(serviceids) {
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
serviceids: serviceids
|
|
||||||
};
|
|
||||||
return this.request('service.get', params);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getSLA',
|
|
||||||
value: function getSLA(serviceids, timeRange) {
|
|
||||||
var _timeRange = _slicedToArray(timeRange, 2),
|
|
||||||
timeFrom = _timeRange[0],
|
|
||||||
timeTo = _timeRange[1];
|
|
||||||
|
|
||||||
var params = {
|
|
||||||
serviceids: serviceids,
|
|
||||||
intervals: [{
|
|
||||||
from: timeFrom,
|
|
||||||
to: timeTo
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
return this.request('service.getsla', params);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getTriggers',
|
|
||||||
value: function getTriggers(groupids, hostids, applicationids, options) {
|
|
||||||
var showTriggers = options.showTriggers,
|
|
||||||
maintenance = options.maintenance,
|
|
||||||
timeFrom = options.timeFrom,
|
|
||||||
timeTo = options.timeTo;
|
|
||||||
|
|
||||||
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
groupids: groupids,
|
|
||||||
hostids: hostids,
|
|
||||||
applicationids: applicationids,
|
|
||||||
expandDescription: true,
|
|
||||||
expandData: true,
|
|
||||||
expandComment: true,
|
|
||||||
monitored: true,
|
|
||||||
skipDependent: true,
|
|
||||||
//only_true: true,
|
|
||||||
filter: {
|
|
||||||
value: 1
|
|
||||||
},
|
|
||||||
selectGroups: ['name'],
|
|
||||||
selectHosts: ['name', 'host', 'maintenance_status'],
|
|
||||||
selectItems: ['name', 'key_', 'lastvalue'],
|
|
||||||
selectLastEvent: 'extend',
|
|
||||||
selectTags: 'extend'
|
|
||||||
};
|
|
||||||
|
|
||||||
if (showTriggers) {
|
|
||||||
params.filter.value = showTriggers;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maintenance) {
|
|
||||||
params.maintenance = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeFrom || timeTo) {
|
|
||||||
params.lastChangeSince = timeFrom;
|
|
||||||
params.lastChangeTill = timeTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.request('trigger.get', params);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getEvents',
|
|
||||||
value: function getEvents(objectids, timeFrom, timeTo, showEvents) {
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
time_from: timeFrom,
|
|
||||||
time_till: timeTo,
|
|
||||||
objectids: objectids,
|
|
||||||
select_acknowledges: 'extend',
|
|
||||||
selectHosts: 'extend',
|
|
||||||
value: showEvents
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('event.get', params);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getAcknowledges',
|
|
||||||
value: function getAcknowledges(eventids) {
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
eventids: eventids,
|
|
||||||
preservekeys: true,
|
|
||||||
select_acknowledges: 'extend',
|
|
||||||
sortfield: 'clock',
|
|
||||||
sortorder: 'DESC'
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('event.get', params).then(function (events) {
|
|
||||||
return _.filter(events, function (event) {
|
|
||||||
return event.acknowledges.length;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getAlerts',
|
|
||||||
value: function getAlerts(itemids, timeFrom, timeTo) {
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
itemids: itemids,
|
|
||||||
expandDescription: true,
|
|
||||||
expandData: true,
|
|
||||||
expandComment: true,
|
|
||||||
monitored: true,
|
|
||||||
skipDependent: true,
|
|
||||||
//only_true: true,
|
|
||||||
// filter: {
|
|
||||||
// value: 1
|
|
||||||
// },
|
|
||||||
selectLastEvent: 'extend'
|
|
||||||
};
|
|
||||||
|
|
||||||
if (timeFrom || timeTo) {
|
|
||||||
params.lastChangeSince = timeFrom;
|
|
||||||
params.lastChangeTill = timeTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.request('trigger.get', params);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getHostAlerts',
|
|
||||||
value: function getHostAlerts(hostids, applicationids, options) {
|
|
||||||
var minSeverity = options.minSeverity,
|
|
||||||
acknowledged = options.acknowledged,
|
|
||||||
count = options.count,
|
|
||||||
timeFrom = options.timeFrom,
|
|
||||||
timeTo = options.timeTo;
|
|
||||||
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
hostids: hostids,
|
|
||||||
min_severity: minSeverity,
|
|
||||||
filter: { value: 1 },
|
|
||||||
expandDescription: true,
|
|
||||||
expandData: true,
|
|
||||||
expandComment: true,
|
|
||||||
monitored: true,
|
|
||||||
skipDependent: true,
|
|
||||||
selectLastEvent: 'extend',
|
|
||||||
selectGroups: 'extend',
|
|
||||||
selectHosts: ['host', 'name']
|
|
||||||
};
|
|
||||||
|
|
||||||
if (count && acknowledged !== 0 && acknowledged !== 1) {
|
|
||||||
params.countOutput = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (applicationids && applicationids.length) {
|
|
||||||
params.applicationids = applicationids;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeFrom || timeTo) {
|
|
||||||
params.lastChangeSince = timeFrom;
|
|
||||||
params.lastChangeTill = timeTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.request('trigger.get', params).then(function (triggers) {
|
|
||||||
if (!count || acknowledged === 0 || acknowledged === 1) {
|
|
||||||
triggers = filterTriggersByAcknowledge(triggers, acknowledged);
|
|
||||||
if (count) {
|
|
||||||
triggers = triggers.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return triggers;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}]);
|
|
||||||
|
|
||||||
return ZabbixAPI;
|
|
||||||
}();
|
|
||||||
|
|
||||||
return ZabbixAPI;
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterTriggersByAcknowledge(triggers, acknowledged) {
|
|
||||||
if (acknowledged === 0) {
|
|
||||||
return _.filter(triggers, function (trigger) {
|
|
||||||
return trigger.lastEvent.acknowledged === "0";
|
|
||||||
});
|
|
||||||
} else if (acknowledged === 1) {
|
|
||||||
return _.filter(triggers, function (trigger) {
|
|
||||||
return trigger.lastEvent.acknowledged === "1";
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return triggers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isNotAuthorized(message) {
|
|
||||||
return message === "Session terminated, re-login, please." || message === "Not authorised." || message === "Not authorized.";
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
setters: [function (_angular) {
|
|
||||||
angular = _angular.default;
|
|
||||||
}, function (_lodash) {
|
|
||||||
_ = _lodash.default;
|
|
||||||
}, function (_utils) {
|
|
||||||
utils = _utils;
|
|
||||||
}, function (_zabbixAPICoreService) {}],
|
|
||||||
execute: function () {
|
|
||||||
_slicedToArray = function () {
|
|
||||||
function sliceIterator(arr, i) {
|
|
||||||
var _arr = [];
|
|
||||||
var _n = true;
|
|
||||||
var _d = false;
|
|
||||||
var _e = undefined;
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
|
|
||||||
_arr.push(_s.value);
|
|
||||||
|
|
||||||
if (i && _arr.length === i) break;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
_d = true;
|
|
||||||
_e = err;
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (!_n && _i["return"]) _i["return"]();
|
|
||||||
} finally {
|
|
||||||
if (_d) throw _e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return _arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return function (arr, i) {
|
|
||||||
if (Array.isArray(arr)) {
|
|
||||||
return arr;
|
|
||||||
} else if (Symbol.iterator in Object(arr)) {
|
|
||||||
return sliceIterator(arr, i);
|
|
||||||
} else {
|
|
||||||
throw new TypeError("Invalid attempt to destructure non-iterable instance");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}();
|
|
||||||
|
|
||||||
_createClass = function () {
|
|
||||||
function defineProperties(target, props) {
|
|
||||||
for (var i = 0; i < props.length; i++) {
|
|
||||||
var descriptor = props[i];
|
|
||||||
descriptor.enumerable = descriptor.enumerable || false;
|
|
||||||
descriptor.configurable = true;
|
|
||||||
if ("value" in descriptor) descriptor.writable = true;
|
|
||||||
Object.defineProperty(target, descriptor.key, descriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return function (Constructor, protoProps, staticProps) {
|
|
||||||
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
|
||||||
if (staticProps) defineProperties(Constructor, staticProps);
|
|
||||||
return Constructor;
|
|
||||||
};
|
|
||||||
}();
|
|
||||||
|
|
||||||
angular.module('grafana.services').factory('zabbixAPIService', ZabbixAPIServiceFactory);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
//# sourceMappingURL=zabbixAPI.service.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
291
dist/datasource-zabbix/zabbixCachingProxy.service.js
vendored
291
dist/datasource-zabbix/zabbixCachingProxy.service.js
vendored
@@ -1,291 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
System.register(['angular', 'lodash'], function (_export, _context) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var angular, _, _createClass;
|
|
||||||
|
|
||||||
function _toConsumableArray(arr) {
|
|
||||||
if (Array.isArray(arr)) {
|
|
||||||
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
|
|
||||||
arr2[i] = arr[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return arr2;
|
|
||||||
} else {
|
|
||||||
return Array.from(arr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _classCallCheck(instance, Constructor) {
|
|
||||||
if (!(instance instanceof Constructor)) {
|
|
||||||
throw new TypeError("Cannot call a class as a function");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use factory() instead service() for multiple datasources support.
|
|
||||||
// Each datasource instance must initialize its own cache.
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
function ZabbixCachingProxyFactory() {
|
|
||||||
var ZabbixCachingProxy = function () {
|
|
||||||
function ZabbixCachingProxy(zabbixAPI, zabbixDBConnector, cacheOptions) {
|
|
||||||
_classCallCheck(this, ZabbixCachingProxy);
|
|
||||||
|
|
||||||
this.zabbixAPI = zabbixAPI;
|
|
||||||
this.dbConnector = zabbixDBConnector;
|
|
||||||
this.cacheEnabled = cacheOptions.enabled;
|
|
||||||
this.ttl = cacheOptions.ttl || 600000; // 10 minutes by default
|
|
||||||
|
|
||||||
// Internal objects for data storing
|
|
||||||
this.cache = {
|
|
||||||
groups: {},
|
|
||||||
hosts: {},
|
|
||||||
applications: {},
|
|
||||||
items: {},
|
|
||||||
history: {},
|
|
||||||
trends: {},
|
|
||||||
macros: {},
|
|
||||||
globalMacros: {},
|
|
||||||
itServices: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.historyPromises = {};
|
|
||||||
|
|
||||||
// Don't run duplicated history requests
|
|
||||||
this.getHistory = callAPIRequestOnce(_.bind(this.zabbixAPI.getHistory, this.zabbixAPI), this.historyPromises, getHistoryRequestHash);
|
|
||||||
|
|
||||||
if (this.dbConnector) {
|
|
||||||
this.getHistoryDB = callAPIRequestOnce(_.bind(this.dbConnector.getHistory, this.dbConnector), this.historyPromises, getDBQueryHash);
|
|
||||||
this.getTrendsDB = callAPIRequestOnce(_.bind(this.dbConnector.getTrends, this.dbConnector), this.historyPromises, getDBQueryHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't run duplicated requests
|
|
||||||
this.groupPromises = {};
|
|
||||||
this.getGroupsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getGroups, this.zabbixAPI), this.groupPromises, getRequestHash);
|
|
||||||
|
|
||||||
this.hostPromises = {};
|
|
||||||
this.getHostsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getHosts, this.zabbixAPI), this.hostPromises, getRequestHash);
|
|
||||||
|
|
||||||
this.appPromises = {};
|
|
||||||
this.getAppsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getApps, this.zabbixAPI), this.appPromises, getRequestHash);
|
|
||||||
|
|
||||||
this.itemPromises = {};
|
|
||||||
this.getItemsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getItems, this.zabbixAPI), this.itemPromises, getRequestHash);
|
|
||||||
|
|
||||||
this.itemByIdPromises = {};
|
|
||||||
this.getItemsByIdOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getItemsByIDs, this.zabbixAPI), this.itemPromises, getRequestHash);
|
|
||||||
|
|
||||||
this.itServicesPromises = {};
|
|
||||||
this.getITServicesOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getITService, this.zabbixAPI), this.itServicesPromises, getRequestHash);
|
|
||||||
|
|
||||||
this.macroPromises = {};
|
|
||||||
this.getMacrosOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getMacros, this.zabbixAPI), this.macroPromises, getRequestHash);
|
|
||||||
|
|
||||||
this.globalMacroPromises = {};
|
|
||||||
this.getGlobalMacrosOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getGlobalMacros, this.zabbixAPI), this.globalMacroPromises, getRequestHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
_createClass(ZabbixCachingProxy, [{
|
|
||||||
key: 'isExpired',
|
|
||||||
value: function isExpired(cacheObject) {
|
|
||||||
if (cacheObject) {
|
|
||||||
var object_age = Date.now() - cacheObject.timestamp;
|
|
||||||
return !(cacheObject.timestamp && object_age < this.ttl);
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'proxyRequest',
|
|
||||||
value: function proxyRequest(request, params, cacheObject) {
|
|
||||||
var hash = getRequestHash(params);
|
|
||||||
if (this.cacheEnabled && !this.isExpired(cacheObject[hash])) {
|
|
||||||
return Promise.resolve(cacheObject[hash].value);
|
|
||||||
} else {
|
|
||||||
return request.apply(undefined, _toConsumableArray(params)).then(function (result) {
|
|
||||||
cacheObject[hash] = {
|
|
||||||
value: result,
|
|
||||||
timestamp: Date.now()
|
|
||||||
};
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getGroups',
|
|
||||||
value: function getGroups() {
|
|
||||||
return this.proxyRequest(this.getGroupsOnce, [], this.cache.groups);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getHosts',
|
|
||||||
value: function getHosts(groupids) {
|
|
||||||
return this.proxyRequest(this.getHostsOnce, [groupids], this.cache.hosts);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getApps',
|
|
||||||
value: function getApps(hostids) {
|
|
||||||
return this.proxyRequest(this.getAppsOnce, [hostids], this.cache.applications);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getItems',
|
|
||||||
value: function getItems(hostids, appids, itemtype) {
|
|
||||||
var params = [hostids, appids, itemtype];
|
|
||||||
return this.proxyRequest(this.getItemsOnce, params, this.cache.items);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getItemsByIDs',
|
|
||||||
value: function getItemsByIDs(itemids) {
|
|
||||||
var params = [itemids];
|
|
||||||
return this.proxyRequest(this.getItemsByIdOnce, params, this.cache.items);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getITServices',
|
|
||||||
value: function getITServices() {
|
|
||||||
return this.proxyRequest(this.getITServicesOnce, [], this.cache.itServices);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getMacros',
|
|
||||||
value: function getMacros(hostids) {
|
|
||||||
// Merge global macros and host macros
|
|
||||||
var promises = [this.proxyRequest(this.getMacrosOnce, [hostids], this.cache.macros), this.proxyRequest(this.getGlobalMacrosOnce, [], this.cache.globalMacros)];
|
|
||||||
|
|
||||||
return Promise.all(promises).then(_.flatten);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getHistoryFromCache',
|
|
||||||
value: function getHistoryFromCache(items, time_from, time_till) {
|
|
||||||
var historyStorage = this.cache.history;
|
|
||||||
var full_history;
|
|
||||||
var expired = _.filter(_.keyBy(items, 'itemid'), function (item, itemid) {
|
|
||||||
return !historyStorage[itemid];
|
|
||||||
});
|
|
||||||
if (expired.length) {
|
|
||||||
return this.zabbixAPI.getHistory(expired, time_from, time_till).then(function (history) {
|
|
||||||
var grouped_history = _.groupBy(history, 'itemid');
|
|
||||||
_.forEach(expired, function (item) {
|
|
||||||
var itemid = item.itemid;
|
|
||||||
historyStorage[itemid] = item;
|
|
||||||
historyStorage[itemid].time_from = time_from;
|
|
||||||
historyStorage[itemid].time_till = time_till;
|
|
||||||
historyStorage[itemid].history = grouped_history[itemid];
|
|
||||||
});
|
|
||||||
full_history = _.map(items, function (item) {
|
|
||||||
return historyStorage[item.itemid].history;
|
|
||||||
});
|
|
||||||
return _.flatten(full_history, true);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
full_history = _.map(items, function (item) {
|
|
||||||
return historyStorage[item.itemid].history;
|
|
||||||
});
|
|
||||||
return Promise.resolve(_.flatten(full_history, true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getHistoryFromAPI',
|
|
||||||
value: function getHistoryFromAPI(items, time_from, time_till) {
|
|
||||||
return this.zabbixAPI.getHistory(items, time_from, time_till);
|
|
||||||
}
|
|
||||||
}]);
|
|
||||||
|
|
||||||
return ZabbixCachingProxy;
|
|
||||||
}();
|
|
||||||
|
|
||||||
return ZabbixCachingProxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap zabbix API request to prevent multiple calls
|
|
||||||
* with same params when waiting for result.
|
|
||||||
*/
|
|
||||||
function callAPIRequestOnce(func, promiseKeeper, argsHashFunc) {
|
|
||||||
return function () {
|
|
||||||
var hash = argsHashFunc(arguments);
|
|
||||||
if (!promiseKeeper[hash]) {
|
|
||||||
promiseKeeper[hash] = Promise.resolve(func.apply(this, arguments).then(function (result) {
|
|
||||||
promiseKeeper[hash] = null;
|
|
||||||
return result;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
return promiseKeeper[hash];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRequestHash(args) {
|
|
||||||
var requestStamp = _.map(args, function (arg) {
|
|
||||||
if (arg === undefined) {
|
|
||||||
return 'undefined';
|
|
||||||
} else {
|
|
||||||
if (_.isArray(arg)) {
|
|
||||||
return arg.sort().toString();
|
|
||||||
} else {
|
|
||||||
return arg.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).join();
|
|
||||||
return requestStamp.getHash();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getHistoryRequestHash(args) {
|
|
||||||
var itemids = _.map(args[0], 'itemid');
|
|
||||||
var stamp = itemids.join() + args[1] + args[2];
|
|
||||||
return stamp.getHash();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDBQueryHash(args) {
|
|
||||||
var itemids = _.map(args[0], 'itemid');
|
|
||||||
var consolidateBy = args[3].consolidateBy;
|
|
||||||
var intervalMs = args[3].intervalMs;
|
|
||||||
var stamp = itemids.join() + args[1] + args[2] + consolidateBy + intervalMs;
|
|
||||||
return stamp.getHash();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
setters: [function (_angular) {
|
|
||||||
angular = _angular.default;
|
|
||||||
}, function (_lodash) {
|
|
||||||
_ = _lodash.default;
|
|
||||||
}],
|
|
||||||
execute: function () {
|
|
||||||
_createClass = function () {
|
|
||||||
function defineProperties(target, props) {
|
|
||||||
for (var i = 0; i < props.length; i++) {
|
|
||||||
var descriptor = props[i];
|
|
||||||
descriptor.enumerable = descriptor.enumerable || false;
|
|
||||||
descriptor.configurable = true;
|
|
||||||
if ("value" in descriptor) descriptor.writable = true;
|
|
||||||
Object.defineProperty(target, descriptor.key, descriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return function (Constructor, protoProps, staticProps) {
|
|
||||||
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
|
||||||
if (staticProps) defineProperties(Constructor, staticProps);
|
|
||||||
return Constructor;
|
|
||||||
};
|
|
||||||
}();
|
|
||||||
|
|
||||||
angular.module('grafana.services').factory('ZabbixCachingProxy', ZabbixCachingProxyFactory);String.prototype.getHash = function () {
|
|
||||||
var hash = 0,
|
|
||||||
i,
|
|
||||||
chr,
|
|
||||||
len;
|
|
||||||
if (this.length !== 0) {
|
|
||||||
for (i = 0, len = this.length; i < len; i++) {
|
|
||||||
chr = this.charCodeAt(i);
|
|
||||||
hash = (hash << 5) - hash + chr;
|
|
||||||
hash |= 0; // Convert to 32bit integer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fix for backward compatibility with lodash 2.4
|
|
||||||
if (!_.keyBy) {
|
|
||||||
_.keyBy = _.indexBy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
//# sourceMappingURL=zabbixCachingProxy.service.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
296
dist/datasource-zabbix/zabbixDBConnector.js
vendored
296
dist/datasource-zabbix/zabbixDBConnector.js
vendored
@@ -1,296 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
System.register(['angular', 'lodash'], function (_export, _context) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var angular, _, _createClass, DEFAULT_QUERY_LIMIT, HISTORY_TO_TABLE_MAP, TREND_TO_TABLE_MAP, consolidateByFunc, consolidateByTrendColumns, TEST_MYSQL_QUERY, itemid_format, TEST_POSTGRES_QUERY;
|
|
||||||
|
|
||||||
function _classCallCheck(instance, Constructor) {
|
|
||||||
if (!(instance instanceof Constructor)) {
|
|
||||||
throw new TypeError("Cannot call a class as a function");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {
|
|
||||||
var ZabbixDBConnector = function () {
|
|
||||||
function ZabbixDBConnector(sqlDataSourceId) {
|
|
||||||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
||||||
|
|
||||||
_classCallCheck(this, ZabbixDBConnector);
|
|
||||||
|
|
||||||
var limit = options.limit;
|
|
||||||
|
|
||||||
|
|
||||||
this.sqlDataSourceId = sqlDataSourceId;
|
|
||||||
this.limit = limit || DEFAULT_QUERY_LIMIT;
|
|
||||||
|
|
||||||
this.loadSQLDataSource(sqlDataSourceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to load DS with given id to check it's exist.
|
|
||||||
* @param {*} datasourceId ID of SQL data source
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
_createClass(ZabbixDBConnector, [{
|
|
||||||
key: 'loadSQLDataSource',
|
|
||||||
value: function loadSQLDataSource(datasourceId) {
|
|
||||||
var _this = this;
|
|
||||||
|
|
||||||
var ds = _.find(datasourceSrv.getAll(), { 'id': datasourceId });
|
|
||||||
if (ds) {
|
|
||||||
return datasourceSrv.loadDatasource(ds.name).then(function (ds) {
|
|
||||||
_this.sqlDataSourceType = ds.meta.id;
|
|
||||||
return ds;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Promise.reject('SQL Data Source with ID ' + datasourceId + ' not found');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'testSQLDataSource',
|
|
||||||
value: function testSQLDataSource() {
|
|
||||||
var testQuery = TEST_MYSQL_QUERY;
|
|
||||||
if (this.sqlDataSourceType === 'postgres') {
|
|
||||||
testQuery = TEST_POSTGRES_QUERY;
|
|
||||||
}
|
|
||||||
return this.invokeSQLQuery(testQuery);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getHistory',
|
|
||||||
value: function getHistory(items, timeFrom, timeTill, options) {
|
|
||||||
var _this2 = this;
|
|
||||||
|
|
||||||
var intervalMs = options.intervalMs,
|
|
||||||
consolidateBy = options.consolidateBy;
|
|
||||||
|
|
||||||
var intervalSec = Math.ceil(intervalMs / 1000);
|
|
||||||
|
|
||||||
consolidateBy = consolidateBy || 'avg';
|
|
||||||
var aggFunction = consolidateByFunc[consolidateBy];
|
|
||||||
|
|
||||||
// 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 dialect = _this2.sqlDataSourceType;
|
|
||||||
var query = buildSQLHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, dialect);
|
|
||||||
|
|
||||||
query = compactSQLQuery(query);
|
|
||||||
return _this2.invokeSQLQuery(query);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises).then(function (results) {
|
|
||||||
return _.flatten(results);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getTrends',
|
|
||||||
value: function getTrends(items, timeFrom, timeTill, options) {
|
|
||||||
var _this3 = this;
|
|
||||||
|
|
||||||
var intervalMs = options.intervalMs,
|
|
||||||
consolidateBy = options.consolidateBy;
|
|
||||||
|
|
||||||
var intervalSec = Math.ceil(intervalMs / 1000);
|
|
||||||
|
|
||||||
consolidateBy = consolidateBy || 'avg';
|
|
||||||
var aggFunction = consolidateByFunc[consolidateBy];
|
|
||||||
|
|
||||||
// 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 = TREND_TO_TABLE_MAP[value_type];
|
|
||||||
var valueColumn = _.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg';
|
|
||||||
valueColumn = consolidateByTrendColumns[valueColumn];
|
|
||||||
|
|
||||||
var dialect = _this3.sqlDataSourceType;
|
|
||||||
var query = buildSQLTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn, dialect);
|
|
||||||
|
|
||||||
query = compactSQLQuery(query);
|
|
||||||
return _this3.invokeSQLQuery(query);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises).then(function (results) {
|
|
||||||
return _.flatten(results);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'handleGrafanaTSResponse',
|
|
||||||
value: function handleGrafanaTSResponse(history, items) {
|
|
||||||
var addHostName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
|
||||||
|
|
||||||
return convertGrafanaTSResponse(history, items, addHostName);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'invokeSQLQuery',
|
|
||||||
value: function invokeSQLQuery(query) {
|
|
||||||
var queryDef = {
|
|
||||||
refId: 'A',
|
|
||||||
format: 'time_series',
|
|
||||||
datasourceId: this.sqlDataSourceId,
|
|
||||||
rawSql: query,
|
|
||||||
maxDataPoints: this.limit
|
|
||||||
};
|
|
||||||
|
|
||||||
return backendSrv.datasourceRequest({
|
|
||||||
url: '/api/tsdb/query',
|
|
||||||
method: 'POST',
|
|
||||||
data: {
|
|
||||||
queries: [queryDef]
|
|
||||||
}
|
|
||||||
}).then(function (response) {
|
|
||||||
var results = response.data.results;
|
|
||||||
if (results['A']) {
|
|
||||||
return results['A'].series;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}]);
|
|
||||||
|
|
||||||
return ZabbixDBConnector;
|
|
||||||
}();
|
|
||||||
|
|
||||||
return ZabbixDBConnector;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function convertGrafanaTSResponse(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 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;
|
|
||||||
}
|
|
||||||
// zabbixCachingProxy deduplicates requests and returns one time series for equal queries.
|
|
||||||
// Clone is needed to prevent changing of series object shared between all targets.
|
|
||||||
var datapoints = _.cloneDeep(series.points);
|
|
||||||
return {
|
|
||||||
target: alias,
|
|
||||||
datapoints: datapoints
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return _.sortBy(grafanaSeries, 'target');
|
|
||||||
}
|
|
||||||
|
|
||||||
function compactSQLQuery(query) {
|
|
||||||
return query.replace(/\s+/g, ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildSQLHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
|
||||||
var dialect = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : 'mysql';
|
|
||||||
|
|
||||||
if (dialect === 'postgres') {
|
|
||||||
return buildPostgresHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction);
|
|
||||||
} else {
|
|
||||||
return buildMysqlHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildSQLTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
|
||||||
var dialect = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 'mysql';
|
|
||||||
|
|
||||||
if (dialect === 'postgres') {
|
|
||||||
return buildPostgresTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn);
|
|
||||||
} else {
|
|
||||||
return buildMysqlTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// MySQL //
|
|
||||||
///////////
|
|
||||||
|
|
||||||
function buildMysqlHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
|
||||||
var time_expression = 'clock DIV ' + intervalSec + ' * ' + intervalSec;
|
|
||||||
var query = '\n SELECT CAST(itemid AS CHAR) 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 ORDER BY time_sec ASC\n ';
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildMysqlTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
|
||||||
var time_expression = 'clock DIV ' + intervalSec + ' * ' + intervalSec;
|
|
||||||
var query = '\n SELECT CAST(itemid AS CHAR) 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 ORDER BY time_sec ASC\n ';
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildPostgresHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
|
||||||
var time_expression = 'clock / ' + intervalSec + ' * ' + intervalSec;
|
|
||||||
var query = '\n SELECT to_char(itemid, \'' + itemid_format + '\') AS metric, ' + time_expression + ' AS time, ' + aggFunction + '(value) AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY 1, 2\n ORDER BY time ASC\n ';
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildPostgresTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
|
||||||
var time_expression = 'clock / ' + intervalSec + ' * ' + intervalSec;
|
|
||||||
var query = '\n SELECT to_char(itemid, \'' + itemid_format + '\') AS metric, ' + time_expression + ' AS time, ' + aggFunction + '(' + valueColumn + ') AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY 1, 2\n ORDER BY time ASC\n ';
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
setters: [function (_angular) {
|
|
||||||
angular = _angular.default;
|
|
||||||
}, function (_lodash) {
|
|
||||||
_ = _lodash.default;
|
|
||||||
}],
|
|
||||||
execute: function () {
|
|
||||||
_createClass = function () {
|
|
||||||
function defineProperties(target, props) {
|
|
||||||
for (var i = 0; i < props.length; i++) {
|
|
||||||
var descriptor = props[i];
|
|
||||||
descriptor.enumerable = descriptor.enumerable || false;
|
|
||||||
descriptor.configurable = true;
|
|
||||||
if ("value" in descriptor) descriptor.writable = true;
|
|
||||||
Object.defineProperty(target, descriptor.key, descriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return function (Constructor, protoProps, staticProps) {
|
|
||||||
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
|
||||||
if (staticProps) defineProperties(Constructor, staticProps);
|
|
||||||
return Constructor;
|
|
||||||
};
|
|
||||||
}();
|
|
||||||
|
|
||||||
DEFAULT_QUERY_LIMIT = 10000;
|
|
||||||
HISTORY_TO_TABLE_MAP = {
|
|
||||||
'0': 'history',
|
|
||||||
'1': 'history_str',
|
|
||||||
'2': 'history_log',
|
|
||||||
'3': 'history_uint',
|
|
||||||
'4': 'history_text'
|
|
||||||
};
|
|
||||||
TREND_TO_TABLE_MAP = {
|
|
||||||
'0': 'trends',
|
|
||||||
'3': 'trends_uint'
|
|
||||||
};
|
|
||||||
consolidateByFunc = {
|
|
||||||
'avg': 'AVG',
|
|
||||||
'min': 'MIN',
|
|
||||||
'max': 'MAX',
|
|
||||||
'sum': 'SUM',
|
|
||||||
'count': 'COUNT'
|
|
||||||
};
|
|
||||||
consolidateByTrendColumns = {
|
|
||||||
'avg': 'value_avg',
|
|
||||||
'min': 'value_min',
|
|
||||||
'max': 'value_max'
|
|
||||||
};
|
|
||||||
angular.module('grafana.services').factory('ZabbixDBConnector', ZabbixDBConnectorFactory);TEST_MYSQL_QUERY = 'SELECT CAST(itemid AS CHAR) AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1';
|
|
||||||
itemid_format = 'FM99999999999999999999';
|
|
||||||
TEST_POSTGRES_QUERY = '\n SELECT to_char(itemid, \'' + itemid_format + '\') AS metric, clock AS time, value_avg AS value\n FROM trends_uint LIMIT 1\n';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
//# sourceMappingURL=zabbixDBConnector.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
2
dist/vendor/npm/tether.min.js
vendored
2
dist/vendor/npm/tether.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -47,7 +47,6 @@
|
|||||||
"jshint-stylish": "^2.1.0",
|
"jshint-stylish": "^2.1.0",
|
||||||
"load-grunt-tasks": "~3.2.0",
|
"load-grunt-tasks": "~3.2.0",
|
||||||
"moment": "~2.21.0",
|
"moment": "~2.21.0",
|
||||||
"q": "~1.4.1",
|
|
||||||
"tether-drop": "^1.4.2"
|
"tether-drop": "^1.4.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ import _ from 'lodash';
|
|||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import * as metricFunctions from './metricFunctions';
|
import * as metricFunctions from './metricFunctions';
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
angular
|
angular
|
||||||
.module('grafana.directives')
|
.module('grafana.directives')
|
||||||
.directive('addMetricFunction', function($compile) {
|
.directive('addMetricFunction',
|
||||||
|
|
||||||
|
/** @ngInject */
|
||||||
|
function($compile) {
|
||||||
var inputTemplate = '<input type="text"'+
|
var inputTemplate = '<input type="text"'+
|
||||||
' class="gf-form-input"' +
|
' class="gf-form-input"' +
|
||||||
' spellcheck="false" style="display:none"></input>';
|
' spellcheck="false" style="display:none"></input>';
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const defaultConfig = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class ZabbixDSConfigController {
|
export class ZabbixDSConfigController {
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor($scope, $injector, datasourceSrv) {
|
constructor($scope, $injector, datasourceSrv) {
|
||||||
this.datasourceSrv = datasourceSrv;
|
this.datasourceSrv = datasourceSrv;
|
||||||
@@ -24,5 +25,3 @@ export class ZabbixDSConfigController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZabbixDSConfigController.templateUrl = 'datasource-zabbix/partials/config.html';
|
|
||||||
|
|||||||
@@ -6,17 +6,14 @@ import * as metricFunctions from './metricFunctions';
|
|||||||
import * as c from './constants';
|
import * as c from './constants';
|
||||||
import dataProcessor from './dataProcessor';
|
import dataProcessor from './dataProcessor';
|
||||||
import responseHandler from './responseHandler';
|
import responseHandler from './responseHandler';
|
||||||
import './zabbix.js';
|
import { Zabbix } from './zabbix/zabbix';
|
||||||
import './zabbixAlerting.service.js';
|
import { ZabbixAPIError } from './zabbix/connectors/zabbix_api/zabbixAPICore';
|
||||||
import {ZabbixAPIError} from './zabbixAPICore.service.js';
|
|
||||||
|
|
||||||
class ZabbixAPIDatasource {
|
export class ZabbixDatasource {
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor(instanceSettings, templateSrv, alertSrv, dashboardSrv, zabbixAlertingSrv, Zabbix) {
|
constructor(instanceSettings, templateSrv, backendSrv, datasourceSrv, zabbixAlertingSrv) {
|
||||||
this.templateSrv = templateSrv;
|
this.templateSrv = templateSrv;
|
||||||
this.alertSrv = alertSrv;
|
|
||||||
this.dashboardSrv = dashboardSrv;
|
|
||||||
this.zabbixAlertingSrv = zabbixAlertingSrv;
|
this.zabbixAlertingSrv = zabbixAlertingSrv;
|
||||||
|
|
||||||
// Use custom format for template variables
|
// Use custom format for template variables
|
||||||
@@ -54,19 +51,20 @@ class ZabbixAPIDatasource {
|
|||||||
// Direct DB Connection options
|
// Direct DB Connection options
|
||||||
let dbConnectionOptions = jsonData.dbConnection || {};
|
let dbConnectionOptions = jsonData.dbConnection || {};
|
||||||
this.enableDirectDBConnection = dbConnectionOptions.enable;
|
this.enableDirectDBConnection = dbConnectionOptions.enable;
|
||||||
this.sqlDatasourceId = dbConnectionOptions.datasourceId;
|
this.datasourceId = dbConnectionOptions.datasourceId;
|
||||||
|
|
||||||
let zabbixOptions = {
|
let zabbixOptions = {
|
||||||
|
url: this.url,
|
||||||
username: this.username,
|
username: this.username,
|
||||||
password: this.password,
|
password: this.password,
|
||||||
basicAuth: this.basicAuth,
|
basicAuth: this.basicAuth,
|
||||||
withCredentials: this.withCredentials,
|
withCredentials: this.withCredentials,
|
||||||
cacheTTL: this.cacheTTL,
|
cacheTTL: this.cacheTTL,
|
||||||
enableDirectDBConnection: this.enableDirectDBConnection,
|
enableDirectDBConnection: this.enableDirectDBConnection,
|
||||||
sqlDatasourceId: this.sqlDatasourceId
|
datasourceId: this.datasourceId
|
||||||
};
|
};
|
||||||
|
|
||||||
this.zabbix = new Zabbix(this.url, zabbixOptions);
|
this.zabbix = new Zabbix(zabbixOptions, backendSrv, datasourceSrv);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
@@ -95,7 +93,7 @@ class ZabbixAPIDatasource {
|
|||||||
|
|
||||||
// Create request for each target
|
// Create request for each target
|
||||||
let promises = _.map(options.targets, t => {
|
let promises = _.map(options.targets, t => {
|
||||||
// Don't request undefined and hidden targets
|
// Don't request for hidden targets
|
||||||
if (t.hide) {
|
if (t.hide) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -110,7 +108,7 @@ class ZabbixAPIDatasource {
|
|||||||
// Apply Time-related functions (timeShift(), etc)
|
// Apply Time-related functions (timeShift(), etc)
|
||||||
let timeFunctions = bindFunctionDefs(target.functions, 'Time');
|
let timeFunctions = bindFunctionDefs(target.functions, 'Time');
|
||||||
if (timeFunctions.length) {
|
if (timeFunctions.length) {
|
||||||
const [time_from, time_to] = sequence(timeFunctions)([timeFrom, timeTo]);
|
const [time_from, time_to] = utils.sequence(timeFunctions)([timeFrom, timeTo]);
|
||||||
timeFrom = time_from;
|
timeFrom = time_from;
|
||||||
timeTo = time_to;
|
timeTo = time_to;
|
||||||
}
|
}
|
||||||
@@ -123,8 +121,8 @@ class ZabbixAPIDatasource {
|
|||||||
// Migrate old targets
|
// Migrate old targets
|
||||||
target = migrations.migrate(target);
|
target = migrations.migrate(target);
|
||||||
|
|
||||||
// Don't request undefined and hidden targets
|
// Don't request undefined targets
|
||||||
if (target.hide || !target.group || !target.host || !target.item) {
|
if (!target.group || !target.host || !target.item) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,44 +164,21 @@ class ZabbixAPIDatasource {
|
|||||||
itemtype: 'num'
|
itemtype: 'num'
|
||||||
};
|
};
|
||||||
return this.zabbix.getItemsFromTarget(target, getItemOptions)
|
return this.zabbix.getItemsFromTarget(target, getItemOptions)
|
||||||
.then(items => {
|
.then(items => this.queryNumericDataForItems(items, target, timeRange, useTrends, options));
|
||||||
return this.queryNumericDataForItems(items, target, timeRange, useTrends, options);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query history for numeric items
|
* Query history for numeric items
|
||||||
*/
|
*/
|
||||||
queryNumericDataForItems(items, target, timeRange, useTrends, options) {
|
queryNumericDataForItems(items, target, timeRange, useTrends, options) {
|
||||||
let [timeFrom, timeTo] = timeRange;
|
|
||||||
let getHistoryPromise;
|
let getHistoryPromise;
|
||||||
options.consolidateBy = getConsolidateBy(target);
|
options.valueType = this.getTrendValueType(target);
|
||||||
|
options.consolidateBy = getConsolidateBy(target) || options.valueType;
|
||||||
|
|
||||||
if (useTrends) {
|
if (useTrends) {
|
||||||
if (this.enableDirectDBConnection) {
|
getHistoryPromise = this.zabbix.getTrends(items, timeRange, options);
|
||||||
getHistoryPromise = this.zabbix.getTrendsDB(items, timeFrom, timeTo, options)
|
|
||||||
.then(history => this.zabbix.dbConnector.handleGrafanaTSResponse(history, items));
|
|
||||||
} else {
|
|
||||||
let valueType = this.getTrendValueType(target);
|
|
||||||
getHistoryPromise = this.zabbix.getTrend(items, timeFrom, timeTo)
|
|
||||||
.then(history => responseHandler.handleTrends(history, items, valueType))
|
|
||||||
.then(timeseries => {
|
|
||||||
// Sort trend data, issue #202
|
|
||||||
_.forEach(timeseries, series => {
|
|
||||||
series.datapoints = _.sortBy(series.datapoints, point => point[c.DATAPOINT_TS]);
|
|
||||||
});
|
|
||||||
return timeseries;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Use history
|
getHistoryPromise = this.zabbix.getHistoryTS(items, timeRange, options);
|
||||||
if (this.enableDirectDBConnection) {
|
|
||||||
getHistoryPromise = this.zabbix.getHistoryDB(items, timeFrom, timeTo, options)
|
|
||||||
.then(history => this.zabbix.dbConnector.handleGrafanaTSResponse(history, items));
|
|
||||||
} else {
|
|
||||||
getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo)
|
|
||||||
.then(history => responseHandler.handleHistory(history, items));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return getHistoryPromise
|
return getHistoryPromise
|
||||||
@@ -228,19 +203,19 @@ class ZabbixAPIDatasource {
|
|||||||
|
|
||||||
// Apply transformation functions
|
// Apply transformation functions
|
||||||
timeseries_data = _.cloneDeep(_.map(timeseries_data, timeseries => {
|
timeseries_data = _.cloneDeep(_.map(timeseries_data, timeseries => {
|
||||||
timeseries.datapoints = sequence(transformFunctions)(timeseries.datapoints);
|
timeseries.datapoints = utils.sequence(transformFunctions)(timeseries.datapoints);
|
||||||
return timeseries;
|
return timeseries;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Apply filter functions
|
// Apply filter functions
|
||||||
if (filterFunctions.length) {
|
if (filterFunctions.length) {
|
||||||
timeseries_data = sequence(filterFunctions)(timeseries_data);
|
timeseries_data = utils.sequence(filterFunctions)(timeseries_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply aggregations
|
// Apply aggregations
|
||||||
if (aggregationFunctions.length) {
|
if (aggregationFunctions.length) {
|
||||||
let dp = _.map(timeseries_data, 'datapoints');
|
let dp = _.map(timeseries_data, 'datapoints');
|
||||||
dp = sequence(aggregationFunctions)(dp);
|
dp = utils.sequence(aggregationFunctions)(dp);
|
||||||
|
|
||||||
let aggFuncNames = _.map(metricFunctions.getCategories()['Aggregate'], 'name');
|
let aggFuncNames = _.map(metricFunctions.getCategories()['Aggregate'], 'name');
|
||||||
let lastAgg = _.findLast(target.functions, func => {
|
let lastAgg = _.findLast(target.functions, func => {
|
||||||
@@ -254,7 +229,7 @@ class ZabbixAPIDatasource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply alias functions
|
// Apply alias functions
|
||||||
_.forEach(timeseries_data, sequence(aliasFunctions));
|
_.forEach(timeseries_data, utils.sequence(aliasFunctions));
|
||||||
|
|
||||||
// Apply Time-related functions (timeShift(), etc)
|
// Apply Time-related functions (timeShift(), etc)
|
||||||
// Find timeShift() function and get specified trend value
|
// Find timeShift() function and get specified trend value
|
||||||
@@ -280,25 +255,13 @@ class ZabbixAPIDatasource {
|
|||||||
* Query target data for Text mode
|
* Query target data for Text mode
|
||||||
*/
|
*/
|
||||||
queryTextData(target, timeRange) {
|
queryTextData(target, timeRange) {
|
||||||
let [timeFrom, timeTo] = timeRange;
|
|
||||||
let options = {
|
let options = {
|
||||||
itemtype: 'text'
|
itemtype: 'text'
|
||||||
};
|
};
|
||||||
return this.zabbix.getItemsFromTarget(target, options)
|
return this.zabbix.getItemsFromTarget(target, options)
|
||||||
.then(items => {
|
.then(items => {
|
||||||
if (items.length) {
|
return this.zabbix.getHistoryText(items, timeRange, target);
|
||||||
return this.zabbix.getHistory(items, timeFrom, timeTo)
|
});
|
||||||
.then(history => {
|
|
||||||
if (target.resultFormat === 'table') {
|
|
||||||
return responseHandler.handleHistoryAsTable(history, items, target);
|
|
||||||
} else {
|
|
||||||
return responseHandler.handleText(history, items, target);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Promise.resolve([]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -328,12 +291,10 @@ class ZabbixAPIDatasource {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
let itServiceIds = [];
|
|
||||||
let itServices = [];
|
|
||||||
let itServiceFilter;
|
let itServiceFilter;
|
||||||
let isOldVersion = target.itservice && !target.itServiceFilter;
|
options.isOldVersion = target.itservice && !target.itServiceFilter;
|
||||||
|
|
||||||
if (isOldVersion) {
|
if (options.isOldVersion) {
|
||||||
// Backward compatibility
|
// Backward compatibility
|
||||||
itServiceFilter = '/.*/';
|
itServiceFilter = '/.*/';
|
||||||
} else {
|
} else {
|
||||||
@@ -342,22 +303,7 @@ class ZabbixAPIDatasource {
|
|||||||
|
|
||||||
return this.zabbix.getITServices(itServiceFilter)
|
return this.zabbix.getITServices(itServiceFilter)
|
||||||
.then(itservices => {
|
.then(itservices => {
|
||||||
itServices = itservices;
|
return this.zabbix.getSLA(itservices, timeRange, target, options);
|
||||||
if (isOldVersion) {
|
|
||||||
itServices = _.filter(itServices, {'serviceid': target.itservice.serviceid});
|
|
||||||
}
|
|
||||||
|
|
||||||
itServiceIds = _.map(itServices, 'serviceid');
|
|
||||||
return itServiceIds;
|
|
||||||
})
|
|
||||||
.then(serviceids => {
|
|
||||||
return this.zabbix.getSLA(serviceids, timeRange);
|
|
||||||
})
|
|
||||||
.then(slaResponse => {
|
|
||||||
return _.map(itServiceIds, serviceid => {
|
|
||||||
let itservice = _.find(itServices, {'serviceid': serviceid});
|
|
||||||
return responseHandler.handleSLAResponse(itservice, target.slaProperty, slaResponse);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,28 +333,20 @@ class ZabbixAPIDatasource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test connection to Zabbix API
|
* Test connection to Zabbix API and external history DB.
|
||||||
* @return {object} Connection status and Zabbix API version
|
|
||||||
*/
|
*/
|
||||||
testDatasource() {
|
testDatasource() {
|
||||||
let zabbixVersion;
|
return this.zabbix.testDataSource()
|
||||||
return this.zabbix.getVersion()
|
.then(result => {
|
||||||
.then(version => {
|
const { zabbixVersion, dbConnectorStatus } = result;
|
||||||
zabbixVersion = version;
|
let message = `Zabbix API version: ${zabbixVersion}`;
|
||||||
return this.zabbix.login();
|
if (dbConnectorStatus) {
|
||||||
})
|
message += `, DB connector type: ${dbConnectorStatus.dsType}`;
|
||||||
.then(() => {
|
|
||||||
if (this.enableDirectDBConnection) {
|
|
||||||
return this.zabbix.dbConnector.testSQLDataSource();
|
|
||||||
} else {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
return {
|
return {
|
||||||
status: "success",
|
status: "success",
|
||||||
title: "Success",
|
title: "Success",
|
||||||
message: "Zabbix API version: " + zabbixVersion
|
message: message
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
@@ -424,7 +362,14 @@ class ZabbixAPIDatasource {
|
|||||||
title: "Connection failed",
|
title: "Connection failed",
|
||||||
message: "Connection failed: " + error.data.message
|
message: "Connection failed: " + error.data.message
|
||||||
};
|
};
|
||||||
|
} else if (typeof(error) === 'string') {
|
||||||
|
return {
|
||||||
|
status: "error",
|
||||||
|
title: "Connection failed",
|
||||||
|
message: "Connection failed: " + error
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
|
console.log(error);
|
||||||
return {
|
return {
|
||||||
status: "error",
|
status: "error",
|
||||||
title: "Connection failed",
|
title: "Connection failed",
|
||||||
@@ -658,7 +603,7 @@ function bindFunctionDefs(functionDefs, category) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getConsolidateBy(target) {
|
function getConsolidateBy(target) {
|
||||||
let consolidateBy = 'avg';
|
let consolidateBy;
|
||||||
let funcDef = _.find(target.functions, func => {
|
let funcDef = _.find(target.functions, func => {
|
||||||
return func.def.name === 'consolidateBy';
|
return func.def.name === 'consolidateBy';
|
||||||
});
|
});
|
||||||
@@ -697,7 +642,7 @@ function formatMetric(metricObj) {
|
|||||||
* template variables, for example
|
* template variables, for example
|
||||||
* /CPU $cpu_item.*time/ where $cpu_item is system,user,iowait
|
* /CPU $cpu_item.*time/ where $cpu_item is system,user,iowait
|
||||||
*/
|
*/
|
||||||
function zabbixTemplateFormat(value) {
|
export function zabbixTemplateFormat(value) {
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
return utils.escapeRegex(value);
|
return utils.escapeRegex(value);
|
||||||
}
|
}
|
||||||
@@ -729,17 +674,6 @@ function replaceTemplateVars(templateSrv, target, scopedVars) {
|
|||||||
return replacedTarget;
|
return replacedTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply function one by one:
|
|
||||||
// sequence([a(), b(), c()]) = c(b(a()));
|
|
||||||
function sequence(funcsArray) {
|
|
||||||
return function(result) {
|
|
||||||
for (var i = 0; i < funcsArray.length; i++) {
|
|
||||||
result = funcsArray[i].call(this, result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterEnabledTargets(targets) {
|
function filterEnabledTargets(targets) {
|
||||||
return _.filter(targets, target => {
|
return _.filter(targets, target => {
|
||||||
return !(target.hide || !target.group || !target.host || !target.item);
|
return !(target.hide || !target.group || !target.host || !target.item);
|
||||||
@@ -758,8 +692,6 @@ function getTriggerThreshold(expression) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {ZabbixAPIDatasource, zabbixTemplateFormat};
|
|
||||||
|
|
||||||
// Fix for backward compatibility with lodash 2.4
|
// Fix for backward compatibility with lodash 2.4
|
||||||
if (!_.includes) {_.includes = _.contains;}
|
if (!_.includes) {_.includes = _.contains;}
|
||||||
if (!_.keyBy) {_.keyBy = _.indexBy;}
|
if (!_.keyBy) {_.keyBy = _.indexBy;}
|
||||||
|
|||||||
@@ -2,10 +2,14 @@ import angular from 'angular';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
|
||||||
/** @ngInject */
|
const DOCS_FUNC_REF_URL = 'http://docs.grafana-zabbix.org/reference/functions/';
|
||||||
|
|
||||||
angular
|
angular
|
||||||
.module('grafana.directives')
|
.module('grafana.directives')
|
||||||
.directive('metricFunctionEditor', function($compile, templateSrv) {
|
.directive('metricFunctionEditor',
|
||||||
|
|
||||||
|
/** @ngInject */
|
||||||
|
function($compile, templateSrv) {
|
||||||
|
|
||||||
var funcSpanTemplate = '<a ng-click="">{{func.def.name}}</a><span>(</span>';
|
var funcSpanTemplate = '<a ng-click="">{{func.def.name}}</a><span>(</span>';
|
||||||
var paramTemplate = '<input type="text" style="display:none"' +
|
var paramTemplate = '<input type="text" style="display:none"' +
|
||||||
@@ -221,7 +225,7 @@ angular
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($target.hasClass('fa-question-circle')) {
|
if ($target.hasClass('fa-question-circle')) {
|
||||||
var docSite = "http://docs.grafana-zabbix.org/reference/functions/";
|
var docSite = DOCS_FUNC_REF_URL;
|
||||||
window.open(docSite + '#' + funcDef.name.toLowerCase(),'_blank');
|
window.open(docSite + '#' + funcDef.name.toLowerCase(),'_blank');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import {loadPluginCss} from 'app/plugins/sdk';
|
import { loadPluginCss } from 'app/plugins/sdk';
|
||||||
import {ZabbixAPIDatasource} from './datasource';
|
import { ZabbixDatasource } from './datasource';
|
||||||
import {ZabbixQueryController} from './query.controller';
|
import { ZabbixQueryController } from './query.controller';
|
||||||
import {ZabbixDSConfigController} from './config.controller';
|
import { ZabbixDSConfigController } from './config.controller';
|
||||||
|
import './zabbixAlerting.service.js';
|
||||||
|
import './add-metric-function.directive';
|
||||||
|
import './metric-function-editor.directive';
|
||||||
|
|
||||||
loadPluginCss({
|
loadPluginCss({
|
||||||
dark: 'plugins/alexanderzobnin-zabbix-app/css/grafana-zabbix.dark.css',
|
dark: 'plugins/alexanderzobnin-zabbix-app/css/grafana-zabbix.dark.css',
|
||||||
@@ -14,8 +17,11 @@ ZabbixQueryOptionsController.templateUrl = 'datasource-zabbix/partials/query.opt
|
|||||||
class ZabbixAnnotationsQueryController {}
|
class ZabbixAnnotationsQueryController {}
|
||||||
ZabbixAnnotationsQueryController.templateUrl = 'datasource-zabbix/partials/annotations.editor.html';
|
ZabbixAnnotationsQueryController.templateUrl = 'datasource-zabbix/partials/annotations.editor.html';
|
||||||
|
|
||||||
|
ZabbixQueryController.templateUrl = 'datasource-zabbix/partials/query.editor.html';
|
||||||
|
ZabbixDSConfigController.templateUrl = 'datasource-zabbix/partials/config.html';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
ZabbixAPIDatasource as Datasource,
|
ZabbixDatasource as Datasource,
|
||||||
ZabbixDSConfigController as ConfigCtrl,
|
ZabbixDSConfigController as ConfigCtrl,
|
||||||
ZabbixQueryController as QueryCtrl,
|
ZabbixQueryController as QueryCtrl,
|
||||||
ZabbixQueryOptionsController as QueryOptionsCtrl,
|
ZabbixQueryOptionsController as QueryOptionsCtrl,
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
import {QueryCtrl} from 'app/plugins/sdk';
|
import { QueryCtrl } from 'app/plugins/sdk';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import * as c from './constants';
|
import * as c from './constants';
|
||||||
import * as utils from './utils';
|
import * as utils from './utils';
|
||||||
import * as metricFunctions from './metricFunctions';
|
import * as metricFunctions from './metricFunctions';
|
||||||
import * as migrations from './migrations';
|
import * as migrations from './migrations';
|
||||||
|
|
||||||
import './add-metric-function.directive';
|
|
||||||
import './metric-function-editor.directive';
|
|
||||||
|
|
||||||
export class ZabbixQueryController extends QueryCtrl {
|
export class ZabbixQueryController extends QueryCtrl {
|
||||||
|
|
||||||
// ZabbixQueryCtrl constructor
|
// ZabbixQueryCtrl constructor
|
||||||
@@ -333,6 +330,3 @@ export class ZabbixQueryController extends QueryCtrl {
|
|||||||
this.targetChanged();
|
this.targetChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set templateUrl as static property
|
|
||||||
ZabbixQueryController.templateUrl = 'datasource-zabbix/partials/query.editor.html';
|
|
||||||
|
|||||||
@@ -40,6 +40,14 @@ function convertHistory(history, items, addHostName, convertPointCallback) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sortTimeseries(timeseries) {
|
||||||
|
// Sort trend data, issue #202
|
||||||
|
_.forEach(timeseries, series => {
|
||||||
|
series.datapoints = _.sortBy(series.datapoints, point => point[c.DATAPOINT_TS]);
|
||||||
|
});
|
||||||
|
return timeseries;
|
||||||
|
}
|
||||||
|
|
||||||
function handleHistory(history, items, addHostName = true) {
|
function handleHistory(history, items, addHostName = true) {
|
||||||
return convertHistory(history, items, addHostName, convertHistoryPoint);
|
return convertHistory(history, items, addHostName, convertHistoryPoint);
|
||||||
}
|
}
|
||||||
@@ -211,13 +219,14 @@ function convertTrendPoint(valueType, point) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
handleHistory: handleHistory,
|
handleHistory,
|
||||||
convertHistory: convertHistory,
|
convertHistory,
|
||||||
handleTrends: handleTrends,
|
handleTrends,
|
||||||
handleText: handleText,
|
handleText,
|
||||||
handleHistoryAsTable: handleHistoryAsTable,
|
handleHistoryAsTable,
|
||||||
handleSLAResponse: handleSLAResponse,
|
handleSLAResponse,
|
||||||
handleTriggersResponse: handleTriggersResponse
|
handleTriggersResponse,
|
||||||
|
sortTimeseries
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fix for backward compatibility with lodash 2.4
|
// Fix for backward compatibility with lodash 2.4
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import Q, { Promise } from "q";
|
import { Datasource } from "../module";
|
||||||
import {Datasource} from "../module";
|
import { zabbixTemplateFormat } from "../datasource";
|
||||||
import {zabbixTemplateFormat} from "../datasource";
|
|
||||||
|
|
||||||
describe('ZabbixDatasource', () => {
|
describe('ZabbixDatasource', () => {
|
||||||
let ctx = {};
|
let ctx = {};
|
||||||
@@ -9,7 +8,7 @@ describe('ZabbixDatasource', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ctx.instanceSettings = {
|
ctx.instanceSettings = {
|
||||||
jsonData: {
|
jsonData: {
|
||||||
alerting: true,
|
alerting: false,
|
||||||
username: 'zabbix',
|
username: 'zabbix',
|
||||||
password: 'zabbix',
|
password: 'zabbix',
|
||||||
trends: true,
|
trends: true,
|
||||||
@@ -21,21 +20,21 @@ describe('ZabbixDatasource', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
ctx.templateSrv = {};
|
ctx.templateSrv = {};
|
||||||
ctx.alertSrv = {};
|
ctx.backendSrv = {
|
||||||
ctx.dashboardSrv = {};
|
datasourceRequest: jest.fn()
|
||||||
|
};
|
||||||
|
ctx.datasourceSrv = {};
|
||||||
ctx.zabbixAlertingSrv = {
|
ctx.zabbixAlertingSrv = {
|
||||||
setPanelAlertState: jest.fn(),
|
setPanelAlertState: jest.fn(),
|
||||||
removeZabbixThreshold: jest.fn(),
|
removeZabbixThreshold: jest.fn(),
|
||||||
};
|
};
|
||||||
ctx.zabbix = () => {};
|
|
||||||
|
|
||||||
ctx.ds = new Datasource(ctx.instanceSettings, ctx.templateSrv, ctx.alertSrv, ctx.dashboardSrv, ctx.zabbixAlertingSrv, ctx.zabbix);
|
ctx.ds = new Datasource(ctx.instanceSettings, ctx.templateSrv, ctx.backendSrv, ctx.datasourceSrv, ctx.zabbixAlertingSrv);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('When querying data', () => {
|
describe('When querying data', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ctx.ds.replaceTemplateVars = (str) => str;
|
ctx.ds.replaceTemplateVars = (str) => str;
|
||||||
ctx.ds.alertQuery = () => Q.when([]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.options = {
|
ctx.options = {
|
||||||
@@ -99,8 +98,7 @@ describe('ZabbixDatasource', () => {
|
|||||||
describe('When querying text data', () => {
|
describe('When querying text data', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ctx.ds.replaceTemplateVars = (str) => str;
|
ctx.ds.replaceTemplateVars = (str) => str;
|
||||||
ctx.ds.alertQuery = () => Q.when([]);
|
ctx.ds.zabbix.zabbixAPI.getHistory = jest.fn().mockReturnValue(Promise.resolve([
|
||||||
ctx.ds.zabbix.getHistory = jest.fn().mockReturnValue(Promise.resolve([
|
|
||||||
{clock: "1500010200", itemid:"10100", ns:"900111000", value:"Linux first"},
|
{clock: "1500010200", itemid:"10100", ns:"900111000", value:"Linux first"},
|
||||||
{clock: "1500010300", itemid:"10100", ns:"900111000", value:"Linux 2nd"},
|
{clock: "1500010300", itemid:"10100", ns:"900111000", value:"Linux 2nd"},
|
||||||
{clock: "1500010400", itemid:"10100", ns:"900111000", value:"Linux last"}
|
{clock: "1500010400", itemid:"10100", ns:"900111000", value:"Linux last"}
|
||||||
@@ -243,10 +241,10 @@ describe('ZabbixDatasource', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ctx.ds.replaceTemplateVars = (str) => str;
|
ctx.ds.replaceTemplateVars = (str) => str;
|
||||||
ctx.ds.zabbix = {
|
ctx.ds.zabbix = {
|
||||||
getGroups: jest.fn().mockReturnValue(Q.when([])),
|
getGroups: jest.fn().mockReturnValue(Promise.resolve([])),
|
||||||
getHosts: jest.fn().mockReturnValue(Q.when([])),
|
getHosts: jest.fn().mockReturnValue(Promise.resolve([])),
|
||||||
getApps: jest.fn().mockReturnValue(Q.when([])),
|
getApps: jest.fn().mockReturnValue(Promise.resolve([])),
|
||||||
getItems: jest.fn().mockReturnValue(Q.when([]))
|
getItems: jest.fn().mockReturnValue(Promise.resolve([]))
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -341,7 +339,7 @@ describe('ZabbixDatasource', () => {
|
|||||||
"hosts": [{"hostid": "10631", "name": "Test host"}],
|
"hosts": [{"hostid": "10631", "name": "Test host"}],
|
||||||
"item": "Test item"
|
"item": "Test item"
|
||||||
}];
|
}];
|
||||||
ctx.ds.zabbix.getItemsFromTarget = () => Promise.resolve(targetItems);
|
ctx.ds.zabbix.getItemsFromTarget = jest.fn().mockReturnValue(Promise.resolve(targetItems));
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
"panelId": 10,
|
"panelId": 10,
|
||||||
@@ -362,7 +360,7 @@ describe('ZabbixDatasource', () => {
|
|||||||
"expression": "{15915}<100",
|
"expression": "{15915}<100",
|
||||||
}];
|
}];
|
||||||
|
|
||||||
ctx.ds.zabbix.getAlerts = () => Promise.resolve(itemTriggers);
|
ctx.ds.zabbix.getAlerts = jest.fn().mockReturnValue(Promise.resolve(itemTriggers));
|
||||||
|
|
||||||
return ctx.ds.alertQuery(options)
|
return ctx.ds.alertQuery(options)
|
||||||
.then(resp => {
|
.then(resp => {
|
||||||
@@ -380,7 +378,7 @@ describe('ZabbixDatasource', () => {
|
|||||||
"expression": "{15915}<=100",
|
"expression": "{15915}<=100",
|
||||||
}];
|
}];
|
||||||
|
|
||||||
ctx.ds.zabbix.getAlerts = () => Promise.resolve(itemTriggers);
|
ctx.ds.zabbix.getAlerts = jest.fn().mockReturnValue(Promise.resolve(itemTriggers));
|
||||||
|
|
||||||
return ctx.ds.alertQuery(options)
|
return ctx.ds.alertQuery(options)
|
||||||
.then(resp => {
|
.then(resp => {
|
||||||
@@ -398,7 +396,7 @@ describe('ZabbixDatasource', () => {
|
|||||||
"expression": "{15915}>=30",
|
"expression": "{15915}>=30",
|
||||||
}];
|
}];
|
||||||
|
|
||||||
ctx.ds.zabbix.getAlerts = () => Promise.resolve(itemTriggers);
|
ctx.ds.zabbix.getAlerts = jest.fn().mockReturnValue(Promise.resolve(itemTriggers));
|
||||||
|
|
||||||
return ctx.ds.alertQuery(options)
|
return ctx.ds.alertQuery(options)
|
||||||
.then(resp => {
|
.then(resp => {
|
||||||
@@ -416,7 +414,7 @@ describe('ZabbixDatasource', () => {
|
|||||||
"expression": "{15915}=50",
|
"expression": "{15915}=50",
|
||||||
}];
|
}];
|
||||||
|
|
||||||
ctx.ds.zabbix.getAlerts = () => Promise.resolve(itemTriggers);
|
ctx.ds.zabbix.getAlerts = jest.fn().mockReturnValue(Promise.resolve(itemTriggers));
|
||||||
|
|
||||||
return ctx.ds.alertQuery(options)
|
return ctx.ds.alertQuery(options)
|
||||||
.then(resp => {
|
.then(resp => {
|
||||||
|
|||||||
@@ -227,6 +227,19 @@ export function callOnce(func, promiseKeeper) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply function one by one: `sequence([a(), b(), c()]) = c(b(a()))`
|
||||||
|
* @param {*} funcsArray functions to apply
|
||||||
|
*/
|
||||||
|
export function sequence(funcsArray) {
|
||||||
|
return function(result) {
|
||||||
|
for (var i = 0; i < funcsArray.length; i++) {
|
||||||
|
result = funcsArray[i].call(this, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Fix for backward compatibility with lodash 2.4
|
// Fix for backward compatibility with lodash 2.4
|
||||||
if (!_.includes) {
|
if (!_.includes) {
|
||||||
_.includes = _.contains;
|
_.includes = _.contains;
|
||||||
|
|||||||
@@ -1,276 +0,0 @@
|
|||||||
import angular from 'angular';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import * as utils from './utils';
|
|
||||||
import './zabbixAPI.service.js';
|
|
||||||
import './zabbixCachingProxy.service.js';
|
|
||||||
import './zabbixDBConnector';
|
|
||||||
|
|
||||||
// Use factory() instead service() for multiple data sources support.
|
|
||||||
// Each Zabbix data source instance should initialize its own API instance.
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy, ZabbixDBConnector) {
|
|
||||||
|
|
||||||
class Zabbix {
|
|
||||||
constructor(url, options) {
|
|
||||||
let {
|
|
||||||
username, password, basicAuth, withCredentials, cacheTTL,
|
|
||||||
enableDirectDBConnection, sqlDatasourceId
|
|
||||||
} = options;
|
|
||||||
|
|
||||||
// Initialize Zabbix API
|
|
||||||
var ZabbixAPI = zabbixAPIService;
|
|
||||||
this.zabbixAPI = new ZabbixAPI(url, username, password, basicAuth, withCredentials);
|
|
||||||
|
|
||||||
if (enableDirectDBConnection) {
|
|
||||||
this.dbConnector = new ZabbixDBConnector(sqlDatasourceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize caching proxy for requests
|
|
||||||
let cacheOptions = {
|
|
||||||
enabled: true,
|
|
||||||
ttl: cacheTTL
|
|
||||||
};
|
|
||||||
this.cachingProxy = new ZabbixCachingProxy(this.zabbixAPI, this.dbConnector, cacheOptions);
|
|
||||||
|
|
||||||
// Proxy methods
|
|
||||||
this.getHistory = this.cachingProxy.getHistory.bind(this.cachingProxy);
|
|
||||||
this.getMacros = this.cachingProxy.getMacros.bind(this.cachingProxy);
|
|
||||||
this.getItemsByIDs = this.cachingProxy.getItemsByIDs.bind(this.cachingProxy);
|
|
||||||
|
|
||||||
if (enableDirectDBConnection) {
|
|
||||||
this.getHistoryDB = this.cachingProxy.getHistoryDB.bind(this.cachingProxy);
|
|
||||||
this.getTrendsDB = this.cachingProxy.getTrendsDB.bind(this.cachingProxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.getTrend = this.zabbixAPI.getTrend.bind(this.zabbixAPI);
|
|
||||||
this.getEvents = this.zabbixAPI.getEvents.bind(this.zabbixAPI);
|
|
||||||
this.getAlerts = this.zabbixAPI.getAlerts.bind(this.zabbixAPI);
|
|
||||||
this.getHostAlerts = this.zabbixAPI.getHostAlerts.bind(this.zabbixAPI);
|
|
||||||
this.getAcknowledges = this.zabbixAPI.getAcknowledges.bind(this.zabbixAPI);
|
|
||||||
this.getITService = this.zabbixAPI.getITService.bind(this.zabbixAPI);
|
|
||||||
this.getSLA = this.zabbixAPI.getSLA.bind(this.zabbixAPI);
|
|
||||||
this.getVersion = this.zabbixAPI.getVersion.bind(this.zabbixAPI);
|
|
||||||
this.login = this.zabbixAPI.login.bind(this.zabbixAPI);
|
|
||||||
}
|
|
||||||
|
|
||||||
getItemsFromTarget(target, options) {
|
|
||||||
let parts = ['group', 'host', 'application', 'item'];
|
|
||||||
let filters = _.map(parts, p => target[p].filter);
|
|
||||||
return this.getItems(...filters, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
getHostsFromTarget(target) {
|
|
||||||
let parts = ['group', 'host', 'application'];
|
|
||||||
let filters = _.map(parts, p => target[p].filter);
|
|
||||||
return Promise.all([
|
|
||||||
this.getHosts(...filters),
|
|
||||||
this.getApps(...filters),
|
|
||||||
]).then((results) => {
|
|
||||||
let [hosts, apps] = results;
|
|
||||||
if (apps.appFilterEmpty) {
|
|
||||||
apps = [];
|
|
||||||
}
|
|
||||||
return [hosts, apps];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getAllGroups() {
|
|
||||||
return this.cachingProxy.getGroups();
|
|
||||||
}
|
|
||||||
|
|
||||||
getGroups(groupFilter) {
|
|
||||||
return this.getAllGroups()
|
|
||||||
.then(groups => findByFilter(groups, groupFilter));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get list of host belonging to given groups.
|
|
||||||
*/
|
|
||||||
getAllHosts(groupFilter) {
|
|
||||||
return this.getGroups(groupFilter)
|
|
||||||
.then(groups => {
|
|
||||||
let groupids = _.map(groups, 'groupid');
|
|
||||||
return this.cachingProxy.getHosts(groupids);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getHosts(groupFilter, hostFilter) {
|
|
||||||
return this.getAllHosts(groupFilter)
|
|
||||||
.then(hosts => findByFilter(hosts, hostFilter));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get list of applications belonging to given groups and hosts.
|
|
||||||
*/
|
|
||||||
getAllApps(groupFilter, hostFilter) {
|
|
||||||
return this.getHosts(groupFilter, hostFilter)
|
|
||||||
.then(hosts => {
|
|
||||||
let hostids = _.map(hosts, 'hostid');
|
|
||||||
return this.cachingProxy.getApps(hostids);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getApps(groupFilter, hostFilter, appFilter) {
|
|
||||||
return this.getHosts(groupFilter, hostFilter)
|
|
||||||
.then(hosts => {
|
|
||||||
let hostids = _.map(hosts, 'hostid');
|
|
||||||
if (appFilter) {
|
|
||||||
return this.cachingProxy.getApps(hostids)
|
|
||||||
.then(apps => filterByQuery(apps, appFilter));
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
appFilterEmpty: true,
|
|
||||||
hostids: hostids
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getAllItems(groupFilter, hostFilter, appFilter, options = {}) {
|
|
||||||
return this.getApps(groupFilter, hostFilter, appFilter)
|
|
||||||
.then(apps => {
|
|
||||||
if (apps.appFilterEmpty) {
|
|
||||||
return this.cachingProxy.getItems(apps.hostids, undefined, options.itemtype);
|
|
||||||
} else {
|
|
||||||
let appids = _.map(apps, 'applicationid');
|
|
||||||
return this.cachingProxy.getItems(undefined, appids, options.itemtype);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(items => {
|
|
||||||
if (!options.showDisabledItems) {
|
|
||||||
items = _.filter(items, {'status': '0'});
|
|
||||||
}
|
|
||||||
|
|
||||||
return items;
|
|
||||||
})
|
|
||||||
.then(this.expandUserMacro.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
expandUserMacro(items) {
|
|
||||||
let hostids = getHostIds(items);
|
|
||||||
return this.getMacros(hostids)
|
|
||||||
.then(macros => {
|
|
||||||
_.forEach(items, item => {
|
|
||||||
if (utils.containsMacro(item.name)) {
|
|
||||||
item.name = utils.replaceMacro(item, macros);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return items;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getItems(groupFilter, hostFilter, appFilter, itemFilter, options = {}) {
|
|
||||||
return this.getAllItems(groupFilter, hostFilter, appFilter, options)
|
|
||||||
.then(items => filterByQuery(items, itemFilter));
|
|
||||||
}
|
|
||||||
|
|
||||||
getITServices(itServiceFilter) {
|
|
||||||
return this.cachingProxy.getITServices()
|
|
||||||
.then(itServices => findByFilter(itServices, itServiceFilter));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build query - convert target filters to array of Zabbix items
|
|
||||||
*/
|
|
||||||
getTriggers(groupFilter, hostFilter, appFilter, options) {
|
|
||||||
let promises = [
|
|
||||||
this.getGroups(groupFilter),
|
|
||||||
this.getHosts(groupFilter, hostFilter),
|
|
||||||
this.getApps(groupFilter, hostFilter, appFilter)
|
|
||||||
];
|
|
||||||
|
|
||||||
return Promise.all(promises)
|
|
||||||
.then(results => {
|
|
||||||
let filteredGroups = results[0];
|
|
||||||
let filteredHosts = results[1];
|
|
||||||
let filteredApps = results[2];
|
|
||||||
let query = {};
|
|
||||||
|
|
||||||
if (appFilter) {
|
|
||||||
query.applicationids = _.flatten(_.map(filteredApps, 'applicationid'));
|
|
||||||
}
|
|
||||||
if (hostFilter) {
|
|
||||||
query.hostids = _.map(filteredHosts, 'hostid');
|
|
||||||
}
|
|
||||||
if (groupFilter) {
|
|
||||||
query.groupids = _.map(filteredGroups, 'groupid');
|
|
||||||
}
|
|
||||||
|
|
||||||
return query;
|
|
||||||
}).then(query => {
|
|
||||||
return this.zabbixAPI.getTriggers(query.groupids, query.hostids, query.applicationids, options);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Zabbix;
|
|
||||||
}
|
|
||||||
|
|
||||||
angular
|
|
||||||
.module('grafana.services')
|
|
||||||
.factory('Zabbix', ZabbixFactory);
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find group, host, app or item by given name.
|
|
||||||
* @param list list of groups, apps or other
|
|
||||||
* @param name visible name
|
|
||||||
* @return array with finded element or empty array
|
|
||||||
*/
|
|
||||||
function findByName(list, name) {
|
|
||||||
var finded = _.find(list, {'name': name});
|
|
||||||
if (finded) {
|
|
||||||
return [finded];
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Different hosts can contains applications and items with same name.
|
|
||||||
* For this reason use _.filter, which return all elements instead _.find,
|
|
||||||
* which return only first finded.
|
|
||||||
* @param {[type]} list list of elements
|
|
||||||
* @param {[type]} name app name
|
|
||||||
* @return {[type]} array with finded element or empty array
|
|
||||||
*/
|
|
||||||
function filterByName(list, name) {
|
|
||||||
var finded = _.filter(list, {'name': name});
|
|
||||||
if (finded) {
|
|
||||||
return finded;
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterByRegex(list, regex) {
|
|
||||||
var filterPattern = utils.buildRegex(regex);
|
|
||||||
return _.filter(list, function (zbx_obj) {
|
|
||||||
return filterPattern.test(zbx_obj.name);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function findByFilter(list, filter) {
|
|
||||||
if (utils.isRegex(filter)) {
|
|
||||||
return filterByRegex(list, filter);
|
|
||||||
} else {
|
|
||||||
return findByName(list, filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterByQuery(list, filter) {
|
|
||||||
if (utils.isRegex(filter)) {
|
|
||||||
return filterByRegex(list, filter);
|
|
||||||
} else {
|
|
||||||
return filterByName(list, filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getHostIds(items) {
|
|
||||||
let hostIds = _.map(items, item => {
|
|
||||||
return _.map(item.hosts, 'hostid');
|
|
||||||
});
|
|
||||||
return _.uniq(_.flatten(hostIds));
|
|
||||||
}
|
|
||||||
65
src/datasource-zabbix/zabbix/connectors/dbConnector.js
Normal file
65
src/datasource-zabbix/zabbix/connectors/dbConnector.js
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for external history database connectors. Subclasses should implement `getHistory()`, `getTrends()` and
|
||||||
|
* `testDataSource()` methods, which describe how to fetch data from source other than Zabbix API.
|
||||||
|
*/
|
||||||
|
export default class DBConnector {
|
||||||
|
constructor(options, backendSrv, datasourceSrv) {
|
||||||
|
this.backendSrv = backendSrv;
|
||||||
|
this.datasourceSrv = datasourceSrv;
|
||||||
|
this.datasourceId = options.datasourceId;
|
||||||
|
this.datasourceName = options.datasourceName;
|
||||||
|
this.datasourceTypeId = null;
|
||||||
|
this.datasourceTypeName = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadDBDataSource() {
|
||||||
|
let ds = _.find(this.datasourceSrv.getAll(), {'id': this.datasourceId});
|
||||||
|
if (ds) {
|
||||||
|
return this.datasourceSrv.loadDatasource(ds.name)
|
||||||
|
.then(ds => {
|
||||||
|
this.datasourceName = ds.name;
|
||||||
|
this.datasourceTypeId = ds.meta.id;
|
||||||
|
this.datasourceTypeName = ds.meta.name;
|
||||||
|
return ds;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Promise.reject(`SQL Data Source with ID ${this.datasourceId} not found`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send test request to datasource in order to ensure it's working.
|
||||||
|
*/
|
||||||
|
testDataSource() {
|
||||||
|
throw new ZabbixNotImplemented('testDataSource()');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get history data from external sources.
|
||||||
|
*/
|
||||||
|
getHistory() {
|
||||||
|
throw new ZabbixNotImplemented('getHistory()');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get trends data from external sources.
|
||||||
|
*/
|
||||||
|
getTrends() {
|
||||||
|
throw new ZabbixNotImplemented('getTrends()');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define Zabbix DB Connector exception type for non-implemented methods
|
||||||
|
export class ZabbixNotImplemented {
|
||||||
|
constructor(methodName) {
|
||||||
|
this.code = null;
|
||||||
|
this.name = 'ZabbixNotImplemented';
|
||||||
|
this.message = `Zabbix DB Connector Error: method ${methodName || ''} should be implemented in subclass of DBConnector`;
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return this.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
43
src/datasource-zabbix/zabbix/connectors/sql/mysql.js
Normal file
43
src/datasource-zabbix/zabbix/connectors/sql/mysql.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* MySQL queries
|
||||||
|
*/
|
||||||
|
|
||||||
|
function historyQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
||||||
|
let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`;
|
||||||
|
let query = `
|
||||||
|
SELECT CAST(itemid AS CHAR) 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_expression}, metric
|
||||||
|
ORDER BY time_sec ASC
|
||||||
|
`;
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
function trendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
||||||
|
let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`;
|
||||||
|
let query = `
|
||||||
|
SELECT CAST(itemid AS CHAR) 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_expression}, metric
|
||||||
|
ORDER BY time_sec ASC
|
||||||
|
`;
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TEST_QUERY = `SELECT CAST(itemid AS CHAR) AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1`;
|
||||||
|
|
||||||
|
function testQuery() {
|
||||||
|
return TEST_QUERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mysql = {
|
||||||
|
historyQuery,
|
||||||
|
trendsQuery,
|
||||||
|
testQuery
|
||||||
|
};
|
||||||
|
|
||||||
|
export default mysql;
|
||||||
48
src/datasource-zabbix/zabbix/connectors/sql/postgres.js
Normal file
48
src/datasource-zabbix/zabbix/connectors/sql/postgres.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* Postgres queries
|
||||||
|
*/
|
||||||
|
|
||||||
|
const ITEMID_FORMAT = 'FM99999999999999999999';
|
||||||
|
|
||||||
|
function historyQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
||||||
|
let time_expression = `clock / ${intervalSec} * ${intervalSec}`;
|
||||||
|
let query = `
|
||||||
|
SELECT to_char(itemid, '${ITEMID_FORMAT}') AS metric, ${time_expression} AS time, ${aggFunction}(value) AS value
|
||||||
|
FROM ${table}
|
||||||
|
WHERE itemid IN (${itemids})
|
||||||
|
AND clock > ${timeFrom} AND clock < ${timeTill}
|
||||||
|
GROUP BY 1, 2
|
||||||
|
ORDER BY time ASC
|
||||||
|
`;
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
function trendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
||||||
|
let time_expression = `clock / ${intervalSec} * ${intervalSec}`;
|
||||||
|
let query = `
|
||||||
|
SELECT to_char(itemid, '${ITEMID_FORMAT}') AS metric, ${time_expression} AS time, ${aggFunction}(${valueColumn}) AS value
|
||||||
|
FROM ${table}
|
||||||
|
WHERE itemid IN (${itemids})
|
||||||
|
AND clock > ${timeFrom} AND clock < ${timeTill}
|
||||||
|
GROUP BY 1, 2
|
||||||
|
ORDER BY time ASC
|
||||||
|
`;
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TEST_QUERY = `
|
||||||
|
SELECT to_char(itemid, '${ITEMID_FORMAT}') AS metric, clock AS time, value_avg AS value
|
||||||
|
FROM trends_uint LIMIT 1
|
||||||
|
`;
|
||||||
|
|
||||||
|
function testQuery() {
|
||||||
|
return TEST_QUERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
const postgres = {
|
||||||
|
historyQuery,
|
||||||
|
trendsQuery,
|
||||||
|
testQuery
|
||||||
|
};
|
||||||
|
|
||||||
|
export default postgres;
|
||||||
173
src/datasource-zabbix/zabbix/connectors/sql/sqlConnector.js
Normal file
173
src/datasource-zabbix/zabbix/connectors/sql/sqlConnector.js
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
|
import mysql from './mysql';
|
||||||
|
import postgres from './postgres';
|
||||||
|
import DBConnector from '../dbConnector';
|
||||||
|
|
||||||
|
const supportedDatabases = {
|
||||||
|
mysql: 'mysql',
|
||||||
|
postgres: 'postgres'
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEFAULT_QUERY_LIMIT = 10000;
|
||||||
|
const HISTORY_TO_TABLE_MAP = {
|
||||||
|
'0': 'history',
|
||||||
|
'1': 'history_str',
|
||||||
|
'2': 'history_log',
|
||||||
|
'3': 'history_uint',
|
||||||
|
'4': 'history_text'
|
||||||
|
};
|
||||||
|
|
||||||
|
const TREND_TO_TABLE_MAP = {
|
||||||
|
'0': 'trends',
|
||||||
|
'3': 'trends_uint'
|
||||||
|
};
|
||||||
|
|
||||||
|
const consolidateByFunc = {
|
||||||
|
'avg': 'AVG',
|
||||||
|
'min': 'MIN',
|
||||||
|
'max': 'MAX',
|
||||||
|
'sum': 'SUM',
|
||||||
|
'count': 'COUNT'
|
||||||
|
};
|
||||||
|
|
||||||
|
const consolidateByTrendColumns = {
|
||||||
|
'avg': 'value_avg',
|
||||||
|
'min': 'value_min',
|
||||||
|
'max': 'value_max'
|
||||||
|
};
|
||||||
|
|
||||||
|
export class SQLConnector extends DBConnector {
|
||||||
|
constructor(options, backendSrv, datasourceSrv) {
|
||||||
|
super(options, backendSrv, datasourceSrv);
|
||||||
|
|
||||||
|
this.limit = options.limit || DEFAULT_QUERY_LIMIT;
|
||||||
|
this.sqlDialect = null;
|
||||||
|
|
||||||
|
super.loadDBDataSource()
|
||||||
|
.then(() => this.loadSQLDialect());
|
||||||
|
}
|
||||||
|
|
||||||
|
loadSQLDialect() {
|
||||||
|
if (this.datasourceTypeId === supportedDatabases.postgres) {
|
||||||
|
this.sqlDialect = postgres;
|
||||||
|
} else {
|
||||||
|
this.sqlDialect = mysql;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to invoke test query for one of Zabbix database tables.
|
||||||
|
*/
|
||||||
|
testDataSource() {
|
||||||
|
let testQuery = this.sqlDialect.testQuery();
|
||||||
|
return this.invokeSQLQuery(testQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
getHistory(items, timeFrom, timeTill, options) {
|
||||||
|
let {intervalMs, consolidateBy} = options;
|
||||||
|
let intervalSec = Math.ceil(intervalMs / 1000);
|
||||||
|
|
||||||
|
consolidateBy = consolidateBy || 'avg';
|
||||||
|
let aggFunction = consolidateByFunc[consolidateBy];
|
||||||
|
|
||||||
|
// 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 = this.sqlDialect.historyQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction);
|
||||||
|
|
||||||
|
query = compactSQLQuery(query);
|
||||||
|
return this.invokeSQLQuery(query);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(promises).then(results => {
|
||||||
|
return _.flatten(results);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getTrends(items, timeFrom, timeTill, options) {
|
||||||
|
let { intervalMs, consolidateBy } = options;
|
||||||
|
let intervalSec = Math.ceil(intervalMs / 1000);
|
||||||
|
|
||||||
|
consolidateBy = consolidateBy || 'avg';
|
||||||
|
let aggFunction = consolidateByFunc[consolidateBy];
|
||||||
|
|
||||||
|
// 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 = TREND_TO_TABLE_MAP[value_type];
|
||||||
|
let valueColumn = _.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg';
|
||||||
|
valueColumn = consolidateByTrendColumns[valueColumn];
|
||||||
|
let query = this.sqlDialect.trendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn);
|
||||||
|
|
||||||
|
query = compactSQLQuery(query);
|
||||||
|
return this.invokeSQLQuery(query);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(promises).then(results => {
|
||||||
|
return _.flatten(results);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGrafanaTSResponse(history, items, addHostName = true) {
|
||||||
|
return convertGrafanaTSResponse(history, items, addHostName);
|
||||||
|
}
|
||||||
|
|
||||||
|
invokeSQLQuery(query) {
|
||||||
|
let queryDef = {
|
||||||
|
refId: 'A',
|
||||||
|
format: 'time_series',
|
||||||
|
datasourceId: this.datasourceId,
|
||||||
|
rawSql: query,
|
||||||
|
maxDataPoints: this.limit
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.backendSrv.datasourceRequest({
|
||||||
|
url: '/api/tsdb/query',
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
queries: [queryDef],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
let results = response.data.results;
|
||||||
|
if (results['A']) {
|
||||||
|
return results['A'].series;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function convertGrafanaTSResponse(time_series, items, addHostName) {
|
||||||
|
//uniqBy is needed to deduplicate
|
||||||
|
var hosts = _.uniqBy(_.flatten(_.map(items, 'hosts')), 'hostid');
|
||||||
|
let grafanaSeries = _.map(time_series, series => {
|
||||||
|
let itemid = series.name;
|
||||||
|
var item = _.find(items, {'itemid': itemid});
|
||||||
|
var alias = item.name;
|
||||||
|
//only when actual multi hosts selected
|
||||||
|
if (_.keys(hosts).length > 1 && addHostName) {
|
||||||
|
var host = _.find(hosts, {'hostid': item.hostid});
|
||||||
|
alias = host.name + ": " + alias;
|
||||||
|
}
|
||||||
|
// CachingProxy deduplicates requests and returns one time series for equal queries.
|
||||||
|
// Clone is needed to prevent changing of series object shared between all targets.
|
||||||
|
let datapoints = _.cloneDeep(series.points);
|
||||||
|
return {
|
||||||
|
target: alias,
|
||||||
|
datapoints: datapoints
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return _.sortBy(grafanaSeries, 'target');
|
||||||
|
}
|
||||||
|
|
||||||
|
function compactSQLQuery(query) {
|
||||||
|
return query.replace(/\s+/g, ' ');
|
||||||
|
}
|
||||||
@@ -0,0 +1,482 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
|
import * as utils from '../../../utils';
|
||||||
|
import { ZabbixAPICore } from './zabbixAPICore';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zabbix API Wrapper.
|
||||||
|
* Creates Zabbix API instance with given parameters (url, credentials and other).
|
||||||
|
* Wraps API calls and provides high-level methods.
|
||||||
|
*/
|
||||||
|
export class ZabbixAPIConnector {
|
||||||
|
constructor(api_url, username, password, basicAuth, withCredentials, backendSrv) {
|
||||||
|
this.url = api_url;
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
this.auth = "";
|
||||||
|
|
||||||
|
this.requestOptions = {
|
||||||
|
basicAuth: basicAuth,
|
||||||
|
withCredentials: withCredentials
|
||||||
|
};
|
||||||
|
|
||||||
|
this.loginPromise = null;
|
||||||
|
this.loginErrorCount = 0;
|
||||||
|
this.maxLoginAttempts = 3;
|
||||||
|
|
||||||
|
this.zabbixAPICore = new ZabbixAPICore(backendSrv);
|
||||||
|
|
||||||
|
this.getTrend = this.getTrend_ZBXNEXT1193;
|
||||||
|
//getTrend = getTrend_30;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
// Core method wrappers //
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
request(method, params) {
|
||||||
|
return this.zabbixAPICore.request(this.url, method, params, this.requestOptions, this.auth)
|
||||||
|
.catch(error => {
|
||||||
|
if (isNotAuthorized(error.data)) {
|
||||||
|
// Handle auth errors
|
||||||
|
this.loginErrorCount++;
|
||||||
|
if (this.loginErrorCount > this.maxLoginAttempts) {
|
||||||
|
this.loginErrorCount = 0;
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return this.loginOnce()
|
||||||
|
.then(() => this.request(method, params));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Handle API errors
|
||||||
|
let message = error.data ? error.data : error.statusText;
|
||||||
|
return Promise.reject(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When API unauthenticated or auth token expired each request produce login()
|
||||||
|
* call. But auth token is common to all requests. This function wraps login() method
|
||||||
|
* and call it once. If login() already called just wait for it (return its promise).
|
||||||
|
* @return login promise
|
||||||
|
*/
|
||||||
|
loginOnce() {
|
||||||
|
if (!this.loginPromise) {
|
||||||
|
this.loginPromise = Promise.resolve(
|
||||||
|
this.login().then(auth => {
|
||||||
|
this.auth = auth;
|
||||||
|
this.loginPromise = null;
|
||||||
|
return auth;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this.loginPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get authentication token.
|
||||||
|
*/
|
||||||
|
login() {
|
||||||
|
return this.zabbixAPICore.login(this.url, this.username, this.password, this.requestOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Zabbix API version
|
||||||
|
*/
|
||||||
|
getVersion() {
|
||||||
|
return this.zabbixAPICore.getVersion(this.url, this.requestOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Zabbix API method wrappers //
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
acknowledgeEvent(eventid, message) {
|
||||||
|
var params = {
|
||||||
|
eventids: eventid,
|
||||||
|
message: message
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('event.acknowledge', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
getGroups() {
|
||||||
|
var params = {
|
||||||
|
output: ['name'],
|
||||||
|
sortfield: 'name',
|
||||||
|
real_hosts: true
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('hostgroup.get', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
getHosts(groupids) {
|
||||||
|
var params = {
|
||||||
|
output: ['name', 'host'],
|
||||||
|
sortfield: 'name'
|
||||||
|
};
|
||||||
|
if (groupids) {
|
||||||
|
params.groupids = groupids;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.request('host.get', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
getApps(hostids) {
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
hostids: hostids
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('application.get', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Zabbix items
|
||||||
|
* @param {[type]} hostids host ids
|
||||||
|
* @param {[type]} appids application ids
|
||||||
|
* @param {String} itemtype 'num' or 'text'
|
||||||
|
* @return {[type]} array of items
|
||||||
|
*/
|
||||||
|
getItems(hostids, appids, itemtype) {
|
||||||
|
var params = {
|
||||||
|
output: [
|
||||||
|
'name', 'key_',
|
||||||
|
'value_type',
|
||||||
|
'hostid',
|
||||||
|
'status',
|
||||||
|
'state'
|
||||||
|
],
|
||||||
|
sortfield: 'name',
|
||||||
|
webitems: true,
|
||||||
|
filter: {},
|
||||||
|
selectHosts: ['hostid', 'name']
|
||||||
|
};
|
||||||
|
if (hostids) {
|
||||||
|
params.hostids = hostids;
|
||||||
|
}
|
||||||
|
if (appids) {
|
||||||
|
params.applicationids = appids;
|
||||||
|
}
|
||||||
|
if (itemtype === 'num') {
|
||||||
|
// Return only numeric metrics
|
||||||
|
params.filter.value_type = [0, 3];
|
||||||
|
}
|
||||||
|
if (itemtype === 'text') {
|
||||||
|
// Return only text metrics
|
||||||
|
params.filter.value_type = [1, 2, 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.request('item.get', params)
|
||||||
|
.then(utils.expandItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
getItemsByIDs(itemids) {
|
||||||
|
var params = {
|
||||||
|
itemids: itemids,
|
||||||
|
output: [
|
||||||
|
'name', 'key_',
|
||||||
|
'value_type',
|
||||||
|
'hostid',
|
||||||
|
'status',
|
||||||
|
'state'
|
||||||
|
],
|
||||||
|
webitems: true,
|
||||||
|
selectHosts: ['hostid', 'name']
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('item.get', params)
|
||||||
|
.then(utils.expandItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
getMacros(hostids) {
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
hostids: hostids
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('usermacro.get', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
getGlobalMacros() {
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
globalmacro: true
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('usermacro.get', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastValue(itemid) {
|
||||||
|
var params = {
|
||||||
|
output: ['lastvalue'],
|
||||||
|
itemids: itemid
|
||||||
|
};
|
||||||
|
return this.request('item.get', params)
|
||||||
|
.then(items => items.length ? items[0].lastvalue : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform history query from Zabbix API
|
||||||
|
*
|
||||||
|
* @param {Array} items Array of Zabbix item objects
|
||||||
|
* @param {Number} timeFrom Time in seconds
|
||||||
|
* @param {Number} timeTill Time in seconds
|
||||||
|
* @return {Array} Array of Zabbix history objects
|
||||||
|
*/
|
||||||
|
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');
|
||||||
|
let params = {
|
||||||
|
output: 'extend',
|
||||||
|
history: value_type,
|
||||||
|
itemids: itemids,
|
||||||
|
sortfield: 'clock',
|
||||||
|
sortorder: 'ASC',
|
||||||
|
time_from: timeFrom
|
||||||
|
};
|
||||||
|
|
||||||
|
// Relative queries (e.g. last hour) don't include an end time
|
||||||
|
if (timeTill) {
|
||||||
|
params.time_till = timeTill;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.request('history.get', params);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(promises).then(_.flatten);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform trends query from Zabbix API
|
||||||
|
* Use trends api extension from ZBXNEXT-1193 patch.
|
||||||
|
*
|
||||||
|
* @param {Array} items Array of Zabbix item objects
|
||||||
|
* @param {Number} time_from Time in seconds
|
||||||
|
* @param {Number} time_till Time in seconds
|
||||||
|
* @return {Array} Array of Zabbix trend objects
|
||||||
|
*/
|
||||||
|
getTrend_ZBXNEXT1193(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');
|
||||||
|
let params = {
|
||||||
|
output: 'extend',
|
||||||
|
trend: value_type,
|
||||||
|
itemids: itemids,
|
||||||
|
sortfield: 'clock',
|
||||||
|
sortorder: 'ASC',
|
||||||
|
time_from: timeFrom
|
||||||
|
};
|
||||||
|
|
||||||
|
// Relative queries (e.g. last hour) don't include an end time
|
||||||
|
if (timeTill) {
|
||||||
|
params.time_till = timeTill;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.request('trend.get', params);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(promises).then(_.flatten);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTrend_30(items, time_from, time_till, value_type) {
|
||||||
|
var self = this;
|
||||||
|
var itemids = _.map(items, 'itemid');
|
||||||
|
|
||||||
|
var params = {
|
||||||
|
output: ["itemid",
|
||||||
|
"clock",
|
||||||
|
value_type
|
||||||
|
],
|
||||||
|
itemids: itemids,
|
||||||
|
time_from: time_from
|
||||||
|
};
|
||||||
|
|
||||||
|
// Relative queries (e.g. last hour) don't include an end time
|
||||||
|
if (time_till) {
|
||||||
|
params.time_till = time_till;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.request('trend.get', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
getITService(serviceids) {
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
serviceids: serviceids
|
||||||
|
};
|
||||||
|
return this.request('service.get', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSLA(serviceids, timeRange) {
|
||||||
|
let [timeFrom, timeTo] = timeRange;
|
||||||
|
var params = {
|
||||||
|
serviceids: serviceids,
|
||||||
|
intervals: [{
|
||||||
|
from: timeFrom,
|
||||||
|
to: timeTo
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
return this.request('service.getsla', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTriggers(groupids, hostids, applicationids, options) {
|
||||||
|
let {showTriggers, maintenance, timeFrom, timeTo} = options;
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
output: 'extend',
|
||||||
|
groupids: groupids,
|
||||||
|
hostids: hostids,
|
||||||
|
applicationids: applicationids,
|
||||||
|
expandDescription: true,
|
||||||
|
expandData: true,
|
||||||
|
expandComment: true,
|
||||||
|
monitored: true,
|
||||||
|
skipDependent: true,
|
||||||
|
//only_true: true,
|
||||||
|
filter: {
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
selectGroups: ['name'],
|
||||||
|
selectHosts: ['name', 'host', 'maintenance_status'],
|
||||||
|
selectItems: ['name', 'key_', 'lastvalue'],
|
||||||
|
selectLastEvent: 'extend',
|
||||||
|
selectTags: 'extend'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (showTriggers) {
|
||||||
|
params.filter.value = showTriggers;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maintenance) {
|
||||||
|
params.maintenance = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeFrom || timeTo) {
|
||||||
|
params.lastChangeSince = timeFrom;
|
||||||
|
params.lastChangeTill = timeTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.request('trigger.get', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
getEvents(objectids, timeFrom, timeTo, showEvents) {
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
time_from: timeFrom,
|
||||||
|
time_till: timeTo,
|
||||||
|
objectids: objectids,
|
||||||
|
select_acknowledges: 'extend',
|
||||||
|
selectHosts: 'extend',
|
||||||
|
value: showEvents
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('event.get', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
getAcknowledges(eventids) {
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
eventids: eventids,
|
||||||
|
preservekeys: true,
|
||||||
|
select_acknowledges: 'extend',
|
||||||
|
sortfield: 'clock',
|
||||||
|
sortorder: 'DESC'
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('event.get', params)
|
||||||
|
.then(events => {
|
||||||
|
return _.filter(events, (event) => event.acknowledges.length);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getAlerts(itemids, timeFrom, timeTo) {
|
||||||
|
var params = {
|
||||||
|
output: 'extend',
|
||||||
|
itemids: itemids,
|
||||||
|
expandDescription: true,
|
||||||
|
expandData: true,
|
||||||
|
expandComment: true,
|
||||||
|
monitored: true,
|
||||||
|
skipDependent: true,
|
||||||
|
//only_true: true,
|
||||||
|
// filter: {
|
||||||
|
// value: 1
|
||||||
|
// },
|
||||||
|
selectLastEvent: 'extend'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (timeFrom || timeTo) {
|
||||||
|
params.lastChangeSince = timeFrom;
|
||||||
|
params.lastChangeTill = timeTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.request('trigger.get', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
getHostAlerts(hostids, applicationids, options) {
|
||||||
|
let {minSeverity, acknowledged, count, timeFrom, timeTo} = options;
|
||||||
|
let params = {
|
||||||
|
output: 'extend',
|
||||||
|
hostids: hostids,
|
||||||
|
min_severity: minSeverity,
|
||||||
|
filter: { value: 1 },
|
||||||
|
expandDescription: true,
|
||||||
|
expandData: true,
|
||||||
|
expandComment: true,
|
||||||
|
monitored: true,
|
||||||
|
skipDependent: true,
|
||||||
|
selectLastEvent: 'extend',
|
||||||
|
selectGroups: 'extend',
|
||||||
|
selectHosts: ['host', 'name']
|
||||||
|
};
|
||||||
|
|
||||||
|
if (count && acknowledged !== 0 && acknowledged !== 1) {
|
||||||
|
params.countOutput = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (applicationids && applicationids.length) {
|
||||||
|
params.applicationids = applicationids;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeFrom || timeTo) {
|
||||||
|
params.lastChangeSince = timeFrom;
|
||||||
|
params.lastChangeTill = timeTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.request('trigger.get', params)
|
||||||
|
.then((triggers) => {
|
||||||
|
if (!count || acknowledged === 0 || acknowledged === 1) {
|
||||||
|
triggers = filterTriggersByAcknowledge(triggers, acknowledged);
|
||||||
|
if (count) {
|
||||||
|
triggers = triggers.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return triggers;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterTriggersByAcknowledge(triggers, acknowledged) {
|
||||||
|
if (acknowledged === 0) {
|
||||||
|
return _.filter(triggers, (trigger) => trigger.lastEvent.acknowledged === "0");
|
||||||
|
} else if (acknowledged === 1) {
|
||||||
|
return _.filter(triggers, (trigger) => trigger.lastEvent.acknowledged === "1");
|
||||||
|
} else {
|
||||||
|
return triggers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isNotAuthorized(message) {
|
||||||
|
return (
|
||||||
|
message === "Session terminated, re-login, please." ||
|
||||||
|
message === "Not authorised." ||
|
||||||
|
message === "Not authorized."
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,9 +2,7 @@
|
|||||||
* General Zabbix API methods
|
* General Zabbix API methods
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import angular from 'angular';
|
export class ZabbixAPICore {
|
||||||
|
|
||||||
class ZabbixAPICoreService {
|
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor(backendSrv) {
|
constructor(backendSrv) {
|
||||||
@@ -101,7 +99,3 @@ export class ZabbixAPIError {
|
|||||||
return this.name + " " + this.data;
|
return this.name + " " + this.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
angular
|
|
||||||
.module('grafana.services')
|
|
||||||
.service('zabbixAPICoreService', ZabbixAPICoreService);
|
|
||||||
108
src/datasource-zabbix/zabbix/proxy/cachingProxy.js
Normal file
108
src/datasource-zabbix/zabbix/proxy/cachingProxy.js
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* This module allows to deduplicate function calls with the same params and
|
||||||
|
* cache result of function call.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class CachingProxy {
|
||||||
|
|
||||||
|
constructor(cacheOptions) {
|
||||||
|
this.cacheEnabled = cacheOptions.enabled;
|
||||||
|
this.ttl = cacheOptions.ttl || 600000; // 10 minutes by default
|
||||||
|
|
||||||
|
// Internal objects for data storing
|
||||||
|
this.cache = {};
|
||||||
|
this.promises = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that result is present in the cache and is up to date or send request otherwise.
|
||||||
|
*/
|
||||||
|
cacheRequest(func, funcName, funcScope) {
|
||||||
|
return cacheRequest(func, funcName, funcScope, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap request to prevent multiple calls with same params when request is waiting for response.
|
||||||
|
*/
|
||||||
|
proxyfy(func, funcName, funcScope) {
|
||||||
|
if (!this.promises[funcName]) {
|
||||||
|
this.promises[funcName] = {};
|
||||||
|
}
|
||||||
|
const promiseKeeper = this.promises[funcName];
|
||||||
|
return callOnce(func, promiseKeeper, funcScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
proxyfyWithCache(func, funcName, funcScope) {
|
||||||
|
let proxyfied = this.proxyfy(func, funcName, funcScope);
|
||||||
|
return this.cacheRequest(proxyfied, funcName, funcScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
_isExpired(cacheObject) {
|
||||||
|
if (cacheObject) {
|
||||||
|
let object_age = Date.now() - cacheObject.timestamp;
|
||||||
|
return !(cacheObject.timestamp && object_age < this.ttl);
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap request to prevent multiple calls
|
||||||
|
* with same params when waiting for result.
|
||||||
|
*/
|
||||||
|
function callOnce(func, promiseKeeper, funcScope) {
|
||||||
|
return function() {
|
||||||
|
var hash = getRequestHash(arguments);
|
||||||
|
if (!promiseKeeper[hash]) {
|
||||||
|
promiseKeeper[hash] = Promise.resolve(
|
||||||
|
func.apply(funcScope, arguments)
|
||||||
|
.then(result => {
|
||||||
|
promiseKeeper[hash] = null;
|
||||||
|
return result;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return promiseKeeper[hash];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function cacheRequest(func, funcName, funcScope, self) {
|
||||||
|
return function() {
|
||||||
|
if (!self.cache[funcName]) {
|
||||||
|
self.cache[funcName] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
let cacheObject = self.cache[funcName];
|
||||||
|
let hash = getRequestHash(arguments);
|
||||||
|
if (self.cacheEnabled && !self._isExpired(cacheObject[hash])) {
|
||||||
|
return Promise.resolve(cacheObject[hash].value);
|
||||||
|
} else {
|
||||||
|
return func.apply(funcScope, arguments)
|
||||||
|
.then(result => {
|
||||||
|
cacheObject[hash] = {
|
||||||
|
value: result,
|
||||||
|
timestamp: Date.now()
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRequestHash(args) {
|
||||||
|
const argsJson = JSON.stringify(args);
|
||||||
|
return argsJson.getHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
String.prototype.getHash = function() {
|
||||||
|
var hash = 0, i, chr, len;
|
||||||
|
if (this.length !== 0) {
|
||||||
|
for (i = 0, len = this.length; i < len; i++) {
|
||||||
|
chr = this.charCodeAt(i);
|
||||||
|
hash = ((hash << 5) - hash) + chr;
|
||||||
|
hash |= 0; // Convert to 32bit integer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
389
src/datasource-zabbix/zabbix/zabbix.js
Normal file
389
src/datasource-zabbix/zabbix/zabbix.js
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
|
import * as utils from '../utils';
|
||||||
|
import responseHandler from '../responseHandler';
|
||||||
|
import { ZabbixAPIConnector } from './connectors/zabbix_api/zabbixAPIConnector';
|
||||||
|
import { SQLConnector } from './connectors/sql/sqlConnector';
|
||||||
|
import { CachingProxy } from './proxy/cachingProxy';
|
||||||
|
import { ZabbixNotImplemented } from './connectors/dbConnector';
|
||||||
|
|
||||||
|
const REQUESTS_TO_PROXYFY = [
|
||||||
|
'getHistory', 'getTrend', 'getGroups', 'getHosts', 'getApps', 'getItems', 'getMacros', 'getItemsByIDs',
|
||||||
|
'getEvents', 'getAlerts', 'getHostAlerts', 'getAcknowledges', 'getITService', 'getSLA', 'getVersion'
|
||||||
|
];
|
||||||
|
|
||||||
|
const REQUESTS_TO_CACHE = [
|
||||||
|
'getGroups', 'getHosts', 'getApps', 'getItems', 'getMacros', 'getItemsByIDs', 'getITService'
|
||||||
|
];
|
||||||
|
|
||||||
|
const REQUESTS_TO_BIND = [
|
||||||
|
'getHistory', 'getTrend', 'getMacros', 'getItemsByIDs', 'getEvents', 'getAlerts', 'getHostAlerts',
|
||||||
|
'getAcknowledges', 'getITService', 'getVersion', 'login'
|
||||||
|
];
|
||||||
|
|
||||||
|
export class Zabbix {
|
||||||
|
constructor(options, backendSrv, datasourceSrv) {
|
||||||
|
let {
|
||||||
|
url,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
basicAuth,
|
||||||
|
withCredentials,
|
||||||
|
cacheTTL,
|
||||||
|
enableDirectDBConnection,
|
||||||
|
datasourceId
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
this.enableDirectDBConnection = enableDirectDBConnection;
|
||||||
|
|
||||||
|
// Initialize caching proxy for requests
|
||||||
|
let cacheOptions = {
|
||||||
|
enabled: true,
|
||||||
|
ttl: cacheTTL
|
||||||
|
};
|
||||||
|
this.cachingProxy = new CachingProxy(cacheOptions);
|
||||||
|
|
||||||
|
this.zabbixAPI = new ZabbixAPIConnector(url, username, password, basicAuth, withCredentials, backendSrv);
|
||||||
|
|
||||||
|
if (enableDirectDBConnection) {
|
||||||
|
let dbConnectorOptions = { datasourceId };
|
||||||
|
this.dbConnector = new SQLConnector(dbConnectorOptions, backendSrv, datasourceSrv);
|
||||||
|
this.getHistoryDB = this.cachingProxy.proxyfyWithCache(this.dbConnector.getHistory, 'getHistory', this.dbConnector);
|
||||||
|
this.getTrendsDB = this.cachingProxy.proxyfyWithCache(this.dbConnector.getTrends, 'getTrends', this.dbConnector);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.proxyfyRequests();
|
||||||
|
this.cacheRequests();
|
||||||
|
this.bindRequests();
|
||||||
|
}
|
||||||
|
|
||||||
|
proxyfyRequests() {
|
||||||
|
for (let request of REQUESTS_TO_PROXYFY) {
|
||||||
|
this.zabbixAPI[request] = this.cachingProxy.proxyfy(this.zabbixAPI[request], request, this.zabbixAPI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheRequests() {
|
||||||
|
for (let request of REQUESTS_TO_CACHE) {
|
||||||
|
this.zabbixAPI[request] = this.cachingProxy.cacheRequest(this.zabbixAPI[request], request, this.zabbixAPI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bindRequests() {
|
||||||
|
for (let request of REQUESTS_TO_BIND) {
|
||||||
|
this[request] = this.zabbixAPI[request].bind(this.zabbixAPI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform test query for Zabbix API and external history DB.
|
||||||
|
* @return {object} test result object:
|
||||||
|
* ```
|
||||||
|
{
|
||||||
|
zabbixVersion,
|
||||||
|
dbConnectorStatus: {
|
||||||
|
dsType,
|
||||||
|
dsName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
testDataSource() {
|
||||||
|
let zabbixVersion;
|
||||||
|
let dbConnectorStatus;
|
||||||
|
return this.getVersion()
|
||||||
|
.then(version => {
|
||||||
|
zabbixVersion = version;
|
||||||
|
return this.login();
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
if (this.enableDirectDBConnection) {
|
||||||
|
return this.dbConnector.testDataSource();
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
if (error instanceof ZabbixNotImplemented) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return Promise.reject(error);
|
||||||
|
})
|
||||||
|
.then(testResult => {
|
||||||
|
if (testResult) {
|
||||||
|
dbConnectorStatus = {
|
||||||
|
dsType: this.dbConnector.datasourceTypeName,
|
||||||
|
dsName: this.dbConnector.datasourceName
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return { zabbixVersion, dbConnectorStatus };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getItemsFromTarget(target, options) {
|
||||||
|
let parts = ['group', 'host', 'application', 'item'];
|
||||||
|
let filters = _.map(parts, p => target[p].filter);
|
||||||
|
return this.getItems(...filters, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
getHostsFromTarget(target) {
|
||||||
|
let parts = ['group', 'host', 'application'];
|
||||||
|
let filters = _.map(parts, p => target[p].filter);
|
||||||
|
return Promise.all([
|
||||||
|
this.getHosts(...filters),
|
||||||
|
this.getApps(...filters),
|
||||||
|
]).then((results) => {
|
||||||
|
let [hosts, apps] = results;
|
||||||
|
if (apps.appFilterEmpty) {
|
||||||
|
apps = [];
|
||||||
|
}
|
||||||
|
return [hosts, apps];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllGroups() {
|
||||||
|
return this.zabbixAPI.getGroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
getGroups(groupFilter) {
|
||||||
|
return this.getAllGroups()
|
||||||
|
.then(groups => findByFilter(groups, groupFilter));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of host belonging to given groups.
|
||||||
|
*/
|
||||||
|
getAllHosts(groupFilter) {
|
||||||
|
return this.getGroups(groupFilter)
|
||||||
|
.then(groups => {
|
||||||
|
let groupids = _.map(groups, 'groupid');
|
||||||
|
return this.zabbixAPI.getHosts(groupids);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getHosts(groupFilter, hostFilter) {
|
||||||
|
return this.getAllHosts(groupFilter)
|
||||||
|
.then(hosts => findByFilter(hosts, hostFilter));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of applications belonging to given groups and hosts.
|
||||||
|
*/
|
||||||
|
getAllApps(groupFilter, hostFilter) {
|
||||||
|
return this.getHosts(groupFilter, hostFilter)
|
||||||
|
.then(hosts => {
|
||||||
|
let hostids = _.map(hosts, 'hostid');
|
||||||
|
return this.zabbixAPI.getApps(hostids);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getApps(groupFilter, hostFilter, appFilter) {
|
||||||
|
return this.getHosts(groupFilter, hostFilter)
|
||||||
|
.then(hosts => {
|
||||||
|
let hostids = _.map(hosts, 'hostid');
|
||||||
|
if (appFilter) {
|
||||||
|
return this.zabbixAPI.getApps(hostids)
|
||||||
|
.then(apps => filterByQuery(apps, appFilter));
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
appFilterEmpty: true,
|
||||||
|
hostids: hostids
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllItems(groupFilter, hostFilter, appFilter, options = {}) {
|
||||||
|
return this.getApps(groupFilter, hostFilter, appFilter)
|
||||||
|
.then(apps => {
|
||||||
|
if (apps.appFilterEmpty) {
|
||||||
|
return this.zabbixAPI.getItems(apps.hostids, undefined, options.itemtype);
|
||||||
|
} else {
|
||||||
|
let appids = _.map(apps, 'applicationid');
|
||||||
|
return this.zabbixAPI.getItems(undefined, appids, options.itemtype);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(items => {
|
||||||
|
if (!options.showDisabledItems) {
|
||||||
|
items = _.filter(items, {'status': '0'});
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
})
|
||||||
|
.then(this.expandUserMacro.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
expandUserMacro(items) {
|
||||||
|
let hostids = getHostIds(items);
|
||||||
|
return this.getMacros(hostids)
|
||||||
|
.then(macros => {
|
||||||
|
_.forEach(items, item => {
|
||||||
|
if (utils.containsMacro(item.name)) {
|
||||||
|
item.name = utils.replaceMacro(item, macros);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return items;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getItems(groupFilter, hostFilter, appFilter, itemFilter, options = {}) {
|
||||||
|
return this.getAllItems(groupFilter, hostFilter, appFilter, options)
|
||||||
|
.then(items => filterByQuery(items, itemFilter));
|
||||||
|
}
|
||||||
|
|
||||||
|
getITServices(itServiceFilter) {
|
||||||
|
return this.zabbixAPI.getITService()
|
||||||
|
.then(itServices => findByFilter(itServices, itServiceFilter));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build query - convert target filters to array of Zabbix items
|
||||||
|
*/
|
||||||
|
getTriggers(groupFilter, hostFilter, appFilter, options) {
|
||||||
|
let promises = [
|
||||||
|
this.getGroups(groupFilter),
|
||||||
|
this.getHosts(groupFilter, hostFilter),
|
||||||
|
this.getApps(groupFilter, hostFilter, appFilter)
|
||||||
|
];
|
||||||
|
|
||||||
|
return Promise.all(promises)
|
||||||
|
.then(results => {
|
||||||
|
let filteredGroups = results[0];
|
||||||
|
let filteredHosts = results[1];
|
||||||
|
let filteredApps = results[2];
|
||||||
|
let query = {};
|
||||||
|
|
||||||
|
if (appFilter) {
|
||||||
|
query.applicationids = _.flatten(_.map(filteredApps, 'applicationid'));
|
||||||
|
}
|
||||||
|
if (hostFilter) {
|
||||||
|
query.hostids = _.map(filteredHosts, 'hostid');
|
||||||
|
}
|
||||||
|
if (groupFilter) {
|
||||||
|
query.groupids = _.map(filteredGroups, 'groupid');
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}).then(query => {
|
||||||
|
return this.zabbixAPI.getTriggers(query.groupids, query.hostids, query.applicationids, options);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getHistoryTS(items, timeRange, options) {
|
||||||
|
let [timeFrom, timeTo] = timeRange;
|
||||||
|
if (this.enableDirectDBConnection) {
|
||||||
|
return this.getHistoryDB(items, timeFrom, timeTo, options)
|
||||||
|
.then(history => this.dbConnector.handleGrafanaTSResponse(history, items));
|
||||||
|
} else {
|
||||||
|
return this.zabbixAPI.getHistory(items, timeFrom, timeTo)
|
||||||
|
.then(history => responseHandler.handleHistory(history, items));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getTrends(items, timeRange, options) {
|
||||||
|
let [timeFrom, timeTo] = timeRange;
|
||||||
|
if (this.enableDirectDBConnection) {
|
||||||
|
return this.getTrendsDB(items, timeFrom, timeTo, options)
|
||||||
|
.then(history => this.dbConnector.handleGrafanaTSResponse(history, items));
|
||||||
|
} else {
|
||||||
|
let valueType = options.consolidateBy || options.valueType;
|
||||||
|
return this.zabbixAPI.getTrend(items, timeFrom, timeTo)
|
||||||
|
.then(history => responseHandler.handleTrends(history, items, valueType))
|
||||||
|
.then(responseHandler.sortTimeseries); // Sort trend data, issue #202
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getHistoryText(items, timeRange, target) {
|
||||||
|
let [timeFrom, timeTo] = timeRange;
|
||||||
|
if (items.length) {
|
||||||
|
return this.zabbixAPI.getHistory(items, timeFrom, timeTo)
|
||||||
|
.then(history => {
|
||||||
|
if (target.resultFormat === 'table') {
|
||||||
|
return responseHandler.handleHistoryAsTable(history, items, target);
|
||||||
|
} else {
|
||||||
|
return responseHandler.handleText(history, items, target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getSLA(itservices, timeRange, target, options) {
|
||||||
|
let itServices = itservices;
|
||||||
|
if (options.isOldVersion) {
|
||||||
|
itServices = _.filter(itServices, {'serviceid': target.itservice.serviceid});
|
||||||
|
}
|
||||||
|
let itServiceIds = _.map(itServices, 'serviceid');
|
||||||
|
return this.zabbixAPI.getSLA(itServiceIds, timeRange)
|
||||||
|
.then(slaResponse => {
|
||||||
|
return _.map(itServiceIds, serviceid => {
|
||||||
|
let itservice = _.find(itServices, {'serviceid': serviceid});
|
||||||
|
return responseHandler.handleSLAResponse(itservice, target.slaProperty, slaResponse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find group, host, app or item by given name.
|
||||||
|
* @param list list of groups, apps or other
|
||||||
|
* @param name visible name
|
||||||
|
* @return array with finded element or empty array
|
||||||
|
*/
|
||||||
|
function findByName(list, name) {
|
||||||
|
var finded = _.find(list, {'name': name});
|
||||||
|
if (finded) {
|
||||||
|
return [finded];
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Different hosts can contains applications and items with same name.
|
||||||
|
* For this reason use _.filter, which return all elements instead _.find,
|
||||||
|
* which return only first finded.
|
||||||
|
* @param {[type]} list list of elements
|
||||||
|
* @param {[type]} name app name
|
||||||
|
* @return {[type]} array with finded element or empty array
|
||||||
|
*/
|
||||||
|
function filterByName(list, name) {
|
||||||
|
var finded = _.filter(list, {'name': name});
|
||||||
|
if (finded) {
|
||||||
|
return finded;
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterByRegex(list, regex) {
|
||||||
|
var filterPattern = utils.buildRegex(regex);
|
||||||
|
return _.filter(list, function (zbx_obj) {
|
||||||
|
return filterPattern.test(zbx_obj.name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function findByFilter(list, filter) {
|
||||||
|
if (utils.isRegex(filter)) {
|
||||||
|
return filterByRegex(list, filter);
|
||||||
|
} else {
|
||||||
|
return findByName(list, filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterByQuery(list, filter) {
|
||||||
|
if (utils.isRegex(filter)) {
|
||||||
|
return filterByRegex(list, filter);
|
||||||
|
} else {
|
||||||
|
return filterByName(list, filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHostIds(items) {
|
||||||
|
let hostIds = _.map(items, item => {
|
||||||
|
return _.map(item.hosts, 'hostid');
|
||||||
|
});
|
||||||
|
return _.uniq(_.flatten(hostIds));
|
||||||
|
}
|
||||||
@@ -1,504 +0,0 @@
|
|||||||
import angular from 'angular';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import * as utils from './utils';
|
|
||||||
import './zabbixAPICore.service';
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zabbix API Wrapper.
|
|
||||||
* Creates Zabbix API instance with given parameters (url, credentials and other).
|
|
||||||
* Wraps API calls and provides high-level methods.
|
|
||||||
*/
|
|
||||||
class ZabbixAPI {
|
|
||||||
|
|
||||||
constructor(api_url, username, password, basicAuth, withCredentials) {
|
|
||||||
this.url = api_url;
|
|
||||||
this.username = username;
|
|
||||||
this.password = password;
|
|
||||||
this.auth = "";
|
|
||||||
|
|
||||||
this.requestOptions = {
|
|
||||||
basicAuth: basicAuth,
|
|
||||||
withCredentials: withCredentials
|
|
||||||
};
|
|
||||||
|
|
||||||
this.loginPromise = null;
|
|
||||||
this.loginErrorCount = 0;
|
|
||||||
this.maxLoginAttempts = 3;
|
|
||||||
|
|
||||||
this.alertSrv = alertSrv;
|
|
||||||
this.zabbixAPICore = zabbixAPICoreService;
|
|
||||||
|
|
||||||
this.getTrend = this.getTrend_ZBXNEXT1193;
|
|
||||||
//getTrend = getTrend_30;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////
|
|
||||||
// Core method wrappers //
|
|
||||||
//////////////////////////
|
|
||||||
|
|
||||||
request(method, params) {
|
|
||||||
return this.zabbixAPICore.request(this.url, method, params, this.requestOptions, this.auth)
|
|
||||||
.catch(error => {
|
|
||||||
if (isNotAuthorized(error.data)) {
|
|
||||||
// Handle auth errors
|
|
||||||
this.loginErrorCount++;
|
|
||||||
if (this.loginErrorCount > this.maxLoginAttempts) {
|
|
||||||
this.loginErrorCount = 0;
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return this.loginOnce()
|
|
||||||
.then(() => this.request(method, params));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Handle API errors
|
|
||||||
let message = error.data ? error.data : error.statusText;
|
|
||||||
this.alertAPIError(message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
alertAPIError(message, timeout = 5000) {
|
|
||||||
this.alertSrv.set(
|
|
||||||
"Zabbix API Error",
|
|
||||||
message,
|
|
||||||
'error',
|
|
||||||
timeout
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When API unauthenticated or auth token expired each request produce login()
|
|
||||||
* call. But auth token is common to all requests. This function wraps login() method
|
|
||||||
* and call it once. If login() already called just wait for it (return its promise).
|
|
||||||
* @return login promise
|
|
||||||
*/
|
|
||||||
loginOnce() {
|
|
||||||
if (!this.loginPromise) {
|
|
||||||
this.loginPromise = Promise.resolve(
|
|
||||||
this.login().then(auth => {
|
|
||||||
this.auth = auth;
|
|
||||||
this.loginPromise = null;
|
|
||||||
return auth;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return this.loginPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get authentication token.
|
|
||||||
*/
|
|
||||||
login() {
|
|
||||||
return this.zabbixAPICore.login(this.url, this.username, this.password, this.requestOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Zabbix API version
|
|
||||||
*/
|
|
||||||
getVersion() {
|
|
||||||
return this.zabbixAPICore.getVersion(this.url, this.requestOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// Zabbix API method wrappers //
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
acknowledgeEvent(eventid, message) {
|
|
||||||
var params = {
|
|
||||||
eventids: eventid,
|
|
||||||
message: message
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('event.acknowledge', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
getGroups() {
|
|
||||||
var params = {
|
|
||||||
output: ['name'],
|
|
||||||
sortfield: 'name',
|
|
||||||
real_hosts: true
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('hostgroup.get', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
getHosts(groupids) {
|
|
||||||
var params = {
|
|
||||||
output: ['name', 'host'],
|
|
||||||
sortfield: 'name'
|
|
||||||
};
|
|
||||||
if (groupids) {
|
|
||||||
params.groupids = groupids;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.request('host.get', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
getApps(hostids) {
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
hostids: hostids
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('application.get', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Zabbix items
|
|
||||||
* @param {[type]} hostids host ids
|
|
||||||
* @param {[type]} appids application ids
|
|
||||||
* @param {String} itemtype 'num' or 'text'
|
|
||||||
* @return {[type]} array of items
|
|
||||||
*/
|
|
||||||
getItems(hostids, appids, itemtype) {
|
|
||||||
var params = {
|
|
||||||
output: [
|
|
||||||
'name', 'key_',
|
|
||||||
'value_type',
|
|
||||||
'hostid',
|
|
||||||
'status',
|
|
||||||
'state'
|
|
||||||
],
|
|
||||||
sortfield: 'name',
|
|
||||||
webitems: true,
|
|
||||||
filter: {},
|
|
||||||
selectHosts: ['hostid', 'name']
|
|
||||||
};
|
|
||||||
if (hostids) {
|
|
||||||
params.hostids = hostids;
|
|
||||||
}
|
|
||||||
if (appids) {
|
|
||||||
params.applicationids = appids;
|
|
||||||
}
|
|
||||||
if (itemtype === 'num') {
|
|
||||||
// Return only numeric metrics
|
|
||||||
params.filter.value_type = [0, 3];
|
|
||||||
}
|
|
||||||
if (itemtype === 'text') {
|
|
||||||
// Return only text metrics
|
|
||||||
params.filter.value_type = [1, 2, 4];
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.request('item.get', params)
|
|
||||||
.then(utils.expandItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
getItemsByIDs(itemids) {
|
|
||||||
var params = {
|
|
||||||
itemids: itemids,
|
|
||||||
output: [
|
|
||||||
'name', 'key_',
|
|
||||||
'value_type',
|
|
||||||
'hostid',
|
|
||||||
'status',
|
|
||||||
'state'
|
|
||||||
],
|
|
||||||
webitems: true,
|
|
||||||
selectHosts: ['hostid', 'name']
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('item.get', params)
|
|
||||||
.then(utils.expandItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
getMacros(hostids) {
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
hostids: hostids
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('usermacro.get', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
getGlobalMacros() {
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
globalmacro: true
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('usermacro.get', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
getLastValue(itemid) {
|
|
||||||
var params = {
|
|
||||||
output: ['lastvalue'],
|
|
||||||
itemids: itemid
|
|
||||||
};
|
|
||||||
return this.request('item.get', params)
|
|
||||||
.then(items => items.length ? items[0].lastvalue : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform history query from Zabbix API
|
|
||||||
*
|
|
||||||
* @param {Array} items Array of Zabbix item objects
|
|
||||||
* @param {Number} timeFrom Time in seconds
|
|
||||||
* @param {Number} timeTill Time in seconds
|
|
||||||
* @return {Array} Array of Zabbix history objects
|
|
||||||
*/
|
|
||||||
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');
|
|
||||||
let params = {
|
|
||||||
output: 'extend',
|
|
||||||
history: value_type,
|
|
||||||
itemids: itemids,
|
|
||||||
sortfield: 'clock',
|
|
||||||
sortorder: 'ASC',
|
|
||||||
time_from: timeFrom
|
|
||||||
};
|
|
||||||
|
|
||||||
// Relative queries (e.g. last hour) don't include an end time
|
|
||||||
if (timeTill) {
|
|
||||||
params.time_till = timeTill;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.request('history.get', params);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises).then(_.flatten);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform trends query from Zabbix API
|
|
||||||
* Use trends api extension from ZBXNEXT-1193 patch.
|
|
||||||
*
|
|
||||||
* @param {Array} items Array of Zabbix item objects
|
|
||||||
* @param {Number} time_from Time in seconds
|
|
||||||
* @param {Number} time_till Time in seconds
|
|
||||||
* @return {Array} Array of Zabbix trend objects
|
|
||||||
*/
|
|
||||||
getTrend_ZBXNEXT1193(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');
|
|
||||||
let params = {
|
|
||||||
output: 'extend',
|
|
||||||
trend: value_type,
|
|
||||||
itemids: itemids,
|
|
||||||
sortfield: 'clock',
|
|
||||||
sortorder: 'ASC',
|
|
||||||
time_from: timeFrom
|
|
||||||
};
|
|
||||||
|
|
||||||
// Relative queries (e.g. last hour) don't include an end time
|
|
||||||
if (timeTill) {
|
|
||||||
params.time_till = timeTill;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.request('trend.get', params);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises).then(_.flatten);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTrend_30(items, time_from, time_till, value_type) {
|
|
||||||
var self = this;
|
|
||||||
var itemids = _.map(items, 'itemid');
|
|
||||||
|
|
||||||
var params = {
|
|
||||||
output: ["itemid",
|
|
||||||
"clock",
|
|
||||||
value_type
|
|
||||||
],
|
|
||||||
itemids: itemids,
|
|
||||||
time_from: time_from
|
|
||||||
};
|
|
||||||
|
|
||||||
// Relative queries (e.g. last hour) don't include an end time
|
|
||||||
if (time_till) {
|
|
||||||
params.time_till = time_till;
|
|
||||||
}
|
|
||||||
|
|
||||||
return self.request('trend.get', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
getITService(serviceids) {
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
serviceids: serviceids
|
|
||||||
};
|
|
||||||
return this.request('service.get', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
getSLA(serviceids, timeRange) {
|
|
||||||
let [timeFrom, timeTo] = timeRange;
|
|
||||||
var params = {
|
|
||||||
serviceids: serviceids,
|
|
||||||
intervals: [{
|
|
||||||
from: timeFrom,
|
|
||||||
to: timeTo
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
return this.request('service.getsla', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTriggers(groupids, hostids, applicationids, options) {
|
|
||||||
let {showTriggers, maintenance, timeFrom, timeTo} = options;
|
|
||||||
|
|
||||||
let params = {
|
|
||||||
output: 'extend',
|
|
||||||
groupids: groupids,
|
|
||||||
hostids: hostids,
|
|
||||||
applicationids: applicationids,
|
|
||||||
expandDescription: true,
|
|
||||||
expandData: true,
|
|
||||||
expandComment: true,
|
|
||||||
monitored: true,
|
|
||||||
skipDependent: true,
|
|
||||||
//only_true: true,
|
|
||||||
filter: {
|
|
||||||
value: 1
|
|
||||||
},
|
|
||||||
selectGroups: ['name'],
|
|
||||||
selectHosts: ['name', 'host', 'maintenance_status'],
|
|
||||||
selectItems: ['name', 'key_', 'lastvalue'],
|
|
||||||
selectLastEvent: 'extend',
|
|
||||||
selectTags: 'extend'
|
|
||||||
};
|
|
||||||
|
|
||||||
if (showTriggers) {
|
|
||||||
params.filter.value = showTriggers;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maintenance) {
|
|
||||||
params.maintenance = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeFrom || timeTo) {
|
|
||||||
params.lastChangeSince = timeFrom;
|
|
||||||
params.lastChangeTill = timeTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.request('trigger.get', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
getEvents(objectids, timeFrom, timeTo, showEvents) {
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
time_from: timeFrom,
|
|
||||||
time_till: timeTo,
|
|
||||||
objectids: objectids,
|
|
||||||
select_acknowledges: 'extend',
|
|
||||||
selectHosts: 'extend',
|
|
||||||
value: showEvents
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('event.get', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
getAcknowledges(eventids) {
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
eventids: eventids,
|
|
||||||
preservekeys: true,
|
|
||||||
select_acknowledges: 'extend',
|
|
||||||
sortfield: 'clock',
|
|
||||||
sortorder: 'DESC'
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request('event.get', params)
|
|
||||||
.then(events => {
|
|
||||||
return _.filter(events, (event) => event.acknowledges.length);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getAlerts(itemids, timeFrom, timeTo) {
|
|
||||||
var params = {
|
|
||||||
output: 'extend',
|
|
||||||
itemids: itemids,
|
|
||||||
expandDescription: true,
|
|
||||||
expandData: true,
|
|
||||||
expandComment: true,
|
|
||||||
monitored: true,
|
|
||||||
skipDependent: true,
|
|
||||||
//only_true: true,
|
|
||||||
// filter: {
|
|
||||||
// value: 1
|
|
||||||
// },
|
|
||||||
selectLastEvent: 'extend'
|
|
||||||
};
|
|
||||||
|
|
||||||
if (timeFrom || timeTo) {
|
|
||||||
params.lastChangeSince = timeFrom;
|
|
||||||
params.lastChangeTill = timeTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.request('trigger.get', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
getHostAlerts(hostids, applicationids, options) {
|
|
||||||
let {minSeverity, acknowledged, count, timeFrom, timeTo} = options;
|
|
||||||
let params = {
|
|
||||||
output: 'extend',
|
|
||||||
hostids: hostids,
|
|
||||||
min_severity: minSeverity,
|
|
||||||
filter: { value: 1 },
|
|
||||||
expandDescription: true,
|
|
||||||
expandData: true,
|
|
||||||
expandComment: true,
|
|
||||||
monitored: true,
|
|
||||||
skipDependent: true,
|
|
||||||
selectLastEvent: 'extend',
|
|
||||||
selectGroups: 'extend',
|
|
||||||
selectHosts: ['host', 'name']
|
|
||||||
};
|
|
||||||
|
|
||||||
if (count && acknowledged !== 0 && acknowledged !== 1) {
|
|
||||||
params.countOutput = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (applicationids && applicationids.length) {
|
|
||||||
params.applicationids = applicationids;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeFrom || timeTo) {
|
|
||||||
params.lastChangeSince = timeFrom;
|
|
||||||
params.lastChangeTill = timeTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.request('trigger.get', params)
|
|
||||||
.then((triggers) => {
|
|
||||||
if (!count || acknowledged === 0 || acknowledged === 1) {
|
|
||||||
triggers = filterTriggersByAcknowledge(triggers, acknowledged);
|
|
||||||
if (count) {
|
|
||||||
triggers = triggers.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return triggers;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ZabbixAPI;
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterTriggersByAcknowledge(triggers, acknowledged) {
|
|
||||||
if (acknowledged === 0) {
|
|
||||||
return _.filter(triggers, (trigger) => trigger.lastEvent.acknowledged === "0");
|
|
||||||
} else if (acknowledged === 1) {
|
|
||||||
return _.filter(triggers, (trigger) => trigger.lastEvent.acknowledged === "1");
|
|
||||||
} else {
|
|
||||||
return triggers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isNotAuthorized(message) {
|
|
||||||
return (
|
|
||||||
message === "Session terminated, re-login, please." ||
|
|
||||||
message === "Not authorised." ||
|
|
||||||
message === "Not authorized."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
angular
|
|
||||||
.module('grafana.services')
|
|
||||||
.factory('zabbixAPIService', ZabbixAPIServiceFactory);
|
|
||||||
@@ -1,245 +0,0 @@
|
|||||||
import angular from 'angular';
|
|
||||||
import _ from 'lodash';
|
|
||||||
|
|
||||||
// Use factory() instead service() for multiple datasources support.
|
|
||||||
// Each datasource instance must initialize its own cache.
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
function ZabbixCachingProxyFactory() {
|
|
||||||
|
|
||||||
class ZabbixCachingProxy {
|
|
||||||
constructor(zabbixAPI, zabbixDBConnector, cacheOptions) {
|
|
||||||
this.zabbixAPI = zabbixAPI;
|
|
||||||
this.dbConnector = zabbixDBConnector;
|
|
||||||
this.cacheEnabled = cacheOptions.enabled;
|
|
||||||
this.ttl = cacheOptions.ttl || 600000; // 10 minutes by default
|
|
||||||
|
|
||||||
// Internal objects for data storing
|
|
||||||
this.cache = {
|
|
||||||
groups: {},
|
|
||||||
hosts: {},
|
|
||||||
applications: {},
|
|
||||||
items: {},
|
|
||||||
history: {},
|
|
||||||
trends: {},
|
|
||||||
macros: {},
|
|
||||||
globalMacros: {},
|
|
||||||
itServices: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.historyPromises = {};
|
|
||||||
|
|
||||||
// Don't run duplicated history requests
|
|
||||||
this.getHistory = callAPIRequestOnce(_.bind(this.zabbixAPI.getHistory, this.zabbixAPI),
|
|
||||||
this.historyPromises, getHistoryRequestHash);
|
|
||||||
|
|
||||||
if (this.dbConnector) {
|
|
||||||
this.getHistoryDB = callAPIRequestOnce(_.bind(this.dbConnector.getHistory, this.dbConnector),
|
|
||||||
this.historyPromises, getDBQueryHash);
|
|
||||||
this.getTrendsDB = callAPIRequestOnce(_.bind(this.dbConnector.getTrends, this.dbConnector),
|
|
||||||
this.historyPromises, getDBQueryHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't run duplicated requests
|
|
||||||
this.groupPromises = {};
|
|
||||||
this.getGroupsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getGroups, this.zabbixAPI),
|
|
||||||
this.groupPromises, getRequestHash);
|
|
||||||
|
|
||||||
this.hostPromises = {};
|
|
||||||
this.getHostsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getHosts, this.zabbixAPI),
|
|
||||||
this.hostPromises, getRequestHash);
|
|
||||||
|
|
||||||
this.appPromises = {};
|
|
||||||
this.getAppsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getApps, this.zabbixAPI),
|
|
||||||
this.appPromises, getRequestHash);
|
|
||||||
|
|
||||||
this.itemPromises = {};
|
|
||||||
this.getItemsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getItems, this.zabbixAPI),
|
|
||||||
this.itemPromises, getRequestHash);
|
|
||||||
|
|
||||||
this.itemByIdPromises = {};
|
|
||||||
this.getItemsByIdOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getItemsByIDs, this.zabbixAPI),
|
|
||||||
this.itemPromises, getRequestHash);
|
|
||||||
|
|
||||||
this.itServicesPromises = {};
|
|
||||||
this.getITServicesOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getITService, this.zabbixAPI),
|
|
||||||
this.itServicesPromises, getRequestHash);
|
|
||||||
|
|
||||||
this.macroPromises = {};
|
|
||||||
this.getMacrosOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getMacros, this.zabbixAPI),
|
|
||||||
this.macroPromises, getRequestHash);
|
|
||||||
|
|
||||||
this.globalMacroPromises = {};
|
|
||||||
this.getGlobalMacrosOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getGlobalMacros, this.zabbixAPI),
|
|
||||||
this.globalMacroPromises, getRequestHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
isExpired(cacheObject) {
|
|
||||||
if (cacheObject) {
|
|
||||||
let object_age = Date.now() - cacheObject.timestamp;
|
|
||||||
return !(cacheObject.timestamp && object_age < this.ttl);
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check that result is present in cache and up to date
|
|
||||||
* or send request to API.
|
|
||||||
*/
|
|
||||||
proxyRequest(request, params, cacheObject) {
|
|
||||||
let hash = getRequestHash(params);
|
|
||||||
if (this.cacheEnabled && !this.isExpired(cacheObject[hash])) {
|
|
||||||
return Promise.resolve(cacheObject[hash].value);
|
|
||||||
} else {
|
|
||||||
return request(...params)
|
|
||||||
.then(result => {
|
|
||||||
cacheObject[hash] = {
|
|
||||||
value: result,
|
|
||||||
timestamp: Date.now()
|
|
||||||
};
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getGroups() {
|
|
||||||
return this.proxyRequest(this.getGroupsOnce, [], this.cache.groups);
|
|
||||||
}
|
|
||||||
|
|
||||||
getHosts(groupids) {
|
|
||||||
return this.proxyRequest(this.getHostsOnce, [groupids], this.cache.hosts);
|
|
||||||
}
|
|
||||||
|
|
||||||
getApps(hostids) {
|
|
||||||
return this.proxyRequest(this.getAppsOnce, [hostids], this.cache.applications);
|
|
||||||
}
|
|
||||||
|
|
||||||
getItems(hostids, appids, itemtype) {
|
|
||||||
let params = [hostids, appids, itemtype];
|
|
||||||
return this.proxyRequest(this.getItemsOnce, params, this.cache.items);
|
|
||||||
}
|
|
||||||
|
|
||||||
getItemsByIDs(itemids) {
|
|
||||||
let params = [itemids];
|
|
||||||
return this.proxyRequest(this.getItemsByIdOnce, params, this.cache.items);
|
|
||||||
}
|
|
||||||
|
|
||||||
getITServices() {
|
|
||||||
return this.proxyRequest(this.getITServicesOnce, [], this.cache.itServices);
|
|
||||||
}
|
|
||||||
|
|
||||||
getMacros(hostids) {
|
|
||||||
// Merge global macros and host macros
|
|
||||||
let promises = [
|
|
||||||
this.proxyRequest(this.getMacrosOnce, [hostids], this.cache.macros),
|
|
||||||
this.proxyRequest(this.getGlobalMacrosOnce, [], this.cache.globalMacros)
|
|
||||||
];
|
|
||||||
|
|
||||||
return Promise.all(promises).then(_.flatten);
|
|
||||||
}
|
|
||||||
|
|
||||||
getHistoryFromCache(items, time_from, time_till) {
|
|
||||||
var historyStorage = this.cache.history;
|
|
||||||
var full_history;
|
|
||||||
var expired = _.filter(_.keyBy(items, 'itemid'), (item, itemid) => {
|
|
||||||
return !historyStorage[itemid];
|
|
||||||
});
|
|
||||||
if (expired.length) {
|
|
||||||
return this.zabbixAPI.getHistory(expired, time_from, time_till).then(function(history) {
|
|
||||||
var grouped_history = _.groupBy(history, 'itemid');
|
|
||||||
_.forEach(expired, item => {
|
|
||||||
var itemid = item.itemid;
|
|
||||||
historyStorage[itemid] = item;
|
|
||||||
historyStorage[itemid].time_from = time_from;
|
|
||||||
historyStorage[itemid].time_till = time_till;
|
|
||||||
historyStorage[itemid].history = grouped_history[itemid];
|
|
||||||
});
|
|
||||||
full_history = _.map(items, item => {
|
|
||||||
return historyStorage[item.itemid].history;
|
|
||||||
});
|
|
||||||
return _.flatten(full_history, true);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
full_history = _.map(items, function(item) {
|
|
||||||
return historyStorage[item.itemid].history;
|
|
||||||
});
|
|
||||||
return Promise.resolve(_.flatten(full_history, true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getHistoryFromAPI(items, time_from, time_till) {
|
|
||||||
return this.zabbixAPI.getHistory(items, time_from, time_till);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ZabbixCachingProxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
angular
|
|
||||||
.module('grafana.services')
|
|
||||||
.factory('ZabbixCachingProxy', ZabbixCachingProxyFactory);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap zabbix API request to prevent multiple calls
|
|
||||||
* with same params when waiting for result.
|
|
||||||
*/
|
|
||||||
function callAPIRequestOnce(func, promiseKeeper, argsHashFunc) {
|
|
||||||
return function() {
|
|
||||||
var hash = argsHashFunc(arguments);
|
|
||||||
if (!promiseKeeper[hash]) {
|
|
||||||
promiseKeeper[hash] = Promise.resolve(
|
|
||||||
func.apply(this, arguments)
|
|
||||||
.then(result => {
|
|
||||||
promiseKeeper[hash] = null;
|
|
||||||
return result;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return promiseKeeper[hash];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRequestHash(args) {
|
|
||||||
var requestStamp = _.map(args, arg => {
|
|
||||||
if (arg === undefined) {
|
|
||||||
return 'undefined';
|
|
||||||
} else {
|
|
||||||
if (_.isArray(arg)) {
|
|
||||||
return arg.sort().toString();
|
|
||||||
} else {
|
|
||||||
return arg.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).join();
|
|
||||||
return requestStamp.getHash();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getHistoryRequestHash(args) {
|
|
||||||
let itemids = _.map(args[0], 'itemid');
|
|
||||||
let stamp = itemids.join() + args[1] + args[2];
|
|
||||||
return stamp.getHash();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDBQueryHash(args) {
|
|
||||||
let itemids = _.map(args[0], 'itemid');
|
|
||||||
let consolidateBy = args[3].consolidateBy;
|
|
||||||
let intervalMs = args[3].intervalMs;
|
|
||||||
let stamp = itemids.join() + args[1] + args[2] + consolidateBy + intervalMs;
|
|
||||||
return stamp.getHash();
|
|
||||||
}
|
|
||||||
|
|
||||||
String.prototype.getHash = function() {
|
|
||||||
var hash = 0, i, chr, len;
|
|
||||||
if (this.length !== 0) {
|
|
||||||
for (i = 0, len = this.length; i < len; i++) {
|
|
||||||
chr = this.charCodeAt(i);
|
|
||||||
hash = ((hash << 5) - hash) + chr;
|
|
||||||
hash |= 0; // Convert to 32bit integer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fix for backward compatibility with lodash 2.4
|
|
||||||
if (!_.keyBy) {_.keyBy = _.indexBy;}
|
|
||||||
@@ -1,275 +0,0 @@
|
|||||||
import angular from 'angular';
|
|
||||||
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'
|
|
||||||
};
|
|
||||||
|
|
||||||
const TREND_TO_TABLE_MAP = {
|
|
||||||
'0': 'trends',
|
|
||||||
'3': 'trends_uint'
|
|
||||||
};
|
|
||||||
|
|
||||||
const consolidateByFunc = {
|
|
||||||
'avg': 'AVG',
|
|
||||||
'min': 'MIN',
|
|
||||||
'max': 'MAX',
|
|
||||||
'sum': 'SUM',
|
|
||||||
'count': 'COUNT'
|
|
||||||
};
|
|
||||||
|
|
||||||
const consolidateByTrendColumns = {
|
|
||||||
'avg': 'value_avg',
|
|
||||||
'min': 'value_min',
|
|
||||||
'max': 'value_max'
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {
|
|
||||||
|
|
||||||
class ZabbixDBConnector {
|
|
||||||
|
|
||||||
constructor(sqlDataSourceId, options = {}) {
|
|
||||||
let {limit} = options;
|
|
||||||
|
|
||||||
this.sqlDataSourceId = sqlDataSourceId;
|
|
||||||
this.limit = limit || DEFAULT_QUERY_LIMIT;
|
|
||||||
|
|
||||||
this.loadSQLDataSource(sqlDataSourceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to load DS with given id to check it's exist.
|
|
||||||
* @param {*} datasourceId ID of SQL data source
|
|
||||||
*/
|
|
||||||
loadSQLDataSource(datasourceId) {
|
|
||||||
let ds = _.find(datasourceSrv.getAll(), {'id': datasourceId});
|
|
||||||
if (ds) {
|
|
||||||
return datasourceSrv.loadDatasource(ds.name)
|
|
||||||
.then(ds => {
|
|
||||||
this.sqlDataSourceType = ds.meta.id;
|
|
||||||
return ds;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Promise.reject(`SQL Data Source with ID ${datasourceId} not found`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to invoke test query for one of Zabbix database tables.
|
|
||||||
*/
|
|
||||||
testSQLDataSource() {
|
|
||||||
let testQuery = TEST_MYSQL_QUERY;
|
|
||||||
if (this.sqlDataSourceType === 'postgres') {
|
|
||||||
testQuery = TEST_POSTGRES_QUERY;
|
|
||||||
}
|
|
||||||
return this.invokeSQLQuery(testQuery);
|
|
||||||
}
|
|
||||||
|
|
||||||
getHistory(items, timeFrom, timeTill, options) {
|
|
||||||
let {intervalMs, consolidateBy} = options;
|
|
||||||
let intervalSec = Math.ceil(intervalMs / 1000);
|
|
||||||
|
|
||||||
consolidateBy = consolidateBy || 'avg';
|
|
||||||
let aggFunction = consolidateByFunc[consolidateBy];
|
|
||||||
|
|
||||||
// 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 dialect = this.sqlDataSourceType;
|
|
||||||
let query = buildSQLHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, dialect);
|
|
||||||
|
|
||||||
query = compactSQLQuery(query);
|
|
||||||
return this.invokeSQLQuery(query);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises).then(results => {
|
|
||||||
return _.flatten(results);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getTrends(items, timeFrom, timeTill, options) {
|
|
||||||
let {intervalMs, consolidateBy} = options;
|
|
||||||
let intervalSec = Math.ceil(intervalMs / 1000);
|
|
||||||
|
|
||||||
consolidateBy = consolidateBy || 'avg';
|
|
||||||
let aggFunction = consolidateByFunc[consolidateBy];
|
|
||||||
|
|
||||||
// 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 = TREND_TO_TABLE_MAP[value_type];
|
|
||||||
let valueColumn = _.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg';
|
|
||||||
valueColumn = consolidateByTrendColumns[valueColumn];
|
|
||||||
|
|
||||||
let dialect = this.sqlDataSourceType;
|
|
||||||
let query = buildSQLTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn, dialect);
|
|
||||||
|
|
||||||
query = compactSQLQuery(query);
|
|
||||||
return this.invokeSQLQuery(query);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises).then(results => {
|
|
||||||
return _.flatten(results);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleGrafanaTSResponse(history, items, addHostName = true) {
|
|
||||||
return convertGrafanaTSResponse(history, items, addHostName);
|
|
||||||
}
|
|
||||||
|
|
||||||
invokeSQLQuery(query) {
|
|
||||||
let queryDef = {
|
|
||||||
refId: 'A',
|
|
||||||
format: 'time_series',
|
|
||||||
datasourceId: this.sqlDataSourceId,
|
|
||||||
rawSql: query,
|
|
||||||
maxDataPoints: this.limit
|
|
||||||
};
|
|
||||||
|
|
||||||
return backendSrv.datasourceRequest({
|
|
||||||
url: '/api/tsdb/query',
|
|
||||||
method: 'POST',
|
|
||||||
data: {
|
|
||||||
queries: [queryDef],
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
let results = response.data.results;
|
|
||||||
if (results['A']) {
|
|
||||||
return results['A'].series;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ZabbixDBConnector;
|
|
||||||
}
|
|
||||||
|
|
||||||
angular
|
|
||||||
.module('grafana.services')
|
|
||||||
.factory('ZabbixDBConnector', ZabbixDBConnectorFactory);
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function convertGrafanaTSResponse(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;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
// zabbixCachingProxy deduplicates requests and returns one time series for equal queries.
|
|
||||||
// Clone is needed to prevent changing of series object shared between all targets.
|
|
||||||
let datapoints = _.cloneDeep(series.points);
|
|
||||||
return {
|
|
||||||
target: alias,
|
|
||||||
datapoints: datapoints
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return _.sortBy(grafanaSeries, 'target');
|
|
||||||
}
|
|
||||||
|
|
||||||
function compactSQLQuery(query) {
|
|
||||||
return query.replace(/\s+/g, ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildSQLHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, dialect = 'mysql') {
|
|
||||||
if (dialect === 'postgres') {
|
|
||||||
return buildPostgresHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction);
|
|
||||||
} else {
|
|
||||||
return buildMysqlHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildSQLTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn, dialect = 'mysql') {
|
|
||||||
if (dialect === 'postgres') {
|
|
||||||
return buildPostgresTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn);
|
|
||||||
} else {
|
|
||||||
return buildMysqlTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// MySQL //
|
|
||||||
///////////
|
|
||||||
|
|
||||||
function buildMysqlHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
|
||||||
let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`;
|
|
||||||
let query = `
|
|
||||||
SELECT CAST(itemid AS CHAR) 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_expression}, metric
|
|
||||||
ORDER BY time_sec ASC
|
|
||||||
`;
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildMysqlTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
|
||||||
let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`;
|
|
||||||
let query = `
|
|
||||||
SELECT CAST(itemid AS CHAR) 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_expression}, metric
|
|
||||||
ORDER BY time_sec ASC
|
|
||||||
`;
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TEST_MYSQL_QUERY = `SELECT CAST(itemid AS CHAR) AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1`;
|
|
||||||
|
|
||||||
////////////////
|
|
||||||
// PostgreSQL //
|
|
||||||
////////////////
|
|
||||||
|
|
||||||
const itemid_format = 'FM99999999999999999999';
|
|
||||||
|
|
||||||
function buildPostgresHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
|
||||||
let time_expression = `clock / ${intervalSec} * ${intervalSec}`;
|
|
||||||
let query = `
|
|
||||||
SELECT to_char(itemid, '${itemid_format}') AS metric, ${time_expression} AS time, ${aggFunction}(value) AS value
|
|
||||||
FROM ${table}
|
|
||||||
WHERE itemid IN (${itemids})
|
|
||||||
AND clock > ${timeFrom} AND clock < ${timeTill}
|
|
||||||
GROUP BY 1, 2
|
|
||||||
ORDER BY time ASC
|
|
||||||
`;
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildPostgresTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
|
||||||
let time_expression = `clock / ${intervalSec} * ${intervalSec}`;
|
|
||||||
let query = `
|
|
||||||
SELECT to_char(itemid, '${itemid_format}') AS metric, ${time_expression} AS time, ${aggFunction}(${valueColumn}) AS value
|
|
||||||
FROM ${table}
|
|
||||||
WHERE itemid IN (${itemids})
|
|
||||||
AND clock > ${timeFrom} AND clock < ${timeTill}
|
|
||||||
GROUP BY 1, 2
|
|
||||||
ORDER BY time ASC
|
|
||||||
`;
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TEST_POSTGRES_QUERY = `
|
|
||||||
SELECT to_char(itemid, '${itemid_format}') AS metric, clock AS time, value_avg AS value
|
|
||||||
FROM trends_uint LIMIT 1
|
|
||||||
`;
|
|
||||||
@@ -4042,10 +4042,6 @@ q@^1.1.2:
|
|||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||||
|
|
||||||
q@~1.4.1:
|
|
||||||
version "1.4.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e"
|
|
||||||
|
|
||||||
qs@~0.5.2:
|
qs@~0.5.2:
|
||||||
version "0.5.6"
|
version "0.5.6"
|
||||||
resolved "https://registry.yarnpkg.com/qs/-/qs-0.5.6.tgz#31b1ad058567651c526921506b9a8793911a0384"
|
resolved "https://registry.yarnpkg.com/qs/-/qs-0.5.6.tgz#31b1ad058567651c526921506b9a8793911a0384"
|
||||||
|
|||||||
Reference in New Issue
Block a user