diff --git a/CHANGELOG.md b/CHANGELOG.md index 62fc90e..40296d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Fixed +- Item name expanding when key contains commas in quoted params, like my_key["a=1,b=2",c,d] ## [3.4.0] - 2017-05-17 ### Added diff --git a/dist/datasource-zabbix/specs/utils_specs.js b/dist/datasource-zabbix/specs/utils_specs.js new file mode 100644 index 0000000..ca52597 --- /dev/null +++ b/dist/datasource-zabbix/specs/utils_specs.js @@ -0,0 +1,60 @@ +import _ from 'lodash'; +import * as utils from '../utils'; + +describe('Utils', () => { + + describe('expandItemName()', () => { + + it('should properly expand unquoted params', (done) => { + let test_cases = [ + { + name: `CPU $2 time`, + key: `system.cpu.util[,user,avg1]`, + expected: "CPU user time" + }, + { + name: `CPU $2 time - $3`, + key: `system.cpu.util[,system,avg1]`, + expected: "CPU system time - avg1" + } + ]; + + _.each(test_cases, test_case => { + let expandedName = utils.expandItemName(test_case.name, test_case.key); + expect(expandedName).to.equal(test_case.expected); + }); + done(); + }); + + it('should properly expand quoted params with commas', (done) => { + let test_cases = [ + { + name: `CPU $2 time`, + key: `system.cpu.util["type=user,value=avg",user]`, + expected: "CPU user time" + }, + { + name: `CPU $1 time`, + key: `system.cpu.util["type=user,value=avg","user"]`, + expected: "CPU type=user,value=avg time" + }, + { + name: `CPU $1 time $3`, + key: `system.cpu.util["type=user,value=avg",,"user"]`, + expected: "CPU type=user,value=avg time user" + }, + { + name: `CPU $1 $2 $3`, + key: `system.cpu.util["type=user,value=avg",time,"user"]`, + expected: "CPU type=user,value=avg time user" + } + ]; + + _.each(test_cases, test_case => { + let expandedName = utils.expandItemName(test_case.name, test_case.key); + expect(expandedName).to.equal(test_case.expected); + }); + done(); + }); + }); +}); diff --git a/dist/datasource-zabbix/utils.js b/dist/datasource-zabbix/utils.js index 4db6fb0..c9afe87 100644 --- a/dist/datasource-zabbix/utils.js +++ b/dist/datasource-zabbix/utils.js @@ -16,7 +16,8 @@ System.register(['lodash', 'moment'], function (_export, _context) { // extract params from key: // "system.cpu.util[,system,avg1]" --> ["", "system", "avg1"] - var key_params = key.substring(key.indexOf('[') + 1, key.lastIndexOf(']')).split(','); + var key_params_str = key.substring(key.indexOf('[') + 1, key.lastIndexOf(']')); + var key_params = splitKeyParams(key_params_str); // replace item parameters for (var i = key_params.length; i >= 1; i--) { @@ -25,10 +26,32 @@ System.register(['lodash', 'moment'], function (_export, _context) { return name; } - // Pattern for testing regex - _export('expandItemName', expandItemName); + function splitKeyParams(paramStr) { + var params = []; + var quoted = false; + var split_symbol = ','; + var param = ''; + + _.forEach(paramStr, function (symbol) { + if (symbol === '"' && !quoted) { + quoted = true; + } else if (symbol === '"' && quoted) { + quoted = false; + } else if (symbol === split_symbol && !quoted) { + params.push(param); + param = ''; + } else { + param += symbol; + } + }); + + params.push(param); + return params; + } + + // Pattern for testing regex function isRegex(str) { return regexPattern.test(str); } diff --git a/dist/datasource-zabbix/utils.js.map b/dist/datasource-zabbix/utils.js.map index bfec5a5..cd8bc71 100644 --- a/dist/datasource-zabbix/utils.js.map +++ b/dist/datasource-zabbix/utils.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/datasource-zabbix/utils.js"],"names":["expandItemName","name","key","key_params","substring","indexOf","lastIndexOf","split","i","length","replace","isRegex","str","regexPattern","test","isTemplateVariable","templateVariables","variablePattern","variables","_","map","variable","includes","buildRegex","matches","match","pattern","flags","undefined","RegExp","escapeRegex","value","parseInterval","interval","intervalPattern","momentInterval","exec","moment","duration","Number","valueOf","parseTimeShiftInterval","formatAcknowledges","acknowledges","formatted_acknowledges","each","ack","timestamp","unix","clock","format","alias","surname","message","concat","convertToZabbixAPIUrl","url","zabbixAPIUrlPattern","trimSlashPattern","callOnce","func","promiseKeeper","Promise","resolve","apply","arguments","then","result","contains"],"mappings":"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","file":"utils.js","sourcesContent":["import _ from 'lodash';\nimport moment from 'moment';\n\n/**\n * Expand Zabbix item name\n *\n * @param {string} name item name, ie \"CPU $2 time\"\n * @param {string} key item key, ie system.cpu.util[,system,avg1]\n * @return {string} expanded name, ie \"CPU system time\"\n */\nexport function expandItemName(name, key) {\n\n // extract params from key:\n // \"system.cpu.util[,system,avg1]\" --> [\"\", \"system\", \"avg1\"]\n var key_params = key.substring(key.indexOf('[') + 1, key.lastIndexOf(']')).split(',');\n\n // replace item parameters\n for (var i = key_params.length; i >= 1; i--) {\n name = name.replace('$' + i, key_params[i - 1]);\n }\n return name;\n}\n\n// Pattern for testing regex\nexport var regexPattern = /^\\/(.*)\\/([gmi]*)$/m;\n\nexport function isRegex(str) {\n return regexPattern.test(str);\n}\n\nexport function isTemplateVariable(str, templateVariables) {\n var variablePattern = /^\\$\\w+/;\n if (variablePattern.test(str)) {\n var variables = _.map(templateVariables, variable => {\n return '$' + variable.name;\n });\n return _.includes(variables, str);\n } else {\n return false;\n }\n}\n\nexport function buildRegex(str) {\n var matches = str.match(regexPattern);\n var pattern = matches[1];\n var flags = matches[2] !== \"\" ? matches[2] : undefined;\n return new RegExp(pattern, flags);\n}\n\n// Need for template variables replace\n// From Grafana's templateSrv.js\nexport function escapeRegex(value) {\n return value.replace(/[\\\\^$*+?.()|[\\]{}\\/]/g, '\\\\$&');\n}\n\nexport function parseInterval(interval) {\n var intervalPattern = /(^[\\d]+)(y|M|w|d|h|m|s)/g;\n var momentInterval = intervalPattern.exec(interval);\n return moment.duration(Number(momentInterval[1]), momentInterval[2]).valueOf();\n}\n\nexport function parseTimeShiftInterval(interval) {\n let intervalPattern = /^([\\+\\-]*)([\\d]+)(y|M|w|d|h|m|s)/g;\n let momentInterval = intervalPattern.exec(interval);\n let duration = 0;\n\n if (momentInterval[1] === '+') {\n duration = 0 - moment.duration(Number(momentInterval[2]), momentInterval[3]).valueOf();\n } else {\n duration = moment.duration(Number(momentInterval[2]), momentInterval[3]).valueOf();\n }\n\n return duration;\n}\n\n/**\n * Format acknowledges.\n *\n * @param {array} acknowledges array of Zabbix acknowledge objects\n * @return {string} HTML-formatted table\n */\nexport function formatAcknowledges(acknowledges) {\n if (acknowledges.length) {\n var formatted_acknowledges = '

Acknowledges:
'\n + '';\n _.each(_.map(acknowledges, function (ack) {\n var timestamp = moment.unix(ack.clock);\n return '';\n }), function (ack) {\n formatted_acknowledges = formatted_acknowledges.concat(ack);\n });\n formatted_acknowledges = formatted_acknowledges.concat('
TimeUserComments
' + timestamp.format(\"DD MMM YYYY HH:mm:ss\") + '' + ack.alias\n + ' (' + ack.name + ' ' + ack.surname + ')' + '' + ack.message + '
');\n return formatted_acknowledges;\n } else {\n return '';\n }\n}\n\nexport function convertToZabbixAPIUrl(url) {\n var zabbixAPIUrlPattern = /.*api_jsonrpc.php$/;\n var trimSlashPattern = /(.*?)[\\/]*$/;\n if (url.match(zabbixAPIUrlPattern)) {\n return url;\n } else {\n return url.replace(trimSlashPattern, \"$1\");\n }\n}\n\n/**\n * Wrap function to prevent multiple calls\n * when waiting for result.\n */\nexport function callOnce(func, promiseKeeper) {\n return function() {\n if (!promiseKeeper) {\n promiseKeeper = Promise.resolve(\n func.apply(this, arguments)\n .then(result => {\n promiseKeeper = null;\n return result;\n })\n );\n }\n return promiseKeeper;\n };\n}\n\n// Fix for backward compatibility with lodash 2.4\nif (!_.includes) {\n _.includes = _.contains;\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/datasource-zabbix/utils.js"],"names":["expandItemName","name","key","key_params_str","substring","indexOf","lastIndexOf","key_params","splitKeyParams","i","length","replace","paramStr","params","quoted","split_symbol","param","_","forEach","symbol","push","isRegex","str","regexPattern","test","isTemplateVariable","templateVariables","variablePattern","variables","map","variable","includes","buildRegex","matches","match","pattern","flags","undefined","RegExp","escapeRegex","value","parseInterval","interval","intervalPattern","momentInterval","exec","moment","duration","Number","valueOf","parseTimeShiftInterval","formatAcknowledges","acknowledges","formatted_acknowledges","each","ack","timestamp","unix","clock","format","alias","surname","message","concat","convertToZabbixAPIUrl","url","zabbixAPIUrlPattern","trimSlashPattern","callOnce","func","promiseKeeper","Promise","resolve","apply","arguments","then","result","contains"],"mappings":";;;;;;;AAGA;;;;;;;AAOO,WAASA,cAAT,CAAwBC,IAAxB,EAA8BC,GAA9B,EAAmC;;AAExC;AACA;AACA,QAAIC,iBAAiBD,IAAIE,SAAJ,CAAcF,IAAIG,OAAJ,CAAY,GAAZ,IAAmB,CAAjC,EAAoCH,IAAII,WAAJ,CAAgB,GAAhB,CAApC,CAArB;AACA,QAAIC,aAAaC,eAAeL,cAAf,CAAjB;;AAEA;AACA,SAAK,IAAIM,IAAIF,WAAWG,MAAxB,EAAgCD,KAAK,CAArC,EAAwCA,GAAxC,EAA6C;AAC3CR,aAAOA,KAAKU,OAAL,CAAa,MAAMF,CAAnB,EAAsBF,WAAWE,IAAI,CAAf,CAAtB,CAAP;AACD;AACD,WAAOR,IAAP;AACD;;4BAZeD,c;;AAchB,WAASQ,cAAT,CAAwBI,QAAxB,EAAkC;AAChC,QAAIC,SAAS,EAAb;AACA,QAAIC,SAAS,KAAb;AACA,QAAIC,eAAe,GAAnB;AACA,QAAIC,QAAQ,EAAZ;;AAEAC,MAAEC,OAAF,CAAUN,QAAV,EAAoB,kBAAU;AAC5B,UAAIO,WAAW,GAAX,IAAkB,CAACL,MAAvB,EAA+B;AAC7BA,iBAAS,IAAT;AACD,OAFD,MAEO,IAAIK,WAAW,GAAX,IAAkBL,MAAtB,EAA8B;AACnCA,iBAAS,KAAT;AACD,OAFM,MAEA,IAAIK,WAAWJ,YAAX,IAA2B,CAACD,MAAhC,EAAwC;AAC7CD,eAAOO,IAAP,CAAYJ,KAAZ;AACAA,gBAAQ,EAAR;AACD,OAHM,MAGA;AACLA,iBAASG,MAAT;AACD;AACF,KAXD;;AAaAN,WAAOO,IAAP,CAAYJ,KAAZ;AACA,WAAOH,MAAP;AACD;;AAED;AAGO,WAASQ,OAAT,CAAiBC,GAAjB,EAAsB;AAC3B,WAAOC,aAAaC,IAAb,CAAkBF,GAAlB,CAAP;AACD;;qBAFeD,O;;AAIT,WAASI,kBAAT,CAA4BH,GAA5B,EAAiCI,iBAAjC,EAAoD;AACzD,QAAIC,kBAAkB,QAAtB;AACA,QAAIA,gBAAgBH,IAAhB,CAAqBF,GAArB,CAAJ,EAA+B;AAC7B,UAAIM,YAAYX,EAAEY,GAAF,CAAMH,iBAAN,EAAyB,oBAAY;AACnD,eAAO,MAAMI,SAAS7B,IAAtB;AACD,OAFe,CAAhB;AAGA,aAAOgB,EAAEc,QAAF,CAAWH,SAAX,EAAsBN,GAAtB,CAAP;AACD,KALD,MAKO;AACL,aAAO,KAAP;AACD;AACF;;gCAVeG,kB;;AAYT,WAASO,UAAT,CAAoBV,GAApB,EAAyB;AAC9B,QAAIW,UAAUX,IAAIY,KAAJ,CAAUX,YAAV,CAAd;AACA,QAAIY,UAAUF,QAAQ,CAAR,CAAd;AACA,QAAIG,QAAQH,QAAQ,CAAR,MAAe,EAAf,GAAoBA,QAAQ,CAAR,CAApB,GAAiCI,SAA7C;AACA,WAAO,IAAIC,MAAJ,CAAWH,OAAX,EAAoBC,KAApB,CAAP;AACD;;AAED;AACA;;wBARgBJ,U;;AAST,WAASO,WAAT,CAAqBC,KAArB,EAA4B;AACjC,WAAOA,MAAM7B,OAAN,CAAc,uBAAd,EAAuC,MAAvC,CAAP;AACD;;yBAFe4B,W;;AAIT,WAASE,aAAT,CAAuBC,QAAvB,EAAiC;AACtC,QAAIC,kBAAkB,0BAAtB;AACA,QAAIC,iBAAiBD,gBAAgBE,IAAhB,CAAqBH,QAArB,CAArB;AACA,WAAOI,OAAOC,QAAP,CAAgBC,OAAOJ,eAAe,CAAf,CAAP,CAAhB,EAA2CA,eAAe,CAAf,CAA3C,EAA8DK,OAA9D,EAAP;AACD;;2BAJeR,a;;AAMT,WAASS,sBAAT,CAAgCR,QAAhC,EAA0C;AAC/C,QAAIC,kBAAkB,mCAAtB;AACA,QAAIC,iBAAiBD,gBAAgBE,IAAhB,CAAqBH,QAArB,CAArB;AACA,QAAIK,WAAW,CAAf;;AAEA,QAAIH,eAAe,CAAf,MAAsB,GAA1B,EAA+B;AAC7BG,iBAAW,IAAID,OAAOC,QAAP,CAAgBC,OAAOJ,eAAe,CAAf,CAAP,CAAhB,EAA2CA,eAAe,CAAf,CAA3C,EAA8DK,OAA9D,EAAf;AACD,KAFD,MAEO;AACLF,iBAAWD,OAAOC,QAAP,CAAgBC,OAAOJ,eAAe,CAAf,CAAP,CAAhB,EAA2CA,eAAe,CAAf,CAA3C,EAA8DK,OAA9D,EAAX;AACD;;AAED,WAAOF,QAAP;AACD;;AAED;;;;;;;oCAdgBG,sB;;AAoBT,WAASC,kBAAT,CAA4BC,YAA5B,EAA0C;AAC/C,QAAIA,aAAa1C,MAAjB,EAAyB;AACvB,UAAI2C,yBAAyB,6DACzB,mDADJ;AAEApC,QAAEqC,IAAF,CAAOrC,EAAEY,GAAF,CAAMuB,YAAN,EAAoB,UAAUG,GAAV,EAAe;AACxC,YAAIC,YAAYV,OAAOW,IAAP,CAAYF,IAAIG,KAAhB,CAAhB;AACA,eAAO,gBAAgBF,UAAUG,MAAV,CAAiB,sBAAjB,CAAhB,GAA2D,eAA3D,GAA6EJ,IAAIK,KAAjF,GACH,IADG,GACIL,IAAItD,IADR,GACe,GADf,GACqBsD,IAAIM,OADzB,GACmC,GADnC,GACyC,WADzC,GACuDN,IAAIO,OAD3D,GACqE,YAD5E;AAED,OAJM,CAAP,EAII,UAAUP,GAAV,EAAe;AACjBF,iCAAyBA,uBAAuBU,MAAvB,CAA8BR,GAA9B,CAAzB;AACD,OAND;AAOAF,+BAAyBA,uBAAuBU,MAAvB,CAA8B,UAA9B,CAAzB;AACA,aAAOV,sBAAP;AACD,KAZD,MAYO;AACL,aAAO,EAAP;AACD;AACF;;gCAhBeF,kB;;AAkBT,WAASa,qBAAT,CAA+BC,GAA/B,EAAoC;AACzC,QAAIC,sBAAsB,oBAA1B;AACA,QAAIC,mBAAmB,aAAvB;AACA,QAAIF,IAAI/B,KAAJ,CAAUgC,mBAAV,CAAJ,EAAoC;AAClC,aAAOD,GAAP;AACD,KAFD,MAEO;AACL,aAAOA,IAAItD,OAAJ,CAAYwD,gBAAZ,EAA8B,IAA9B,CAAP;AACD;AACF;;AAED;;;;;mCAVgBH,qB;;AAcT,WAASI,QAAT,CAAkBC,IAAlB,EAAwBC,aAAxB,EAAuC;AAC5C,WAAO,YAAW;AAChB,UAAI,CAACA,aAAL,EAAoB;AAClBA,wBAAgBC,QAAQC,OAAR,CACdH,KAAKI,KAAL,CAAW,IAAX,EAAiBC,SAAjB,EACCC,IADD,CACM,kBAAU;AACdL,0BAAgB,IAAhB;AACA,iBAAOM,MAAP;AACD,SAJD,CADc,CAAhB;AAOD;AACD,aAAON,aAAP;AACD,KAXD;AAYD;;AAED;;sBAfgBF,Q;;;;AAzITnD,O;;AACA6B,Y;;;8BA+CIvB,Y,GAAe,qB;;;;AAyG1B,UAAI,CAACN,EAAEc,QAAP,EAAiB;AACfd,UAAEc,QAAF,GAAad,EAAE4D,QAAf;AACD","file":"utils.js","sourcesContent":["import _ from 'lodash';\nimport moment from 'moment';\n\n/**\n * Expand Zabbix item name\n *\n * @param {string} name item name, ie \"CPU $2 time\"\n * @param {string} key item key, ie system.cpu.util[,system,avg1]\n * @return {string} expanded name, ie \"CPU system time\"\n */\nexport function expandItemName(name, key) {\n\n // extract params from key:\n // \"system.cpu.util[,system,avg1]\" --> [\"\", \"system\", \"avg1\"]\n let key_params_str = key.substring(key.indexOf('[') + 1, key.lastIndexOf(']'));\n let key_params = splitKeyParams(key_params_str);\n\n // replace item parameters\n for (let i = key_params.length; i >= 1; i--) {\n name = name.replace('$' + i, key_params[i - 1]);\n }\n return name;\n}\n\nfunction splitKeyParams(paramStr) {\n let params = [];\n let quoted = false;\n let split_symbol = ',';\n let param = '';\n\n _.forEach(paramStr, symbol => {\n if (symbol === '\"' && !quoted) {\n quoted = true;\n } else if (symbol === '\"' && quoted) {\n quoted = false;\n } else if (symbol === split_symbol && !quoted) {\n params.push(param);\n param = '';\n } else {\n param += symbol;\n }\n });\n\n params.push(param);\n return params;\n}\n\n// Pattern for testing regex\nexport var regexPattern = /^\\/(.*)\\/([gmi]*)$/m;\n\nexport function isRegex(str) {\n return regexPattern.test(str);\n}\n\nexport function isTemplateVariable(str, templateVariables) {\n var variablePattern = /^\\$\\w+/;\n if (variablePattern.test(str)) {\n var variables = _.map(templateVariables, variable => {\n return '$' + variable.name;\n });\n return _.includes(variables, str);\n } else {\n return false;\n }\n}\n\nexport function buildRegex(str) {\n var matches = str.match(regexPattern);\n var pattern = matches[1];\n var flags = matches[2] !== \"\" ? matches[2] : undefined;\n return new RegExp(pattern, flags);\n}\n\n// Need for template variables replace\n// From Grafana's templateSrv.js\nexport function escapeRegex(value) {\n return value.replace(/[\\\\^$*+?.()|[\\]{}\\/]/g, '\\\\$&');\n}\n\nexport function parseInterval(interval) {\n var intervalPattern = /(^[\\d]+)(y|M|w|d|h|m|s)/g;\n var momentInterval = intervalPattern.exec(interval);\n return moment.duration(Number(momentInterval[1]), momentInterval[2]).valueOf();\n}\n\nexport function parseTimeShiftInterval(interval) {\n let intervalPattern = /^([\\+\\-]*)([\\d]+)(y|M|w|d|h|m|s)/g;\n let momentInterval = intervalPattern.exec(interval);\n let duration = 0;\n\n if (momentInterval[1] === '+') {\n duration = 0 - moment.duration(Number(momentInterval[2]), momentInterval[3]).valueOf();\n } else {\n duration = moment.duration(Number(momentInterval[2]), momentInterval[3]).valueOf();\n }\n\n return duration;\n}\n\n/**\n * Format acknowledges.\n *\n * @param {array} acknowledges array of Zabbix acknowledge objects\n * @return {string} HTML-formatted table\n */\nexport function formatAcknowledges(acknowledges) {\n if (acknowledges.length) {\n var formatted_acknowledges = '

Acknowledges:
'\n + '';\n _.each(_.map(acknowledges, function (ack) {\n var timestamp = moment.unix(ack.clock);\n return '';\n }), function (ack) {\n formatted_acknowledges = formatted_acknowledges.concat(ack);\n });\n formatted_acknowledges = formatted_acknowledges.concat('
TimeUserComments
' + timestamp.format(\"DD MMM YYYY HH:mm:ss\") + '' + ack.alias\n + ' (' + ack.name + ' ' + ack.surname + ')' + '' + ack.message + '
');\n return formatted_acknowledges;\n } else {\n return '';\n }\n}\n\nexport function convertToZabbixAPIUrl(url) {\n var zabbixAPIUrlPattern = /.*api_jsonrpc.php$/;\n var trimSlashPattern = /(.*?)[\\/]*$/;\n if (url.match(zabbixAPIUrlPattern)) {\n return url;\n } else {\n return url.replace(trimSlashPattern, \"$1\");\n }\n}\n\n/**\n * Wrap function to prevent multiple calls\n * when waiting for result.\n */\nexport function callOnce(func, promiseKeeper) {\n return function() {\n if (!promiseKeeper) {\n promiseKeeper = Promise.resolve(\n func.apply(this, arguments)\n .then(result => {\n promiseKeeper = null;\n return result;\n })\n );\n }\n return promiseKeeper;\n };\n}\n\n// Fix for backward compatibility with lodash 2.4\nif (!_.includes) {\n _.includes = _.contains;\n}\n"]} \ No newline at end of file diff --git a/dist/test/datasource-zabbix/specs/utils_specs.js b/dist/test/datasource-zabbix/specs/utils_specs.js new file mode 100644 index 0000000..995bdf8 --- /dev/null +++ b/dist/test/datasource-zabbix/specs/utils_specs.js @@ -0,0 +1,63 @@ +'use strict'; + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _utils = require('../utils'); + +var utils = _interopRequireWildcard(_utils); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +describe('Utils', function () { + + describe('expandItemName()', function () { + + it('should properly expand unquoted params', function (done) { + var test_cases = [{ + name: 'CPU $2 time', + key: 'system.cpu.util[,user,avg1]', + expected: "CPU user time" + }, { + name: 'CPU $2 time - $3', + key: 'system.cpu.util[,system,avg1]', + expected: "CPU system time - avg1" + }]; + + _lodash2.default.each(test_cases, function (test_case) { + var expandedName = utils.expandItemName(test_case.name, test_case.key); + expect(expandedName).to.equal(test_case.expected); + }); + done(); + }); + + it('should properly expand quoted params with commas', function (done) { + var test_cases = [{ + name: 'CPU $2 time', + key: 'system.cpu.util["type=user,value=avg",user]', + expected: "CPU user time" + }, { + name: 'CPU $1 time', + key: 'system.cpu.util["type=user,value=avg","user"]', + expected: "CPU type=user,value=avg time" + }, { + name: 'CPU $1 time $3', + key: 'system.cpu.util["type=user,value=avg",,"user"]', + expected: "CPU type=user,value=avg time user" + }, { + name: 'CPU $1 $2 $3', + key: 'system.cpu.util["type=user,value=avg",time,"user"]', + expected: "CPU type=user,value=avg time user" + }]; + + _lodash2.default.each(test_cases, function (test_case) { + var expandedName = utils.expandItemName(test_case.name, test_case.key); + expect(expandedName).to.equal(test_case.expected); + }); + done(); + }); + }); +}); diff --git a/dist/test/datasource-zabbix/utils.js b/dist/test/datasource-zabbix/utils.js index 36eceb9..00f6418 100644 --- a/dist/test/datasource-zabbix/utils.js +++ b/dist/test/datasource-zabbix/utils.js @@ -36,7 +36,8 @@ function expandItemName(name, key) { // extract params from key: // "system.cpu.util[,system,avg1]" --> ["", "system", "avg1"] - var key_params = key.substring(key.indexOf('[') + 1, key.lastIndexOf(']')).split(','); + var key_params_str = key.substring(key.indexOf('[') + 1, key.lastIndexOf(']')); + var key_params = splitKeyParams(key_params_str); // replace item parameters for (var i = key_params.length; i >= 1; i--) { @@ -45,6 +46,29 @@ function expandItemName(name, key) { return name; } +function splitKeyParams(paramStr) { + var params = []; + var quoted = false; + var split_symbol = ','; + var param = ''; + + _lodash2.default.forEach(paramStr, function (symbol) { + if (symbol === '"' && !quoted) { + quoted = true; + } else if (symbol === '"' && quoted) { + quoted = false; + } else if (symbol === split_symbol && !quoted) { + params.push(param); + param = ''; + } else { + param += symbol; + } + }); + + params.push(param); + return params; +} + // Pattern for testing regex var regexPattern = exports.regexPattern = /^\/(.*)\/([gmi]*)$/m; diff --git a/src/datasource-zabbix/specs/utils_specs.js b/src/datasource-zabbix/specs/utils_specs.js new file mode 100644 index 0000000..ca52597 --- /dev/null +++ b/src/datasource-zabbix/specs/utils_specs.js @@ -0,0 +1,60 @@ +import _ from 'lodash'; +import * as utils from '../utils'; + +describe('Utils', () => { + + describe('expandItemName()', () => { + + it('should properly expand unquoted params', (done) => { + let test_cases = [ + { + name: `CPU $2 time`, + key: `system.cpu.util[,user,avg1]`, + expected: "CPU user time" + }, + { + name: `CPU $2 time - $3`, + key: `system.cpu.util[,system,avg1]`, + expected: "CPU system time - avg1" + } + ]; + + _.each(test_cases, test_case => { + let expandedName = utils.expandItemName(test_case.name, test_case.key); + expect(expandedName).to.equal(test_case.expected); + }); + done(); + }); + + it('should properly expand quoted params with commas', (done) => { + let test_cases = [ + { + name: `CPU $2 time`, + key: `system.cpu.util["type=user,value=avg",user]`, + expected: "CPU user time" + }, + { + name: `CPU $1 time`, + key: `system.cpu.util["type=user,value=avg","user"]`, + expected: "CPU type=user,value=avg time" + }, + { + name: `CPU $1 time $3`, + key: `system.cpu.util["type=user,value=avg",,"user"]`, + expected: "CPU type=user,value=avg time user" + }, + { + name: `CPU $1 $2 $3`, + key: `system.cpu.util["type=user,value=avg",time,"user"]`, + expected: "CPU type=user,value=avg time user" + } + ]; + + _.each(test_cases, test_case => { + let expandedName = utils.expandItemName(test_case.name, test_case.key); + expect(expandedName).to.equal(test_case.expected); + }); + done(); + }); + }); +}); diff --git a/src/datasource-zabbix/utils.js b/src/datasource-zabbix/utils.js index 7f7c15b..0efa807 100644 --- a/src/datasource-zabbix/utils.js +++ b/src/datasource-zabbix/utils.js @@ -12,15 +12,39 @@ export function expandItemName(name, key) { // extract params from key: // "system.cpu.util[,system,avg1]" --> ["", "system", "avg1"] - var key_params = key.substring(key.indexOf('[') + 1, key.lastIndexOf(']')).split(','); + let key_params_str = key.substring(key.indexOf('[') + 1, key.lastIndexOf(']')); + let key_params = splitKeyParams(key_params_str); // replace item parameters - for (var i = key_params.length; i >= 1; i--) { + for (let i = key_params.length; i >= 1; i--) { name = name.replace('$' + i, key_params[i - 1]); } return name; } +function splitKeyParams(paramStr) { + let params = []; + let quoted = false; + let split_symbol = ','; + let param = ''; + + _.forEach(paramStr, symbol => { + if (symbol === '"' && !quoted) { + quoted = true; + } else if (symbol === '"' && quoted) { + quoted = false; + } else if (symbol === split_symbol && !quoted) { + params.push(param); + param = ''; + } else { + param += symbol; + } + }); + + params.push(param); + return params; +} + // Pattern for testing regex export var regexPattern = /^\/(.*)\/([gmi]*)$/m;