From 12be5fff5668e07687ace0cc41cf2016ad848aa8 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 24 Jul 2015 19:33:22 +0300 Subject: [PATCH 01/31] Refactoring - resolve code inspection problems. --- zabbix/datasource.js | 4 +- zabbix/helperFunctions.js | 12 ++- zabbix/partials/annotations.editor.html | 24 +++-- zabbix/partials/config.html | 20 +++- zabbix/partials/query.editor.html | 117 +++++++++++++----------- zabbix/zabbixAPIWrapper.js | 6 +- 6 files changed, 107 insertions(+), 76 deletions(-) diff --git a/zabbix/datasource.js b/zabbix/datasource.js index e77b35e..8099ad7 100644 --- a/zabbix/datasource.js +++ b/zabbix/datasource.js @@ -115,7 +115,7 @@ function (angular, _, kbn) { // Remove hostnames from item names and then // extract item names // "hostname: itemname" --> "itemname" - var delete_hostname_pattern = /(?:\[[\w\.]+\]\:\s)/g; + var delete_hostname_pattern = /(?:\[[\w\.]+]:\s)/g; var itemnames = zabbixHelperSrv.splitMetrics(itemname.replace(delete_hostname_pattern, '')); // Find items by item names and perform queries @@ -323,7 +323,7 @@ function (angular, _, kbn) { annotation: annotation, time: e.clock * 1000, title: Number(e.value) ? 'Problem' : 'OK', - text: objects[e.objectid].description + formatted_acknowledges, + text: objects[e.objectid].description + formatted_acknowledges }); }); return events; diff --git a/zabbix/helperFunctions.js b/zabbix/helperFunctions.js index 34bb84e..881c69b 100644 --- a/zabbix/helperFunctions.js +++ b/zabbix/helperFunctions.js @@ -14,6 +14,8 @@ function (angular, _) { * Convert Zabbix API history.get response to Grafana format * * @param {Array} items Array of Zabbix Items + * @param alias + * @param scale * @param {Array} history Array of Zabbix History * * @return {Array} Array of timeseries in Grafana format @@ -44,7 +46,7 @@ function (angular, _) { var self = this; return $q.when(_.map(grouped_history, function (history, itemid) { var item = indexed_items[itemid]; - var series = { + return { target: (item.hosts ? item.hosts[0].name+': ' : '') + (alias ? alias : self.expandItemName(item)), datapoints: _.map(history, function (p) { @@ -59,7 +61,6 @@ function (angular, _) { return [value, p.clock * 1000]; }) }; - return series; })).then(function (result) { return _.sortBy(result, 'target'); }); @@ -69,6 +70,8 @@ function (angular, _) { * Convert Zabbix API trends.get response to Grafana format * * @param {Array} items Array of Zabbix Items + * @param alias + * @param scale * @param {Array} trends Array of Zabbix Trends * * @return {Array} Array of timeseries in Grafana format @@ -86,7 +89,7 @@ function (angular, _) { var self = this; return $q.when(_.map(grouped_trends, function (trends, itemid) { var item = indexed_items[itemid]; - var series = { + return { target: (item.hosts ? item.hosts[0].name+': ' : '') + (alias ? alias : self.expandItemName(item)), datapoints: _.map(trends, function (p) { @@ -101,7 +104,6 @@ function (angular, _) { return [value, p.clock * 1000]; }) }; - return series; })).then(function (result) { return _.sortBy(result, 'target'); }); @@ -112,7 +114,7 @@ function (angular, _) { * CPU $2 time ($3) --> CPU system time (avg1) * * @param item: zabbix api item object - * @return: expanded item name (string) + * @return {string} expanded item name (string) */ this.expandItemName = function(item) { var name = item.name; diff --git a/zabbix/partials/annotations.editor.html b/zabbix/partials/annotations.editor.html index 1dcfe6f..1e9caba 100644 --- a/zabbix/partials/annotations.editor.html +++ b/zabbix/partials/annotations.editor.html @@ -1,16 +1,24 @@
-
-
Zabbix trigger Example: Lack of free swap space
-
- -
-
+
+
Zabbix trigger + Example: Lack of free swap space +
+
+ +
+
Options
- - + +
diff --git a/zabbix/partials/config.html b/zabbix/partials/config.html index de32561..fed5320 100644 --- a/zabbix/partials/config.html +++ b/zabbix/partials/config.html @@ -10,13 +10,17 @@ User
  • - +
  • Password
  • - +
  • @@ -28,14 +32,18 @@
  • Enable  - +
  • Use trends from
  • - +
  • @@ -46,7 +54,9 @@ Metrics limit
  • - +
  • diff --git a/zabbix/partials/query.editor.html b/zabbix/partials/query.editor.html index 6fc6627..30b767b 100644 --- a/zabbix/partials/query.editor.html +++ b/zabbix/partials/query.editor.html @@ -1,18 +1,18 @@
    -
    +
    -
    @@ -218,7 +227,9 @@
    Max data points
      -
    • Grafana-Zabbix plugin uses maxDataPoints parameter to consolidate the real number of values down to this number
    • +
    • Grafana-Zabbix plugin uses maxDataPoints parameter to consolidate the real number of values down to this + number +
    • If there are more real values, then by default they will be consolidated using averages
    • This could hide real peaks and max values in your series
    • Point consolidation will effect series legend values (min,max,total,current)
    • diff --git a/zabbix/zabbixAPIWrapper.js b/zabbix/zabbixAPIWrapper.js index 45a14d1..0399915 100644 --- a/zabbix/zabbixAPIWrapper.js +++ b/zabbix/zabbixAPIWrapper.js @@ -1,7 +1,7 @@ define([ 'angular', - 'lodash', -], + 'lodash' + ], function (angular, _) { 'use strict'; @@ -94,7 +94,7 @@ function (angular, _) { }, auth: null, id: 1 - }, + } }; if (this.basicAuth || this.withCredentials) { From 560d476102156ee59d0ffd1274701bf99abd62b7 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 24 Jul 2015 20:51:44 +0300 Subject: [PATCH 02/31] Refactoring - resolve some code inspection problems for JSDoc. --- zabbix/zabbixAPIWrapper.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/zabbix/zabbixAPIWrapper.js b/zabbix/zabbixAPIWrapper.js index 0399915..3954b36 100644 --- a/zabbix/zabbixAPIWrapper.js +++ b/zabbix/zabbixAPIWrapper.js @@ -245,8 +245,8 @@ function (angular, _) { /** * Get the list of hosts * - * @param {array} groupids - * @return {array} array of Zabbix host objects + * @param {string|string[]} groupids + * @return {Object} array of Zabbix host objects */ p.performHostSuggestQuery = function(groupids) { var params = { @@ -269,7 +269,7 @@ function (angular, _) { * * @param {array} hostids * @param {array} groupids - * @return {array} array of Zabbix application objects + * @return {Object} array of Zabbix application objects */ p.performAppSuggestQuery = function(hostids, /* optional */ groupids) { var params = { @@ -289,10 +289,10 @@ function (angular, _) { /** * Items request * - * @param {string or Array} hostids /////////////////////////// - * @param {string or Array} applicationids // Zabbix API parameters // - * @param {string or Array} groupids /////////////////////////// - * @return {string or Array} Array of Zabbix API item objects + * @param {string|string[]} hostids /////////////////////////// + * @param {string|string[]} applicationids // Zabbix API parameters // + * @param {string|string[]} groupids /////////////////////////// + * @return {string|string[]} Array of Zabbix API item objects */ p.performItemSuggestQuery = function(hostids, applicationids, /* optional */ groupids) { var params = { From e6c5dd35bf71d988501d4af956cab42b28efed9e Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 24 Jul 2015 20:53:50 +0300 Subject: [PATCH 03/31] iss #19 - implements getITService() and getSLA() methods. --- zabbix/zabbixAPIWrapper.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/zabbix/zabbixAPIWrapper.js b/zabbix/zabbixAPIWrapper.js index 3954b36..c0b8980 100644 --- a/zabbix/zabbixAPIWrapper.js +++ b/zabbix/zabbixAPIWrapper.js @@ -508,6 +508,25 @@ function (angular, _) { }); }; + p.getITService = function(/* optional */ serviceids) { + var params = { + output: 'extend', + serviceids: serviceids + }; + return this.performZabbixAPIRequest('service.get', params); + }; + + p.getSLA = function(serviceids, from, to) { + var params = { + serviceids: serviceids, + intervals: [{ + from: from, + to: to + }] + }; + return this.performZabbixAPIRequest('service.getsla', params); + }; + return ZabbixAPI; }); From f5cd2a0830f36e1c0a72b23207bf624bbaf2c0f2 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 24 Jul 2015 23:28:24 +0300 Subject: [PATCH 04/31] Fixed layout in query editor. --- zabbix/partials/query.editor.html | 67 ++++++++++++++----------------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/zabbix/partials/query.editor.html b/zabbix/partials/query.editor.html index 30b767b..4fccecb 100644 --- a/zabbix/partials/query.editor.html +++ b/zabbix/partials/query.editor.html @@ -55,15 +55,13 @@
    • Group
    • - + @@ -73,15 +71,13 @@
    • Host
    • - + @@ -105,7 +101,9 @@
    +
    + From add7ed0f0f6be99d3ed49df0301c4f6466966e3e Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 24 Jul 2015 23:50:24 +0300 Subject: [PATCH 05/31] iss #19 - Implemented base behavior for switching editor to IT Services. --- zabbix/partials/query.editor.html | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/zabbix/partials/query.editor.html b/zabbix/partials/query.editor.html index 4fccecb..fe8a516 100644 --- a/zabbix/partials/query.editor.html +++ b/zabbix/partials/query.editor.html @@ -16,6 +16,15 @@ -
    -
    +
    + diff --git a/zabbix/queryCtrl.js b/zabbix/queryCtrl.js index 0a02a58..bca12e5 100644 --- a/zabbix/queryCtrl.js +++ b/zabbix/queryCtrl.js @@ -13,20 +13,31 @@ function (angular, _) { $scope.init = function() { $scope.targetLetters = targetLetters; - $scope.metric = { - hostGroupList: [], - hostList: [{name: '*', visible_name: 'All'}], - applicationList: [{name: '*', visible_name: 'All'}], - itemList: [{name: 'All'}] - }; + if ($scope.target.ITService) { + $scope.slaPropertyList = [ + "sla", + "okTime", + "problemTime", + "downtimeTime" + ]; + $scope.itserviceList = [{name: "test"}]; + $scope.updateITServiceList(); + } else { + $scope.metric = { + hostGroupList: [], + hostList: [{name: '*', visible_name: 'All'}], + applicationList: [{name: '*', visible_name: 'All'}], + itemList: [{name: 'All'}] + }; - // Update host group, host, application and item lists - $scope.updateGroupList(); - $scope.updateHostList(); - $scope.updateAppList(); - $scope.updateItemList(); + // Update host group, host, application and item lists + $scope.updateGroupList(); + $scope.updateHostList(); + $scope.updateAppList(); + $scope.updateItemList(); - setItemAlias(); + setItemAlias(); + } $scope.target.errors = validateTarget($scope.target); }; @@ -49,6 +60,17 @@ function (angular, _) { } }; + /** + * Call when IT service is selected. + */ + $scope.selectITService = function() { + $scope.target.errors = validateTarget($scope.target); + if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) { + $scope.oldTarget = angular.copy($scope.target); + $scope.get_data(); + } + }; + /** * Call when host group selected */ @@ -116,6 +138,17 @@ function (angular, _) { // SUGGESTION QUERIES ////////////////////////////// + + /** + * Update list of IT services + */ + $scope.updateITServiceList = function() { + $scope.datasource.zabbixAPI.getITService().then(function (iteservices) { + $scope.itserviceList = []; + $scope.itserviceList = $scope.itserviceList.concat(iteservices); + }); + }; + /** * Update list of host groups */ From 53d6b60e6fab54f5bcfca5ba41fd8099ec2f2cfc Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Sat, 25 Jul 2015 17:17:22 +0300 Subject: [PATCH 07/31] iss #19 - Reinitialize query editor when mode switched to IT services. --- zabbix/partials/query.editor.html | 4 ++-- zabbix/queryCtrl.js | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/zabbix/partials/query.editor.html b/zabbix/partials/query.editor.html index e7f2916..86dbcc2 100644 --- a/zabbix/partials/query.editor.html +++ b/zabbix/partials/query.editor.html @@ -19,11 +19,11 @@
  • IT Services + ng-click="switchEditorMode()">IT Services
  • Items + ng-click="switchEditorMode()">Items
  • Duplicate
  • Move up
  • diff --git a/zabbix/queryCtrl.js b/zabbix/queryCtrl.js index bca12e5..4fc469e 100644 --- a/zabbix/queryCtrl.js +++ b/zabbix/queryCtrl.js @@ -42,6 +42,11 @@ function (angular, _) { $scope.target.errors = validateTarget($scope.target); }; + $scope.switchEditorMode = function() { + $scope.target.ITService = !$scope.target.ITService; + $scope.init(); + }; + /** * Take alias from item name by default */ From d2db53fcfb636a578883baee877a3f005dd697ee Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Sat, 25 Jul 2015 17:23:35 +0300 Subject: [PATCH 08/31] iss #19 - Friendly names for SLA properties. --- zabbix/partials/query.editor.html | 2 +- zabbix/queryCtrl.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/zabbix/partials/query.editor.html b/zabbix/partials/query.editor.html index 86dbcc2..6ad59f3 100644 --- a/zabbix/partials/query.editor.html +++ b/zabbix/partials/query.editor.html @@ -68,7 +68,7 @@ diff --git a/zabbix/queryCtrl.js b/zabbix/queryCtrl.js index 4fc469e..69839b3 100644 --- a/zabbix/queryCtrl.js +++ b/zabbix/queryCtrl.js @@ -15,10 +15,10 @@ function (angular, _) { $scope.targetLetters = targetLetters; if ($scope.target.ITService) { $scope.slaPropertyList = [ - "sla", - "okTime", - "problemTime", - "downtimeTime" + {name: "SLA", property: "sla"}, + {name: "OK time", property: "okTime"}, + {name: "Problem time", property: "problemTime"}, + {name: "Down time", property: "downtimeTime"} ]; $scope.itserviceList = [{name: "test"}]; $scope.updateITServiceList(); From 218f8b8f352a886cb95a9040cb0eebfaf0de9c30 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Sat, 25 Jul 2015 18:17:38 +0300 Subject: [PATCH 09/31] iss #19 - Get IT service data and handle response. --- zabbix/datasource.js | 150 ++++++++++++++++++++------------------ zabbix/helperFunctions.js | 18 +++++ 2 files changed, 98 insertions(+), 70 deletions(-) diff --git a/zabbix/datasource.js b/zabbix/datasource.js index 8099ad7..ec0798a 100644 --- a/zabbix/datasource.js +++ b/zabbix/datasource.js @@ -94,93 +94,103 @@ function (angular, _, kbn) { // Create request for each target var promises = _.map(options.targets, function(target) { - // Don't show undefined and hidden targets - if (target.hide || !target.group || !target.host - || !target.application || !target.item) { - return []; - } + if (!target.ITService) { + // Don't show undefined and hidden targets + if (target.hide || !target.group || !target.host + || !target.application || !target.item) { + return []; + } - // Replace templated variables - var groupname = templateSrv.replace(target.group.name); - var hostname = templateSrv.replace(target.host.name); - var appname = templateSrv.replace(target.application.name); - var itemname = templateSrv.replace(target.item.name); + // Replace templated variables + var groupname = templateSrv.replace(target.group.name); + var hostname = templateSrv.replace(target.host.name); + var appname = templateSrv.replace(target.application.name); + var itemname = templateSrv.replace(target.item.name); - // Extract zabbix groups, hosts and apps from string: - // "{host1,host2,...,hostN}" --> [host1, host2, ..., hostN] - var groups = zabbixHelperSrv.splitMetrics(groupname); - var hosts = zabbixHelperSrv.splitMetrics(hostname); - var apps = zabbixHelperSrv.splitMetrics(appname); + // Extract zabbix groups, hosts and apps from string: + // "{host1,host2,...,hostN}" --> [host1, host2, ..., hostN] + var groups = zabbixHelperSrv.splitMetrics(groupname); + var hosts = zabbixHelperSrv.splitMetrics(hostname); + var apps = zabbixHelperSrv.splitMetrics(appname); - // Remove hostnames from item names and then - // extract item names - // "hostname: itemname" --> "itemname" - var delete_hostname_pattern = /(?:\[[\w\.]+]:\s)/g; - var itemnames = zabbixHelperSrv.splitMetrics(itemname.replace(delete_hostname_pattern, '')); + // Remove hostnames from item names and then + // extract item names + // "hostname: itemname" --> "itemname" + var delete_hostname_pattern = /(?:\[[\w\.]+]:\s)/g; + var itemnames = zabbixHelperSrv.splitMetrics(itemname.replace(delete_hostname_pattern, '')); - // Find items by item names and perform queries - var self = this; - return this.zabbixAPI.itemFindQuery(groups, hosts, apps) - .then(function (items) { + // Find items by item names and perform queries + var self = this; + return this.zabbixAPI.itemFindQuery(groups, hosts, apps) + .then(function (items) { - // Filter hosts by regex - if (target.host.visible_name === 'All') { - if (target.hostFilter && _.every(items, _.identity.hosts)) { + // Filter hosts by regex + if (target.host.visible_name === 'All') { + if (target.hostFilter && _.every(items, _.identity.hosts)) { - // Use templated variables in filter - var host_pattern = new RegExp(templateSrv.replace(target.hostFilter)); - items = _.filter(items, function (item) { - return _.some(item.hosts, function (host) { - return host_pattern.test(host.name); + // Use templated variables in filter + var host_pattern = new RegExp(templateSrv.replace(target.hostFilter)); + items = _.filter(items, function (item) { + return _.some(item.hosts, function (host) { + return host_pattern.test(host.name); + }); }); - }); + } } - } - if (itemnames[0] === 'All') { + if (itemnames[0] === 'All') { - // Filter items by regex - if (target.itemFilter) { + // Filter items by regex + if (target.itemFilter) { - // Use templated variables in filter - var item_pattern = new RegExp(templateSrv.replace(target.itemFilter)); + // Use templated variables in filter + var item_pattern = new RegExp(templateSrv.replace(target.itemFilter)); + return _.filter(items, function (item) { + return item_pattern.test(zabbixHelperSrv.expandItemName(item)); + }); + } else { + return items; + } + } else { + + // Filtering items return _.filter(items, function (item) { - return item_pattern.test(zabbixHelperSrv.expandItemName(item)); + return _.contains(itemnames, zabbixHelperSrv.expandItemName(item)); }); - } else { - return items; } - } else { + }).then(function (items) { - // Filtering items - return _.filter(items, function (item) { - return _.contains(itemnames, zabbixHelperSrv.expandItemName(item)); - }); - } - }).then(function (items) { - - // Don't perform query for high number of items - // to prevent Grafana slowdown - if (items.length > self.limitmetrics) { - var message = "Try to increase limitmetrics parameter in datasource config.
    " - + "Current limitmetrics value is " + self.limitmetrics; - alertSrv.set("Metrics limit exceeded", message, "warning", 10000); - return []; - } else { - items = _.flatten(items); - - // Use alias only for single metric, otherwise use item names - var alias = target.item.name === 'All' || itemnames.length > 1 ? undefined : templateSrv.replace(target.alias); - - if ((from < useTrendsFrom) && self.trends) { - return self.zabbixAPI.getTrends(items, from, to) - .then(_.bind(zabbixHelperSrv.handleTrendResponse, zabbixHelperSrv, items, alias, target.scale)); + // Don't perform query for high number of items + // to prevent Grafana slowdown + if (items.length > self.limitmetrics) { + var message = "Try to increase limitmetrics parameter in datasource config.
    " + + "Current limitmetrics value is " + self.limitmetrics; + alertSrv.set("Metrics limit exceeded", message, "warning", 10000); + return []; } else { - return self.zabbixAPI.getHistory(items, from, to) - .then(_.bind(zabbixHelperSrv.handleHistoryResponse, zabbixHelperSrv, items, alias, target.scale)); + items = _.flatten(items); + + // Use alias only for single metric, otherwise use item names + var alias = target.item.name === 'All' || itemnames.length > 1 ? undefined : templateSrv.replace(target.alias); + + if ((from < useTrendsFrom) && self.trends) { + return self.zabbixAPI.getTrends(items, from, to) + .then(_.bind(zabbixHelperSrv.handleTrendResponse, zabbixHelperSrv, items, alias, target.scale)); + } else { + return self.zabbixAPI.getHistory(items, from, to) + .then(_.bind(zabbixHelperSrv.handleHistoryResponse, zabbixHelperSrv, items, alias, target.scale)); + } } - } - }); + }); + } else { + // Don't show undefined and hidden targets + if (target.hide || !target.itservice || !target.slaProperty) { + return []; + } else { + return this.zabbixAPI.getSLA(target.itservice.serviceid, from, to) + .then(_.bind(zabbixHelperSrv.handleSLAResponse, zabbixHelperSrv, target.itservice, target.slaProperty)); + } + } }, this); return $q.all(_.flatten(promises)).then(function (results) { diff --git a/zabbix/helperFunctions.js b/zabbix/helperFunctions.js index 881c69b..a07a1e2 100644 --- a/zabbix/helperFunctions.js +++ b/zabbix/helperFunctions.js @@ -109,6 +109,24 @@ function (angular, _) { }); }; + /** + * Convert Zabbix API service.getsla response to Grafana format + * + * @param itservice + * @param slaProperty + * @param slaObject + * @returns {{target: *, datapoints: *[]}} + */ + this.handleSLAResponse = function (itservice, slaProperty, slaObject) { + var targetSLA = slaObject[itservice.serviceid].sla[0]; + return { + target: itservice.name, + datapoints: [ + [targetSLA[slaProperty.property], targetSLA.to * 1000] + ] + }; + }; + /** * Expand item parameters, for example: * CPU $2 time ($3) --> CPU system time (avg1) From f53ebaa9fcda03ace63b1c50a3294097c02937fb Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Sat, 25 Jul 2015 18:42:52 +0300 Subject: [PATCH 10/31] iss #19 - Fix item list updating when application selected. --- zabbix/partials/query.editor.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/partials/query.editor.html b/zabbix/partials/query.editor.html index 6ad59f3..ceda668 100644 --- a/zabbix/partials/query.editor.html +++ b/zabbix/partials/query.editor.html @@ -147,7 +147,7 @@
  • Application
  • -
  • -
    +
    @@ -244,6 +244,11 @@ max data points +
  • + + IT service property + +
  • @@ -264,6 +269,16 @@
  • If you override maxDataPoint and set a high value performance can be severely effected
  • - +
    +
    IT service property
    +
      +
    • Zabbix returns the following availability information about IT service
    • +
    • Status - current status of the IT service
    • +
    • SLA - SLA for the given time interval
    • +
    • OK time - time the service was in OK state, in seconds
    • +
    • Problem time - time the service was in problem state, in seconds
    • +
    • Down time - time the service was in scheduled downtime, in seconds
    • +
    +
    \ No newline at end of file From b61e715d6a877b92e3ed5554d0a58b447acbb731 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Mon, 27 Jul 2015 18:23:12 +0300 Subject: [PATCH 18/31] iss #19 - Fix panel update when IT service property changed. --- zabbix/partials/query.editor.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/partials/query.editor.html b/zabbix/partials/query.editor.html index 98703dc..f48e196 100644 --- a/zabbix/partials/query.editor.html +++ b/zabbix/partials/query.editor.html @@ -67,7 +67,7 @@
  • IT service property
  • Name + +
    + +
    +
    From 221d42c172be29955b40199fd0772e1aa12e3b04 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Tue, 11 Aug 2015 21:55:26 +0300 Subject: [PATCH 22/31] iss #60 - Added processing functions for downsampling: min, max, avg. --- zabbix/datasource.js | 37 +++++++++++++++++++------------ zabbix/helperFunctions.js | 23 +++++++++++++++---- zabbix/partials/query.editor.html | 15 +++++++++++++ zabbix/queryCtrl.js | 10 +++++++++ 4 files changed, 67 insertions(+), 18 deletions(-) diff --git a/zabbix/datasource.js b/zabbix/datasource.js index ec0798a..31b0252 100644 --- a/zabbix/datasource.js +++ b/zabbix/datasource.js @@ -173,13 +173,31 @@ function (angular, _, kbn) { // Use alias only for single metric, otherwise use item names var alias = target.item.name === 'All' || itemnames.length > 1 ? undefined : templateSrv.replace(target.alias); + var history; + var handleFunction; if ((from < useTrendsFrom) && self.trends) { - return self.zabbixAPI.getTrends(items, from, to) - .then(_.bind(zabbixHelperSrv.handleTrendResponse, zabbixHelperSrv, items, alias, target.scale)); + history = self.zabbixAPI.getTrends(items, from, to); + handleFunction = zabbixHelperSrv.handleTrendResponse; } else { - return self.zabbixAPI.getHistory(items, from, to) - .then(_.bind(zabbixHelperSrv.handleHistoryResponse, zabbixHelperSrv, items, alias, target.scale)); + history = self.zabbixAPI.getHistory(items, from, to); + handleFunction = zabbixHelperSrv.handleHistoryResponse; } + + return history + .then(_.bind(handleFunction, zabbixHelperSrv, items, alias, target.scale)) + .then(function (timeseries) { + var timeseries_data = _.flatten(timeseries); + return _.map(timeseries_data, function (timeseries) { + + // Series downsampling + if (timeseries.datapoints.length > options.maxDataPoints) { + var ms_interval = Math.floor((to - from) / options.maxDataPoints) * 1000; + var downsampleFunc = target.downsampleFunction ? target.downsampleFunction.value : "avg"; + timeseries.datapoints = zabbixHelperSrv.downsampleSeries(timeseries.datapoints, to, ms_interval, downsampleFunc); + } + return timeseries; + }); + }); } }); } else { @@ -195,16 +213,7 @@ function (angular, _, kbn) { return $q.all(_.flatten(promises)).then(function (results) { var timeseries_data = _.flatten(results); - var data = _.map(timeseries_data, function (timeseries) { - - // Series downsampling - if (timeseries.datapoints.length > options.maxDataPoints) { - var ms_interval = Math.floor((to - from) / options.maxDataPoints) * 1000; - timeseries.datapoints = zabbixHelperSrv.downsampleSeries(timeseries.datapoints, to, ms_interval); - } - return timeseries; - }); - return { data: data }; + return { data: timeseries_data }; }); }; diff --git a/zabbix/helperFunctions.js b/zabbix/helperFunctions.js index 4f076b3..a1d064a 100644 --- a/zabbix/helperFunctions.js +++ b/zabbix/helperFunctions.js @@ -216,12 +216,12 @@ function (angular, _) { /** * Downsample datapoints series * - * @param {array} datapoints [[, ], ...] + * @param {Object[]} datapoints [[, ], ...] * @param {integer} time_to Panel time to * @param {integer} ms_interval Interval in milliseconds for grouping datapoints - * @return {array} [[, ], ...] + * @return {Object[]} [[, ], ...] */ - this.downsampleSeries = function(datapoints, time_to, ms_interval) { + this.downsampleSeries = function(datapoints, time_to, ms_interval, func) { var downsampledSeries = []; var timeWindow = { from: time_to * 1000 - ms_interval, @@ -231,14 +231,28 @@ function (angular, _) { var points_sum = 0; var points_num = 0; var value_avg = 0; + var frame = []; + for (var i = datapoints.length - 1; i >= 0; i -= 1) { if (timeWindow.from < datapoints[i][1] && datapoints[i][1] <= timeWindow.to) { points_sum += datapoints[i][0]; points_num++; + frame.push(datapoints[i][0]); } else { value_avg = points_num ? points_sum / points_num : 0; - downsampledSeries.push([value_avg, timeWindow.to]); + + if (func === "max") { + downsampledSeries.push([_.max(frame), timeWindow.to]); + } + else if (func === "min") { + downsampledSeries.push([_.min(frame), timeWindow.to]); + } + + // avg by default + else { + downsampledSeries.push([value_avg, timeWindow.to]); + } // Shift time window timeWindow.to = timeWindow.from; @@ -246,6 +260,7 @@ function (angular, _) { points_sum = 0; points_num = 0; + frame = []; // Process point again i++; diff --git a/zabbix/partials/query.editor.html b/zabbix/partials/query.editor.html index 1ac3ccc..d5a7170 100644 --- a/zabbix/partials/query.editor.html +++ b/zabbix/partials/query.editor.html @@ -131,6 +131,21 @@ placeholder="Host filter (regex)" ng-blur="targetBlur()">
  • + +
  • Downsampling
  • +
  • + + + + +
  • diff --git a/zabbix/queryCtrl.js b/zabbix/queryCtrl.js index d565d1a..ad2a2bb 100644 --- a/zabbix/queryCtrl.js +++ b/zabbix/queryCtrl.js @@ -24,6 +24,16 @@ define([ $scope.itserviceList = [{name: "test"}]; $scope.updateITServiceList(); } else { + $scope.downsampleFunctionList = [ + {name: "avg", value: "avg"}, + {name: "min", value: "min"}, + {name: "max", value: "max"} + ]; + + // Set avg by default + if (!$scope.target.downsampleFunction) { + $scope.target.downsampleFunction = $scope.downsampleFunctionList[0]; + } $scope.metric = { hostGroupList: [], hostList: [{name: '*', visible_name: 'All'}], From 3c7b0160122e709d2c43e50f8d4451d570531c6a Mon Sep 17 00:00:00 2001 From: Jean Baptiste Favre Date: Wed, 12 Aug 2015 22:11:56 +0200 Subject: [PATCH 23/31] Enable scoped variables in Zabbix datasource --- zabbix/datasource.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/zabbix/datasource.js b/zabbix/datasource.js index ec0798a..6f8a9a2 100644 --- a/zabbix/datasource.js +++ b/zabbix/datasource.js @@ -102,10 +102,10 @@ function (angular, _, kbn) { } // Replace templated variables - var groupname = templateSrv.replace(target.group.name); - var hostname = templateSrv.replace(target.host.name); - var appname = templateSrv.replace(target.application.name); - var itemname = templateSrv.replace(target.item.name); + var groupname = templateSrv.replace(target.group.name, options.scopedVars); + var hostname = templateSrv.replace(target.host.name, options.scopedVars); + var appname = templateSrv.replace(target.application.name, options.scopedVars); + var itemname = templateSrv.replace(target.item.name, options.scopedVars); // Extract zabbix groups, hosts and apps from string: // "{host1,host2,...,hostN}" --> [host1, host2, ..., hostN] @@ -129,7 +129,7 @@ function (angular, _, kbn) { if (target.hostFilter && _.every(items, _.identity.hosts)) { // Use templated variables in filter - var host_pattern = new RegExp(templateSrv.replace(target.hostFilter)); + var host_pattern = new RegExp(templateSrv.replace(target.hostFilter, options.scopedVars)); items = _.filter(items, function (item) { return _.some(item.hosts, function (host) { return host_pattern.test(host.name); @@ -144,7 +144,7 @@ function (angular, _, kbn) { if (target.itemFilter) { // Use templated variables in filter - var item_pattern = new RegExp(templateSrv.replace(target.itemFilter)); + var item_pattern = new RegExp(templateSrv.replace(target.itemFilter, options.scopedVars)); return _.filter(items, function (item) { return item_pattern.test(zabbixHelperSrv.expandItemName(item)); }); @@ -171,7 +171,7 @@ function (angular, _, kbn) { items = _.flatten(items); // Use alias only for single metric, otherwise use item names - var alias = target.item.name === 'All' || itemnames.length > 1 ? undefined : templateSrv.replace(target.alias); + var alias = target.item.name === 'All' || itemnames.length > 1 ? undefined : templateSrv.replace(target.alias, options.scopedVars); if ((from < useTrendsFrom) && self.trends) { return self.zabbixAPI.getTrends(items, from, to) From 877cadecaea2326e2f2bdb8ffa8848cc9e52bb57 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 14 Aug 2015 19:44:45 +0300 Subject: [PATCH 24/31] Fixed #68 - Option "Use trends from" at configuration page don't work --- zabbix/partials/config.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/partials/config.html b/zabbix/partials/config.html index fed5320..a0a7f50 100644 --- a/zabbix/partials/config.html +++ b/zabbix/partials/config.html @@ -42,7 +42,7 @@
  • From bf07637fc144777ba94d547bb2a640f01b389cd8 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 14 Aug 2015 21:22:19 +0300 Subject: [PATCH 25/31] Resolved #69 - Able to select min, max or avg value for downsampling. --- zabbix/datasource.js | 17 ++++++++--------- zabbix/helperFunctions.js | 15 +++++++++++++-- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/zabbix/datasource.js b/zabbix/datasource.js index 3c7d03e..cd5c0a1 100644 --- a/zabbix/datasource.js +++ b/zabbix/datasource.js @@ -171,21 +171,20 @@ function (angular, _, kbn) { items = _.flatten(items); // Use alias only for single metric, otherwise use item names - var alias = target.item.name === 'All' || itemnames.length > 1 ? undefined : templateSrv.replace(target.alias, options.scopedVars); + var alias = target.item.name === 'All' || itemnames.length > 1 ? + undefined : templateSrv.replace(target.alias, options.scopedVars); var history; - var handleFunction; if ((from < useTrendsFrom) && self.trends) { - history = self.zabbixAPI.getTrends(items, from, to); - handleFunction = zabbixHelperSrv.handleTrendResponse; + var points = target.downsampleFunction ? target.downsampleFunction.value : "avg"; + history = self.zabbixAPI.getTrends(items, from, to) + .then(_.bind(zabbixHelperSrv.handleTrendResponse, zabbixHelperSrv, items, alias, target.scale, points)); } else { - history = self.zabbixAPI.getHistory(items, from, to); - handleFunction = zabbixHelperSrv.handleHistoryResponse; + history = self.zabbixAPI.getHistory(items, from, to) + .then(_.bind(zabbixHelperSrv.handleHistoryResponse, zabbixHelperSrv, items, alias, target.scale)); } - return history - .then(_.bind(handleFunction, zabbixHelperSrv, items, alias, target.scale)) - .then(function (timeseries) { + return history.then(function (timeseries) { var timeseries_data = _.flatten(timeseries); return _.map(timeseries_data, function (timeseries) { diff --git a/zabbix/helperFunctions.js b/zabbix/helperFunctions.js index a1d064a..f59a470 100644 --- a/zabbix/helperFunctions.js +++ b/zabbix/helperFunctions.js @@ -72,6 +72,7 @@ function (angular, _) { * @param {Array} items Array of Zabbix Items * @param alias * @param scale + * @param {string} points Point value to return: min, max or avg * @param {Array} trends Array of Zabbix Trends * * @return {Array} Array of timeseries in Grafana format @@ -80,7 +81,7 @@ function (angular, _) { * datapoints: [[, ], ...] * } */ - this.handleTrendResponse = function (items, alias, scale, trends) { + this.handleTrendResponse = function (items, alias, scale, points, trends) { // Group items and trends by itemid var indexed_items = _.indexBy(items, 'itemid'); @@ -95,7 +96,16 @@ function (angular, _) { datapoints: _.map(trends, function (p) { // Value must be a number for properly work - var value = Number(p.value_avg); + var value; + if (points === "min") { + value = Number(p.value_min); + } + else if (points === "max") { + value = Number(p.value_max); + } + else { + value = Number(p.value_avg); + } // Apply scale if (scale) { @@ -219,6 +229,7 @@ function (angular, _) { * @param {Object[]} datapoints [[, ], ...] * @param {integer} time_to Panel time to * @param {integer} ms_interval Interval in milliseconds for grouping datapoints + * @param {string} func Value to return: min, max or avg * @return {Object[]} [[, ], ...] */ this.downsampleSeries = function(datapoints, time_to, ms_interval, func) { From ad83ecfe69a71d11b016e96c13fbc03f90d7f78a Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Sat, 15 Aug 2015 22:32:14 +0300 Subject: [PATCH 26/31] iss #61 - Improved annotations editor. Able to specify Group and Host for triggers search. --- zabbix/datasource.js | 8 +++++++- zabbix/partials/annotations.editor.html | 22 ++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/zabbix/datasource.js b/zabbix/datasource.js index ec0798a..a036043 100644 --- a/zabbix/datasource.js +++ b/zabbix/datasource.js @@ -301,11 +301,17 @@ function (angular, _, kbn) { var params = { output: ['triggerid', 'description'], search: { - 'description': annotation.query + 'description': annotation.trigger }, searchWildcardsEnabled: true, expandDescription: true }; + if (annotation.host) { + params.host = annotation.host; + } + else if (annotation.group) { + params.group = annotation.group; + } return this.zabbixAPI.performZabbixAPIRequest('trigger.get', params) .then(function (result) { diff --git a/zabbix/partials/annotations.editor.html b/zabbix/partials/annotations.editor.html index 2b98557..eef6f78 100644 --- a/zabbix/partials/annotations.editor.html +++ b/zabbix/partials/annotations.editor.html @@ -1,37 +1,31 @@
    Zabbix trigger - Example: Lack of free swap space
    - -
    + +
    +
    + + +
    +
    + + +
    +
    + +
    From 9ec32b26e886ae12b528e41800376889094dab45 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Tue, 18 Aug 2015 20:39:01 +0300 Subject: [PATCH 29/31] iss #71 - Added text metrics editor. --- zabbix/datasource.js | 12 ++++++++-- zabbix/partials/query.editor.html | 34 ++++++++++++++++------------ zabbix/queryCtrl.js | 37 +++++++++++++++++-------------- 3 files changed, 50 insertions(+), 33 deletions(-) diff --git a/zabbix/datasource.js b/zabbix/datasource.js index a6cfcbd..9fdb34d 100644 --- a/zabbix/datasource.js +++ b/zabbix/datasource.js @@ -94,7 +94,7 @@ function (angular, _, kbn) { // Create request for each target var promises = _.map(options.targets, function(target) { - if (!target.ITService) { + if (!target.mode || target.mode === 0) { // Don't show undefined and hidden targets if (target.hide || !target.group || !target.host || !target.application || !target.item) { @@ -199,7 +199,10 @@ function (angular, _, kbn) { }); } }); - } else { + } + + // IT services mode + else if (target.mode === 1) { // Don't show undefined and hidden targets if (target.hide || !target.itservice || !target.slaProperty) { return []; @@ -208,6 +211,11 @@ function (angular, _, kbn) { .then(_.bind(zabbixHelperSrv.handleSLAResponse, zabbixHelperSrv, target.itservice, target.slaProperty)); } } + + // Text metrics mode + else if (target.mode === 2) { + return []; + } }, this); return $q.all(_.flatten(promises)).then(function (results) { diff --git a/zabbix/partials/query.editor.html b/zabbix/partials/query.editor.html index d5a7170..26e2ea5 100644 --- a/zabbix/partials/query.editor.html +++ b/zabbix/partials/query.editor.html @@ -16,14 +16,18 @@ -