diff --git a/CHANGELOG.md b/CHANGELOG.md index 46489c2..5e1adc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,14 +4,51 @@ As of July, 2017, all significant changes will be logged in this document. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). +## [4.0.3] - 2017-07-28 + +### Fixed + +- **Query Editor**: Fixed structure of editor elements, alignment and other visual tweaks +- **API**: Fixed an issue with some sensors where the displayed name is different from the name returned by the histdata XML query. + +### Added + +### Changed + +- **Plugin**: Cleaned up package.json and plugin.json, updated version number, updated plugin README.md, removed unused content, and, replaced PRTG logo image. + +## [4.0.2] - 2017-07-24 + +### Fixed + +- **API**: Missed a bug that caused the query editor to show ALL sensors when Device was set to "*" even if Group was specified. +- **API**: Added query string parameter "&count=9999" to group, device, and sensor queries to resolve issues for larger deployments. Addresses [#49](https://github.com/neuralfraud/grafana-prtg/issues/49) + +### Changed + +- **API**: Updated method to retrieve historic data, fixes an issue where no values are returned if the channel display name differes from the name in the API XML response. For instance, SSL Security sensors display the channel "Security Rating", when the actual value contains additional descriptive text. +- **API**: Performance improvements in the collection of historic data, the array index to retrieve the channel value from is determined using the first result record instead of being determined for each result, which has a noticable impact with multiple-channel queries and thousands of data points. + +### Added + +- **Query Editor**: Added option to include a device's name in an item's label. Addresses [#47](https://github.com/neuralfraud/grafana-prtg/issues/47) + ## [4.0.1] - 2017-07-24 +### Fixed + - **Query Editor**: Fixed color highlighting. Addresses [#48](https://github.com/neuralfraud/grafana-prtg/issues/48) -- **Query Editor**: Added option to include a device's name in an item's label. Addresses [#47](https://github.com/neuralfraud/grafana-prtg/issues/47) -- **API**: Added query string parameter "&count=9999" to group, device, and sensor queries to resolve issues for larger deployments. Addresses [#49](https://github.com/neuralfraud/grafana-prtg/issues/49) + +### Changed + - **API**: Updated method to retrieve historic data, fixes an issue where no values are returned if the channel display name differes from the name in the API XML response. For instance, SSL Security sensors display the channel "Security Rating", when the actual value contains additional descriptive text. - **API**: Performance improvements in the collection of historic data, the array index to retrieve the channel value from is determined using the first result record instead of being determined for each result, which has a noticable impact with multiple-channel queries and thousands of data points. +### Added + +- **Query Editor**: Added option to include a device's name in an item's label. Addresses [#47](https://github.com/neuralfraud/grafana-prtg/issues/47) +- **API**: Added query string parameter "&count=9999" to group, device, and sensor queries to resolve issues for larger deployments. Addresses [#49](https://github.com/neuralfraud/grafana-prtg/issues/49) + ## [4.0.0] - 2017-07-17 ### Fixed diff --git a/jasonlashua-prtg-datasource/dist/PRTGAPIService.js b/jasonlashua-prtg-datasource/dist/PRTGAPIService.js index fa352c4..ae10949 100644 --- a/jasonlashua-prtg-datasource/dist/PRTGAPIService.js +++ b/jasonlashua-prtg-datasource/dist/PRTGAPIService.js @@ -406,11 +406,17 @@ System.register(["angular", "lodash", "./utils", "./xmlparser"], function (_expo if (testdata.value_raw && testdata.value_raw.length > 0) { //try to get idx numbers on first row, saves cycles. for (var idx = 0; idx < testdata.value_raw.length; idx++) { + // this hack specifically applies to bandwidth sensors that track speed AND volume, a better solution remains to be implemented. if (testdata.value_raw[idx].channel.match(channel + " [(]speed[)]") || testdata.value_raw[idx].channel == channel) { chanIndex = idx; - } else if (testdata.value_raw[idx].channel.match('/' + channel + '/')) { - chanIndex = idx; } + // + else { + var rex = new RegExp(utils.escapeRegex(channel), 'g'); + if (rex.test(testdata.value_raw[idx].channel)) { + chanIndex = idx; + } + } } } diff --git a/jasonlashua-prtg-datasource/dist/PRTGAPIService.js.map b/jasonlashua-prtg-datasource/dist/PRTGAPIService.js.map index e8ae666..aa964ea 100644 --- a/jasonlashua-prtg-datasource/dist/PRTGAPIService.js.map +++ b/jasonlashua-prtg-datasource/dist/PRTGAPIService.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/PRTGAPIService.js"],"names":["PRTGAPIService","alertSrv","backendSrv","PRTGAPI","api_url","username","passhash","cacheTimeoutMinutes","url","lastId","cache","Date","now","hashValue","Promise","resolve","data","getCache","str","hash","length","idx","chr","charCodeAt","val","slice","unixtime","dt","getFullYear","pad","getMonth","getDate","getHours","getMinutes","getSeconds","join","method","params","queryString","options","inCache","setCache","datasourceRequest","then","response","reject","message","groups","devices","sensors","channels","values","sensordata","messages","Version","XMLXform","console","log","error","status","statusText","performPRTGAPIRequest","groupFilter","deviceFilter","items","queryStr","invert","filterItems","match","_","trim","split","push","filter","findItem","item","group","device","sensor","name","utils","isRegex","rex","buildRegex","result","test","includes","performGroupSuggestQuery","filterQuery","hostFilter","performDeviceSuggestQuery","getGroups","filters","each","filteredGroups","sensorFilter","getHosts","hosts","host","performSensorSuggestQuery","getSensors","promises","map","objid","all","channel","sensor_raw","flatten","channelFilter","invertChannelFilter","getAllItems","target","getItems","dateFrom","dateTo","hours","avg","getPRTGDate","history","results","histdata","rCnt","testdata","chanIndex","value_raw","iter","prtgDate","datetime_raw","Number","text","datetime","value","from","to","sensorId","events","time","Math","round","title","parent","type","angular","module","factory"],"mappings":"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","file":"PRTGAPIService.js","sourcesContent":["import angular from \"angular\";\r\nimport _ from \"lodash\";\r\nimport * as utils from \"./utils\";\r\nimport { XMLXform } from \"./xmlparser\";\r\n/**\r\n * PRTG API Service\r\n * Implements the high level functions that process data from PRTG\r\n */\r\n\r\n/** @ngInject */\r\nfunction PRTGAPIService(alertSrv, backendSrv) {\r\n class PRTGAPI {\r\n constructor(api_url, username, passhash, cacheTimeoutMinutes) {\r\n this.url = api_url;\r\n this.username = username;\r\n this.passhash = passhash;\r\n this.lastId = false;\r\n this.cache = {};\r\n this.cacheTimeoutMinutes = cacheTimeoutMinutes;\r\n this.alertSrv = alertSrv;\r\n this.backendSrv = backendSrv;\r\n }\r\n\r\n /**\r\n * Tests whether a url has been stored in the cache.\r\n * Returns boolean true | false\r\n * \r\n * @param url \r\n * @return boolean\r\n */\r\n inCache(url) {\r\n if (\r\n Date.now() - this.cache[this.hashValue(url)] >\r\n this.cacheTimeoutMinutes * 60 * 1000\r\n ) {\r\n return false;\r\n }\r\n if (this.cache[this.hashValue(url)]) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * retrieves a cached data result from the cache\r\n *\r\n * @param url the URL of the request\r\n * @return Promise\r\n */\r\n getCache(url) {\r\n return Promise.resolve(this.cache[this.hashValue(url)]);\r\n }\r\n\r\n /**\r\n * stores a data result in the cache\r\n *\r\n * @param url the URL of the request\r\n * @param data the response.data object of the request\r\n * @return promise\r\n */\r\n setCache(url, data) {\r\n this.cache[this.hashValue(url)] = data;\r\n return this.getCache(url);\r\n }\r\n\r\n /**\r\n * simple clone of a java hash value\r\n * Kevin \"Pancake\" (http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/)\r\n *\r\n * @param e string to hash\r\n * @return int32\r\n */\r\n hashValue(str) {\r\n let hash = 0;\r\n if (str.length === 0) return hash;\r\n for (let idx = 0; idx < str.length; idx++) {\r\n const chr = str.charCodeAt(idx);\r\n hash = (hash << 5) - hash + chr;\r\n hash = hash & hash; // Convert to 32bit integer\r\n }\r\n return hash;\r\n }\r\n\r\n /**\r\n * pad date parts and optionally add one\r\n */\r\n pad(idx, val) {\r\n if (val) return (\"0\" + (idx + 1)).slice(-2);\r\n return (\"0\" + idx).slice(-2);\r\n }\r\n\r\n /**\r\n * convert a UNIX timestamp into a PRTG date string for queries\r\n * YYYY-MM-DD-HH-MM-SS\r\n * \r\n * @param unixtime UNIX format timestamp\r\n */\r\n getPRTGDate(unixtime) {\r\n const dt = new Date(unixtime * 1000);\r\n const str = [\r\n dt.getFullYear(),\r\n this.pad(dt.getMonth(), true),\r\n this.pad(dt.getDate()),\r\n this.pad(dt.getHours()),\r\n this.pad(dt.getMinutes()),\r\n this.pad(dt.getSeconds())\r\n ];\r\n return str.join(\"-\");\r\n }\r\n\r\n /**\r\n * Request data from PRTG API\r\n *\r\n * @param method the API method (e.g., table.json)\r\n * @param params HTTP query string query parameters\r\n * @return promise\r\n */\r\n performPRTGAPIRequest(method, params) {\r\n const queryString =\r\n \"username=\" +\r\n this.username +\r\n \"&passhash=\" +\r\n this.passhash +\r\n \"&\" +\r\n params;\r\n const options = {\r\n method: \"GET\",\r\n url: this.url + \"/\" + method + \"?\" + queryString\r\n };\r\n\r\n if (this.inCache(options.url)) {\r\n return this.getCache(options.url);\r\n } else {\r\n return this.setCache(\r\n options.url,\r\n this.backendSrv.datasourceRequest(options).then(\r\n response => {\r\n if (!response.data) {\r\n return Promise.reject({\r\n message: \"Response contained no data\"\r\n });\r\n }\r\n\r\n if (response.data.groups) {\r\n return response.data.groups;\r\n } else if (response.data.devices) {\r\n return response.data.devices;\r\n } else if (response.data.sensors) {\r\n return response.data.sensors;\r\n } else if (response.data.channels) {\r\n return response.data.channels;\r\n } else if (response.data.values) {\r\n return response.data.values;\r\n } else if (response.data.sensordata) {\r\n return response.data.sensordata;\r\n } else if (response.data.messages) {\r\n return response.data.messages;\r\n } else if (response.data.Version) {\r\n return response.data;\r\n } else {\r\n //All else must be XML from table.xml so throw it into the transformer and get JSON back.\r\n if (response.data == \"Not enough monitoring data\") {\r\n //Fixes Issue #5 - reject the promise with a message. The message is displayed instead of an uncaught exception.\r\n return Promise.reject({\r\n message:\r\n \"Not enough monitoring data.\\n\\nRequest:\\n\" +\r\n params +\r\n \"\\n\"\r\n });\r\n }\r\n if (response.data.length > 200) {\r\n return new XMLXform(method, response.data);\r\n } else {\r\n console.log(\"Short Response! :( \\n\" + response.data);\r\n return {};\r\n }\r\n }\r\n },\r\n error => {\r\n return Promise.reject(error.status + \": \" + error.statusText);\r\n }\r\n )\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Only used in connection testing\r\n * \r\n * @return Promise\r\n */\r\n getVersion() {\r\n return this.performPRTGAPIRequest(\"status.json\").then(function(response) {\r\n if (!response) {\r\n return \"ERROR. No response.\";\r\n } else {\r\n return response.Version;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Authenticate to the PRTG interface\r\n * Only used in connection testing because PRTG API is sessionless.\r\n * \r\n * @return Promise\r\n */\r\n performPRTGAPILogin() {\r\n const username = this.username;\r\n const passhash = this.passhash;\r\n const options = {\r\n method: \"GET\",\r\n url:\r\n this.url +\r\n \"/getstatus.htm?id=0&username=\" +\r\n username +\r\n \"&passhash=\" +\r\n passhash\r\n };\r\n return this.backendSrv.datasourceRequest(options).then(response => {\r\n this.passhash = response;\r\n return response;\r\n });\r\n }\r\n\r\n /**\r\n * Query API for list of groups\r\n *\r\n * @return Promise - JSON result set\r\n */\r\n performGroupSuggestQuery() {\r\n const params =\r\n \"content=groups&count=9999&columns=objid,group,probe,tags,active,status,message,priority\";\r\n return this.performPRTGAPIRequest(\"table.json\", params);\r\n }\r\n\r\n /**\r\n * Query API for list of devices\r\n * @param {string} groupFilter - raw string, comma separated strings, or regular expression pattern\r\n * @return Promise - JSON result set\r\n */\r\n performDeviceSuggestQuery(groupFilter) {\r\n let params =\r\n \"content=devices&count=9999&columns=objid,device,group,probe,tags,active,status,message,priority\";\r\n if (groupFilter) {\r\n params += \",group\" + groupFilter;\r\n }\r\n return this.performPRTGAPIRequest(\"table.json\", params);\r\n }\r\n\r\n /**\r\n * Query API for list of sensors bound to a given device\r\n * @param {string} deviceFilter - raw string, comma separated strings, or regular expression pattern\r\n * @return promise - JSON result set\r\n */\r\n performSensorSuggestQuery(deviceFilter) {\r\n let params =\r\n \"content=sensors&count=9999&columns=objid,sensor,device,group,probe,tags,active,status,message,priority\";\r\n if (deviceFilter) {\r\n params += deviceFilter;\r\n }\r\n \r\n return this.performPRTGAPIRequest(\"table.json\", params);\r\n }\r\n\r\n /**\r\n * Filter a PRTG collection against a filter string \r\n * \r\n * @param {collection} items - PRTG Data object \r\n * @param {string} queryStr - Query filter, raw string, comma separated strings, or regular expression pattern\r\n * @param {boolean} invert - when set to boolean true, negates the return value. \r\n * @return {boolean} result of text expression\r\n */\r\n filterQuery(items, queryStr, invert = false) {\r\n /**\r\n * group device sensor includes properties:\r\n * objid: num\r\n * sensor: Name\r\n * device: Device name\r\n * group: Group name\r\n * tags: comma separated\r\n * active: true|false\r\n * active_raw: -1 for true? wtf\r\n * status: Status text\r\n * status_raw: number\r\n * message: html message\r\n * message_raw: text message\r\n * priority: number 1-5\r\n */\r\n let filterItems = [];\r\n if (queryStr.match(/{[^{}]+}/g)) {\r\n filterItems = _.trim(queryStr, \"{}\").split(\",\");\r\n } else {\r\n filterItems.push(queryStr);\r\n }\r\n return _.filter(items, item => {\r\n let findItem;\r\n if (item.group && !item.device) {\r\n findItem = item.group;\r\n } else if (item.device && !item.sensor) {\r\n findItem = item.device;\r\n } else if (item.sensor && !item.name) {\r\n findItem = item.sensor;\r\n } else if (item.name) {\r\n findItem = item.name;\r\n } else {\r\n return false;\r\n }\r\n if (utils.isRegex(queryStr)) {\r\n const rex = utils.buildRegex(queryStr);\r\n const result = rex.test(findItem);\r\n if (invert) {\r\n return !result;\r\n }\r\n return result;\r\n }\r\n if (filterItems.length === 0) {\r\n return true;\r\n }\r\n if (invert) {\r\n return !filterItems.includes(findItem);\r\n }\r\n return filterItems.includes(findItem);\r\n });\r\n }\r\n\r\n /**\r\n * Retrive groups and filter with an optional filter string\r\n * \r\n * @param {string} groupFilter - raw string, comma separated strings, or regular expression pattern\r\n * @return {collection} - filtered PRTG data object\r\n */\r\n getGroups(groupFilter = \"/.*/\") {\r\n return this.performGroupSuggestQuery().then(groups => {\r\n return this.filterQuery(groups, groupFilter);\r\n });\r\n }\r\n\r\n /**\r\n * Retrieve hosts and filter with an optional filter string.\r\n * \r\n * @param {*} groupFilter - raw string, comma separated strings, or regular expression pattern\r\n * @param {*} hostFilter - raw string, comma separated strings, or regular expression pattern\r\n * @return {collection} - filtered PRTG data object\r\n */\r\n getHosts(groupFilter = \"/.*/\", hostFilter = \"/.*/\") {\r\n //this is kind of silly but no need to include filter_group params if you include all...\r\n if (groupFilter == \"/.*/\") {\r\n return this.performDeviceSuggestQuery().then(devices => {\r\n return this.filterQuery(devices, hostFilter);\r\n });\r\n } else {\r\n return this.getGroups(groupFilter).then(filteredGroups => {\r\n const filters = [];\r\n _.each(filteredGroups, group => {\r\n filters.push(\"filter_group=\" + group.group);\r\n });\r\n\r\n return this.performDeviceSuggestQuery(\r\n \"&\" + filters.join(\"&\")\r\n ).then(devices => {\r\n return this.filterQuery(devices, hostFilter);\r\n });\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Retrieve sensors and filter with an optional filter string.\r\n * \r\n * @param {string} groupFilter - raw string, comma separated strings, or regular expression pattern\r\n * @param {string} hostFilter - raw string, comma separated strings, or regular expression pattern\r\n * @param {string} sensorFilter - raw string, comma separated strings, or regular expression pattern\r\n * @return {collection} - filtered PRTG data object\r\n */\r\n getSensors(\r\n groupFilter = \"/.*/\",\r\n hostFilter = \"/.*/\",\r\n sensorFilter = \"/.*/\"\r\n ) {\r\n return this.getHosts(groupFilter, hostFilter).then(hosts => {\r\n const filters = [];\r\n _.each(hosts, host => {\r\n filters.push(\"filter_device=\" + host.device);\r\n });\r\n if (hostFilter == \"/.*/\" && groupFilter == \"/.*/\") {\r\n return this.performSensorSuggestQuery().then(sensors => {\r\n return this.filterQuery(sensors, sensorFilter);\r\n });\r\n } else {\r\n return this.performSensorSuggestQuery(\r\n \"&\" + filters.join(\"&\")\r\n ).then(sensors => {\r\n return this.filterQuery(sensors, sensorFilter);\r\n });\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Retrieve full data object with channel definitions using an optional filter string\r\n * \r\n * @param {*} groupFilter - raw string, comma separated strings, or regular expression pattern \r\n * @param {*} hostFilter - raw string, comma separated strings, or regular expression pattern \r\n * @param {*} sensorFilter - raw string, comma separated strings, or regular expression pattern \r\n * @return {collection} - PRTG data object with channel and sensor properties\r\n */\r\n getAllItems(\r\n groupFilter = \"/.*/\",\r\n hostFilter = \"/.*/\",\r\n sensorFilter = \"/.*/\"\r\n ) {\r\n return this.getSensors(\r\n groupFilter,\r\n hostFilter,\r\n sensorFilter\r\n ).then(sensors => {\r\n /**\r\n * In this context, if i simply iterate an array with _.each and then execute performPRTGAPIRequest, even\r\n * though the returned object is a promise which can be used in a chain, the execution falls outside of the existing\r\n * promise chain and thus executs asynchronously. To keep everything in the same execution context, create a\r\n * promise array for each object, then execute them in context.\r\n */\r\n const promises = _.map(sensors, sensor => {\r\n const params =\r\n \"content=channels&columns=sensor,name&id=\" + sensor.objid;\r\n return this.performPRTGAPIRequest(\r\n \"table.json\",\r\n params\r\n ).then(channels => {\r\n /**\r\n * Create an object that contains all of the information necessary to query this metric.\r\n * This information will be used at render time to group the datapoints and name them.\r\n */\r\n return Promise.all(\r\n _.map(channels, channel => {\r\n channel.sensor = sensor.objid;\r\n channel.sensor_raw = sensor.sensor;\r\n channel.device = sensor.device;\r\n channel.group = sensor.group;\r\n channel.channel = channel.name;\r\n return channel;\r\n })\r\n );\r\n });\r\n });\r\n return Promise.all(promises).then(_.flatten);\r\n });\r\n }\r\n\r\n /**\r\n * Retrieve full data object with channel definitions using an optional filter string.\r\n * The results are then filtered against a channelFilter expression.\r\n * \r\n * @param {string} groupFilter - raw string, comma separated strings, or regular expression patter \r\n * @param {string} deviceFilter - raw string, comma separated strings, or regular expression patter \r\n * @param {string} sensorFilter - raw string, comma separated strings, or regular expression pattern\r\n * @param {string} channelFilter - raw string, comma separated strings, or regular expression pattern\r\n * @param {boolean} invertChannelFilter - if set to boolean true, negates the result of the channelFilter expression\r\n */\r\n getItems(\r\n groupFilter,\r\n deviceFilter,\r\n sensorFilter,\r\n channelFilter,\r\n invertChannelFilter = false\r\n ) {\r\n return this.getAllItems(\r\n groupFilter,\r\n deviceFilter,\r\n sensorFilter\r\n ).then(items => {\r\n return this.filterQuery(items, channelFilter, invertChannelFilter);\r\n });\r\n }\r\n getItemsFromTarget(target) {\r\n if (target.options) {\r\n if (target.options.invertChannelFilter) {\r\n return this.getItems(\r\n target.group.name,\r\n target.device.name,\r\n target.sensor.name,\r\n target.channel.name,\r\n true\r\n );\r\n } else {\r\n return this.getItems(\r\n target.group.name,\r\n target.device.name,\r\n target.sensor.name,\r\n target.channel.name\r\n );\r\n }\r\n }\r\n return this.getItems(\r\n target.group.name,\r\n target.device.name,\r\n target.sensor.name,\r\n target.channel.name\r\n );\r\n }\r\n\r\n /**\r\n * Retrieve history data from a single sensor.\r\n * @param {number} sensor - sensor ID\r\n * @param {string} channel - channel name\r\n * @param {number} dateFrom - timestamp of start time\r\n * @param {number} dateTo - timestamp of end time\r\n */\r\n getItemHistory(sensor, channel, dateFrom, dateTo) {\r\n const hours = (dateTo - dateFrom) / 3600;\r\n let avg = 0;\r\n if (hours > 12 && hours < 36) {\r\n avg = \"300\";\r\n } else if (hours > 36 && hours < 745) {\r\n avg = \"3600\";\r\n } else if (hours > 745) {\r\n avg = \"86400\";\r\n }\r\n\r\n const method = \"historicdata.xml\";\r\n const params =\r\n \"id=\" +\r\n sensor +\r\n \"&sdate=\" +\r\n this.getPRTGDate(dateFrom) +\r\n \"&edate=\" +\r\n this.getPRTGDate(dateTo) +\r\n \"&avg=\" +\r\n avg +\r\n \"&pctshow=false&pctmode=false\";\r\n /*\r\n * Modified to read the \"statusid\" value, this can then be mapped via lookup table to a PRTG status type\r\n * 1=Unknown, 2=Scanning, 3=Up, 4=Warning, 5=Down, 6=No Probe, 7=Paused by User, 8=Paused by Dependency,\r\n * 9=Paused by Schedule, 10=Unusual, 11=Not Licensed, 12=Paused Until, 13=Down Acknowledged, 14=Down Partial\r\n */\r\n const history = [];\r\n return this.performPRTGAPIRequest(method, params).then(results => {\r\n if (!results.histdata) {\r\n return history;\r\n }\r\n const rCnt = results.histdata.item.length;\r\n const testdata = results.histdata.item[0];\r\n let chanIndex = 0;\r\n\r\n \r\n if (\r\n testdata.value_raw &&\r\n testdata.value_raw.length > 0\r\n )\r\n {\r\n //try to get idx numbers on first row, saves cycles.\r\n for (let idx = 0; idx < testdata.value_raw.length; idx++) {\r\n if (testdata.value_raw[idx].channel.match(channel + \" [(]speed[)]\") || testdata.value_raw[idx].channel == channel)\r\n {\r\n chanIndex = idx;\r\n } else if (testdata.value_raw[idx].channel.match('/' + channel + '/')) {\r\n chanIndex = idx;\r\n }\r\n }\r\n }\r\n \r\n\r\n for (let iter = 0; iter < rCnt; iter++) {\r\n let val;\r\n const prtgDate = results.histdata.item[iter].datetime_raw;\r\n const dt = new Date((prtgDate - 25569) * 86400 * 1000);\r\n //var dt = Math.round((results.histdata.item[i].datetime_raw - 25568) * 86400,0) * 1000;\r\n if (\r\n results.histdata.item[iter].value_raw &&\r\n results.histdata.item[iter].value_raw.length > 0\r\n ) {\r\n //FIXME: better way of dealing with multiple channels of same name\r\n //IE you select \"Traffic In\" but PRTG provides Volume AND Speed channels.\r\n /*\r\n for (\r\n let iter2 = 0;\r\n iter2 < results.histdata.item[iter].value_raw.length;\r\n iter2++\r\n ) {\r\n //workaround for SNMP Bandwidth Issue #3. Check for presence of (speed) suffix, and use that.\r\n if (\r\n results.histdata.item[iter].value_raw[iter2].channel.match(\r\n channel + \" [(]speed[)]\"\r\n ) ||\r\n results.histdata.item[iter].value_raw[iter2].channel == channel\r\n )\r\n {\r\n val = Number(results.histdata.item[iter].value_raw[iter2].text);\r\n }\r\n */\r\n val = Number(results.histdata.item[iter].value_raw[chanIndex].text);\r\n // }\r\n } else if (results.histdata.item[iter].value_raw) {\r\n val = Number(results.histdata.item[iter].value_raw.text);\r\n }\r\n history.push({\r\n sensor: sensor,\r\n channel: channel,\r\n datetime: dt,\r\n value: val\r\n });\r\n }\r\n return history;\r\n });\r\n }\r\n\r\n /**\r\n * Retrieve messages for a given sensor. Used only for annotation queries.\r\n * \r\n * @param {number} from - Earliest time in range\r\n * @param {number} to - Latest time in range\r\n * @param {number} sensorId - Numeric ID of Sensor \r\n */\r\n getMessages(from, to, sensorId) {\r\n const method = \"table.json\";\r\n const params =\r\n \"&content=messages&columns=objid,datetime,parent,type,name,status,message&id=\" +\r\n sensorId;\r\n return this.performPRTGAPIRequest(method, params).then(function(\r\n messages\r\n ) {\r\n const events = [];\r\n let time = 0;\r\n _.each(messages, function(message) {\r\n time = Math.round((message.datetime_raw - 25569) * 86400, 0);\r\n if (time > from && time < to) {\r\n events.push({\r\n time: time * 1000,\r\n title: message.status,\r\n text:\r\n \"

\" +\r\n message.parent +\r\n \"(\" +\r\n message.type +\r\n \") Message:
\" +\r\n message.message +\r\n \"

\"\r\n });\r\n }\r\n });\r\n return events;\r\n });\r\n }\r\n }\r\n return PRTGAPI;\r\n}\r\n\r\n//register a new module\r\nangular.module(\"grafana.services\").factory(\"PRTGAPIService\", PRTGAPIService);\r\n"]} \ No newline at end of file +{"version":3,"sources":["../src/PRTGAPIService.js"],"names":["PRTGAPIService","alertSrv","backendSrv","PRTGAPI","api_url","username","passhash","cacheTimeoutMinutes","url","lastId","cache","Date","now","hashValue","Promise","resolve","data","getCache","str","hash","length","idx","chr","charCodeAt","val","slice","unixtime","dt","getFullYear","pad","getMonth","getDate","getHours","getMinutes","getSeconds","join","method","params","queryString","options","inCache","setCache","datasourceRequest","then","response","reject","message","groups","devices","sensors","channels","values","sensordata","messages","Version","XMLXform","console","log","error","status","statusText","performPRTGAPIRequest","groupFilter","deviceFilter","items","queryStr","invert","filterItems","match","_","trim","split","push","filter","findItem","item","group","device","sensor","name","utils","isRegex","rex","buildRegex","result","test","includes","performGroupSuggestQuery","filterQuery","hostFilter","performDeviceSuggestQuery","getGroups","filters","each","filteredGroups","sensorFilter","getHosts","hosts","host","performSensorSuggestQuery","getSensors","promises","map","objid","all","channel","sensor_raw","flatten","channelFilter","invertChannelFilter","getAllItems","target","getItems","dateFrom","dateTo","hours","avg","getPRTGDate","history","results","histdata","rCnt","testdata","chanIndex","value_raw","RegExp","escapeRegex","iter","prtgDate","datetime_raw","Number","text","datetime","value","from","to","sensorId","events","time","Math","round","title","parent","type","angular","module","factory"],"mappings":"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","file":"PRTGAPIService.js","sourcesContent":["import angular from \"angular\";\r\nimport _ from \"lodash\";\r\nimport * as utils from \"./utils\";\r\nimport { XMLXform } from \"./xmlparser\";\r\n/**\r\n * PRTG API Service\r\n * Implements the high level functions that process data from PRTG\r\n */\r\n\r\n/** @ngInject */\r\nfunction PRTGAPIService(alertSrv, backendSrv) {\r\n class PRTGAPI {\r\n constructor(api_url, username, passhash, cacheTimeoutMinutes) {\r\n this.url = api_url;\r\n this.username = username;\r\n this.passhash = passhash;\r\n this.lastId = false;\r\n this.cache = {};\r\n this.cacheTimeoutMinutes = cacheTimeoutMinutes;\r\n this.alertSrv = alertSrv;\r\n this.backendSrv = backendSrv;\r\n }\r\n\r\n /**\r\n * Tests whether a url has been stored in the cache.\r\n * Returns boolean true | false\r\n * \r\n * @param url \r\n * @return boolean\r\n */\r\n inCache(url) {\r\n if (\r\n Date.now() - this.cache[this.hashValue(url)] >\r\n this.cacheTimeoutMinutes * 60 * 1000\r\n ) {\r\n return false;\r\n }\r\n if (this.cache[this.hashValue(url)]) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * retrieves a cached data result from the cache\r\n *\r\n * @param url the URL of the request\r\n * @return Promise\r\n */\r\n getCache(url) {\r\n return Promise.resolve(this.cache[this.hashValue(url)]);\r\n }\r\n\r\n /**\r\n * stores a data result in the cache\r\n *\r\n * @param url the URL of the request\r\n * @param data the response.data object of the request\r\n * @return promise\r\n */\r\n setCache(url, data) {\r\n this.cache[this.hashValue(url)] = data;\r\n return this.getCache(url);\r\n }\r\n\r\n /**\r\n * simple clone of a java hash value\r\n * Kevin \"Pancake\" (http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/)\r\n *\r\n * @param e string to hash\r\n * @return int32\r\n */\r\n hashValue(str) {\r\n let hash = 0;\r\n if (str.length === 0) return hash;\r\n for (let idx = 0; idx < str.length; idx++) {\r\n const chr = str.charCodeAt(idx);\r\n hash = (hash << 5) - hash + chr;\r\n hash = hash & hash; // Convert to 32bit integer\r\n }\r\n return hash;\r\n }\r\n\r\n /**\r\n * pad date parts and optionally add one\r\n */\r\n pad(idx, val) {\r\n if (val) return (\"0\" + (idx + 1)).slice(-2);\r\n return (\"0\" + idx).slice(-2);\r\n }\r\n\r\n /**\r\n * convert a UNIX timestamp into a PRTG date string for queries\r\n * YYYY-MM-DD-HH-MM-SS\r\n * \r\n * @param unixtime UNIX format timestamp\r\n */\r\n getPRTGDate(unixtime) {\r\n const dt = new Date(unixtime * 1000);\r\n const str = [\r\n dt.getFullYear(),\r\n this.pad(dt.getMonth(), true),\r\n this.pad(dt.getDate()),\r\n this.pad(dt.getHours()),\r\n this.pad(dt.getMinutes()),\r\n this.pad(dt.getSeconds())\r\n ];\r\n return str.join(\"-\");\r\n }\r\n\r\n /**\r\n * Request data from PRTG API\r\n *\r\n * @param method the API method (e.g., table.json)\r\n * @param params HTTP query string query parameters\r\n * @return promise\r\n */\r\n performPRTGAPIRequest(method, params) {\r\n const queryString =\r\n \"username=\" +\r\n this.username +\r\n \"&passhash=\" +\r\n this.passhash +\r\n \"&\" +\r\n params;\r\n const options = {\r\n method: \"GET\",\r\n url: this.url + \"/\" + method + \"?\" + queryString\r\n };\r\n\r\n if (this.inCache(options.url)) {\r\n return this.getCache(options.url);\r\n } else {\r\n return this.setCache(\r\n options.url,\r\n this.backendSrv.datasourceRequest(options).then(\r\n response => {\r\n if (!response.data) {\r\n return Promise.reject({\r\n message: \"Response contained no data\"\r\n });\r\n }\r\n\r\n if (response.data.groups) {\r\n return response.data.groups;\r\n } else if (response.data.devices) {\r\n return response.data.devices;\r\n } else if (response.data.sensors) {\r\n return response.data.sensors;\r\n } else if (response.data.channels) {\r\n return response.data.channels;\r\n } else if (response.data.values) {\r\n return response.data.values;\r\n } else if (response.data.sensordata) {\r\n return response.data.sensordata;\r\n } else if (response.data.messages) {\r\n return response.data.messages;\r\n } else if (response.data.Version) {\r\n return response.data;\r\n } else {\r\n //All else must be XML from table.xml so throw it into the transformer and get JSON back.\r\n if (response.data == \"Not enough monitoring data\") {\r\n //Fixes Issue #5 - reject the promise with a message. The message is displayed instead of an uncaught exception.\r\n return Promise.reject({\r\n message:\r\n \"Not enough monitoring data.\\n\\nRequest:\\n\" +\r\n params +\r\n \"\\n\"\r\n });\r\n }\r\n if (response.data.length > 200) {\r\n return new XMLXform(method, response.data);\r\n } else {\r\n console.log(\"Short Response! :( \\n\" + response.data);\r\n return {};\r\n }\r\n }\r\n },\r\n error => {\r\n return Promise.reject(error.status + \": \" + error.statusText);\r\n }\r\n )\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Only used in connection testing\r\n * \r\n * @return Promise\r\n */\r\n getVersion() {\r\n return this.performPRTGAPIRequest(\"status.json\").then(function(response) {\r\n if (!response) {\r\n return \"ERROR. No response.\";\r\n } else {\r\n return response.Version;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Authenticate to the PRTG interface\r\n * Only used in connection testing because PRTG API is sessionless.\r\n * \r\n * @return Promise\r\n */\r\n performPRTGAPILogin() {\r\n const username = this.username;\r\n const passhash = this.passhash;\r\n const options = {\r\n method: \"GET\",\r\n url:\r\n this.url +\r\n \"/getstatus.htm?id=0&username=\" +\r\n username +\r\n \"&passhash=\" +\r\n passhash\r\n };\r\n return this.backendSrv.datasourceRequest(options).then(response => {\r\n this.passhash = response;\r\n return response;\r\n });\r\n }\r\n\r\n /**\r\n * Query API for list of groups\r\n *\r\n * @return Promise - JSON result set\r\n */\r\n performGroupSuggestQuery() {\r\n const params =\r\n \"content=groups&count=9999&columns=objid,group,probe,tags,active,status,message,priority\";\r\n return this.performPRTGAPIRequest(\"table.json\", params);\r\n }\r\n\r\n /**\r\n * Query API for list of devices\r\n * @param {string} groupFilter - raw string, comma separated strings, or regular expression pattern\r\n * @return Promise - JSON result set\r\n */\r\n performDeviceSuggestQuery(groupFilter) {\r\n let params =\r\n \"content=devices&count=9999&columns=objid,device,group,probe,tags,active,status,message,priority\";\r\n if (groupFilter) {\r\n params += \",group\" + groupFilter;\r\n }\r\n return this.performPRTGAPIRequest(\"table.json\", params);\r\n }\r\n\r\n /**\r\n * Query API for list of sensors bound to a given device\r\n * @param {string} deviceFilter - raw string, comma separated strings, or regular expression pattern\r\n * @return promise - JSON result set\r\n */\r\n performSensorSuggestQuery(deviceFilter) {\r\n let params =\r\n \"content=sensors&count=9999&columns=objid,sensor,device,group,probe,tags,active,status,message,priority\";\r\n if (deviceFilter) {\r\n params += deviceFilter;\r\n }\r\n \r\n return this.performPRTGAPIRequest(\"table.json\", params);\r\n }\r\n\r\n /**\r\n * Filter a PRTG collection against a filter string \r\n * \r\n * @param {collection} items - PRTG Data object \r\n * @param {string} queryStr - Query filter, raw string, comma separated strings, or regular expression pattern\r\n * @param {boolean} invert - when set to boolean true, negates the return value. \r\n * @return {boolean} result of text expression\r\n */\r\n filterQuery(items, queryStr, invert = false) {\r\n /**\r\n * group device sensor includes properties:\r\n * objid: num\r\n * sensor: Name\r\n * device: Device name\r\n * group: Group name\r\n * tags: comma separated\r\n * active: true|false\r\n * active_raw: -1 for true? wtf\r\n * status: Status text\r\n * status_raw: number\r\n * message: html message\r\n * message_raw: text message\r\n * priority: number 1-5\r\n */\r\n let filterItems = [];\r\n if (queryStr.match(/{[^{}]+}/g)) {\r\n filterItems = _.trim(queryStr, \"{}\").split(\",\");\r\n } else {\r\n filterItems.push(queryStr);\r\n }\r\n return _.filter(items, item => {\r\n let findItem;\r\n if (item.group && !item.device) {\r\n findItem = item.group;\r\n } else if (item.device && !item.sensor) {\r\n findItem = item.device;\r\n } else if (item.sensor && !item.name) {\r\n findItem = item.sensor;\r\n } else if (item.name) {\r\n findItem = item.name;\r\n } else {\r\n return false;\r\n }\r\n if (utils.isRegex(queryStr)) {\r\n const rex = utils.buildRegex(queryStr);\r\n const result = rex.test(findItem);\r\n if (invert) {\r\n return !result;\r\n }\r\n return result;\r\n }\r\n if (filterItems.length === 0) {\r\n return true;\r\n }\r\n if (invert) {\r\n return !filterItems.includes(findItem);\r\n }\r\n return filterItems.includes(findItem);\r\n });\r\n }\r\n\r\n /**\r\n * Retrive groups and filter with an optional filter string\r\n * \r\n * @param {string} groupFilter - raw string, comma separated strings, or regular expression pattern\r\n * @return {collection} - filtered PRTG data object\r\n */\r\n getGroups(groupFilter = \"/.*/\") {\r\n return this.performGroupSuggestQuery().then(groups => {\r\n return this.filterQuery(groups, groupFilter);\r\n });\r\n }\r\n\r\n /**\r\n * Retrieve hosts and filter with an optional filter string.\r\n * \r\n * @param {*} groupFilter - raw string, comma separated strings, or regular expression pattern\r\n * @param {*} hostFilter - raw string, comma separated strings, or regular expression pattern\r\n * @return {collection} - filtered PRTG data object\r\n */\r\n getHosts(groupFilter = \"/.*/\", hostFilter = \"/.*/\") {\r\n //this is kind of silly but no need to include filter_group params if you include all...\r\n if (groupFilter == \"/.*/\") {\r\n return this.performDeviceSuggestQuery().then(devices => {\r\n return this.filterQuery(devices, hostFilter);\r\n });\r\n } else {\r\n return this.getGroups(groupFilter).then(filteredGroups => {\r\n const filters = [];\r\n _.each(filteredGroups, group => {\r\n filters.push(\"filter_group=\" + group.group);\r\n });\r\n\r\n return this.performDeviceSuggestQuery(\r\n \"&\" + filters.join(\"&\")\r\n ).then(devices => {\r\n return this.filterQuery(devices, hostFilter);\r\n });\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Retrieve sensors and filter with an optional filter string.\r\n * \r\n * @param {string} groupFilter - raw string, comma separated strings, or regular expression pattern\r\n * @param {string} hostFilter - raw string, comma separated strings, or regular expression pattern\r\n * @param {string} sensorFilter - raw string, comma separated strings, or regular expression pattern\r\n * @return {collection} - filtered PRTG data object\r\n */\r\n getSensors(\r\n groupFilter = \"/.*/\",\r\n hostFilter = \"/.*/\",\r\n sensorFilter = \"/.*/\"\r\n ) {\r\n return this.getHosts(groupFilter, hostFilter).then(hosts => {\r\n const filters = [];\r\n _.each(hosts, host => {\r\n filters.push(\"filter_device=\" + host.device);\r\n });\r\n if (hostFilter == \"/.*/\" && groupFilter == \"/.*/\") {\r\n return this.performSensorSuggestQuery().then(sensors => {\r\n return this.filterQuery(sensors, sensorFilter);\r\n });\r\n } else {\r\n return this.performSensorSuggestQuery(\r\n \"&\" + filters.join(\"&\")\r\n ).then(sensors => {\r\n return this.filterQuery(sensors, sensorFilter);\r\n });\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Retrieve full data object with channel definitions using an optional filter string\r\n * \r\n * @param {*} groupFilter - raw string, comma separated strings, or regular expression pattern \r\n * @param {*} hostFilter - raw string, comma separated strings, or regular expression pattern \r\n * @param {*} sensorFilter - raw string, comma separated strings, or regular expression pattern \r\n * @return {collection} - PRTG data object with channel and sensor properties\r\n */\r\n getAllItems(\r\n groupFilter = \"/.*/\",\r\n hostFilter = \"/.*/\",\r\n sensorFilter = \"/.*/\"\r\n ) {\r\n return this.getSensors(\r\n groupFilter,\r\n hostFilter,\r\n sensorFilter\r\n ).then(sensors => {\r\n /**\r\n * In this context, if i simply iterate an array with _.each and then execute performPRTGAPIRequest, even\r\n * though the returned object is a promise which can be used in a chain, the execution falls outside of the existing\r\n * promise chain and thus executs asynchronously. To keep everything in the same execution context, create a\r\n * promise array for each object, then execute them in context.\r\n */\r\n const promises = _.map(sensors, sensor => {\r\n const params =\r\n \"content=channels&columns=sensor,name&id=\" + sensor.objid;\r\n return this.performPRTGAPIRequest(\r\n \"table.json\",\r\n params\r\n ).then(channels => {\r\n /**\r\n * Create an object that contains all of the information necessary to query this metric.\r\n * This information will be used at render time to group the datapoints and name them.\r\n */\r\n return Promise.all(\r\n _.map(channels, channel => {\r\n channel.sensor = sensor.objid;\r\n channel.sensor_raw = sensor.sensor;\r\n channel.device = sensor.device;\r\n channel.group = sensor.group;\r\n channel.channel = channel.name;\r\n return channel;\r\n })\r\n );\r\n });\r\n });\r\n return Promise.all(promises).then(_.flatten);\r\n });\r\n }\r\n\r\n /**\r\n * Retrieve full data object with channel definitions using an optional filter string.\r\n * The results are then filtered against a channelFilter expression.\r\n * \r\n * @param {string} groupFilter - raw string, comma separated strings, or regular expression patter \r\n * @param {string} deviceFilter - raw string, comma separated strings, or regular expression patter \r\n * @param {string} sensorFilter - raw string, comma separated strings, or regular expression pattern\r\n * @param {string} channelFilter - raw string, comma separated strings, or regular expression pattern\r\n * @param {boolean} invertChannelFilter - if set to boolean true, negates the result of the channelFilter expression\r\n */\r\n getItems(\r\n groupFilter,\r\n deviceFilter,\r\n sensorFilter,\r\n channelFilter,\r\n invertChannelFilter = false\r\n ) {\r\n return this.getAllItems(\r\n groupFilter,\r\n deviceFilter,\r\n sensorFilter\r\n ).then(items => {\r\n return this.filterQuery(items, channelFilter, invertChannelFilter);\r\n });\r\n }\r\n getItemsFromTarget(target) {\r\n if (target.options) {\r\n if (target.options.invertChannelFilter) {\r\n return this.getItems(\r\n target.group.name,\r\n target.device.name,\r\n target.sensor.name,\r\n target.channel.name,\r\n true\r\n );\r\n } else {\r\n return this.getItems(\r\n target.group.name,\r\n target.device.name,\r\n target.sensor.name,\r\n target.channel.name\r\n );\r\n }\r\n }\r\n return this.getItems(\r\n target.group.name,\r\n target.device.name,\r\n target.sensor.name,\r\n target.channel.name\r\n );\r\n }\r\n\r\n /**\r\n * Retrieve history data from a single sensor.\r\n * @param {number} sensor - sensor ID\r\n * @param {string} channel - channel name\r\n * @param {number} dateFrom - timestamp of start time\r\n * @param {number} dateTo - timestamp of end time\r\n */\r\n getItemHistory(sensor, channel, dateFrom, dateTo) {\r\n const hours = (dateTo - dateFrom) / 3600;\r\n let avg = 0;\r\n if (hours > 12 && hours < 36) {\r\n avg = \"300\";\r\n } else if (hours > 36 && hours < 745) {\r\n avg = \"3600\";\r\n } else if (hours > 745) {\r\n avg = \"86400\";\r\n }\r\n\r\n const method = \"historicdata.xml\";\r\n const params =\r\n \"id=\" +\r\n sensor +\r\n \"&sdate=\" +\r\n this.getPRTGDate(dateFrom) +\r\n \"&edate=\" +\r\n this.getPRTGDate(dateTo) +\r\n \"&avg=\" +\r\n avg +\r\n \"&pctshow=false&pctmode=false\";\r\n /*\r\n * Modified to read the \"statusid\" value, this can then be mapped via lookup table to a PRTG status type\r\n * 1=Unknown, 2=Scanning, 3=Up, 4=Warning, 5=Down, 6=No Probe, 7=Paused by User, 8=Paused by Dependency,\r\n * 9=Paused by Schedule, 10=Unusual, 11=Not Licensed, 12=Paused Until, 13=Down Acknowledged, 14=Down Partial\r\n */\r\n const history = [];\r\n return this.performPRTGAPIRequest(method, params).then(results => {\r\n if (!results.histdata) {\r\n return history;\r\n }\r\n const rCnt = results.histdata.item.length;\r\n const testdata = results.histdata.item[0];\r\n let chanIndex = 0;\r\n\r\n \r\n if (\r\n testdata.value_raw &&\r\n testdata.value_raw.length > 0\r\n )\r\n {\r\n //try to get idx numbers on first row, saves cycles.\r\n for (let idx = 0; idx < testdata.value_raw.length; idx++) {\r\n // this hack specifically applies to bandwidth sensors that track speed AND volume, a better solution remains to be implemented.\r\n if (testdata.value_raw[idx].channel.match(channel + \" [(]speed[)]\") || testdata.value_raw[idx].channel == channel)\r\n {\r\n chanIndex = idx;\r\n }\r\n // \r\n else\r\n {\r\n let rex = new RegExp(utils.escapeRegex(channel), 'g');\r\n if (rex.test(testdata.value_raw[idx].channel)) {\r\n chanIndex = idx;\r\n }\r\n } \r\n }\r\n }\r\n \r\n\r\n for (let iter = 0; iter < rCnt; iter++) {\r\n let val;\r\n const prtgDate = results.histdata.item[iter].datetime_raw;\r\n const dt = new Date((prtgDate - 25569) * 86400 * 1000);\r\n //var dt = Math.round((results.histdata.item[i].datetime_raw - 25568) * 86400,0) * 1000;\r\n if (\r\n results.histdata.item[iter].value_raw &&\r\n results.histdata.item[iter].value_raw.length > 0\r\n ) {\r\n //FIXME: better way of dealing with multiple channels of same name\r\n //IE you select \"Traffic In\" but PRTG provides Volume AND Speed channels.\r\n /*\r\n for (\r\n let iter2 = 0;\r\n iter2 < results.histdata.item[iter].value_raw.length;\r\n iter2++\r\n ) {\r\n //workaround for SNMP Bandwidth Issue #3. Check for presence of (speed) suffix, and use that.\r\n if (\r\n results.histdata.item[iter].value_raw[iter2].channel.match(\r\n channel + \" [(]speed[)]\"\r\n ) ||\r\n results.histdata.item[iter].value_raw[iter2].channel == channel\r\n )\r\n {\r\n val = Number(results.histdata.item[iter].value_raw[iter2].text);\r\n }\r\n */\r\n val = Number(results.histdata.item[iter].value_raw[chanIndex].text);\r\n // }\r\n } else if (results.histdata.item[iter].value_raw) {\r\n val = Number(results.histdata.item[iter].value_raw.text);\r\n }\r\n history.push({\r\n sensor: sensor,\r\n channel: channel,\r\n datetime: dt,\r\n value: val\r\n });\r\n }\r\n return history;\r\n });\r\n }\r\n\r\n /**\r\n * Retrieve messages for a given sensor. Used only for annotation queries.\r\n * \r\n * @param {number} from - Earliest time in range\r\n * @param {number} to - Latest time in range\r\n * @param {number} sensorId - Numeric ID of Sensor \r\n */\r\n getMessages(from, to, sensorId) {\r\n const method = \"table.json\";\r\n const params =\r\n \"&content=messages&columns=objid,datetime,parent,type,name,status,message&id=\" +\r\n sensorId;\r\n return this.performPRTGAPIRequest(method, params).then(function(\r\n messages\r\n ) {\r\n const events = [];\r\n let time = 0;\r\n _.each(messages, function(message) {\r\n time = Math.round((message.datetime_raw - 25569) * 86400, 0);\r\n if (time > from && time < to) {\r\n events.push({\r\n time: time * 1000,\r\n title: message.status,\r\n text:\r\n \"

\" +\r\n message.parent +\r\n \"(\" +\r\n message.type +\r\n \") Message:
\" +\r\n message.message +\r\n \"

\"\r\n });\r\n }\r\n });\r\n return events;\r\n });\r\n }\r\n }\r\n return PRTGAPI;\r\n}\r\n\r\n//register a new module\r\nangular.module(\"grafana.services\").factory(\"PRTGAPIService\", PRTGAPIService);\r\n"]} \ No newline at end of file diff --git a/jasonlashua-prtg-datasource/dist/README.md b/jasonlashua-prtg-datasource/dist/README.md index d22a52e..e2df72f 100644 --- a/jasonlashua-prtg-datasource/dist/README.md +++ b/jasonlashua-prtg-datasource/dist/README.md @@ -1,5 +1,17 @@ -# PRTG Datasource for Grafana 3.x +# PRTG Datasource for Grafana -This is a **beta** plugin designed to work with Grafana 3.0 and newer. +[![GitHub version](https://badge.fury.io/gh/neuralfraud%2Fgrafana-prtg.svg)](https://badge.fury.io/gh/neuralfraud%2Fgrafana-prtg) +[![Change Log](https://img.shields.io/badge/change-log-blue.svg?style=flat)](https://github.com/neuralfraud/grafana-prtg/blob/master/CHANGELOG.md) +[![Docs](https://img.shields.io/badge/docs-latest-red.svg?style=flat)](https://github.com/neuralfraud/grafana-prtg/wiki) +[![Donate](https://img.shields.io/badge/donate-paypal-2c9eda.svg?style=flat&colorA=0b3684)](https://paypal.me/jaylashua/10) -Please participate on GitHub! +Vizualize your PRTG data with rich, powerful Grafana dashboards! + +## Features + +- Select multiple metrics in a single query using regular expressions +- Select from an array of PRTG metadata properties, including Status, Message, Active, Tags, Priortiy, and more. +- Query raw JSON direct from the PRTG API and render using the Table panel +- Show sensor status messages on graphs with Annotations + +For more information, see [The Grafana-PRTG Wiki](https://github.com/neuralfraud/grafana-prtg/wiki) \ No newline at end of file diff --git a/jasonlashua-prtg-datasource/dist/XMLtoJSON.xsl b/jasonlashua-prtg-datasource/dist/XMLtoJSON.xsl deleted file mode 100644 index 6a78b09..0000000 --- a/jasonlashua-prtg-datasource/dist/XMLtoJSON.xsl +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - [{ - - }] - - - - - - - ] - , - - - - , - - - "" : [ - , - - - "" : - , - - - "" : "" - , - - - - - - { - - , - - - "" : "" - - - "text" : "" - - } - , - - - - "" : "" - , - - - - - - - - - - - - - - - - diff --git a/jasonlashua-prtg-datasource/dist/img/PRTG_logo_lg.png b/jasonlashua-prtg-datasource/dist/img/PRTG_logo_lg.png deleted file mode 100644 index f32b9d0..0000000 Binary files a/jasonlashua-prtg-datasource/dist/img/PRTG_logo_lg.png and /dev/null differ diff --git a/jasonlashua-prtg-datasource/dist/img/PRTG_logo_sm.png b/jasonlashua-prtg-datasource/dist/img/PRTG_logo_sm.png deleted file mode 100644 index 3c1085b..0000000 Binary files a/jasonlashua-prtg-datasource/dist/img/PRTG_logo_sm.png and /dev/null differ diff --git a/jasonlashua-prtg-datasource/dist/img/prtglogo.png b/jasonlashua-prtg-datasource/dist/img/prtglogo.png index 54f3182..244cd0d 100644 Binary files a/jasonlashua-prtg-datasource/dist/img/prtglogo.png and b/jasonlashua-prtg-datasource/dist/img/prtglogo.png differ diff --git a/jasonlashua-prtg-datasource/dist/module.js b/jasonlashua-prtg-datasource/dist/module.js index 09a24f8..658b797 100644 --- a/jasonlashua-prtg-datasource/dist/module.js +++ b/jasonlashua-prtg-datasource/dist/module.js @@ -3,7 +3,7 @@ System.register(['./datasource', './query_ctrl'], function (_export, _context) { "use strict"; - var PRTGDataSource, PRTGQueryController, PRTGConfigController, PRTGQueryOptionsController, PRTGAnnotationsQueryController; + var PRTGDataSource, PRTGQueryController, PRTGConfigController, PRTGAnnotationsQueryController; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { @@ -24,11 +24,8 @@ System.register(['./datasource', './query_ctrl'], function (_export, _context) { PRTGConfigController.templateUrl = './partials/config.html'; - _export('QueryOptionsCtrl', PRTGQueryOptionsController = function PRTGQueryOptionsController() { - _classCallCheck(this, PRTGQueryOptionsController); - }); - - PRTGQueryOptionsController.templateUrl = './partials/query.options.html'; + //class PRTGQueryOptionsController {} + //PRTGQueryOptionsController.templateUrl = './partials/query.options.html'; _export('AnnotationsQueryCtrl', PRTGAnnotationsQueryController = function PRTGAnnotationsQueryController() { _classCallCheck(this, PRTGAnnotationsQueryController); @@ -42,8 +39,6 @@ System.register(['./datasource', './query_ctrl'], function (_export, _context) { _export('ConfigCtrl', PRTGConfigController); - _export('QueryOptionsCtrl', PRTGQueryOptionsController); - _export('AnnotationsQueryCtrl', PRTGAnnotationsQueryController); } }; diff --git a/jasonlashua-prtg-datasource/dist/module.js.map b/jasonlashua-prtg-datasource/dist/module.js.map index 41bf58f..2e4a94e 100644 --- a/jasonlashua-prtg-datasource/dist/module.js.map +++ b/jasonlashua-prtg-datasource/dist/module.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/module.js"],"names":["PRTGDataSource","PRTGQueryController","PRTGConfigController","templateUrl","PRTGQueryOptionsController","PRTGAnnotationsQueryController"],"mappings":";;;;;;;;;;;;;;;AAAQA,oB,eAAAA,c;;AACAC,yB,eAAAA,mB;;;4BAEFC,oB;;;;AACNA,2BAAqBC,WAArB,GAAmC,wBAAnC;;kCAEMC,0B;;;;AACNA,iCAA2BD,WAA3B,GAAyC,+BAAzC;;sCAEME,8B;;;;AACNA,qCAA+BF,WAA/B,GAA6C,oCAA7C;;4BAGEH,c;;2BACAC,mB;;4BACAC,oB;;kCACAE,0B;;sCACAC,8B","file":"module.js","sourcesContent":["import {PRTGDataSource} from './datasource';\nimport {PRTGQueryController} from './query_ctrl';\n\nclass PRTGConfigController {}\nPRTGConfigController.templateUrl = './partials/config.html';\n\nclass PRTGQueryOptionsController {}\nPRTGQueryOptionsController.templateUrl = './partials/query.options.html';\n\nclass PRTGAnnotationsQueryController {}\nPRTGAnnotationsQueryController.templateUrl = './partials/annotations.editor.html';\n\nexport {\n PRTGDataSource as Datasource,\n PRTGQueryController as QueryCtrl,\n PRTGConfigController as ConfigCtrl,\n PRTGQueryOptionsController as QueryOptionsCtrl,\n PRTGAnnotationsQueryController as AnnotationsQueryCtrl\n};\n"]} \ No newline at end of file +{"version":3,"sources":["../src/module.js"],"names":["PRTGDataSource","PRTGQueryController","PRTGConfigController","templateUrl","PRTGAnnotationsQueryController"],"mappings":";;;;;;;;;;;;;;;AAAQA,oB,eAAAA,c;;AACAC,yB,eAAAA,mB;;;4BAEFC,oB;;;;AACNA,2BAAqBC,WAArB,GAAmC,wBAAnC;;AAEA;AACA;;sCAEMC,8B;;;;AACNA,qCAA+BD,WAA/B,GAA6C,oCAA7C;;4BAGEH,c;;2BACAC,mB;;4BACAC,oB;;sCAEAE,8B","file":"module.js","sourcesContent":["import {PRTGDataSource} from './datasource';\nimport {PRTGQueryController} from './query_ctrl';\n\nclass PRTGConfigController {}\nPRTGConfigController.templateUrl = './partials/config.html';\n\n//class PRTGQueryOptionsController {}\n//PRTGQueryOptionsController.templateUrl = './partials/query.options.html';\n\nclass PRTGAnnotationsQueryController {}\nPRTGAnnotationsQueryController.templateUrl = './partials/annotations.editor.html';\n\nexport {\n PRTGDataSource as Datasource,\n PRTGQueryController as QueryCtrl,\n PRTGConfigController as ConfigCtrl,\n //PRTGQueryOptionsController as QueryOptionsCtrl,\n PRTGAnnotationsQueryController as AnnotationsQueryCtrl\n};\n"]} \ No newline at end of file diff --git a/jasonlashua-prtg-datasource/dist/partials/query.editor.html b/jasonlashua-prtg-datasource/dist/partials/query.editor.html index 3ba7b5c..0020450 100644 --- a/jasonlashua-prtg-datasource/dist/partials/query.editor.html +++ b/jasonlashua-prtg-datasource/dist/partials/query.editor.html @@ -16,7 +16,7 @@
- +
-
- +
+
@@ -53,7 +53,7 @@ }">
-
+
-
+
-
+
Options
- +
- + -
-
    -
  • - -
  • -
  • - Max data points -
  • -
  • - -
  • -
-
-
-
- -
-
- -
-
- -
-
Max data points
-
    -
  • Don't exceed pixel width of graph. Don't go crazy. Your graphs are built from real-time queries. Perhaps you should consider a SQL summary database?
  • -
-
-
-
---> - diff --git a/jasonlashua-prtg-datasource/dist/plugin.json b/jasonlashua-prtg-datasource/dist/plugin.json index 590c2ae..8e2ace8 100644 --- a/jasonlashua-prtg-datasource/dist/plugin.json +++ b/jasonlashua-prtg-datasource/dist/plugin.json @@ -2,11 +2,9 @@ "type": "datasource", "name": "PRTG", "id": "jasonlashua-prtg-datasource", - "metrics": true, - "alerting":true, + "alerting": true, "annotations": true, - "info": { "description": "PRTG Datasource plugin for Grafana", "author": { @@ -18,9 +16,12 @@ "large": "img/prtglogo.png" }, "links": [ - {"name": "GitHub", "url": "https://github.com/neuralfraud/grafana-prtg"} + { + "name": "GitHub", + "url": "https://github.com/neuralfraud/grafana-prtg" + } ], - "version": "4.0.0", - "updated": "2017-07-17" + "version": "4.0.3", + "updated": "2017-07-28" } -} +} \ No newline at end of file diff --git a/jasonlashua-prtg-datasource/gruntfile.js b/jasonlashua-prtg-datasource/gruntfile.js index 9876206..f442541 100644 --- a/jasonlashua-prtg-datasource/gruntfile.js +++ b/jasonlashua-prtg-datasource/gruntfile.js @@ -4,6 +4,7 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-execute'); grunt.loadNpmTasks('grunt-contrib-clean'); + grunt.loadNpmTasks('grunt-build-number'); grunt.initConfig({ diff --git a/jasonlashua-prtg-datasource/package.json b/jasonlashua-prtg-datasource/package.json index 64e0863..72754be 100644 --- a/jasonlashua-prtg-datasource/package.json +++ b/jasonlashua-prtg-datasource/package.json @@ -1,7 +1,7 @@ { "name": "grafana-prtg", "private": false, - "version": "4.0.0", + "version": "4.0.3", "description": "PRTG Datasource plugin for Grafana", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" @@ -16,17 +16,17 @@ "url": "https://github.com/neuralfraud/grafana-prtg/issues" }, "devDependencies": { - "grunt": "~0.4.5", "babel": "~6.5.1", + "grunt": "~0.4.5", "grunt-babel": "~6.0.0", - "grunt-sass": "^1.1.0", + "grunt-contrib-clean": "~0.6.0", "grunt-contrib-copy": "~0.8.2", - "grunt-contrib-watch": "^0.6.1", "grunt-contrib-uglify": "~0.11.0", - "grunt-systemjs-builder": "^0.2.5", - "load-grunt-tasks": "~3.2.0", + "grunt-contrib-watch": "^0.6.1", "grunt-execute": "~0.2.2", - "grunt-contrib-clean": "~0.6.0" + "grunt-sass": "^1.1.0", + "grunt-systemjs-builder": "^0.2.5", + "load-grunt-tasks": "~3.2.0" }, "dependencies": { "babel-plugin-transform-es2015-modules-systemjs": "^6.5.0", @@ -35,4 +35,4 @@ "lodash": "~4.0.0" }, "homepage": "https://github.com/neuralfraud/grafana-prtg" -} \ No newline at end of file +} diff --git a/jasonlashua-prtg-datasource/src/PRTGAPIService.js b/jasonlashua-prtg-datasource/src/PRTGAPIService.js index 89c4c1d..2ca1ccf 100644 --- a/jasonlashua-prtg-datasource/src/PRTGAPIService.js +++ b/jasonlashua-prtg-datasource/src/PRTGAPIService.js @@ -551,12 +551,19 @@ function PRTGAPIService(alertSrv, backendSrv) { { //try to get idx numbers on first row, saves cycles. for (let idx = 0; idx < testdata.value_raw.length; idx++) { + // this hack specifically applies to bandwidth sensors that track speed AND volume, a better solution remains to be implemented. if (testdata.value_raw[idx].channel.match(channel + " [(]speed[)]") || testdata.value_raw[idx].channel == channel) { chanIndex = idx; - } else if (testdata.value_raw[idx].channel.match('/' + channel + '/')) { - chanIndex = idx; } + // + else + { + let rex = new RegExp(utils.escapeRegex(channel), 'g'); + if (rex.test(testdata.value_raw[idx].channel)) { + chanIndex = idx; + } + } } } diff --git a/jasonlashua-prtg-datasource/src/README.md b/jasonlashua-prtg-datasource/src/README.md index d22a52e..e2df72f 100644 --- a/jasonlashua-prtg-datasource/src/README.md +++ b/jasonlashua-prtg-datasource/src/README.md @@ -1,5 +1,17 @@ -# PRTG Datasource for Grafana 3.x +# PRTG Datasource for Grafana -This is a **beta** plugin designed to work with Grafana 3.0 and newer. +[![GitHub version](https://badge.fury.io/gh/neuralfraud%2Fgrafana-prtg.svg)](https://badge.fury.io/gh/neuralfraud%2Fgrafana-prtg) +[![Change Log](https://img.shields.io/badge/change-log-blue.svg?style=flat)](https://github.com/neuralfraud/grafana-prtg/blob/master/CHANGELOG.md) +[![Docs](https://img.shields.io/badge/docs-latest-red.svg?style=flat)](https://github.com/neuralfraud/grafana-prtg/wiki) +[![Donate](https://img.shields.io/badge/donate-paypal-2c9eda.svg?style=flat&colorA=0b3684)](https://paypal.me/jaylashua/10) -Please participate on GitHub! +Vizualize your PRTG data with rich, powerful Grafana dashboards! + +## Features + +- Select multiple metrics in a single query using regular expressions +- Select from an array of PRTG metadata properties, including Status, Message, Active, Tags, Priortiy, and more. +- Query raw JSON direct from the PRTG API and render using the Table panel +- Show sensor status messages on graphs with Annotations + +For more information, see [The Grafana-PRTG Wiki](https://github.com/neuralfraud/grafana-prtg/wiki) \ No newline at end of file diff --git a/jasonlashua-prtg-datasource/src/XMLtoJSON.xsl b/jasonlashua-prtg-datasource/src/XMLtoJSON.xsl deleted file mode 100644 index 6a78b09..0000000 --- a/jasonlashua-prtg-datasource/src/XMLtoJSON.xsl +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - [{ - - }] - - - - - - - ] - , - - - - , - - - "" : [ - , - - - "" : - , - - - "" : "" - , - - - - - - { - - , - - - "" : "" - - - "text" : "" - - } - , - - - - "" : "" - , - - - - - - - - - - - - - - - - diff --git a/jasonlashua-prtg-datasource/src/img/PRTG_logo_lg.png b/jasonlashua-prtg-datasource/src/img/PRTG_logo_lg.png deleted file mode 100644 index f32b9d0..0000000 Binary files a/jasonlashua-prtg-datasource/src/img/PRTG_logo_lg.png and /dev/null differ diff --git a/jasonlashua-prtg-datasource/src/img/PRTG_logo_sm.png b/jasonlashua-prtg-datasource/src/img/PRTG_logo_sm.png deleted file mode 100644 index 3c1085b..0000000 Binary files a/jasonlashua-prtg-datasource/src/img/PRTG_logo_sm.png and /dev/null differ diff --git a/jasonlashua-prtg-datasource/src/img/prtglogo.png b/jasonlashua-prtg-datasource/src/img/prtglogo.png index 54f3182..244cd0d 100644 Binary files a/jasonlashua-prtg-datasource/src/img/prtglogo.png and b/jasonlashua-prtg-datasource/src/img/prtglogo.png differ diff --git a/jasonlashua-prtg-datasource/src/module.js b/jasonlashua-prtg-datasource/src/module.js index 392e4c2..fe136c1 100644 --- a/jasonlashua-prtg-datasource/src/module.js +++ b/jasonlashua-prtg-datasource/src/module.js @@ -4,8 +4,8 @@ import {PRTGQueryController} from './query_ctrl'; class PRTGConfigController {} PRTGConfigController.templateUrl = './partials/config.html'; -class PRTGQueryOptionsController {} -PRTGQueryOptionsController.templateUrl = './partials/query.options.html'; +//class PRTGQueryOptionsController {} +//PRTGQueryOptionsController.templateUrl = './partials/query.options.html'; class PRTGAnnotationsQueryController {} PRTGAnnotationsQueryController.templateUrl = './partials/annotations.editor.html'; @@ -14,6 +14,6 @@ export { PRTGDataSource as Datasource, PRTGQueryController as QueryCtrl, PRTGConfigController as ConfigCtrl, - PRTGQueryOptionsController as QueryOptionsCtrl, + //PRTGQueryOptionsController as QueryOptionsCtrl, PRTGAnnotationsQueryController as AnnotationsQueryCtrl }; diff --git a/jasonlashua-prtg-datasource/src/partials/query.editor.html b/jasonlashua-prtg-datasource/src/partials/query.editor.html index 3ba7b5c..0020450 100644 --- a/jasonlashua-prtg-datasource/src/partials/query.editor.html +++ b/jasonlashua-prtg-datasource/src/partials/query.editor.html @@ -16,7 +16,7 @@
- +
-
- +
+
@@ -53,7 +53,7 @@ }">
-
+
-
+
-
+
Options
- +
- + -
-
    -
  • - -
  • -
  • - Max data points -
  • -
  • - -
  • -
-
-
-
- -
-
- -
-
- -
-
Max data points
-
    -
  • Don't exceed pixel width of graph. Don't go crazy. Your graphs are built from real-time queries. Perhaps you should consider a SQL summary database?
  • -
-
-
-
---> - diff --git a/jasonlashua-prtg-datasource/src/plugin.json b/jasonlashua-prtg-datasource/src/plugin.json index 590c2ae..8e2ace8 100644 --- a/jasonlashua-prtg-datasource/src/plugin.json +++ b/jasonlashua-prtg-datasource/src/plugin.json @@ -2,11 +2,9 @@ "type": "datasource", "name": "PRTG", "id": "jasonlashua-prtg-datasource", - "metrics": true, - "alerting":true, + "alerting": true, "annotations": true, - "info": { "description": "PRTG Datasource plugin for Grafana", "author": { @@ -18,9 +16,12 @@ "large": "img/prtglogo.png" }, "links": [ - {"name": "GitHub", "url": "https://github.com/neuralfraud/grafana-prtg"} + { + "name": "GitHub", + "url": "https://github.com/neuralfraud/grafana-prtg" + } ], - "version": "4.0.0", - "updated": "2017-07-17" + "version": "4.0.3", + "updated": "2017-07-28" } -} +} \ No newline at end of file