Merge branch 'text-to-table'
This commit is contained in:
6
dist/datasource-zabbix/datasource.js
vendored
6
dist/datasource-zabbix/datasource.js
vendored
@@ -502,7 +502,11 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations',
|
||||
return this.zabbix.getItemsFromTarget(target, options).then(function (items) {
|
||||
if (items.length) {
|
||||
return _this4.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
|
||||
return responseHandler.handleText(history, items, target);
|
||||
if (target.resultFormat === 'table') {
|
||||
return responseHandler.handleHistoryAsTable(history, items, target);
|
||||
} else {
|
||||
return responseHandler.handleText(history, items, target);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return Promise.resolve([]);
|
||||
|
||||
2
dist/datasource-zabbix/datasource.js.map
vendored
2
dist/datasource-zabbix/datasource.js.map
vendored
File diff suppressed because one or more lines are too long
1
dist/datasource-zabbix/migrations.js
vendored
1
dist/datasource-zabbix/migrations.js
vendored
@@ -32,6 +32,7 @@ System.register([], function (_export, _context) {
|
||||
_export("migrateFrom2To3version", migrateFrom2To3version);
|
||||
|
||||
function migrate(target) {
|
||||
target.resultFormat = target.resultFormat || 'time_series';
|
||||
if (isGrafana2target(target)) {
|
||||
return migrateFrom2To3version(target);
|
||||
} else {
|
||||
|
||||
2
dist/datasource-zabbix/migrations.js.map
vendored
2
dist/datasource-zabbix/migrations.js.map
vendored
@@ -1 +1 @@
|
||||
{"version":3,"sources":["../../src/datasource-zabbix/migrations.js"],"names":["isGrafana2target","target","mode","hostFilter","itemFilter","downsampleFunction","host","item","filter","undefined","migrateFrom2To3version","group","name","convertToRegex","application","migrate","str"],"mappings":";;;;;AAAA;;;;;AAKO,WAASA,gBAAT,CAA0BC,MAA1B,EAAkC;AACvC,QAAI,CAACA,OAAOC,IAAR,IAAgBD,OAAOC,IAAP,KAAgB,CAAhC,IAAqCD,OAAOC,IAAP,KAAgB,CAAzD,EAA4D;AAC1D,UAAI,CAACD,OAAOE,UAAP,IAAqBF,OAAOG,UAA5B,IAA0CH,OAAOI,kBAAjD,IACAJ,OAAOK,IAAP,IAAeL,OAAOK,IAAP,CAAYA,IAD5B,KAECL,OAAOM,IAAP,CAAYC,MAAZ,KAAuBC,SAAvB,IAAoCR,OAAOK,IAAP,CAAYE,MAAZ,KAAuBC,SAFhE,EAE4E;AAC1E,eAAO,IAAP;AACD,OAJD,MAIO;AACL,eAAO,KAAP;AACD;AACF,KARD,MAQO;AACL,aAAO,KAAP;AACD;AACF;;8BAZeT,gB;;AAcT,WAASU,sBAAT,CAAgCT,MAAhC,EAAwC;AAC7CA,WAAOU,KAAP,CAAaH,MAAb,GAAsBP,OAAOU,KAAP,CAAaC,IAAb,KAAsB,GAAtB,GAA4B,MAA5B,GAAqCX,OAAOU,KAAP,CAAaC,IAAxE;AACAX,WAAOK,IAAP,CAAYE,MAAZ,GAAqBP,OAAOK,IAAP,CAAYM,IAAZ,KAAqB,GAArB,GAA2BC,eAAeZ,OAAOE,UAAtB,CAA3B,GAA+DF,OAAOK,IAAP,CAAYM,IAAhG;AACAX,WAAOa,WAAP,CAAmBN,MAAnB,GAA4BP,OAAOa,WAAP,CAAmBF,IAAnB,KAA4B,GAA5B,GAAkC,EAAlC,GAAuCX,OAAOa,WAAP,CAAmBF,IAAtF;AACAX,WAAOM,IAAP,CAAYC,MAAZ,GAAqBP,OAAOM,IAAP,CAAYK,IAAZ,KAAqB,KAArB,GAA6BC,eAAeZ,OAAOG,UAAtB,CAA7B,GAAiEH,OAAOM,IAAP,CAAYK,IAAlG;AACA,WAAOX,MAAP;AACD;oCANeS,sB;;AAQT,WAASK,OAAT,CAAiBd,MAAjB,EAAyB;AAC9B,QAAID,iBAAiBC,MAAjB,CAAJ,EAA8B;AAC5B,aAAOS,uBAAuBT,MAAvB,CAAP;AACD,KAFD,MAEO;AACL,aAAOA,MAAP;AACD;AACF;;qBANec,O;;AAQhB,WAASF,cAAT,CAAwBG,GAAxB,EAA6B;AAC3B,QAAIA,GAAJ,EAAS;AACP,aAAO,MAAMA,GAAN,GAAY,GAAnB;AACD,KAFD,MAEO;AACL,aAAO,MAAP;AACD;AACF,G","file":"migrations.js","sourcesContent":["/**\n * Query format migration.\n * This module can detect query format version and make migration.\n */\n\nexport function isGrafana2target(target) {\n if (!target.mode || target.mode === 0 || target.mode === 2) {\n if ((target.hostFilter || target.itemFilter || target.downsampleFunction ||\n (target.host && target.host.host)) &&\n (target.item.filter === undefined && target.host.filter === undefined)) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n}\n\nexport function migrateFrom2To3version(target) {\n target.group.filter = target.group.name === \"*\" ? \"/.*/\" : target.group.name;\n target.host.filter = target.host.name === \"*\" ? convertToRegex(target.hostFilter) : target.host.name;\n target.application.filter = target.application.name === \"*\" ? \"\" : target.application.name;\n target.item.filter = target.item.name === \"All\" ? convertToRegex(target.itemFilter) : target.item.name;\n return target;\n}\n\nexport function migrate(target) {\n if (isGrafana2target(target)) {\n return migrateFrom2To3version(target);\n } else {\n return target;\n }\n}\n\nfunction convertToRegex(str) {\n if (str) {\n return '/' + str + '/';\n } else {\n return '/.*/';\n }\n}\n"]}
|
||||
{"version":3,"sources":["../../src/datasource-zabbix/migrations.js"],"names":["isGrafana2target","target","mode","hostFilter","itemFilter","downsampleFunction","host","item","filter","undefined","migrateFrom2To3version","group","name","convertToRegex","application","migrate","resultFormat","str"],"mappings":";;;;;AAAA;;;;;AAKO,WAASA,gBAAT,CAA0BC,MAA1B,EAAkC;AACvC,QAAI,CAACA,OAAOC,IAAR,IAAgBD,OAAOC,IAAP,KAAgB,CAAhC,IAAqCD,OAAOC,IAAP,KAAgB,CAAzD,EAA4D;AAC1D,UAAI,CAACD,OAAOE,UAAP,IAAqBF,OAAOG,UAA5B,IAA0CH,OAAOI,kBAAjD,IACAJ,OAAOK,IAAP,IAAeL,OAAOK,IAAP,CAAYA,IAD5B,KAECL,OAAOM,IAAP,CAAYC,MAAZ,KAAuBC,SAAvB,IAAoCR,OAAOK,IAAP,CAAYE,MAAZ,KAAuBC,SAFhE,EAE4E;AAC1E,eAAO,IAAP;AACD,OAJD,MAIO;AACL,eAAO,KAAP;AACD;AACF,KARD,MAQO;AACL,aAAO,KAAP;AACD;AACF;;8BAZeT,gB;;AAcT,WAASU,sBAAT,CAAgCT,MAAhC,EAAwC;AAC7CA,WAAOU,KAAP,CAAaH,MAAb,GAAsBP,OAAOU,KAAP,CAAaC,IAAb,KAAsB,GAAtB,GAA4B,MAA5B,GAAqCX,OAAOU,KAAP,CAAaC,IAAxE;AACAX,WAAOK,IAAP,CAAYE,MAAZ,GAAqBP,OAAOK,IAAP,CAAYM,IAAZ,KAAqB,GAArB,GAA2BC,eAAeZ,OAAOE,UAAtB,CAA3B,GAA+DF,OAAOK,IAAP,CAAYM,IAAhG;AACAX,WAAOa,WAAP,CAAmBN,MAAnB,GAA4BP,OAAOa,WAAP,CAAmBF,IAAnB,KAA4B,GAA5B,GAAkC,EAAlC,GAAuCX,OAAOa,WAAP,CAAmBF,IAAtF;AACAX,WAAOM,IAAP,CAAYC,MAAZ,GAAqBP,OAAOM,IAAP,CAAYK,IAAZ,KAAqB,KAArB,GAA6BC,eAAeZ,OAAOG,UAAtB,CAA7B,GAAiEH,OAAOM,IAAP,CAAYK,IAAlG;AACA,WAAOX,MAAP;AACD;oCANeS,sB;;AAQT,WAASK,OAAT,CAAiBd,MAAjB,EAAyB;AAC9BA,WAAOe,YAAP,GAAsBf,OAAOe,YAAP,IAAuB,aAA7C;AACA,QAAIhB,iBAAiBC,MAAjB,CAAJ,EAA8B;AAC5B,aAAOS,uBAAuBT,MAAvB,CAAP;AACD,KAFD,MAEO;AACL,aAAOA,MAAP;AACD;AACF;;qBAPec,O;;AAShB,WAASF,cAAT,CAAwBI,GAAxB,EAA6B;AAC3B,QAAIA,GAAJ,EAAS;AACP,aAAO,MAAMA,GAAN,GAAY,GAAnB;AACD,KAFD,MAEO;AACL,aAAO,MAAP;AACD;AACF,G","file":"migrations.js","sourcesContent":["/**\n * Query format migration.\n * This module can detect query format version and make migration.\n */\n\nexport function isGrafana2target(target) {\n if (!target.mode || target.mode === 0 || target.mode === 2) {\n if ((target.hostFilter || target.itemFilter || target.downsampleFunction ||\n (target.host && target.host.host)) &&\n (target.item.filter === undefined && target.host.filter === undefined)) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n}\n\nexport function migrateFrom2To3version(target) {\n target.group.filter = target.group.name === \"*\" ? \"/.*/\" : target.group.name;\n target.host.filter = target.host.name === \"*\" ? convertToRegex(target.hostFilter) : target.host.name;\n target.application.filter = target.application.name === \"*\" ? \"\" : target.application.name;\n target.item.filter = target.item.name === \"All\" ? convertToRegex(target.itemFilter) : target.item.name;\n return target;\n}\n\nexport function migrate(target) {\n target.resultFormat = target.resultFormat || 'time_series';\n if (isGrafana2target(target)) {\n return migrateFrom2To3version(target);\n } else {\n return target;\n }\n}\n\nfunction convertToRegex(str) {\n if (str) {\n return '/' + str + '/';\n } else {\n return '/.*/';\n }\n}\n"]}
|
||||
@@ -11,6 +11,12 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form" ng-show="ctrl.target.mode == editorMode.TEXT">
|
||||
<label class="gf-form-label query-keyword width-8">Format As</label>
|
||||
<div class="gf-form-select-wrapper">
|
||||
<select class="gf-form-input gf-size-auto" ng-model="ctrl.target.resultFormat" ng-options="f.value as f.text for f in ctrl.resultFormats" ng-change="ctrl.refresh()"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form gf-form--grow">
|
||||
<div class="gf-form-label gf-form-label--grow"></div>
|
||||
</div>
|
||||
|
||||
2
dist/datasource-zabbix/query.controller.js
vendored
2
dist/datasource-zabbix/query.controller.js
vendored
@@ -97,6 +97,8 @@ System.register(['app/plugins/sdk', 'lodash', './constants', './utils', './metri
|
||||
|
||||
_this.ackFilters = [{ text: 'all triggers', value: 2 }, { text: 'unacknowledged', value: 0 }, { text: 'acknowledged', value: 1 }];
|
||||
|
||||
_this.resultFormats = [{ text: 'Time series', value: 'time_series' }, { text: 'Table', value: 'table' }];
|
||||
|
||||
_this.triggerSeverity = c.TRIGGER_SEVERITY;
|
||||
|
||||
// Map functions for bs-typeahead
|
||||
|
||||
File diff suppressed because one or more lines are too long
58
dist/datasource-zabbix/responseHandler.js
vendored
58
dist/datasource-zabbix/responseHandler.js
vendored
@@ -72,7 +72,34 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
||||
|
||||
var convertTextCallback = _.partial(convertText, target);
|
||||
return convertHistory(history, items, addHostName, convertTextCallback);
|
||||
}function convertText(target, point) {
|
||||
}function handleHistoryAsTable(history, items, target) {
|
||||
var table = new TableModel();
|
||||
table.addColumn({ text: 'Host' });
|
||||
table.addColumn({ text: 'Item' });
|
||||
table.addColumn({ text: 'Key' });
|
||||
table.addColumn({ text: 'Last value' });
|
||||
|
||||
var grouped_history = _.groupBy(history, 'itemid');
|
||||
_.each(items, function (item) {
|
||||
var itemHistory = grouped_history[item.itemid] || [];
|
||||
var lastPoint = _.last(itemHistory);
|
||||
var lastValue = lastPoint ? lastPoint.value : null;
|
||||
|
||||
// Regex-based extractor
|
||||
if (target.textFilter) {
|
||||
lastValue = extractText(lastValue, target.textFilter, target.useCaptureGroups);
|
||||
}
|
||||
|
||||
var host = _.first(item.hosts);
|
||||
host = host ? host.name : "";
|
||||
|
||||
table.rows.push([host, item.name, item.key_, lastValue]);
|
||||
});
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
function convertText(target, point) {
|
||||
var value = point.value;
|
||||
|
||||
// Regex-based extractor
|
||||
@@ -81,9 +108,7 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
||||
}
|
||||
|
||||
return [value, point.clock * 1000 + Math.round(point.ns / 1000000)];
|
||||
}
|
||||
|
||||
function extractText(str, pattern, useCaptureGroups) {
|
||||
}function extractText(str, pattern, useCaptureGroups) {
|
||||
var extractPattern = new RegExp(pattern);
|
||||
var extractedValue = extractPattern.exec(str);
|
||||
if (extractedValue) {
|
||||
@@ -94,7 +119,9 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
||||
}
|
||||
}
|
||||
return extractedValue;
|
||||
}function handleSLAResponse(itservice, slaProperty, slaObject) {
|
||||
}
|
||||
|
||||
function handleSLAResponse(itservice, slaProperty, slaObject) {
|
||||
var targetSLA = slaObject[itservice.serviceid].sla[0];
|
||||
if (slaProperty.property === 'status') {
|
||||
var targetStatus = parseInt(slaObject[itservice.serviceid].status);
|
||||
@@ -108,9 +135,7 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
||||
datapoints: [[targetSLA[slaProperty.property], targetSLA.from * 1000], [targetSLA[slaProperty.property], targetSLA.to * 1000]]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function handleTriggersResponse(triggers, timeRange) {
|
||||
}function handleTriggersResponse(triggers, timeRange) {
|
||||
if (_.isNumber(triggers)) {
|
||||
return {
|
||||
target: "triggers count",
|
||||
@@ -134,7 +159,9 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
||||
});
|
||||
return table;
|
||||
}
|
||||
}function getTriggerStats(triggers) {
|
||||
}
|
||||
|
||||
function getTriggerStats(triggers) {
|
||||
var groups = _.uniq(_.flattenDeep(_.map(triggers, function (trigger) {
|
||||
return _.map(trigger.groups, 'name');
|
||||
})));
|
||||
@@ -149,12 +176,12 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
||||
});
|
||||
});
|
||||
return stats;
|
||||
}
|
||||
|
||||
function convertHistoryPoint(point) {
|
||||
}function convertHistoryPoint(point) {
|
||||
// Value must be a number for properly work
|
||||
return [Number(point.value), point.clock * 1000 + Math.round(point.ns / 1000000)];
|
||||
}function convertTrendPoint(valueType, point) {
|
||||
}
|
||||
|
||||
function convertTrendPoint(valueType, point) {
|
||||
var value;
|
||||
switch (valueType) {
|
||||
case "min":
|
||||
@@ -177,9 +204,7 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
||||
}
|
||||
|
||||
return [Number(value), point.clock * 1000];
|
||||
}
|
||||
|
||||
return {
|
||||
}return {
|
||||
setters: [function (_lodash) {
|
||||
_ = _lodash.default;
|
||||
}, function (_appCoreTable_model) {
|
||||
@@ -193,6 +218,7 @@ System.register(['lodash', 'app/core/table_model', './constants'], function (_ex
|
||||
convertHistory: convertHistory,
|
||||
handleTrends: handleTrends,
|
||||
handleText: handleText,
|
||||
handleHistoryAsTable: handleHistoryAsTable,
|
||||
handleSLAResponse: handleSLAResponse,
|
||||
handleTriggersResponse: handleTriggersResponse
|
||||
});
|
||||
|
||||
File diff suppressed because one or more lines are too long
68
dist/datasource-zabbix/specs/datasource.spec.js
vendored
68
dist/datasource-zabbix/specs/datasource.spec.js
vendored
@@ -1,5 +1,5 @@
|
||||
import _ from 'lodash';
|
||||
import Q from "q";
|
||||
import Q, { Promise } from "q";
|
||||
import {Datasource} from "../module";
|
||||
import {zabbixTemplateFormat} from "../datasource";
|
||||
|
||||
@@ -23,7 +23,10 @@ describe('ZabbixDatasource', () => {
|
||||
ctx.templateSrv = {};
|
||||
ctx.alertSrv = {};
|
||||
ctx.dashboardSrv = {};
|
||||
ctx.zabbixAlertingSrv = {};
|
||||
ctx.zabbixAlertingSrv = {
|
||||
setPanelAlertState: jest.fn(),
|
||||
removeZabbixThreshold: jest.fn(),
|
||||
};
|
||||
ctx.zabbix = () => {};
|
||||
|
||||
ctx.ds = new Datasource(ctx.instanceSettings, ctx.templateSrv, ctx.alertSrv, ctx.dashboardSrv, ctx.zabbixAlertingSrv, ctx.zabbix);
|
||||
@@ -93,6 +96,67 @@ describe('ZabbixDatasource', () => {
|
||||
|
||||
});
|
||||
|
||||
describe('When querying text data', () => {
|
||||
beforeEach(() => {
|
||||
ctx.ds.replaceTemplateVars = (str) => str;
|
||||
ctx.ds.alertQuery = () => Q.when([]);
|
||||
ctx.ds.zabbix.getHistory = jest.fn().mockReturnValue(Promise.resolve([
|
||||
{clock: "1500010200", itemid:"10100", ns:"900111000", value:"Linux first"},
|
||||
{clock: "1500010300", itemid:"10100", ns:"900111000", value:"Linux 2nd"},
|
||||
{clock: "1500010400", itemid:"10100", ns:"900111000", value:"Linux last"}
|
||||
]));
|
||||
|
||||
ctx.ds.zabbix.getItemsFromTarget = jest.fn().mockReturnValue(Promise.resolve([
|
||||
{
|
||||
hosts: [{hostid: "10001", name: "Zabbix server"}],
|
||||
itemid: "10100",
|
||||
name: "System information",
|
||||
key_: "system.uname",
|
||||
}
|
||||
]));
|
||||
|
||||
ctx.options = {
|
||||
range: {from: 'now-1h', to: 'now'},
|
||||
targets: [
|
||||
{
|
||||
group: {filter: ""},
|
||||
host: {filter: "Zabbix server"},
|
||||
application: {filter: ""},
|
||||
item: {filter: "System information"},
|
||||
textFilter: "",
|
||||
useCaptureGroups: true,
|
||||
mode: 2,
|
||||
resultFormat: "table"
|
||||
}
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
it('should return data in table format', (done) => {
|
||||
ctx.ds.query(ctx.options).then(result => {
|
||||
expect(result.data.length).toBe(1);
|
||||
|
||||
let tableData = result.data[0];
|
||||
expect(tableData.columns).toEqual([
|
||||
{text: 'Host'}, {text: 'Item'}, {text: 'Key'}, {text: 'Last value'}
|
||||
]);
|
||||
expect(tableData.rows).toEqual([
|
||||
['Zabbix server', 'System information', 'system.uname', 'Linux last']
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should extract value if regex with capture group is used', (done) => {
|
||||
ctx.options.targets[0].textFilter = "Linux (.*)";
|
||||
ctx.ds.query(ctx.options).then(result => {
|
||||
let tableData = result.data[0];
|
||||
expect(tableData.rows[0][3]).toEqual('last');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('When replacing template variables', () => {
|
||||
|
||||
function testReplacingVariable(target, varValue, expectedResult, done) {
|
||||
|
||||
@@ -290,7 +290,11 @@ class ZabbixAPIDatasource {
|
||||
if (items.length) {
|
||||
return this.zabbix.getHistory(items, timeFrom, timeTo)
|
||||
.then(history => {
|
||||
return responseHandler.handleText(history, items, target);
|
||||
if (target.resultFormat === 'table') {
|
||||
return responseHandler.handleHistoryAsTable(history, items, target);
|
||||
} else {
|
||||
return responseHandler.handleText(history, items, target);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return Promise.resolve([]);
|
||||
|
||||
@@ -26,6 +26,7 @@ export function migrateFrom2To3version(target) {
|
||||
}
|
||||
|
||||
export function migrate(target) {
|
||||
target.resultFormat = target.resultFormat || 'time_series';
|
||||
if (isGrafana2target(target)) {
|
||||
return migrateFrom2To3version(target);
|
||||
} else {
|
||||
|
||||
@@ -11,6 +11,12 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form" ng-show="ctrl.target.mode == editorMode.TEXT">
|
||||
<label class="gf-form-label query-keyword width-8">Format As</label>
|
||||
<div class="gf-form-select-wrapper">
|
||||
<select class="gf-form-input gf-size-auto" ng-model="ctrl.target.resultFormat" ng-options="f.value as f.text for f in ctrl.resultFormats" ng-change="ctrl.refresh()"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form gf-form--grow">
|
||||
<div class="gf-form-label gf-form-label--grow"></div>
|
||||
</div>
|
||||
|
||||
@@ -49,6 +49,8 @@ export class ZabbixQueryController extends QueryCtrl {
|
||||
{text: 'acknowledged', value: 1},
|
||||
];
|
||||
|
||||
this.resultFormats = [{ text: 'Time series', value: 'time_series' }, { text: 'Table', value: 'table' }];
|
||||
|
||||
this.triggerSeverity = c.TRIGGER_SEVERITY;
|
||||
|
||||
// Map functions for bs-typeahead
|
||||
|
||||
@@ -54,6 +54,35 @@ function handleText(history, items, target, addHostName = true) {
|
||||
return convertHistory(history, items, addHostName, convertTextCallback);
|
||||
}
|
||||
|
||||
function handleHistoryAsTable(history, items, target) {
|
||||
let table = new TableModel();
|
||||
table.addColumn({text: 'Host'});
|
||||
table.addColumn({text: 'Item'});
|
||||
table.addColumn({text: 'Key'});
|
||||
table.addColumn({text: 'Last value'});
|
||||
|
||||
let grouped_history = _.groupBy(history, 'itemid');
|
||||
_.each(items, (item) => {
|
||||
let itemHistory = grouped_history[item.itemid] || [];
|
||||
let lastPoint = _.last(itemHistory);
|
||||
let lastValue = lastPoint ? lastPoint.value : null;
|
||||
|
||||
// Regex-based extractor
|
||||
if (target.textFilter) {
|
||||
lastValue = extractText(lastValue, target.textFilter, target.useCaptureGroups);
|
||||
}
|
||||
|
||||
let host = _.first(item.hosts);
|
||||
host = host ? host.name : "";
|
||||
|
||||
table.rows.push([
|
||||
host, item.name, item.key_, lastValue
|
||||
]);
|
||||
});
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
function convertText(target, point) {
|
||||
let value = point.value;
|
||||
|
||||
@@ -182,6 +211,7 @@ export default {
|
||||
convertHistory: convertHistory,
|
||||
handleTrends: handleTrends,
|
||||
handleText: handleText,
|
||||
handleHistoryAsTable: handleHistoryAsTable,
|
||||
handleSLAResponse: handleSLAResponse,
|
||||
handleTriggersResponse: handleTriggersResponse
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import _ from 'lodash';
|
||||
import Q from "q";
|
||||
import Q, { Promise } from "q";
|
||||
import {Datasource} from "../module";
|
||||
import {zabbixTemplateFormat} from "../datasource";
|
||||
|
||||
@@ -23,7 +23,10 @@ describe('ZabbixDatasource', () => {
|
||||
ctx.templateSrv = {};
|
||||
ctx.alertSrv = {};
|
||||
ctx.dashboardSrv = {};
|
||||
ctx.zabbixAlertingSrv = {};
|
||||
ctx.zabbixAlertingSrv = {
|
||||
setPanelAlertState: jest.fn(),
|
||||
removeZabbixThreshold: jest.fn(),
|
||||
};
|
||||
ctx.zabbix = () => {};
|
||||
|
||||
ctx.ds = new Datasource(ctx.instanceSettings, ctx.templateSrv, ctx.alertSrv, ctx.dashboardSrv, ctx.zabbixAlertingSrv, ctx.zabbix);
|
||||
@@ -93,6 +96,67 @@ describe('ZabbixDatasource', () => {
|
||||
|
||||
});
|
||||
|
||||
describe('When querying text data', () => {
|
||||
beforeEach(() => {
|
||||
ctx.ds.replaceTemplateVars = (str) => str;
|
||||
ctx.ds.alertQuery = () => Q.when([]);
|
||||
ctx.ds.zabbix.getHistory = jest.fn().mockReturnValue(Promise.resolve([
|
||||
{clock: "1500010200", itemid:"10100", ns:"900111000", value:"Linux first"},
|
||||
{clock: "1500010300", itemid:"10100", ns:"900111000", value:"Linux 2nd"},
|
||||
{clock: "1500010400", itemid:"10100", ns:"900111000", value:"Linux last"}
|
||||
]));
|
||||
|
||||
ctx.ds.zabbix.getItemsFromTarget = jest.fn().mockReturnValue(Promise.resolve([
|
||||
{
|
||||
hosts: [{hostid: "10001", name: "Zabbix server"}],
|
||||
itemid: "10100",
|
||||
name: "System information",
|
||||
key_: "system.uname",
|
||||
}
|
||||
]));
|
||||
|
||||
ctx.options = {
|
||||
range: {from: 'now-1h', to: 'now'},
|
||||
targets: [
|
||||
{
|
||||
group: {filter: ""},
|
||||
host: {filter: "Zabbix server"},
|
||||
application: {filter: ""},
|
||||
item: {filter: "System information"},
|
||||
textFilter: "",
|
||||
useCaptureGroups: true,
|
||||
mode: 2,
|
||||
resultFormat: "table"
|
||||
}
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
it('should return data in table format', (done) => {
|
||||
ctx.ds.query(ctx.options).then(result => {
|
||||
expect(result.data.length).toBe(1);
|
||||
|
||||
let tableData = result.data[0];
|
||||
expect(tableData.columns).toEqual([
|
||||
{text: 'Host'}, {text: 'Item'}, {text: 'Key'}, {text: 'Last value'}
|
||||
]);
|
||||
expect(tableData.rows).toEqual([
|
||||
['Zabbix server', 'System information', 'system.uname', 'Linux last']
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should extract value if regex with capture group is used', (done) => {
|
||||
ctx.options.targets[0].textFilter = "Linux (.*)";
|
||||
ctx.ds.query(ctx.options).then(result => {
|
||||
let tableData = result.data[0];
|
||||
expect(tableData.rows[0][3]).toEqual('last');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('When replacing template variables', () => {
|
||||
|
||||
function testReplacingVariable(target, varValue, expectedResult, done) {
|
||||
|
||||
@@ -38,7 +38,21 @@ jest.mock('app/core/utils/datemath', () => {
|
||||
}, {virtual: true});
|
||||
|
||||
jest.mock('app/core/table_model', () => {
|
||||
return {};
|
||||
return class TableModel {
|
||||
constructor() {
|
||||
this.columns = [];
|
||||
this.columnMap = {};
|
||||
this.rows = [];
|
||||
this.type = 'table';
|
||||
}
|
||||
|
||||
addColumn(col) {
|
||||
if (!this.columnMap[col.text]) {
|
||||
this.columns.push(col);
|
||||
this.columnMap[col.text] = col;
|
||||
}
|
||||
}
|
||||
};
|
||||
}, {virtual: true});
|
||||
|
||||
jest.mock('jquery', () => 'module not found', {virtual: true});
|
||||
|
||||
Reference in New Issue
Block a user