Merge branch 'itemid-query-mode'

This commit is contained in:
Alexander Zobnin
2017-07-26 11:34:55 +03:00
30 changed files with 553 additions and 239 deletions

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

@@ -71,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:
@@ -280,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);
@@ -303,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);
@@ -316,13 +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) {
return _this.queryITServiceData(target, timeRange, options);
}
});
// Data for panel (all targets)
@@ -335,52 +347,59 @@ 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;
options.consolidateBy = getConsolidateBy(target);
return _this2.queryNumericDataForItems(items, target, timeRange, useTrends, options);
});
}
}, {
key: 'queryNumericDataForItems',
value: function queryNumericDataForItems(items, target, timeRange, useTrends, options) {
var _this3 = this;
if (useTrends) {
if (_this2.enableDirectDBConnection) {
getHistoryPromise = _this2.zabbix.getTrendsDB(items, timeFrom, timeTo, options).then(function (history) {
return _this2.zabbix.dbConnector.handleGrafanaTSResponse(history, items);
});
} else {
var valueType = _this2.getTrendValueType(target);
getHistoryPromise = _this2.zabbix.getTrend(items, timeFrom, timeTo).then(function (history) {
return responseHandler.handleTrends(history, items, valueType);
}).then(function (timeseries) {
// Sort trend data, issue #202
_.forEach(timeseries, function (series) {
series.datapoints = _.sortBy(series.datapoints, function (point) {
return point[c.DATAPOINT_TS];
});
});
return timeseries;
});
}
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 {
// Use history
if (_this2.enableDirectDBConnection) {
getHistoryPromise = _this2.zabbix.getHistoryDB(items, timeFrom, timeTo, options).then(function (history) {
return _this2.zabbix.dbConnector.handleGrafanaTSResponse(history, items);
var valueType = this.getTrendValueType(target);
getHistoryPromise = this.zabbix.getTrend(items, timeFrom, timeTo).then(function (history) {
return responseHandler.handleTrends(history, items, valueType);
}).then(function (timeseries) {
// Sort trend data, issue #202
_.forEach(timeseries, function (series) {
series.datapoints = _.sortBy(series.datapoints, function (point) {
return point[c.DATAPOINT_TS];
});
});
} else {
getHistoryPromise = _this2.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
return responseHandler.handleHistory(history, items);
});
}
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 {
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) {
@@ -459,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],
@@ -470,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 {
@@ -478,10 +497,29 @@ 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 _this4 = this;
var _this6 = this;
// Don't show undefined and hidden targets
if (target.hide || !target.itservice && !target.itServiceFilter || !target.slaProperty) {
@@ -509,7 +547,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
itServiceIds = _.map(itServices, 'serviceid');
return itServiceIds;
}).then(function (serviceids) {
return _this4.zabbix.getSLA(serviceids, timeRange);
return _this6.zabbix.getSLA(serviceids, timeRange);
}).then(function (slaResponse) {
return _.map(itServiceIds, function (serviceid) {
var itservice = _.find(itServices, { 'serviceid': serviceid });
@@ -520,15 +558,15 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
}, {
key: 'testDatasource',
value: function testDatasource() {
var _this5 = this;
var _this7 = this;
var zabbixVersion = void 0;
return this.zabbix.getVersion().then(function (version) {
zabbixVersion = version;
return _this5.zabbix.login();
return _this7.zabbix.login();
}).then(function () {
if (_this5.enableDirectDBConnection) {
return _this5.zabbix.dbConnector.testSQLDataSource();
if (_this7.enableDirectDBConnection) {
return _this7.zabbix.dbConnector.testSQLDataSource();
} else {
return Promise.resolve();
}
@@ -563,14 +601,14 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
}, {
key: 'metricFindQuery',
value: function metricFindQuery(query) {
var _this6 = 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 = _this6.replaceTemplateVars(part, {});
part = _this8.replaceTemplateVars(part, {});
// Replace wildcard to regex
if (part === '*') {
@@ -607,7 +645,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
}, {
key: 'annotationQuery',
value: function annotationQuery(options) {
var _this7 = this;
var _this9 = this;
var timeFrom = Math.ceil(dateMath.parse(options.rangeRaw.from) / 1000);
var timeTo = Math.ceil(dateMath.parse(options.rangeRaw.to) / 1000);
@@ -625,7 +663,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
return getTriggers.then(function (triggers) {
// Filter triggers by description
var triggerName = _this7.replaceTemplateVars(annotation.trigger, {});
var triggerName = _this9.replaceTemplateVars(annotation.trigger, {});
if (utils.isRegex(triggerName)) {
triggers = _.filter(triggers, function (trigger) {
return utils.buildRegex(triggerName).test(trigger.description);
@@ -642,7 +680,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
});
var objectids = _.map(triggers, 'triggerid');
return _this7.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
@@ -676,23 +714,23 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
}, {
key: 'alertQuery',
value: function alertQuery(options) {
var _this8 = this;
var _this10 = this;
var enabled_targets = filterEnabledTargets(options.targets);
var getPanelItems = _.map(enabled_targets, function (t) {
var target = _.cloneDeep(t);
_this8.replaceTargetVariables(target, options);
return _this8.zabbix.getItemsFromTarget(target, { itemtype: 'num' });
_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 _this8.zabbix.getAlerts(itemids);
return _this10.zabbix.getAlerts(itemids);
}).then(function (triggers) {
triggers = _.filter(triggers, function (trigger) {
return trigger.priority >= _this8.alertingMinSeverity;
return trigger.priority >= _this10.alertingMinSeverity;
});
if (!triggers || triggers.length === 0) {
@@ -720,12 +758,12 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
}, {
key: 'replaceTargetVariables',
value: function replaceTargetVariables(target, options) {
var _this9 = this;
var _this11 = this;
var parts = ['group', 'host', 'application', 'item'];
_.forEach(parts, function (p) {
if (target[p] && target[p].filter) {
target[p].filter = _this9.replaceTemplateVars(target[p].filter, options.scopedVars);
target[p].filter = _this11.replaceTemplateVars(target[p].filter, options.scopedVars);
}
});
target.textFilter = this.replaceTemplateVars(target.textFilter, options.scopedVars);
@@ -733,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 +_this9.templateSrv.replace(param.toString(), options.scopedVars);
return +_this11.templateSrv.replace(param.toString(), options.scopedVars);
} else {
return _this9.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

@@ -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,7 +17,7 @@
</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>
<input type="text"
@@ -48,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>
@@ -85,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>
@@ -131,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()">
@@ -139,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>
@@ -153,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>
@@ -167,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

@@ -83,10 +83,13 @@ System.register(['app/plugins/sdk', 'lodash', './constants', './utils', './metri
_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" }];
@@ -97,6 +100,7 @@ System.register(['app/plugins/sdk', 'lodash', './constants', './utils', './metri
_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 () {
@@ -156,7 +160,8 @@ System.register(['app/plugins/sdk', 'lodash', './constants', './utils', './metri
_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)]);
}
}, {
@@ -175,6 +180,13 @@ System.register(['app/plugins/sdk', 'lodash', './constants', './utils', './metri
return metrics;
}
}, {
key: 'getTemplateVariables',
value: function getTemplateVariables() {
return _.map(this.templateSrv.variables, function (variable) {
return '$' + variable.name;
});
}
}, {
key: 'suggestGroups',
value: function suggestGroups() {

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

View File

@@ -59,6 +59,7 @@ System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './za
// 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);

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

@@ -73,6 +73,9 @@ 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);
@@ -130,6 +133,12 @@ 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() {

File diff suppressed because one or more lines are too long

View File

@@ -5,8 +5,9 @@ Object.defineProperty(exports, "__esModule", {
});
// Editor modes
var MODE_METRICS = exports.MODE_METRICS = 0;
var MODE_TEXT = exports.MODE_TEXT = 2;
var MODE_ITSERVICE = exports.MODE_ITSERVICE = 1;
var MODE_TEXT = exports.MODE_TEXT = 2;
var MODE_ITEMID = exports.MODE_ITEMID = 3;
// Triggers severity
var SEV_NOT_CLASSIFIED = exports.SEV_NOT_CLASSIFIED = 0;

View File

@@ -140,6 +140,11 @@ var ZabbixAPIDatasource = function () {
// Create request for each target
var promises = _lodash2.default.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);
@@ -163,7 +168,7 @@ var ZabbixAPIDatasource = function () {
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);
@@ -176,13 +181,13 @@ var ZabbixAPIDatasource = function () {
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) {
return _this.queryITServiceData(target, timeRange, options);
}
});
// Data for panel (all targets)
@@ -190,57 +195,74 @@ var ZabbixAPIDatasource = function () {
return { data: data };
});
}
/**
* Query target data for Metrics mode
*/
}, {
key: 'queryNumericData',
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;
options.consolidateBy = getConsolidateBy(target);
return _this2.queryNumericDataForItems(items, target, timeRange, useTrends, options);
});
}
if (useTrends) {
if (_this2.enableDirectDBConnection) {
getHistoryPromise = _this2.zabbix.getTrendsDB(items, timeFrom, timeTo, options).then(function (history) {
return _this2.zabbix.dbConnector.handleGrafanaTSResponse(history, items);
});
} else {
var valueType = _this2.getTrendValueType(target);
getHistoryPromise = _this2.zabbix.getTrend(items, timeFrom, timeTo).then(function (history) {
return _responseHandler2.default.handleTrends(history, items, valueType);
}).then(function (timeseries) {
// Sort trend data, issue #202
_lodash2.default.forEach(timeseries, function (series) {
series.datapoints = _lodash2.default.sortBy(series.datapoints, function (point) {
return point[c.DATAPOINT_TS];
});
});
return timeseries;
});
}
/**
* Query history for numeric items
*/
}, {
key: 'queryNumericDataForItems',
value: function queryNumericDataForItems(items, target, timeRange, useTrends, options) {
var _this3 = this;
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 {
// Use history
if (_this2.enableDirectDBConnection) {
getHistoryPromise = _this2.zabbix.getHistoryDB(items, timeFrom, timeTo, options).then(function (history) {
return _this2.zabbix.dbConnector.handleGrafanaTSResponse(history, items);
var valueType = this.getTrendValueType(target);
getHistoryPromise = this.zabbix.getTrend(items, timeFrom, timeTo).then(function (history) {
return _responseHandler2.default.handleTrends(history, items, valueType);
}).then(function (timeseries) {
// Sort trend data, issue #202
_lodash2.default.forEach(timeseries, function (series) {
series.datapoints = _lodash2.default.sortBy(series.datapoints, function (point) {
return point[c.DATAPOINT_TS];
});
});
} else {
getHistoryPromise = _this2.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
return _responseHandler2.default.handleHistory(history, items);
});
}
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 {
getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
return _responseHandler2.default.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) {
@@ -316,10 +338,15 @@ var ZabbixAPIDatasource = function () {
});
}
}
/**
* Query target data for Text mode
*/
}, {
key: 'queryTextData',
value: function queryTextData(target, timeRange) {
var _this3 = this;
var _this4 = this;
var _timeRange2 = _slicedToArray(timeRange, 2),
timeFrom = _timeRange2[0],
@@ -330,7 +357,7 @@ var ZabbixAPIDatasource = function () {
};
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 _responseHandler2.default.handleText(history, items, target);
});
} else {
@@ -338,10 +365,39 @@ var ZabbixAPIDatasource = function () {
}
});
}
/**
* Query target data for Item ID mode
*/
}, {
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 = _lodash2.default.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);
});
}
/**
* Query target data for IT Services mode
*/
}, {
key: 'queryITServiceData',
value: function queryITServiceData(target, timeRange, options) {
var _this4 = this;
var _this6 = this;
// Don't show undefined and hidden targets
if (target.hide || !target.itservice && !target.itServiceFilter || !target.slaProperty) {
@@ -369,7 +425,7 @@ var ZabbixAPIDatasource = function () {
itServiceIds = _lodash2.default.map(itServices, 'serviceid');
return itServiceIds;
}).then(function (serviceids) {
return _this4.zabbix.getSLA(serviceids, timeRange);
return _this6.zabbix.getSLA(serviceids, timeRange);
}).then(function (slaResponse) {
return _lodash2.default.map(itServiceIds, function (serviceid) {
var itservice = _lodash2.default.find(itServices, { 'serviceid': serviceid });
@@ -386,15 +442,15 @@ var ZabbixAPIDatasource = function () {
}, {
key: 'testDatasource',
value: function testDatasource() {
var _this5 = this;
var _this7 = this;
var zabbixVersion = void 0;
return this.zabbix.getVersion().then(function (version) {
zabbixVersion = version;
return _this5.zabbix.login();
return _this7.zabbix.login();
}).then(function () {
if (_this5.enableDirectDBConnection) {
return _this5.zabbix.dbConnector.testSQLDataSource();
if (_this7.enableDirectDBConnection) {
return _this7.zabbix.dbConnector.testSQLDataSource();
} else {
return Promise.resolve();
}
@@ -442,14 +498,14 @@ var ZabbixAPIDatasource = function () {
}, {
key: 'metricFindQuery',
value: function metricFindQuery(query) {
var _this6 = this;
var _this8 = this;
var result = void 0;
var parts = [];
// Split query. Query structure: group.host.app.item
_lodash2.default.each(utils.splitTemplateQuery(query), function (part) {
part = _this6.replaceTemplateVars(part, {});
part = _this8.replaceTemplateVars(part, {});
// Replace wildcard to regex
if (part === '*') {
@@ -491,7 +547,7 @@ var ZabbixAPIDatasource = function () {
}, {
key: 'annotationQuery',
value: function annotationQuery(options) {
var _this7 = this;
var _this9 = this;
var timeFrom = Math.ceil(dateMath.parse(options.rangeRaw.from) / 1000);
var timeTo = Math.ceil(dateMath.parse(options.rangeRaw.to) / 1000);
@@ -509,7 +565,7 @@ var ZabbixAPIDatasource = function () {
return getTriggers.then(function (triggers) {
// Filter triggers by description
var triggerName = _this7.replaceTemplateVars(annotation.trigger, {});
var triggerName = _this9.replaceTemplateVars(annotation.trigger, {});
if (utils.isRegex(triggerName)) {
triggers = _lodash2.default.filter(triggers, function (trigger) {
return utils.buildRegex(triggerName).test(trigger.description);
@@ -526,7 +582,7 @@ var ZabbixAPIDatasource = function () {
});
var objectids = _lodash2.default.map(triggers, 'triggerid');
return _this7.zabbix.getEvents(objectids, timeFrom, timeTo, showOkEvents).then(function (events) {
return _this9.zabbix.getEvents(objectids, timeFrom, timeTo, showOkEvents).then(function (events) {
var indexedTriggers = _lodash2.default.keyBy(triggers, 'triggerid');
// Hide acknowledged events if option enabled
@@ -567,23 +623,23 @@ var ZabbixAPIDatasource = function () {
}, {
key: 'alertQuery',
value: function alertQuery(options) {
var _this8 = this;
var _this10 = this;
var enabled_targets = filterEnabledTargets(options.targets);
var getPanelItems = _lodash2.default.map(enabled_targets, function (t) {
var target = _lodash2.default.cloneDeep(t);
_this8.replaceTargetVariables(target, options);
return _this8.zabbix.getItemsFromTarget(target, { itemtype: 'num' });
_this10.replaceTargetVariables(target, options);
return _this10.zabbix.getItemsFromTarget(target, { itemtype: 'num' });
});
return Promise.all(getPanelItems).then(function (results) {
var items = _lodash2.default.flatten(results);
var itemids = _lodash2.default.map(items, 'itemid');
return _this8.zabbix.getAlerts(itemids);
return _this10.zabbix.getAlerts(itemids);
}).then(function (triggers) {
triggers = _lodash2.default.filter(triggers, function (trigger) {
return trigger.priority >= _this8.alertingMinSeverity;
return trigger.priority >= _this10.alertingMinSeverity;
});
if (!triggers || triggers.length === 0) {
@@ -614,12 +670,12 @@ var ZabbixAPIDatasource = function () {
}, {
key: 'replaceTargetVariables',
value: function replaceTargetVariables(target, options) {
var _this9 = this;
var _this11 = this;
var parts = ['group', 'host', 'application', 'item'];
_lodash2.default.forEach(parts, function (p) {
if (target[p] && target[p].filter) {
target[p].filter = _this9.replaceTemplateVars(target[p].filter, options.scopedVars);
target[p].filter = _this11.replaceTemplateVars(target[p].filter, options.scopedVars);
}
});
target.textFilter = this.replaceTemplateVars(target.textFilter, options.scopedVars);
@@ -627,9 +683,9 @@ var ZabbixAPIDatasource = function () {
_lodash2.default.forEach(target.functions, function (func) {
func.params = _lodash2.default.map(func.params, function (param) {
if (typeof param === 'number') {
return +_this9.templateSrv.replace(param.toString(), options.scopedVars);
return +_this11.templateSrv.replace(param.toString(), options.scopedVars);
} else {
return _this9.templateSrv.replace(param, options.scopedVars);
return _this11.templateSrv.replace(param, options.scopedVars);
}
});
});
@@ -711,6 +767,13 @@ function zabbixTemplateFormat(value) {
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:

View File

@@ -60,10 +60,13 @@ var ZabbixQueryController = exports.ZabbixQueryController = function (_QueryCtrl
_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" }];
@@ -74,6 +77,7 @@ var ZabbixQueryController = exports.ZabbixQueryController = function (_QueryCtrl
_this.getApplicationNames = _lodash2.default.bind(_this.getMetricNames, _this, 'appList');
_this.getItemNames = _lodash2.default.bind(_this.getMetricNames, _this, 'itemList');
_this.getITServices = _lodash2.default.bind(_this.getMetricNames, _this, 'itServiceList');
_this.getVariables = _lodash2.default.bind(_this.getTemplateVariables, _this);
// Update metric suggestion when template variable was changed
$rootScope.$on('template-variable-value-updated', function () {
@@ -133,7 +137,8 @@ var ZabbixQueryController = exports.ZabbixQueryController = function (_QueryCtrl
_createClass(ZabbixQueryController, [{
key: 'initFilters',
value: function initFilters() {
var itemtype = this.editorModes[this.target.mode].value;
var itemtype = _lodash2.default.find(this.editorModes, { 'mode': this.target.mode });
itemtype = itemtype ? itemtype.value : null;
return Promise.all([this.suggestGroups(), this.suggestHosts(), this.suggestApps(), this.suggestItems(itemtype)]);
}
@@ -155,6 +160,13 @@ var ZabbixQueryController = exports.ZabbixQueryController = function (_QueryCtrl
return metrics;
}
}, {
key: 'getTemplateVariables',
value: function getTemplateVariables() {
return _lodash2.default.map(this.templateSrv.variables, function (variable) {
return '$' + variable.name;
});
}
}, {
key: 'suggestGroups',
value: function suggestGroups() {

View File

@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
});
exports.regexPattern = undefined;
exports.expandItemName = expandItemName;
exports.expandItems = expandItems;
exports.containsMacro = containsMacro;
exports.replaceMacro = replaceMacro;
exports.splitTemplateQuery = splitTemplateQuery;
@@ -49,6 +50,15 @@ function expandItemName(name, key) {
return name;
}
function expandItems(items) {
_lodash2.default.forEach(items, function (item) {
item.item = item.name;
item.name = expandItemName(item.item, item.key_);
return item;
});
return items;
}
function splitKeyParams(paramStr) {
var params = [];
var quoted = false;

View File

@@ -64,6 +64,7 @@ function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy, ZabbixDBConnector)
// 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);

View File

@@ -217,16 +217,19 @@ function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) {
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) {
_lodash2.default.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',

View File

@@ -66,6 +66,9 @@ function ZabbixCachingProxyFactory() {
this.itemPromises = {};
this.getItemsOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getItems, this.zabbixAPI), this.itemPromises, getRequestHash);
this.itemByIdPromises = {};
this.getItemsByIdOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getItemsByIDs, this.zabbixAPI), this.itemPromises, getRequestHash);
this.itServicesPromises = {};
this.getITServicesOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getITService, this.zabbixAPI), this.itServicesPromises, getRequestHash);
@@ -129,6 +132,12 @@ function ZabbixCachingProxyFactory() {
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() {

View File

@@ -1,7 +1,8 @@
// Editor modes
export const MODE_METRICS = 0;
export const MODE_TEXT = 2;
export const MODE_ITSERVICE = 1;
export const MODE_TEXT = 2;
export const MODE_ITEMID = 3;
// Triggers severity
export const SEV_NOT_CLASSIFIED = 0;

View File

@@ -89,6 +89,11 @@ class ZabbixAPIDatasource {
// Create request for each target
let promises = _.map(options.targets, t => {
// Don't request undefined and hidden targets
if (t.hide) {
return [];
}
let timeFrom = Math.ceil(dateMath.parse(options.range.from) / 1000);
let timeTo = Math.ceil(dateMath.parse(options.range.to) / 1000);
@@ -108,7 +113,7 @@ class ZabbixAPIDatasource {
let 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);
@@ -121,11 +126,11 @@ class ZabbixAPIDatasource {
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);
}
}
// IT services mode
else if (target.mode === c.MODE_ITSERVICE) {
} else if (target.mode === c.MODE_ITSERVICE) {
// IT services mode
return this.queryITServiceData(target, timeRange, options);
}
});
@@ -138,45 +143,55 @@ class ZabbixAPIDatasource {
});
}
/**
* Query target data for Metrics mode
*/
queryNumericData(target, timeRange, useTrends, options) {
let [timeFrom, timeTo] = timeRange;
let getItemOptions = {
itemtype: 'num'
};
return this.zabbix.getItemsFromTarget(target, getItemOptions)
.then(items => {
let getHistoryPromise;
options.consolidateBy = getConsolidateBy(target);
return this.queryNumericDataForItems(items, target, timeRange, useTrends, options);
});
}
if (useTrends) {
if (this.enableDirectDBConnection) {
getHistoryPromise = this.zabbix.getTrendsDB(items, timeFrom, timeTo, options)
.then(history => this.zabbix.dbConnector.handleGrafanaTSResponse(history, items));
} else {
let valueType = this.getTrendValueType(target);
getHistoryPromise = this.zabbix.getTrend(items, timeFrom, timeTo)
.then(history => responseHandler.handleTrends(history, items, valueType))
.then(timeseries => {
// Sort trend data, issue #202
_.forEach(timeseries, series => {
series.datapoints = _.sortBy(series.datapoints, point => point[c.DATAPOINT_TS]);
});
return timeseries;
});
}
/**
* Query history for numeric items
*/
queryNumericDataForItems(items, target, timeRange, useTrends, options) {
let [timeFrom, timeTo] = timeRange;
let getHistoryPromise;
options.consolidateBy = getConsolidateBy(target);
if (useTrends) {
if (this.enableDirectDBConnection) {
getHistoryPromise = this.zabbix.getTrendsDB(items, timeFrom, timeTo, options)
.then(history => this.zabbix.dbConnector.handleGrafanaTSResponse(history, items));
} else {
// Use history
if (this.enableDirectDBConnection) {
getHistoryPromise = this.zabbix.getHistoryDB(items, timeFrom, timeTo, options)
.then(history => this.zabbix.dbConnector.handleGrafanaTSResponse(history, items));
} else {
getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo)
.then(history => responseHandler.handleHistory(history, items));
}
let valueType = this.getTrendValueType(target);
getHistoryPromise = this.zabbix.getTrend(items, timeFrom, timeTo)
.then(history => responseHandler.handleTrends(history, items, valueType))
.then(timeseries => {
// Sort trend data, issue #202
_.forEach(timeseries, series => {
series.datapoints = _.sortBy(series.datapoints, point => point[c.DATAPOINT_TS]);
});
return timeseries;
});
}
} else {
// Use history
if (this.enableDirectDBConnection) {
getHistoryPromise = this.zabbix.getHistoryDB(items, timeFrom, timeTo, options)
.then(history => this.zabbix.dbConnector.handleGrafanaTSResponse(history, items));
} else {
getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo)
.then(history => responseHandler.handleHistory(history, items));
}
}
return getHistoryPromise;
})
return getHistoryPromise
.then(timeseries => this.applyDataProcessingFunctions(timeseries, target))
.then(timeseries => downsampleSeries(timeseries, options))
.catch(error => {
@@ -250,6 +265,9 @@ class ZabbixAPIDatasource {
}
}
/**
* Query target data for Text mode
*/
queryTextData(target, timeRange) {
let [timeFrom, timeTo] = timeRange;
let options = {
@@ -268,6 +286,27 @@ class ZabbixAPIDatasource {
});
}
/**
* Query target data for Item ID mode
*/
queryItemIdData(target, timeRange, useTrends, options) {
let itemids = target.itemids;
itemids = this.templateSrv.replace(itemids, options.scopedVars, zabbixItemIdsTemplateFormat);
itemids = _.map(itemids.split(','), itemid => itemid.trim());
if (!itemids) {
return [];
}
return this.zabbix.getItemsByIDs(itemids)
.then(items => {
return this.queryNumericDataForItems(items, target, timeRange, useTrends, options);
});
}
/**
* Query target data for IT Services mode
*/
queryITServiceData(target, timeRange, options) {
// Don't show undefined and hidden targets
if (target.hide || (!target.itservice && !target.itServiceFilter) || !target.slaProperty) {
@@ -624,6 +663,13 @@ function zabbixTemplateFormat(value) {
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:

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,7 +17,7 @@
</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>
<input type="text"
@@ -48,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>
@@ -85,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>
@@ -131,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()">
@@ -139,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>
@@ -153,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>
@@ -167,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

@@ -21,10 +21,18 @@ export class ZabbixQueryController extends QueryCtrl {
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 = [
@@ -41,6 +49,7 @@ export class ZabbixQueryController extends QueryCtrl {
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', () => this.onVariableChange());
@@ -97,7 +106,8 @@ export class ZabbixQueryController extends QueryCtrl {
}
initFilters() {
let itemtype = this.editorModes[this.target.mode].value;
let itemtype = _.find(this.editorModes, {'mode': this.target.mode});
itemtype = itemtype ? itemtype.value : null;
return Promise.all([
this.suggestGroups(),
this.suggestHosts(),
@@ -122,6 +132,12 @@ export class ZabbixQueryController extends QueryCtrl {
return metrics;
}
getTemplateVariables() {
return _.map(this.templateSrv.variables, variable => {
return '$' + variable.name;
});
}
suggestGroups() {
return this.zabbix.getAllGroups()
.then(groups => {

View File

@@ -22,6 +22,15 @@ export function expandItemName(name, key) {
return name;
}
export function expandItems(items) {
_.forEach(items, item => {
item.item = item.name;
item.name = expandItemName(item.item, item.key_);
return item;
});
return items;
}
function splitKeyParams(paramStr) {
let params = [];
let quoted = false;

View File

@@ -36,6 +36,7 @@ function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy, ZabbixDBConnector)
// 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);

View File

@@ -165,10 +165,7 @@ function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) {
sortfield: 'name',
webitems: true,
filter: {},
selectHosts: [
'hostid',
'name'
]
selectHosts: ['hostid', 'name']
};
if (hostids) {
params.hostids = hostids;
@@ -186,16 +183,25 @@ function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) {
}
return this.request('item.get', params)
.then(expandItems);
.then(utils.expandItems);
}
function expandItems(items) {
_.forEach(items, item => {
item.item = item.name;
item.name = utils.expandItemName(item.item, item.key_);
return item;
});
return items;
}
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) {

View File

@@ -57,6 +57,10 @@ function ZabbixCachingProxyFactory() {
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);
@@ -116,6 +120,11 @@ function ZabbixCachingProxyFactory() {
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);
}