refactor: move zabbix modules

This commit is contained in:
Alexander Zobnin
2018-03-17 15:49:34 +03:00
parent 498e9f843c
commit 24e10e885d
43 changed files with 3437 additions and 3266 deletions

View File

@@ -85,7 +85,7 @@ module.exports = function(grunt) {
cwd: 'src',
expand: true,
src: [
'datasource-zabbix/*.js',
'datasource-zabbix/**/*.js',
'panel-triggers/*.js',
'components/*.js',
'vendor/*.js',

View File

@@ -1,70 +1,77 @@
import _ from 'lodash';
import ts from '../timeseries';
'use strict';
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 = [
[[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]]
];
var _, ts, datapoints, series_set, growing_series;
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 = [
{
name: 'groupBy',
tests: {
'groupBy(AVERAGE)': () => {
ts.groupBy(datapoints, '5m', ts.AVERAGE);
},
'groupBy(MAX)': () => {
ts.groupBy(datapoints, '5m', ts.COUNT);
}
module.exports = [{
name: 'groupBy',
tests: {
'groupBy(AVERAGE)': function groupByAVERAGE() {
ts.groupBy(datapoints, '5m', ts.AVERAGE);
},
'groupBy(MAX)': function groupByMAX() {
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',
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);
}
}
}
];
};
});
//# sourceMappingURL=timeseries_bench.js.map

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +1,9 @@
'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";
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) {
if (!(instance instanceof Constructor)) {
@@ -140,8 +140,10 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
dataProcessor = _dataProcessor.default;
}, function (_responseHandler) {
responseHandler = _responseHandler.default;
}, function (_zabbixJs) {}, function (_zabbixAlertingServiceJs) {}, function (_zabbixAPICoreServiceJs) {
ZabbixAPIError = _zabbixAPICoreServiceJs.ZabbixAPIError;
}, function (_zabbixAlertingServiceJs) {}, function (_zabbixZabbix) {
Zabbix = _zabbixZabbix.Zabbix;
}, function (_zabbixConnectorsZabbix_apiZabbixAPICore) {
ZabbixAPIError = _zabbixConnectorsZabbix_apiZabbixAPICore.ZabbixAPIError;
}],
execute: function () {
_slicedToArray = function () {
@@ -203,7 +205,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
_export('ZabbixAPIDatasource', ZabbixAPIDatasource = function () {
/** @ngInject */
function ZabbixAPIDatasource(instanceSettings, templateSrv, alertSrv, dashboardSrv, zabbixAlertingSrv, Zabbix) {
function ZabbixAPIDatasource(instanceSettings, templateSrv, alertSrv, dashboardSrv, backendSrv, datasourceSrv, zabbixAlertingSrv) {
_classCallCheck(this, ZabbixAPIDatasource);
this.templateSrv = templateSrv;
@@ -255,7 +257,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
sqlDatasourceId: this.sqlDatasourceId
};
this.zabbix = new Zabbix(this.url, zabbixOptions);
this.zabbix = new Zabbix(this.url, zabbixOptions, backendSrv, datasourceSrv);
}
////////////////////////

File diff suppressed because one or more lines are too long

View File

@@ -1,51 +1,56 @@
import _ from 'lodash';
import dataProcessor from '../dataProcessor';
'use strict';
describe('dataProcessor', () => {
let ctx = {};
System.register(['lodash', '../dataProcessor'], function (_export, _context) {
"use strict";
beforeEach(() => {
ctx.datapoints = [
[[10, 1500000000000], [2, 1500000001000], [7, 1500000002000], [1, 1500000003000]],
[[9, 1500000000000], [3, 1500000001000], [4, 1500000002000], [8, 1500000003000]],
];
});
var _, dataProcessor;
describe('When apply groupBy() functions', () => {
it('should return series average', () => {
let aggregateBy = dataProcessor.metricFunctions['groupBy'];
const avg2s = _.map(ctx.datapoints, (dp) => aggregateBy('2s', 'avg', dp));
expect(avg2s).toEqual([
[[6, 1500000000000], [4, 1500000002000]],
[[6, 1500000000000], [6, 1500000002000]],
]);
return {
setters: [function (_lodash) {
_ = _lodash.default;
}, function (_dataProcessor) {
dataProcessor = _dataProcessor.default;
}],
execute: function () {
const avg10s = _.map(ctx.datapoints, (dp) => aggregateBy('10s', 'avg', dp));
expect(avg10s).toEqual([
[[5, 1500000000000]],
[[6, 1500000000000]],
]);
describe('dataProcessor', function () {
var ctx = {};
// not aligned
const dp = [[10, 1500000001000], [2, 1500000002000], [7, 1500000003000], [1, 1500000004000]];
expect(aggregateBy('2s', 'avg', dp)).toEqual([
[10, 1500000000000], [4.5, 1500000002000], [1, 1500000004000]
]);
});
});
beforeEach(function () {
ctx.datapoints = [[[10, 1500000000000], [2, 1500000001000], [7, 1500000002000], [1, 1500000003000]], [[9, 1500000000000], [3, 1500000001000], [4, 1500000002000], [8, 1500000003000]]];
});
describe('When apply aggregateBy() functions', () => {
it('should return series average', () => {
let aggregateBy = dataProcessor.metricFunctions['aggregateBy'];
const avg1s = aggregateBy('1s', 'avg', ctx.datapoints);
expect(avg1s).toEqual([
[9.5, 1500000000000], [2.5, 1500000001000], [5.5, 1500000002000], [4.5, 1500000003000]
]);
describe('When apply groupBy() functions', function () {
it('should return series average', function () {
var aggregateBy = dataProcessor.metricFunctions['groupBy'];
var avg2s = _.map(ctx.datapoints, function (dp) {
return aggregateBy('2s', 'avg', dp);
});
expect(avg2s).toEqual([[[6, 1500000000000], [4, 1500000002000]], [[6, 1500000000000], [6, 1500000002000]]]);
const avg10s = aggregateBy('10s', 'avg', ctx.datapoints);
expect(avg10s).toEqual([
[5.5, 1500000000000]
]);
});
});
var avg10s = _.map(ctx.datapoints, function (dp) {
return aggregateBy('10s', 'avg', dp);
});
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

View 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"]}

View File

@@ -1,429 +1,509 @@
import _ from 'lodash';
import Q, { Promise } from "q";
import {Datasource} from "../module";
import {zabbixTemplateFormat} from "../datasource";
"use strict";
describe('ZabbixDatasource', () => {
let ctx = {};
System.register(["lodash", "q", "../module", "../datasource"], function (_export, _context) {
"use strict";
beforeEach(() => {
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 = () => {};
var _, Q, Promise, Datasource, zabbixTemplateFormat;
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', () => {
beforeEach(() => {
ctx.ds.replaceTemplateVars = (str) => str;
ctx.ds.alertQuery = () => Q.when([]);
});
describe('ZabbixDatasource', function () {
var ctx = {};
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', (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
beforeEach(function () {
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 = 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 => {
expect(result.data.length).toBe(1);
/*
* Alphanumerics, spaces, dots, dashes and underscores
* 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];
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();
testReplacingVariable(target, template_var_value, expected_result, done);
});
/*
* Single-value variable
* $host = backend01
* $host => /^backend01|backend01$/
*/
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

File diff suppressed because one or more lines are too long

View File

@@ -1,34 +1,41 @@
// import _ from 'lodash';
import ts from '../timeseries';
'use strict';
describe('timeseries processing functions', () => {
System.register(['../timeseries'], function (_export, _context) {
"use strict";
describe('sumSeries()', () => {
it('should properly sum series', (done) => {
let series = [
[[0, 1], [1, 2], [1, 3]],
[[2, 1], [3, 2], [4, 3]]
];
var ts;
return {
setters: [function (_timeseries) {
ts = _timeseries.default;
}],
execute: function () {
let expected = [[2, 1], [4, 2], [5, 3]];
describe('timeseries processing functions', function () {
let result = ts.sumSeries(series);
expect(result).toEqual(expected);
done();
});
describe('sumSeries()', function () {
it('should properly sum series', function (done) {
var series = [[[0, 1], [1, 2], [1, 3]], [[2, 1], [3, 2], [4, 3]]];
it('should properly sum series with nulls', (done) => {
// issue #286
let series = [
[[1, 1], [1, 2], [1, 3]],
[[3, 2], [4, 3]]
];
var expected = [[2, 1], [4, 2], [5, 3]];
let expected = [[1, 1], [4, 2], [5, 3]];
var result = ts.sumSeries(series);
expect(result).toEqual(expected);
done();
});
let result = ts.sumSeries(series);
expect(result).toEqual(expected);
done();
});
});
it('should properly sum series with nulls', function (done) {
// issue #286
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

View 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"]}

View File

@@ -1,141 +1,136 @@
import _ from 'lodash';
import * as utils from '../utils';
'use strict';
describe('Utils', () => {
System.register(['lodash', '../utils'], function (_export, _context) {
"use strict";
describe('expandItemName()', () => {
var _, utils;
it('should properly expand unquoted params', (done) => {
let 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"
}
];
return {
setters: [function (_lodash) {
_ = _lodash.default;
}, function (_utils) {
utils = _utils;
}],
execute: function () {
_.each(test_cases, test_case => {
let expandedName = utils.expandItemName(test_case.name, test_case.key);
expect(expandedName).toBe(test_case.expected);
describe('Utils', function () {
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

File diff suppressed because one or more lines are too long

View File

@@ -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

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +1,9 @@
'use strict';
System.register(['angular', 'lodash'], function (_export, _context) {
System.register(['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;
var _, _createClass, DEFAULT_QUERY_LIMIT, HISTORY_TO_TABLE_MAP, TREND_TO_TABLE_MAP, consolidateByFunc, consolidateByTrendColumns, ZabbixDBConnector, TEST_MYSQL_QUERY, itemid_format, TEST_POSTGRES_QUERY;
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
@@ -11,156 +11,6 @@ System.register(['angular', 'lodash'], function (_export, _context) {
}
}
/** @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) {
@@ -239,9 +89,7 @@ System.register(['angular', 'lodash'], function (_export, _context) {
}
return {
setters: [function (_angular) {
angular = _angular.default;
}, function (_lodash) {
setters: [function (_lodash) {
_ = _lodash.default;
}],
execute: function () {
@@ -287,7 +135,154 @@ System.register(['angular', 'lodash'], function (_export, _context) {
'min': 'value_min',
'max': 'value_max'
};
angular.module('grafana.services').factory('ZabbixDBConnector', ZabbixDBConnectorFactory);TEST_MYSQL_QUERY = 'SELECT itemid AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1';
_export('ZabbixDBConnector', ZabbixDBConnector = function () {
function ZabbixDBConnector(sqlDataSourceId, options, backendSrv, datasourceSrv) {
_classCallCheck(this, ZabbixDBConnector);
this.backendSrv = backendSrv;
this.datasourceSrv = datasourceSrv;
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(this.datasourceSrv.getAll(), { 'id': datasourceId });
if (ds) {
return this.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 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 ZabbixDBConnector;
}());
_export('ZabbixDBConnector', ZabbixDBConnector);
TEST_MYSQL_QUERY = 'SELECT itemid 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';
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,106 @@
"use strict";
System.register([], function (_export, _context) {
"use strict";
var _createClass, ZabbixConnector;
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
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;
};
}();
ZabbixConnector = function () {
function ZabbixConnector() {
_classCallCheck(this, ZabbixConnector);
}
_createClass(ZabbixConnector, [{
key: "testDataSource",
value: function testDataSource() {}
}, {
key: "getHistory",
value: function getHistory() {}
}, {
key: "getTrends",
value: function getTrends() {}
}, {
key: "getGroups",
value: function getGroups() {}
}, {
key: "getHosts",
value: function getHosts() {}
}, {
key: "getApps",
value: function getApps() {}
}, {
key: "getItems",
value: function getItems() {}
}, {
key: "getItemsByIDs",
value: function getItemsByIDs() {}
}, {
key: "getMacros",
value: function getMacros() {}
}, {
key: "getGlobalMacros",
value: function getGlobalMacros() {}
}, {
key: "getLastValue",
value: function getLastValue() {}
}, {
key: "getTriggers",
value: function getTriggers() {}
}, {
key: "getEvents",
value: function getEvents() {}
}, {
key: "getAlerts",
value: function getAlerts() {}
}, {
key: "getHostAlerts",
value: function getHostAlerts() {}
}, {
key: "getAcknowledges",
value: function getAcknowledges() {}
}, {
key: "getITService",
value: function getITService() {}
}, {
key: "getSLA",
value: function getSLA() {}
}, {
key: "getVersion",
value: function getVersion() {}
}]);
return ZabbixConnector;
}();
_export("default", ZabbixConnector);
}
};
});
//# sourceMappingURL=zabbixConnector.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/datasource-zabbix/zabbix/connectors/zabbixConnector.js"],"names":["ZabbixConnector"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIqBA,qB;AAEnB,mCAAc;AAAA;AAAE;;;;2CAEC,CAAE;;;uCAEN,CAAE;;;sCAEH,CAAE;;;sCAEF,CAAE;;;qCAEH,CAAE;;;oCAEH,CAAE;;;qCAED,CAAE;;;0CAEG,CAAE;;;sCAEN,CAAE;;;4CAEI,CAAE;;;yCAEL,CAAE;;;wCAEH,CAAE;;;sCAEJ,CAAE;;;sCAEF,CAAE;;;0CAEE,CAAE;;;4CAEA,CAAE;;;yCAEL,CAAE;;;mCAER,CAAE;;;uCAEE,CAAE;;;;;;yBAxCIA,e","file":"zabbixConnector.js","sourcesContent":["/**\n * Base class for all Zabbix connectors\n */\n\nexport default class ZabbixConnector {\n\n constructor() {}\n\n testDataSource() {}\n\n getHistory() {}\n\n getTrends() {}\n\n getGroups() {}\n\n getHosts() {}\n\n getApps() {}\n\n getItems() {}\n\n getItemsByIDs() {}\n\n getMacros() {}\n\n getGlobalMacros() {}\n\n getLastValue() {}\n\n getTriggers() {}\n\n getEvents() {}\n\n getAlerts() {}\n\n getHostAlerts() {}\n\n getAcknowledges() {}\n\n getITService() {}\n\n getSLA() {}\n\n getVersion() {}\n}\n"]}

View File

@@ -0,0 +1,547 @@
'use strict';
System.register(['lodash', '../../../utils', './zabbixAPICore'], function (_export, _context) {
"use strict";
var _, utils, ZabbixAPICoreService, _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) {
ZabbixAPICoreService = _zabbixAPICore.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;
};
}();
_export('ZabbixAPIConnector', ZabbixAPIConnector = function () {
/** @ngInject */
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 ZabbixAPICoreService(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

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +1,9 @@
'use strict';
"use strict";
System.register(['angular'], function (_export, _context) {
System.register([], function (_export, _context) {
"use strict";
var angular, _createClass, ZabbixAPICoreService, ZabbixAPIError;
var _createClass, ZabbixAPICoreService, ZabbixAPIError;
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
@@ -12,9 +12,7 @@ System.register(['angular'], function (_export, _context) {
}
return {
setters: [function (_angular) {
angular = _angular.default;
}],
setters: [],
execute: function () {
_createClass = function () {
function defineProperties(target, props) {
@@ -34,7 +32,7 @@ System.register(['angular'], function (_export, _context) {
};
}();
ZabbixAPICoreService = function () {
_export("ZabbixAPICoreService", ZabbixAPICoreService = function () {
/** @ngInject */
function ZabbixAPICoreService(backendSrv) {
@@ -50,7 +48,7 @@ System.register(['angular'], function (_export, _context) {
_createClass(ZabbixAPICoreService, [{
key: 'request',
key: "request",
value: function request(api_url, method, params, options, auth) {
var requestData = {
jsonrpc: '2.0',
@@ -87,7 +85,7 @@ System.register(['angular'], function (_export, _context) {
return this.datasourceRequest(requestOptions);
}
}, {
key: 'datasourceRequest',
key: "datasourceRequest",
value: function datasourceRequest(requestOptions) {
return this.backendSrv.datasourceRequest(requestOptions).then(function (response) {
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) {
var params = {
user: username,
@@ -112,16 +110,18 @@ System.register(['angular'], function (_export, _context) {
return this.request(api_url, 'user.login', params, options, null);
}
}, {
key: 'getVersion',
key: "getVersion",
value: function getVersion(api_url, options) {
return this.request(api_url, 'apiinfo.version', [], options);
}
}]);
return ZabbixAPICoreService;
}();
}());
_export('ZabbixAPIError', ZabbixAPIError = function () {
_export("ZabbixAPICoreService", ZabbixAPICoreService);
_export("ZabbixAPIError", ZabbixAPIError = function () {
function ZabbixAPIError(error) {
_classCallCheck(this, ZabbixAPIError);
@@ -132,7 +132,7 @@ System.register(['angular'], function (_export, _context) {
}
_createClass(ZabbixAPIError, [{
key: 'toString',
key: "toString",
value: function toString() {
return this.name + " " + this.data;
}
@@ -141,10 +141,8 @@ System.register(['angular'], function (_export, _context) {
return ZabbixAPIError;
}());
_export('ZabbixAPIError', ZabbixAPIError);
angular.module('grafana.services').service('zabbixAPICoreService', ZabbixAPICoreService);
_export("ZabbixAPIError", ZabbixAPIError);
}
};
});
//# sourceMappingURL=zabbixAPICore.service.js.map
//# sourceMappingURL=zabbixAPICore.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/datasource-zabbix/zabbix/connectors/zabbix_api/zabbixAPICore.js"],"names":["ZabbixAPICoreService","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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sCAIaA,oB;;AAEX;AACA,sCAAYC,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 ZabbixAPICoreService {\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"]}

View File

@@ -0,0 +1,283 @@
'use strict';
System.register(['lodash'], function (_export, _context) {
"use strict";
var _, _createClass, ZabbixCachingProxy;
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");
}
}
/**
* 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 (_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;
};
}();
_export('ZabbixCachingProxy', 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;
}());
_export('ZabbixCachingProxy', ZabbixCachingProxy);
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.js.map

File diff suppressed because one or more lines are too long

385
dist/datasource-zabbix/zabbix/zabbix.js vendored Normal file
View File

@@ -0,0 +1,385 @@
'use strict';
System.register(['lodash', '../utils', './connectors/zabbix_api/zabbixAPIConnector', './connectors/sql/zabbixDBConnector', './proxy/zabbixCachingProxy'], function (_export, _context) {
"use strict";
var _, utils, ZabbixAPIConnector, ZabbixDBConnector, ZabbixCachingProxy, _slicedToArray, _createClass, 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");
}
}
// 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) {
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 (_connectorsZabbix_apiZabbixAPIConnector) {
ZabbixAPIConnector = _connectorsZabbix_apiZabbixAPIConnector.ZabbixAPIConnector;
}, function (_connectorsSqlZabbixDBConnector) {
ZabbixDBConnector = _connectorsSqlZabbixDBConnector.ZabbixDBConnector;
}, function (_proxyZabbixCachingProxy) {
ZabbixCachingProxy = _proxyZabbixCachingProxy.ZabbixCachingProxy;
}],
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('Zabbix', Zabbix = function () {
/** @ngInject */
function Zabbix(url, options, backendSrv, datasourceSrv) {
_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
this.zabbixAPI = new ZabbixAPIConnector(url, username, password, basicAuth, withCredentials, backendSrv);
if (enableDirectDBConnection) {
this.dbConnector = new ZabbixDBConnector(sqlDatasourceId, {}, backendSrv, datasourceSrv);
}
// 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;
}());
_export('Zabbix', Zabbix);
}
};
});
//# sourceMappingURL=zabbix.js.map

File diff suppressed because one or more lines are too long

View File

@@ -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

View File

@@ -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

File diff suppressed because one or more lines are too long

View File

@@ -6,14 +6,14 @@ import * as metricFunctions from './metricFunctions';
import * as c from './constants';
import dataProcessor from './dataProcessor';
import responseHandler from './responseHandler';
import './zabbix.js';
import './zabbixAlerting.service.js';
import {ZabbixAPIError} from './zabbixAPICore.service.js';
import { Zabbix } from './zabbix/zabbix';
import {ZabbixAPIError} from './zabbix/connectors/zabbix_api/zabbixAPICore';
class ZabbixAPIDatasource {
/** @ngInject */
constructor(instanceSettings, templateSrv, alertSrv, dashboardSrv, zabbixAlertingSrv, Zabbix) {
constructor(instanceSettings, templateSrv, alertSrv, dashboardSrv, backendSrv, datasourceSrv, zabbixAlertingSrv) {
this.templateSrv = templateSrv;
this.alertSrv = alertSrv;
this.dashboardSrv = dashboardSrv;
@@ -63,7 +63,7 @@ class ZabbixAPIDatasource {
sqlDatasourceId: this.sqlDatasourceId
};
this.zabbix = new Zabbix(this.url, zabbixOptions);
this.zabbix = new Zabbix(this.url, zabbixOptions, backendSrv, datasourceSrv);
}
////////////////////////

View File

@@ -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));
}

View File

@@ -1,4 +1,3 @@
import angular from 'angular';
import _ from 'lodash';
const DEFAULT_QUERY_LIMIT = 10000;
@@ -29,137 +28,129 @@ const consolidateByTrendColumns = {
'max': 'value_max'
};
/** @ngInject */
function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {
export class ZabbixDBConnector {
class ZabbixDBConnector {
constructor(sqlDataSourceId, options, backendSrv, datasourceSrv) {
this.backendSrv = backendSrv;
this.datasourceSrv = datasourceSrv;
constructor(sqlDataSourceId, options = {}) {
let {limit} = options;
let limit = options.limit;
this.sqlDataSourceId = sqlDataSourceId;
this.limit = limit || DEFAULT_QUERY_LIMIT;
this.sqlDataSourceId = sqlDataSourceId;
this.limit = limit || DEFAULT_QUERY_LIMIT;
this.loadSQLDataSource(sqlDataSourceId);
}
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;
}
/**
* Try to load DS with given id to check it's exist.
* @param {*} datasourceId ID of SQL data source
*/
loadSQLDataSource(datasourceId) {
let ds = _.find(this.datasourceSrv.getAll(), {'id': datasourceId});
if (ds) {
return this.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`);
}
}
return ZabbixDBConnector;
}
/**
* 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);
}
angular
.module('grafana.services')
.factory('ZabbixDBConnector', ZabbixDBConnectorFactory);
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 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;
}
});
}
}
///////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,46 @@
/**
* Base class for all Zabbix connectors
*/
export default class ZabbixConnector {
constructor() {}
testDataSource() {}
getHistory() {}
getTrends() {}
getGroups() {}
getHosts() {}
getApps() {}
getItems() {}
getItemsByIDs() {}
getMacros() {}
getGlobalMacros() {}
getLastValue() {}
getTriggers() {}
getEvents() {}
getAlerts() {}
getHostAlerts() {}
getAcknowledges() {}
getITService() {}
getSLA() {}
getVersion() {}
}

View File

@@ -0,0 +1,484 @@
import _ from 'lodash';
import * as utils from '../../../utils';
import { ZabbixAPICoreService } 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 {
/** @ngInject */
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 ZabbixAPICoreService(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."
);
}

View File

@@ -2,9 +2,7 @@
* General Zabbix API methods
*/
import angular from 'angular';
class ZabbixAPICoreService {
export class ZabbixAPICoreService {
/** @ngInject */
constructor(backendSrv) {
@@ -101,7 +99,3 @@ export class ZabbixAPIError {
return this.name + " " + this.data;
}
}
angular
.module('grafana.services')
.service('zabbixAPICoreService', ZabbixAPICoreService);

View File

@@ -0,0 +1,231 @@
import _ from 'lodash';
export 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);
}
}
/**
* 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;}

View File

@@ -0,0 +1,268 @@
// import angular from 'angular';
import _ from 'lodash';
import * as utils from '../utils';
import { ZabbixAPIConnector } from './connectors/zabbix_api/zabbixAPIConnector';
import { ZabbixDBConnector } from './connectors/sql/zabbixDBConnector';
import { ZabbixCachingProxy } from './proxy/zabbixCachingProxy';
export class Zabbix {
/** @ngInject */
constructor(url, options, backendSrv, datasourceSrv) {
let {
username, password, basicAuth, withCredentials, cacheTTL,
enableDirectDBConnection, sqlDatasourceId
} = options;
// Initialize Zabbix API
this.zabbixAPI = new ZabbixAPIConnector(url, username, password, basicAuth, withCredentials, backendSrv);
if (enableDirectDBConnection) {
this.dbConnector = new ZabbixDBConnector(sqlDatasourceId, {}, backendSrv, datasourceSrv);
}
// 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);
});
}
}
// 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));
}

View File

@@ -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);

View File

@@ -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;}