Merge branch 'master' into metric-functions

This commit is contained in:
Alexander Zobnin
2017-07-26 11:53:49 +03:00
74 changed files with 2340 additions and 531 deletions

View File

@@ -0,0 +1,74 @@
'use strict';
System.register(['lodash'], function (_export, _context) {
"use strict";
var _, _createClass, SUPPORTED_SQL_DS, defaultConfig, ZabbixDSConfigController;
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
return {
setters: [function (_lodash) {
_ = _lodash.default;
}],
execute: function () {
_createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
SUPPORTED_SQL_DS = ['mysql'];
defaultConfig = {
dbConnection: {
enable: false
}
};
_export('ZabbixDSConfigController', ZabbixDSConfigController = function () {
/** @ngInject */
function ZabbixDSConfigController($scope, $injector, datasourceSrv) {
_classCallCheck(this, ZabbixDSConfigController);
this.datasourceSrv = datasourceSrv;
_.defaults(this.current.jsonData, defaultConfig);
this.sqlDataSources = this.getSupportedSQLDataSources();
}
_createClass(ZabbixDSConfigController, [{
key: 'getSupportedSQLDataSources',
value: function getSupportedSQLDataSources() {
var datasources = this.datasourceSrv.getAll();
return _.filter(datasources, function (ds) {
return _.includes(SUPPORTED_SQL_DS, ds.type);
});
}
}]);
return ZabbixDSConfigController;
}());
_export('ZabbixDSConfigController', ZabbixDSConfigController);
ZabbixDSConfigController.templateUrl = 'datasource-zabbix/partials/config.html';
}
};
});
//# sourceMappingURL=config.controller.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../src/datasource-zabbix/config.controller.js"],"names":["_","SUPPORTED_SQL_DS","defaultConfig","dbConnection","enable","ZabbixDSConfigController","$scope","$injector","datasourceSrv","defaults","current","jsonData","sqlDataSources","getSupportedSQLDataSources","datasources","getAll","filter","includes","ds","type","templateUrl"],"mappings":";;;;;;;;;;;;;;;AAAOA,O;;;;;;;;;;;;;;;;;;;;;AAEDC,sB,GAAmB,CAAC,OAAD,C;AAEnBC,mB,GAAgB;AACpBC,sBAAc;AACZC,kBAAQ;AADI;AADM,O;;0CAMTC,wB;AACX;AACA,0CAAYC,MAAZ,EAAoBC,SAApB,EAA+BC,aAA/B,EAA8C;AAAA;;AAC5C,eAAKA,aAAL,GAAqBA,aAArB;;AAEAR,YAAES,QAAF,CAAW,KAAKC,OAAL,CAAaC,QAAxB,EAAkCT,aAAlC;AACA,eAAKU,cAAL,GAAsB,KAAKC,0BAAL,EAAtB;AACD;;;;uDAE4B;AAC3B,gBAAIC,cAAc,KAAKN,aAAL,CAAmBO,MAAnB,EAAlB;AACA,mBAAOf,EAAEgB,MAAF,CAASF,WAAT,EAAsB,cAAM;AACjC,qBAAOd,EAAEiB,QAAF,CAAWhB,gBAAX,EAA6BiB,GAAGC,IAAhC,CAAP;AACD,aAFM,CAAP;AAGD;;;;;;;;AAGHd,+BAAyBe,WAAzB,GAAuC,wCAAvC","file":"config.controller.js","sourcesContent":["import _ from 'lodash';\n\nconst SUPPORTED_SQL_DS = ['mysql'];\n\nconst defaultConfig = {\n dbConnection: {\n enable: false,\n }\n};\n\nexport class ZabbixDSConfigController {\n /** @ngInject */\n constructor($scope, $injector, datasourceSrv) {\n this.datasourceSrv = datasourceSrv;\n\n _.defaults(this.current.jsonData, defaultConfig);\n this.sqlDataSources = this.getSupportedSQLDataSources();\n }\n\n getSupportedSQLDataSources() {\n let datasources = this.datasourceSrv.getAll();\n return _.filter(datasources, ds => {\n return _.includes(SUPPORTED_SQL_DS, ds.type);\n });\n }\n}\n\nZabbixDSConfigController.templateUrl = 'datasource-zabbix/partials/config.html';\n"]}

View File

@@ -3,7 +3,7 @@
System.register([], function (_export, _context) {
"use strict";
var MODE_METRICS, MODE_TEXT, MODE_ITSERVICE, SEV_NOT_CLASSIFIED, SEV_INFORMATION, SEV_WARNING, SEV_AVERAGE, SEV_HIGH, SEV_DISASTER, SHOW_ALL_TRIGGERS, SHOW_ALL_EVENTS, SHOW_OK_EVENTS, DATAPOINT_VALUE, DATAPOINT_TS;
var MODE_METRICS, MODE_ITSERVICE, MODE_TEXT, MODE_ITEMID, SEV_NOT_CLASSIFIED, SEV_INFORMATION, SEV_WARNING, SEV_AVERAGE, SEV_HIGH, SEV_DISASTER, SHOW_ALL_TRIGGERS, SHOW_ALL_EVENTS, SHOW_OK_EVENTS, DATAPOINT_VALUE, DATAPOINT_TS;
return {
setters: [],
execute: function () {
@@ -11,13 +11,17 @@ System.register([], function (_export, _context) {
_export("MODE_METRICS", MODE_METRICS);
_export("MODE_ITSERVICE", MODE_ITSERVICE = 1);
_export("MODE_ITSERVICE", MODE_ITSERVICE);
_export("MODE_TEXT", MODE_TEXT = 2);
_export("MODE_TEXT", MODE_TEXT);
_export("MODE_ITSERVICE", MODE_ITSERVICE = 1);
_export("MODE_ITEMID", MODE_ITEMID = 3);
_export("MODE_ITSERVICE", MODE_ITSERVICE);
_export("MODE_ITEMID", MODE_ITEMID);
_export("SEV_NOT_CLASSIFIED", SEV_NOT_CLASSIFIED = 0);

View File

@@ -1 +1 @@
{"version":3,"sources":["../../src/datasource-zabbix/constants.js"],"names":["MODE_METRICS","MODE_TEXT","MODE_ITSERVICE","SEV_NOT_CLASSIFIED","SEV_INFORMATION","SEV_WARNING","SEV_AVERAGE","SEV_HIGH","SEV_DISASTER","SHOW_ALL_TRIGGERS","SHOW_ALL_EVENTS","SHOW_OK_EVENTS","DATAPOINT_VALUE","DATAPOINT_TS"],"mappings":";;;;;;;;;8BACaA,Y,GAAe,C;;;;2BACfC,S,GAAY,C;;;;gCACZC,c,GAAiB,C;;;;oCAGjBC,kB,GAAqB,C;;;;iCACrBC,e,GAAkB,C;;;;6BAClBC,W,GAAc,C;;;;6BACdC,W,GAAc,C;;;;0BACdC,Q,GAAW,C;;;;8BACXC,Y,GAAe,C;;;;mCAEfC,iB,GAAoB,CAAC,CAAD,EAAI,CAAJ,C;;;;iCACpBC,e,GAAkB,CAAC,CAAD,EAAI,CAAJ,C;;;;gCAClBC,c,GAAiB,C;;;;iCAGjBC,e,GAAkB,C;;;;8BAClBC,Y,GAAe,C","file":"constants.js","sourcesContent":["// Editor modes\nexport const MODE_METRICS = 0;\nexport const MODE_TEXT = 2;\nexport const MODE_ITSERVICE = 1;\n\n// Triggers severity\nexport const SEV_NOT_CLASSIFIED = 0;\nexport const SEV_INFORMATION = 1;\nexport const SEV_WARNING = 2;\nexport const SEV_AVERAGE = 3;\nexport const SEV_HIGH = 4;\nexport const SEV_DISASTER = 5;\n\nexport const SHOW_ALL_TRIGGERS = [0, 1];\nexport const SHOW_ALL_EVENTS = [0, 1];\nexport const SHOW_OK_EVENTS = 1;\n\n// Data point\nexport const DATAPOINT_VALUE = 0;\nexport const DATAPOINT_TS = 1;\n"]}
{"version":3,"sources":["../../src/datasource-zabbix/constants.js"],"names":["MODE_METRICS","MODE_ITSERVICE","MODE_TEXT","MODE_ITEMID","SEV_NOT_CLASSIFIED","SEV_INFORMATION","SEV_WARNING","SEV_AVERAGE","SEV_HIGH","SEV_DISASTER","SHOW_ALL_TRIGGERS","SHOW_ALL_EVENTS","SHOW_OK_EVENTS","DATAPOINT_VALUE","DATAPOINT_TS"],"mappings":";;;;;;;;;8BACaA,Y,GAAe,C;;;;gCACfC,c,GAAiB,C;;;;2BACjBC,S,GAAY,C;;;;6BACZC,W,GAAc,C;;;;oCAGdC,kB,GAAqB,C;;;;iCACrBC,e,GAAkB,C;;;;6BAClBC,W,GAAc,C;;;;6BACdC,W,GAAc,C;;;;0BACdC,Q,GAAW,C;;;;8BACXC,Y,GAAe,C;;;;mCAEfC,iB,GAAoB,CAAC,CAAD,EAAI,CAAJ,C;;;;iCACpBC,e,GAAkB,CAAC,CAAD,EAAI,CAAJ,C;;;;gCAClBC,c,GAAiB,C;;;;iCAGjBC,e,GAAkB,C;;;;8BAClBC,Y,GAAe,C","file":"constants.js","sourcesContent":["// Editor modes\nexport const MODE_METRICS = 0;\nexport const MODE_ITSERVICE = 1;\nexport const MODE_TEXT = 2;\nexport const MODE_ITEMID = 3;\n\n// Triggers severity\nexport const SEV_NOT_CLASSIFIED = 0;\nexport const SEV_INFORMATION = 1;\nexport const SEV_WARNING = 2;\nexport const SEV_AVERAGE = 3;\nexport const SEV_HIGH = 4;\nexport const SEV_DISASTER = 5;\n\nexport const SHOW_ALL_TRIGGERS = [0, 1];\nexport const SHOW_ALL_EVENTS = [0, 1];\nexport const SHOW_OK_EVENTS = 1;\n\n// Data point\nexport const DATAPOINT_VALUE = 0;\nexport const DATAPOINT_TS = 1;\n"]}

View File

@@ -23,10 +23,23 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
});
}
function getConsolidateBy(target) {
var consolidateBy = 'avg';
var funcDef = _.find(target.functions, function (func) {
return func.def.name === 'consolidateBy';
});
if (funcDef && funcDef.params && funcDef.params.length) {
consolidateBy = funcDef.params[0];
}
return consolidateBy;
}
function downsampleSeries(timeseries_data, options) {
var defaultAgg = dataProcessor.aggregationFunctions['avg'];
var consolidateByFunc = dataProcessor.aggregationFunctions[options.consolidateBy] || defaultAgg;
return _.map(timeseries_data, function (timeseries) {
if (timeseries.datapoints.length > options.maxDataPoints) {
timeseries.datapoints = dataProcessor.groupBy(options.interval, dataProcessor.AVERAGE, timeseries.datapoints);
timeseries.datapoints = dataProcessor.groupBy(options.interval, consolidateByFunc, timeseries.datapoints);
}
return timeseries;
});
@@ -58,6 +71,13 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
return '(' + escapedValues.join('|') + ')';
}
function zabbixItemIdsTemplateFormat(value) {
if (typeof value === 'string') {
return value;
}
return value.join(',');
}
/**
* If template variables are used in request, replace it using regex format
* and wrap with '/' for proper multi-value work. Example:
@@ -191,6 +211,9 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
this.dashboardSrv = dashboardSrv;
this.zabbixAlertingSrv = zabbixAlertingSrv;
// Use custom format for template variables
this.replaceTemplateVars = _.partial(replaceTemplateVars, this.templateSrv);
// General data source settings
this.name = instanceSettings.name;
this.url = instanceSettings.url;
@@ -215,10 +238,21 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
this.addThresholds = instanceSettings.jsonData.addThresholds;
this.alertingMinSeverity = instanceSettings.jsonData.alertingMinSeverity || c.SEV_WARNING;
this.zabbix = new Zabbix(this.url, this.username, this.password, this.basicAuth, this.withCredentials, this.cacheTTL);
// Direct DB Connection options
this.enableDirectDBConnection = instanceSettings.jsonData.dbConnection.enable;
this.sqlDatasourceId = instanceSettings.jsonData.dbConnection.datasourceId;
// Use custom format for template variables
this.replaceTemplateVars = _.partial(replaceTemplateVars, this.templateSrv);
var zabbixOptions = {
username: this.username,
password: this.password,
basicAuth: this.basicAuth,
withCredentials: this.withCredentials,
cacheTTL: this.cacheTTL,
enableDirectDBConnection: this.enableDirectDBConnection,
sqlDatasourceId: this.sqlDatasourceId
};
this.zabbix = new Zabbix(this.url, zabbixOptions);
}
////////////////////////
@@ -253,6 +287,11 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
// Create request for each target
var promises = _.map(options.targets, function (t) {
// Don't request undefined and hidden targets
if (t.hide) {
return [];
}
var timeFrom = Math.ceil(dateMath.parse(options.range.from) / 1000);
var timeTo = Math.ceil(dateMath.parse(options.range.to) / 1000);
@@ -276,7 +315,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
var useTrends = _this.isUseTrends(timeRange);
// Metrics or Text query mode
if (target.mode !== c.MODE_ITSERVICE) {
if (target.mode === c.MODE_METRICS || target.mode === c.MODE_TEXT || target.mode === c.MODE_ITEMID) {
// Migrate old targets
target = migrations.migrate(target);
@@ -289,20 +328,13 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
return _this.queryNumericData(target, timeRange, useTrends, options);
} else if (target.mode === c.MODE_TEXT) {
return _this.queryTextData(target, timeRange);
} else if (target.mode === c.MODE_ITEMID) {
return _this.queryItemIdData(target, timeRange, useTrends, options);
}
} else if (target.mode === c.MODE_ITSERVICE) {
// IT services mode
return _this.queryITServiceData(target, timeRange, options);
}
// IT services mode
else if (target.mode === c.MODE_ITSERVICE) {
// Don't show undefined and hidden targets
if (target.hide || !target.itservice || !target.slaProperty) {
return [];
}
return _this.zabbix.getSLA(target.itservice.serviceid, timeRange).then(function (slaObject) {
return responseHandler.handleSLAResponse(target.itservice, target.slaProperty, slaObject);
});
}
});
// Data for panel (all targets)
@@ -315,19 +347,33 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
value: function queryNumericData(target, timeRange, useTrends, options) {
var _this2 = this;
var _timeRange = _slicedToArray(timeRange, 2),
timeFrom = _timeRange[0],
timeTo = _timeRange[1];
var getItemOptions = {
itemtype: 'num'
};
return this.zabbix.getItemsFromTarget(target, getItemOptions).then(function (items) {
var getHistoryPromise = void 0;
return _this2.queryNumericDataForItems(items, target, timeRange, useTrends, options);
});
}
}, {
key: 'queryNumericDataForItems',
value: function queryNumericDataForItems(items, target, timeRange, useTrends, options) {
var _this3 = this;
if (useTrends) {
var valueType = _this2.getTrendValueType(target);
getHistoryPromise = _this2.zabbix.getTrend(items, timeFrom, timeTo).then(function (history) {
var _timeRange = _slicedToArray(timeRange, 2),
timeFrom = _timeRange[0],
timeTo = _timeRange[1];
var getHistoryPromise = void 0;
options.consolidateBy = getConsolidateBy(target);
if (useTrends) {
if (this.enableDirectDBConnection) {
getHistoryPromise = this.zabbix.getTrendsDB(items, timeFrom, timeTo, options).then(function (history) {
return _this3.zabbix.dbConnector.handleGrafanaTSResponse(history, items);
});
} else {
var valueType = this.getTrendValueType(target);
getHistoryPromise = this.zabbix.getTrend(items, timeFrom, timeTo).then(function (history) {
return responseHandler.handleTrends(history, items, valueType);
}).then(function (timeseries) {
// Sort trend data, issue #202
@@ -336,19 +382,24 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
return point[c.DATAPOINT_TS];
});
});
return timeseries;
});
}
} else {
// Use history
if (this.enableDirectDBConnection) {
getHistoryPromise = this.zabbix.getHistoryDB(items, timeFrom, timeTo, options).then(function (history) {
return _this3.zabbix.dbConnector.handleGrafanaTSResponse(history, items);
});
} else {
// Use history
getHistoryPromise = _this2.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
return responseHandler.handleHistory(history, items);
});
}
}
return getHistoryPromise;
}).then(function (timeseries) {
return _this2.applyDataProcessingFunctions(timeseries, target);
return getHistoryPromise.then(function (timeseries) {
return _this3.applyDataProcessingFunctions(timeseries, target);
}).then(function (timeseries) {
return downsampleSeries(timeseries, options);
}).catch(function (error) {
@@ -427,7 +478,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
}, {
key: 'queryTextData',
value: function queryTextData(target, timeRange) {
var _this3 = this;
var _this4 = this;
var _timeRange2 = _slicedToArray(timeRange, 2),
timeFrom = _timeRange2[0],
@@ -438,7 +489,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
};
return this.zabbix.getItemsFromTarget(target, options).then(function (items) {
if (items.length) {
return _this3.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
return _this4.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
return responseHandler.handleText(history, items, target);
});
} else {
@@ -446,15 +497,79 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
}
});
}
}, {
key: 'queryItemIdData',
value: function queryItemIdData(target, timeRange, useTrends, options) {
var _this5 = this;
var itemids = target.itemids;
itemids = this.templateSrv.replace(itemids, options.scopedVars, zabbixItemIdsTemplateFormat);
itemids = _.map(itemids.split(','), function (itemid) {
return itemid.trim();
});
if (!itemids) {
return [];
}
return this.zabbix.getItemsByIDs(itemids).then(function (items) {
return _this5.queryNumericDataForItems(items, target, timeRange, useTrends, options);
});
}
}, {
key: 'queryITServiceData',
value: function queryITServiceData(target, timeRange, options) {
var _this6 = this;
// Don't show undefined and hidden targets
if (target.hide || !target.itservice && !target.itServiceFilter || !target.slaProperty) {
return [];
}
var itServiceIds = [];
var itServices = [];
var itServiceFilter = void 0;
var isOldVersion = target.itservice && !target.itServiceFilter;
if (isOldVersion) {
// Backward compatibility
itServiceFilter = '/.*/';
} else {
itServiceFilter = this.replaceTemplateVars(target.itServiceFilter, options.scopedVars);
}
return this.zabbix.getITServices(itServiceFilter).then(function (itservices) {
itServices = itservices;
if (isOldVersion) {
itServices = _.filter(itServices, { 'serviceid': target.itservice.serviceid });
}
itServiceIds = _.map(itServices, 'serviceid');
return itServiceIds;
}).then(function (serviceids) {
return _this6.zabbix.getSLA(serviceids, timeRange);
}).then(function (slaResponse) {
return _.map(itServiceIds, function (serviceid) {
var itservice = _.find(itServices, { 'serviceid': serviceid });
return responseHandler.handleSLAResponse(itservice, target.slaProperty, slaResponse);
});
});
}
}, {
key: 'testDatasource',
value: function testDatasource() {
var _this4 = this;
var _this7 = this;
var zabbixVersion = void 0;
return this.zabbix.getVersion().then(function (version) {
zabbixVersion = version;
return _this4.zabbix.login();
return _this7.zabbix.login();
}).then(function () {
if (_this7.enableDirectDBConnection) {
return _this7.zabbix.dbConnector.testSQLDataSource();
} else {
return Promise.resolve();
}
}).then(function () {
return {
status: "success",
@@ -468,6 +583,12 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
title: error.message,
message: error.data
};
} else if (error.data && error.data.message) {
return {
status: "error",
title: "Connection failed",
message: error.data.message
};
} else {
return {
status: "error",
@@ -480,14 +601,14 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
}, {
key: 'metricFindQuery',
value: function metricFindQuery(query) {
var _this5 = this;
var _this8 = this;
var result = void 0;
var parts = [];
// Split query. Query structure: group.host.app.item
_.each(utils.splitTemplateQuery(query), function (part) {
part = _this5.replaceTemplateVars(part, {});
part = _this8.replaceTemplateVars(part, {});
// Replace wildcard to regex
if (part === '*') {
@@ -524,7 +645,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
}, {
key: 'annotationQuery',
value: function annotationQuery(options) {
var _this6 = this;
var _this9 = this;
var timeFrom = Math.ceil(dateMath.parse(options.rangeRaw.from) / 1000);
var timeTo = Math.ceil(dateMath.parse(options.rangeRaw.to) / 1000);
@@ -542,13 +663,14 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
return getTriggers.then(function (triggers) {
// Filter triggers by description
if (utils.isRegex(annotation.trigger)) {
var triggerName = _this9.replaceTemplateVars(annotation.trigger, {});
if (utils.isRegex(triggerName)) {
triggers = _.filter(triggers, function (trigger) {
return utils.buildRegex(annotation.trigger).test(trigger.description);
return utils.buildRegex(triggerName).test(trigger.description);
});
} else if (annotation.trigger) {
} else if (triggerName) {
triggers = _.filter(triggers, function (trigger) {
return trigger.description === annotation.trigger;
return trigger.description === triggerName;
});
}
@@ -558,7 +680,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
});
var objectids = _.map(triggers, 'triggerid');
return _this6.zabbix.getEvents(objectids, timeFrom, timeTo, showOkEvents).then(function (events) {
return _this9.zabbix.getEvents(objectids, timeFrom, timeTo, showOkEvents).then(function (events) {
var indexedTriggers = _.keyBy(triggers, 'triggerid');
// Hide acknowledged events if option enabled
@@ -592,21 +714,23 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
}, {
key: 'alertQuery',
value: function alertQuery(options) {
var _this7 = this;
var _this10 = this;
var enabled_targets = filterEnabledTargets(options.targets);
var getPanelItems = _.map(enabled_targets, function (target) {
return _this7.zabbix.getItemsFromTarget(target, { itemtype: 'num' });
var getPanelItems = _.map(enabled_targets, function (t) {
var target = _.cloneDeep(t);
_this10.replaceTargetVariables(target, options);
return _this10.zabbix.getItemsFromTarget(target, { itemtype: 'num' });
});
return Promise.all(getPanelItems).then(function (results) {
var items = _.flatten(results);
var itemids = _.map(items, 'itemid');
return _this7.zabbix.getAlerts(itemids);
return _this10.zabbix.getAlerts(itemids);
}).then(function (triggers) {
triggers = _.filter(triggers, function (trigger) {
return trigger.priority >= _this7.alertingMinSeverity;
return trigger.priority >= _this10.alertingMinSeverity;
});
if (!triggers || triggers.length === 0) {
@@ -634,12 +758,12 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
}, {
key: 'replaceTargetVariables',
value: function replaceTargetVariables(target, options) {
var _this8 = this;
var _this11 = this;
var parts = ['group', 'host', 'application', 'item'];
_.forEach(parts, function (p) {
if (target[p] && target[p].filter) {
target[p].filter = _this8.replaceTemplateVars(target[p].filter, options.scopedVars);
target[p].filter = _this11.replaceTemplateVars(target[p].filter, options.scopedVars);
}
});
target.textFilter = this.replaceTemplateVars(target.textFilter, options.scopedVars);
@@ -647,9 +771,9 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
_.forEach(target.functions, function (func) {
func.params = _.map(func.params, function (param) {
if (typeof param === 'number') {
return +_this8.templateSrv.replace(param.toString(), options.scopedVars);
return +_this11.templateSrv.replace(param.toString(), options.scopedVars);
} else {
return _this8.templateSrv.replace(param, options.scopedVars);
return _this11.templateSrv.replace(param, options.scopedVars);
}
});
});

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +1,9 @@
'use strict';
System.register(['./datasource', './query.controller'], function (_export, _context) {
System.register(['./datasource', './query.controller', './config.controller'], function (_export, _context) {
"use strict";
var ZabbixAPIDatasource, ZabbixQueryController, ZabbixConfigController, ZabbixQueryOptionsController, ZabbixAnnotationsQueryController;
var ZabbixAPIDatasource, ZabbixQueryController, ZabbixDSConfigController, ZabbixQueryOptionsController, ZabbixAnnotationsQueryController;
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
@@ -16,14 +16,10 @@ System.register(['./datasource', './query.controller'], function (_export, _cont
ZabbixAPIDatasource = _datasource.ZabbixAPIDatasource;
}, function (_queryController) {
ZabbixQueryController = _queryController.ZabbixQueryController;
}, function (_configController) {
ZabbixDSConfigController = _configController.ZabbixDSConfigController;
}],
execute: function () {
_export('ConfigCtrl', ZabbixConfigController = function ZabbixConfigController() {
_classCallCheck(this, ZabbixConfigController);
});
ZabbixConfigController.templateUrl = 'datasource-zabbix/partials/config.html';
_export('QueryOptionsCtrl', ZabbixQueryOptionsController = function ZabbixQueryOptionsController() {
_classCallCheck(this, ZabbixQueryOptionsController);
});
@@ -38,7 +34,7 @@ System.register(['./datasource', './query.controller'], function (_export, _cont
_export('Datasource', ZabbixAPIDatasource);
_export('ConfigCtrl', ZabbixConfigController);
_export('ConfigCtrl', ZabbixDSConfigController);
_export('QueryCtrl', ZabbixQueryController);

View File

@@ -1 +1 @@
{"version":3,"sources":["../../src/datasource-zabbix/module.js"],"names":["ZabbixAPIDatasource","ZabbixQueryController","ZabbixConfigController","templateUrl","ZabbixQueryOptionsController","ZabbixAnnotationsQueryController"],"mappings":";;;;;;;;;;;;;;;AAAQA,yB,eAAAA,mB;;AACAC,2B,oBAAAA,qB;;;4BAEFC,sB;;;;AACNA,6BAAuBC,WAAvB,GAAqC,wCAArC;;kCAEMC,4B;;;;AACNA,mCAA6BD,WAA7B,GAA2C,+CAA3C;;sCAEME,gC;;;;AACNA,uCAAiCF,WAAjC,GAA+C,oDAA/C;;4BAGEH,mB;;4BACAE,sB;;2BACAD,qB;;kCACAG,4B;;sCACAC,gC","file":"module.js","sourcesContent":["import {ZabbixAPIDatasource} from './datasource';\nimport {ZabbixQueryController} from './query.controller';\n\nclass ZabbixConfigController {}\nZabbixConfigController.templateUrl = 'datasource-zabbix/partials/config.html';\n\nclass ZabbixQueryOptionsController {}\nZabbixQueryOptionsController.templateUrl = 'datasource-zabbix/partials/query.options.html';\n\nclass ZabbixAnnotationsQueryController {}\nZabbixAnnotationsQueryController.templateUrl = 'datasource-zabbix/partials/annotations.editor.html';\n\nexport {\n ZabbixAPIDatasource as Datasource,\n ZabbixConfigController as ConfigCtrl,\n ZabbixQueryController as QueryCtrl,\n ZabbixQueryOptionsController as QueryOptionsCtrl,\n ZabbixAnnotationsQueryController as AnnotationsQueryCtrl\n};\n"]}
{"version":3,"sources":["../../src/datasource-zabbix/module.js"],"names":["ZabbixAPIDatasource","ZabbixQueryController","ZabbixDSConfigController","ZabbixQueryOptionsController","templateUrl","ZabbixAnnotationsQueryController"],"mappings":";;;;;;;;;;;;;;;AAAQA,yB,eAAAA,mB;;AACAC,2B,oBAAAA,qB;;AACAC,8B,qBAAAA,wB;;;kCAEFC,4B;;;;AACNA,mCAA6BC,WAA7B,GAA2C,+CAA3C;;sCAEMC,gC;;;;AACNA,uCAAiCD,WAAjC,GAA+C,oDAA/C;;4BAGEJ,mB;;4BACAE,wB;;2BACAD,qB;;kCACAE,4B;;sCACAE,gC","file":"module.js","sourcesContent":["import {ZabbixAPIDatasource} from './datasource';\nimport {ZabbixQueryController} from './query.controller';\nimport {ZabbixDSConfigController} from './config.controller';\n\nclass ZabbixQueryOptionsController {}\nZabbixQueryOptionsController.templateUrl = 'datasource-zabbix/partials/query.options.html';\n\nclass ZabbixAnnotationsQueryController {}\nZabbixAnnotationsQueryController.templateUrl = 'datasource-zabbix/partials/annotations.editor.html';\n\nexport {\n ZabbixAPIDatasource as Datasource,\n ZabbixDSConfigController as ConfigCtrl,\n ZabbixQueryController as QueryCtrl,\n ZabbixQueryOptionsController as QueryOptionsCtrl,\n ZabbixAnnotationsQueryController as AnnotationsQueryCtrl\n};\n"]}

View File

@@ -76,24 +76,53 @@
</div>
<div class="gf-form-group">
<h3 class="page-heading">Alerting</h3>
<gf-form-switch class="gf-form" label-class="width-9"
label="Enable alerting"
checked="ctrl.current.jsonData.alerting">
<h3 class="page-heading">Direct DB Connection</h3>
<gf-form-switch class="gf-form" label-class="width-12"
label="Enable"
checked="ctrl.current.jsonData.dbConnection.enable">
</gf-form-switch>
<gf-form-switch class="gf-form" label-class="width-9"
label="Add thresholds"
checked="ctrl.current.jsonData.addThresholds">
</gf-form-switch>
<div class="gf-form max-width-20">
<span class="gf-form-label width-9">Min severity</span>
<div ng-if="ctrl.current.jsonData.dbConnection.enable">
<div class="gf-form max-width-20">
<span class="gf-form-label width-12">
SQL Data Source
<info-popover mode="right-normal">
Select SQL Data Source for Zabbix database.
In order to use this feature you should <a href="/datasources/new" target="_blank">create</a> and
configure it first. Zabbix plugin uses this data source for querying history data directly from database.
This way usually faster than pulling data from Zabbix API, especially on the wide time ranges, and reduces
amount of data transfered.
</info-popover>
</span>
<div class="gf-form-select-wrapper max-width-16">
<select class="gf-form-input" ng-model="ctrl.current.jsonData.alertingMinSeverity"
ng-options="s.val as s.text for s in [
{val: 0, text: 'Not classified'}, {val: 1, text:'Information'},
{val: 2, text: 'Warning'}, {val: 3, text: 'Average'},
{val: 4, text: 'High'}, {val: 5, text: 'Disaster'}]">
<select class="gf-form-input" ng-model="ctrl.current.jsonData.dbConnection.datasourceId"
ng-options="ds.id as ds.name for ds in ctrl.sqlDataSources">
</select>
</div>
</div>
</div>
</div>
<div class="gf-form-group">
<h3 class="page-heading">Alerting</h3>
<gf-form-switch class="gf-form" label-class="width-12"
label="Enable alerting"
checked="ctrl.current.jsonData.alerting">
</gf-form-switch>
<div ng-if="ctrl.current.jsonData.alerting">
<gf-form-switch class="gf-form" label-class="width-12"
label="Add thresholds"
checked="ctrl.current.jsonData.addThresholds">
</gf-form-switch>
<div class="gf-form max-width-20">
<span class="gf-form-label width-12">Min severity</span>
<div class="gf-form-select-wrapper max-width-16">
<select class="gf-form-input" ng-model="ctrl.current.jsonData.alertingMinSeverity"
ng-options="s.val as s.text for s in [
{val: 0, text: 'Not classified'}, {val: 1, text:'Information'},
{val: 2, text: 'Warning'}, {val: 3, text: 'Average'},
{val: 4, text: 'High'}, {val: 5, text: 'Disaster'}]">
</select>
</div>
</div>
</div>
</div>

View File

@@ -7,7 +7,7 @@
<select class="gf-form-input"
ng-change="ctrl.switchEditorMode(ctrl.target.mode)"
ng-model="ctrl.target.mode"
ng-options="v.mode as v.text for (k, v) in ctrl.editorModes">
ng-options="m.mode as m.text for m in ctrl.editorModes">
</select>
</div>
</div>
@@ -17,27 +17,29 @@
</div>
<!-- IT Service editor -->
<div class="gf-form-inline" ng-show="ctrl.target.mode == 1">
<div class="gf-form-inline" ng-show="ctrl.target.mode == editorMode.ITSERVICE">
<div class="gf-form max-width-20">
<label class="gf-form-label query-keyword width-7">IT Service</label>
<div class="gf-form-select-wrapper max-width-20">
<select class="gf-form-input"
ng-change="ctrl.selectITService()"
ng-model="ctrl.target.itservice"
bs-tooltip="ctrl.target.itservice.name.length > 25 ? ctrl.target.itservice.name : ''"
ng-options="itservice.name for itservice in ctrl.itserviceList track by itservice.name">
<option value="">-- Select IT service --</option>
</select>
</div>
<input type="text"
ng-model="ctrl.target.itServiceFilter"
bs-typeahead="ctrl.getITServices"
ng-blur="ctrl.onTargetBlur()"
data-min-length=0
data-items=100
class="gf-form-input"
ng-class="{
'zbx-variable': ctrl.isVariable(ctrl.target.itServiceFilter),
'zbx-regex': ctrl.isRegex(ctrl.target.itServiceFilter)
}">
</input>
</div>
<div class="gf-form">
<label class="gf-form-label query-keyword">IT service property</label>
<label class="gf-form-label query-keyword">Property</label>
<div class="gf-form-select-wrapper">
<select class="gf-form-input"
ng-change="ctrl.selectITService()"
ng-model="ctrl.target.slaProperty"
ng-options="slaProperty.name for slaProperty in ctrl.slaPropertyList track by slaProperty.name">
<option value="">-- Property --</option>
ng-change="ctrl.onTargetBlur()"
ng-model="ctrl.target.slaProperty"
ng-options="slaProperty.name for slaProperty in ctrl.slaPropertyList track by slaProperty.name">
</select>
</div>
</div>
@@ -46,7 +48,7 @@
</div>
</div>
<div class="gf-form-inline" ng-hide="ctrl.target.mode == 1">
<div class="gf-form-inline" ng-show="ctrl.target.mode == editorMode.METRICS || ctrl.target.mode == editorMode.TEXT">
<!-- Select Group -->
<div class="gf-form max-width-20">
<label class="gf-form-label query-keyword width-7">Group</label>
@@ -83,7 +85,7 @@
</div>
</div>
<div class="gf-form-inline" ng-hide="ctrl.target.mode == 1">
<div class="gf-form-inline" ng-show="ctrl.target.mode == editorMode.METRICS || ctrl.target.mode == editorMode.TEXT">
<!-- Select Application -->
<div class="gf-form max-width-20">
<label class="gf-form-label query-keyword width-7">Application</label>
@@ -129,7 +131,7 @@
<!-- Query options -->
<div class="gf-form-group" ng-if="ctrl.showQueryOptions">
<div class="gf-form offset-width-7">
<gf-form-switch class="gf-form" ng-hide="ctrl.target.mode == 2"
<gf-form-switch class="gf-form"
label="Show disabled items"
checked="ctrl.target.options.showDisabledItems"
on-change="ctrl.onQueryOptionChange()">
@@ -137,8 +139,30 @@
</div>
</div>
<!-- Item IDs editor mode -->
<div class="gf-form-inline" ng-show="ctrl.target.mode == editorMode.ITEMID">
<div class="gf-form max-width-20">
<label class="gf-form-label query-keyword width-7">Item IDs</label>
<input type="text"
ng-model="ctrl.target.itemids"
bs-typeahead="ctrl.getVariables"
ng-blur="ctrl.onTargetBlur()"
data-min-length=0
data-items=100
class="gf-form-input"
ng-class="{
'zbx-variable': ctrl.isVariable(ctrl.target.itServiceFilter),
'zbx-regex': ctrl.isRegex(ctrl.target.itServiceFilter)
}">
</input>
</div>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<!-- Metric processing functions -->
<div class="gf-form-inline" ng-hide="ctrl.target.mode">
<div class="gf-form-inline" ng-show="ctrl.target.mode == editorMode.METRICS || ctrl.target.mode == editorMode.ITEMID">
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">Functions</label>
<div ng-repeat="func in ctrl.target.functions" class="gf-form-label query-part" metric-function-editor></div>
@@ -151,7 +175,7 @@
</div>
<!-- Text mode options -->
<div class="gf-form-inline" ng-show="ctrl.target.mode == 2">
<div class="gf-form-inline" ng-show="ctrl.target.mode == editorMode.TEXT">
<!-- Text metric regex -->
<div class="gf-form max-width-20">
<label class="gf-form-label query-keyword width-7">Text filter</label>
@@ -165,6 +189,8 @@
<gf-form-switch class="gf-form" label="Use capture groups" checked="ctrl.target.useCaptureGroups" on-change="ctrl.onTargetBlur()">
</gf-form-switch>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
</query-editor-row>

View File

@@ -1,9 +1,9 @@
'use strict';
System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils', './metricFunctions', './migrations', './add-metric-function.directive', './metric-function-editor.directive', './css/query-editor.css!'], function (_export, _context) {
System.register(['app/plugins/sdk', 'lodash', './constants', './utils', './metricFunctions', './migrations', './add-metric-function.directive', './metric-function-editor.directive', './css/query-editor.css!'], function (_export, _context) {
"use strict";
var QueryCtrl, angular, _, c, utils, metricFunctions, migrations, _createClass, ZabbixQueryController;
var QueryCtrl, _, c, utils, metricFunctions, migrations, _createClass, ZabbixQueryController;
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
@@ -38,8 +38,6 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils
return {
setters: [function (_appPluginsSdk) {
QueryCtrl = _appPluginsSdk.QueryCtrl;
}, function (_angular) {
angular = _angular.default;
}, function (_lodash) {
_ = _lodash.default;
}, function (_constants) {
@@ -85,17 +83,24 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils
_this.replaceTemplateVars = _this.datasource.replaceTemplateVars;
_this.templateSrv = templateSrv;
_this.editorModes = {
0: { value: 'num', text: 'Metrics', mode: c.MODE_METRICS },
1: { value: 'itservice', text: 'IT Services', mode: c.MODE_ITSERVICE },
2: { value: 'text', text: 'Text', mode: c.MODE_TEXT }
_this.editorModes = [{ value: 'num', text: 'Metrics', mode: c.MODE_METRICS }, { value: 'text', text: 'Text', mode: c.MODE_TEXT }, { value: 'itservice', text: 'IT Services', mode: c.MODE_ITSERVICE }, { value: 'itemid', text: 'Item ID', mode: c.MODE_ITEMID }];
_this.$scope.editorMode = {
METRICS: c.MODE_METRICS,
TEXT: c.MODE_TEXT,
ITSERVICE: c.MODE_ITSERVICE,
ITEMID: c.MODE_ITEMID
};
_this.slaPropertyList = [{ name: "Status", property: "status" }, { name: "SLA", property: "sla" }, { name: "OK time", property: "okTime" }, { name: "Problem time", property: "problemTime" }, { name: "Down time", property: "downtimeTime" }];
// Map functions for bs-typeahead
_this.getGroupNames = _.bind(_this.getMetricNames, _this, 'groupList');
_this.getHostNames = _.bind(_this.getMetricNames, _this, 'hostList', true);
_this.getApplicationNames = _.bind(_this.getMetricNames, _this, 'appList');
_this.getItemNames = _.bind(_this.getMetricNames, _this, 'itemList');
_this.getITServices = _.bind(_this.getMetricNames, _this, 'itServiceList');
_this.getVariables = _.bind(_this.getTemplateVariables, _this);
// Update metric suggestion when template variable was changed
$rootScope.$on('template-variable-value-updated', function () {
@@ -122,14 +127,14 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils
// Load default values
var targetDefaults = {
mode: c.MODE_METRICS,
group: { filter: "" },
host: { filter: "" },
application: { filter: "" },
item: { filter: "" },
functions: [],
options: {
showDisabledItems: false
'mode': c.MODE_METRICS,
'group': { 'filter': "" },
'host': { 'filter': "" },
'application': { 'filter': "" },
'item': { 'filter': "" },
'functions': [],
'options': {
'showDisabledItems': false
}
};
_.defaults(target, targetDefaults);
@@ -141,13 +146,10 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils
if (target.mode === c.MODE_METRICS || target.mode === c.MODE_TEXT) {
this.downsampleFunctionList = [{ name: "avg", value: "avg" }, { name: "min", value: "min" }, { name: "max", value: "max" }, { name: "sum", value: "sum" }, { name: "count", value: "count" }];
this.initFilters();
} else if (target.mode === c.MODE_ITSERVICE) {
this.slaPropertyList = [{ name: "Status", property: "status" }, { name: "SLA", property: "sla" }, { name: "OK time", property: "okTime" }, { name: "Problem time", property: "problemTime" }, { name: "Down time", property: "downtimeTime" }];
this.itserviceList = [{ name: "test" }];
this.updateITServiceList();
_.defaults(target, { slaProperty: { name: "SLA", property: "sla" } });
this.suggestITServices();
}
};
@@ -158,7 +160,8 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils
_createClass(ZabbixQueryController, [{
key: 'initFilters',
value: function initFilters() {
var itemtype = this.editorModes[this.target.mode].value;
var itemtype = _.find(this.editorModes, { 'mode': this.target.mode });
itemtype = itemtype ? itemtype.value : null;
return Promise.all([this.suggestGroups(), this.suggestHosts(), this.suggestApps(), this.suggestItems(itemtype)]);
}
}, {
@@ -177,6 +180,13 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils
return metrics;
}
}, {
key: 'getTemplateVariables',
value: function getTemplateVariables() {
return _.map(this.templateSrv.variables, function (variable) {
return '$' + variable.name;
});
}
}, {
key: 'suggestGroups',
value: function suggestGroups() {
@@ -230,6 +240,16 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils
return items;
});
}
}, {
key: 'suggestITServices',
value: function suggestITServices() {
var _this6 = this;
return this.zabbix.getITService().then(function (itservices) {
_this6.metric.itServiceList = itservices;
return itservices;
});
}
}, {
key: 'isRegex',
value: function isRegex(str) {
@@ -259,11 +279,11 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils
}, {
key: 'isContainsVariables',
value: function isContainsVariables() {
var _this6 = this;
var _this7 = this;
return _.some(['group', 'host', 'application'], function (field) {
if (_this6.target[field] && _this6.target[field].filter) {
return utils.isTemplateVariable(_this6.target[field].filter, _this6.templateSrv.variables);
if (_this7.target[field] && _this7.target[field].filter) {
return utils.isTemplateVariable(_this7.target[field].filter, _this7.templateSrv.variables);
} else {
return false;
}
@@ -356,24 +376,7 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils
value: function switchEditorMode(mode) {
this.target.mode = mode;
this.init();
}
}, {
key: 'updateITServiceList',
value: function updateITServiceList() {
var _this7 = this;
this.zabbix.getITService().then(function (iteservices) {
_this7.itserviceList = [];
_this7.itserviceList = _this7.itserviceList.concat(iteservices);
});
}
}, {
key: 'selectITService',
value: function selectITService() {
if (!_.isEqual(this.oldTarget, this.target) && _.isEmpty(this.target.errors)) {
this.oldTarget = angular.copy(this.target);
this.panelCtrl.refresh();
}
this.targetChanged();
}
}]);

File diff suppressed because one or more lines are too long

View File

@@ -15,7 +15,10 @@ describe('ZabbixDatasource', () => {
password: 'zabbix',
trends: true,
trendsFrom: '14d',
trendsRange: '7d'
trendsRange: '7d',
dbConnection: {
enabled: false
}
}
};
ctx.templateSrv = {};

View File

@@ -88,4 +88,54 @@ describe('Utils', () => {
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).to.eql(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).to.eql(test_case.expected);
});
done();
});
});
});

View File

@@ -28,6 +28,16 @@ System.register(['lodash', 'moment'], function (_export, _context) {
_export('expandItemName', expandItemName);
function expandItems(items) {
_.forEach(items, function (item) {
item.item = item.name;
item.name = expandItemName(item.item, item.key_);
return item;
});
return items;
}
_export('expandItems', expandItems);
function splitKeyParams(paramStr) {
var params = [];
var quoted = false;
@@ -56,7 +66,9 @@ System.register(['lodash', 'moment'], function (_export, _context) {
params.push(param);
return params;
}function containsMacro(itemName) {
}
function containsMacro(itemName) {
return MACRO_PATTERN.test(itemName);
}
@@ -99,7 +111,7 @@ System.register(['lodash', 'moment'], function (_export, _context) {
* {group}{host.com} -> [group, host.com]
*/
function splitTemplateQuery(query) {
var splitPattern = /{[^{}]*}/g;
var splitPattern = /\{[^\{\}]*\}|\{\/.*\/\}/g;
var split = void 0;
if (isContainsBraces(query)) {
@@ -117,7 +129,8 @@ System.register(['lodash', 'moment'], function (_export, _context) {
_export('splitTemplateQuery', splitTemplateQuery);
function isContainsBraces(query) {
return query.includes('{') && query.includes('}');
var bracesPattern = /^\{.+\}$/;
return bracesPattern.test(query);
}
// Pattern for testing regex

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
'use strict';
System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './zabbixCachingProxy.service.js'], function (_export, _context) {
System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './zabbixCachingProxy.service.js', './zabbixDBConnector'], function (_export, _context) {
"use strict";
var angular, _, utils, _createClass;
@@ -27,25 +27,44 @@ System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './za
// Each Zabbix data source instance should initialize its own API instance.
/** @ngInject */
function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy) {
function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy, ZabbixDBConnector) {
var Zabbix = function () {
function Zabbix(url, username, password, basicAuth, withCredentials, cacheTTL) {
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, cacheOptions);
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);
@@ -168,6 +187,13 @@ System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './za
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) {
@@ -274,7 +300,7 @@ System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './za
_ = _lodash.default;
}, function (_utils) {
utils = _utils;
}, function (_zabbixAPIServiceJs) {}, function (_zabbixCachingProxyServiceJs) {}],
}, function (_zabbixAPIServiceJs) {}, function (_zabbixCachingProxyServiceJs) {}, function (_zabbixDBConnector) {}],
execute: function () {
_createClass = function () {
function defineProperties(target, props) {

File diff suppressed because one or more lines are too long

View File

@@ -166,16 +166,19 @@ System.register(['angular', 'lodash', './utils', './zabbixAPICore.service'], fun
params.filter.value_type = [1, 2, 4];
}
return this.request('item.get', params).then(expandItems);
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']
};
function expandItems(items) {
_.forEach(items, function (item) {
item.item = item.name;
item.name = utils.expandItemName(item.item, item.key_);
return item;
});
return items;
}
return this.request('item.get', params).then(utils.expandItems);
}
}, {
key: 'getMacros',

File diff suppressed because one or more lines are too long

View File

@@ -29,10 +29,11 @@ System.register(['angular', 'lodash'], function (_export, _context) {
/** @ngInject */
function ZabbixCachingProxyFactory() {
var ZabbixCachingProxy = function () {
function ZabbixCachingProxy(zabbixAPI, cacheOptions) {
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
@@ -45,7 +46,8 @@ System.register(['angular', 'lodash'], function (_export, _context) {
history: {},
trends: {},
macros: {},
globalMacros: {}
globalMacros: {},
itServices: {}
};
this.historyPromises = {};
@@ -53,6 +55,11 @@ System.register(['angular', 'lodash'], function (_export, _context) {
// 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);
@@ -66,6 +73,12 @@ System.register(['angular', 'lodash'], function (_export, _context) {
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);
@@ -120,6 +133,17 @@ System.register(['angular', 'lodash'], function (_export, _context) {
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) {
@@ -209,6 +233,14 @@ System.register(['angular', 'lodash'], function (_export, _context) {
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;

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,233 @@
'use strict';
System.register(['angular', 'lodash'], function (_export, _context) {
"use strict";
var angular, _, _createClass, DEFAULT_QUERY_LIMIT, HISTORY_TO_TABLE_MAP, TREND_TO_TABLE_MAP, consolidateByFunc, consolidateByTrendColumns;
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
/** @ngInject */
function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {
var ZabbixDBConnector = function () {
function ZabbixDBConnector(sqlDataSourceId) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classCallCheck(this, ZabbixDBConnector);
var limit = options.limit;
this.sqlDataSourceId = sqlDataSourceId;
this.limit = limit || DEFAULT_QUERY_LIMIT;
}
/**
* 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 ds = _.find(datasourceSrv.getAll(), { 'id': datasourceId });
if (ds) {
return datasourceSrv.loadDatasource(ds.name).then(function (ds) {
console.log('SQL data source loaded', ds);
});
} else {
return Promise.reject('SQL Data Source with ID ' + datasourceId + ' not found');
}
}
}, {
key: 'testSQLDataSource',
value: function testSQLDataSource() {
var testQuery = 'SELECT itemid AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1';
return this.invokeSQLQuery(testQuery);
}
}, {
key: 'getHistory',
value: function getHistory(items, timeFrom, timeTill, options) {
var _this = this;
var intervalMs = options.intervalMs,
consolidateBy = options.consolidateBy;
var intervalSec = Math.ceil(intervalMs / 1000);
consolidateBy = consolidateBy || 'avg';
var aggFunction = consolidateByFunc[consolidateBy];
// Group items by value type and perform request for each value type
var grouped_items = _.groupBy(items, 'value_type');
var promises = _.map(grouped_items, function (items, value_type) {
var itemids = _.map(items, 'itemid').join(', ');
var table = HISTORY_TO_TABLE_MAP[value_type];
var query = '\n SELECT itemid AS metric, clock AS time_sec, ' + aggFunction + '(value) AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY time_sec DIV ' + intervalSec + ', metric\n ';
query = compactSQLQuery(query);
return _this.invokeSQLQuery(query);
});
return Promise.all(promises).then(function (results) {
return _.flatten(results);
});
}
}, {
key: 'getTrends',
value: function getTrends(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 = TREND_TO_TABLE_MAP[value_type];
var valueColumn = _.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg';
valueColumn = consolidateByTrendColumns[valueColumn];
var query = '\n SELECT itemid AS metric, clock AS time_sec, ' + aggFunction + '(' + valueColumn + ') AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY time_sec DIV ' + intervalSec + ', metric\n ';
query = compactSQLQuery(query);
return _this2.invokeSQLQuery(query);
});
return Promise.all(promises).then(function (results) {
return _.flatten(results);
});
}
}, {
key: 'handleGrafanaTSResponse',
value: function handleGrafanaTSResponse(history, items) {
var addHostName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
return convertGrafanaTSResponse(history, items, addHostName);
}
}, {
key: 'invokeSQLQuery',
value: function invokeSQLQuery(query) {
var queryDef = {
refId: 'A',
format: 'time_series',
datasourceId: this.sqlDataSourceId,
rawSql: query,
maxDataPoints: this.limit
};
return backendSrv.datasourceRequest({
url: '/api/tsdb/query',
method: 'POST',
data: {
queries: [queryDef]
}
}).then(function (response) {
var results = response.data.results;
if (results['A']) {
return results['A'].series;
} else {
return null;
}
});
}
}]);
return ZabbixDBConnector;
}();
return ZabbixDBConnector;
}
///////////////////////////////////////////////////////////////////////////////
function convertGrafanaTSResponse(time_series, items, addHostName) {
var hosts = _.uniqBy(_.flatten(_.map(items, 'hosts')), 'hostid'); //uniqBy is needed to deduplicate
var grafanaSeries = _.map(time_series, function (series) {
var itemid = series.name;
var datapoints = series.points;
var item = _.find(items, { 'itemid': itemid });
var alias = item.name;
if (_.keys(hosts).length > 1 && addHostName) {
//only when actual multi hosts selected
var host = _.find(hosts, { 'hostid': item.hostid });
alias = host.name + ": " + alias;
}
return {
target: alias,
datapoints: datapoints
};
});
return _.sortBy(grafanaSeries, 'target');
}
function compactSQLQuery(query) {
return query.replace(/\s+/g, ' ');
}
return {
setters: [function (_angular) {
angular = _angular.default;
}, function (_lodash) {
_ = _lodash.default;
}],
execute: function () {
_createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
DEFAULT_QUERY_LIMIT = 10000;
HISTORY_TO_TABLE_MAP = {
'0': 'history',
'1': 'history_str',
'2': 'history_log',
'3': 'history_uint',
'4': 'history_text'
};
TREND_TO_TABLE_MAP = {
'0': 'trends',
'3': 'trends_uint'
};
consolidateByFunc = {
'avg': 'AVG',
'min': 'MIN',
'max': 'MAX',
'sum': 'SUM',
'count': 'COUNT'
};
consolidateByTrendColumns = {
'avg': 'value_avg',
'min': 'value_min',
'max': 'value_max'
};
angular.module('grafana.services').factory('ZabbixDBConnector', ZabbixDBConnectorFactory);
}
};
});
//# sourceMappingURL=zabbixDBConnector.js.map

File diff suppressed because one or more lines are too long