diff --git a/CHANGELOG.md b/CHANGELOG.md index dde703c..ce9c0bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,33 @@ # Change Log + All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added +- `consolidateBy` function, which allows to specify aggregation function for time series data. +- Direct DB Connection, which allows to use existing SQL data source for querying history data directly from Zabbix database. +- **Docs**: Direct DB Connection reference and configuration. + +### Changed +- IT Services query editor. Now user able to select multiple services by using regex, [#415](https://github.com/alexanderzobnin/grafana-zabbix/issues/415) + ### Fixed -- Item name expanding when key contains commas in quoted params, like my_key["a=1,b=2",c,d] -- Incorrect points order when trends are used [#202](https://github.com/alexanderzobnin/grafana-zabbix/issues/202) -- Triggers panel styles for light theme -- Bug with text metrics when singlestat or table shows NaN, [#325](https://github.com/alexanderzobnin/grafana-zabbix/issues/325) +- Template variables support in annotations and triggers panel (trigger name field), [#428](https://github.com/alexanderzobnin/grafana-zabbix/issues/428) +- Parsing of template variable query with braces, [#432](https://github.com/alexanderzobnin/grafana-zabbix/issues/432) + + +## [3.5.1] - 2017-07-10 +### Fixed +- Bug with alerting when template queries are used, [#424](https://github.com/alexanderzobnin/grafana-zabbix/issues/424) + + +## [3.5.0] - 2017-07-05 +### Added +- rate() function, which calculates per-second rate for growing counters. +- Benchmarks for time series functions. Used [Benchmark.js](https://github.com/bestiejs/benchmark.js) library. ### Changed - Template query format. New format is `{group}{host}{app}{item}`. It allows to use names with dot. Updated @@ -19,9 +37,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Improved performance of groupBy() functions (at 6-10x faster than old). - Fill empty intervals by _null_ when aggregations are used, [#388](https://github.com/alexanderzobnin/grafana-zabbix/issues/388) -### Added -- rate() function, which calculates per-second rate for growing counters. -- Benchmarks for time series functions. Used [Benchmark.js](https://github.com/bestiejs/benchmark.js) library. +### Fixed +- Item name expanding when key contains commas in quoted params, like my_key["a=1,b=2",c,d] +- Incorrect points order when trends are used [#202](https://github.com/alexanderzobnin/grafana-zabbix/issues/202) +- Triggers panel styles for light theme +- Bug with text metrics when singlestat or table shows NaN, [#325](https://github.com/alexanderzobnin/grafana-zabbix/issues/325) ## [3.4.0] - 2017-05-17 diff --git a/README.md b/README.md index 267b52f..44cd475 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Zabbix plugin for Grafana [![GitHub version](https://badge.fury.io/gh/alexanderzobnin%2Fgrafana-zabbix.svg)](https://github.com/alexanderzobnin/grafana-zabbix/releases) +[![Change Log](https://img.shields.io/badge/change-log-blue.svg?style=flat)](https://github.com/alexanderzobnin/grafana-zabbix/blob/master/CHANGELOG.md) [![Docs](https://img.shields.io/badge/docs-latest-red.svg?style=flat)](http://docs.grafana-zabbix.org) [![Twitter URL](https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Follow)](https://twitter.com/alexanderzobnin) [![Donate](https://img.shields.io/badge/donate-paypal-2c9eda.svg?style=flat&colorA=0b3684)](https://paypal.me/alexanderzobnin/10) diff --git a/dist/README.md b/dist/README.md index c4b79fd..625f818 100644 --- a/dist/README.md +++ b/dist/README.md @@ -1,28 +1,22 @@ -## Zabbix plugin for Grafana +# Zabbix plugin for Grafana +[![GitHub version](https://badge.fury.io/gh/alexanderzobnin%2Fgrafana-zabbix.svg)](https://github.com/alexanderzobnin/grafana-zabbix/releases) +[![Change Log](https://img.shields.io/badge/change-log-blue.svg?style=flat)](https://github.com/alexanderzobnin/grafana-zabbix/blob/master/CHANGELOG.md) [![Docs](https://img.shields.io/badge/docs-latest-red.svg?style=flat)](http://docs.grafana-zabbix.org) -[![License](https://img.shields.io/badge/license-Apache_2.0-lightgrey.svg?style=flat)](https://github.com/alexanderzobnin/grafana-zabbix/blob/master/LICENSE) -Zabbix plugin allows to show different type of data from [Zabbix](http://www.zabbix.com/) -monitoring system. +Visualize your Zabbix metrics with the leading open source software for time series analytics. ### Live Demo -Check out the [live demo](http://play.grafana-zabbix.org/) with dashboard examples. +See all features overview and dashboards examples at Grafana-Zabbix [Live demo](http://play.grafana-zabbix.org) site. ### Features -#### Flexible metric editor - * Regex-based metric filtering - * Client-side data processing functions - * Template variables support - -#### Templated dashboards support -Group, host, application or item names can be replaced with a template variable. This allows you to create generic dashboards that can quickly be changed to show stats for a specific cluster, server or application. - -#### Annotations support - * Display zabbix events on graphs - * Show acknowledges for problems - -#### Triggers panel -Panel for showing Zabbix triggers (like Last 20 issues) with some customizable features. +- Select multiple metrics [by using Regex](http://docs.grafana-zabbix.org/guides/gettingstarted/#multiple-items-on-one-graph) +- Create interactive and reusable dashboards with [template variables](http://docs.grafana-zabbix.org/guides/templating/) +- Show events on graphs with [Annotations](http://docs.grafana.org/reference/annotations/) +- Display active problems with Triggers panel +- Transform and shape your data with [metric processing functions](http://docs.grafana-zabbix.org/reference/functions/) (Avg, Median, Min, Max, Multiply, Summarize, Time shift, Alias) +- Find problems faster with [Alerting](http://docs.grafana-zabbix.org/reference/alerting/) feature +- Mix metrics from multiple data sources in the same dashboard or even graph +- Discover and share [dashboards](https://grafana.com/dashboards) in the official library diff --git a/dist/datasource-zabbix/config.controller.js b/dist/datasource-zabbix/config.controller.js new file mode 100644 index 0000000..9b753aa --- /dev/null +++ b/dist/datasource-zabbix/config.controller.js @@ -0,0 +1,74 @@ +'use strict'; + +System.register(['lodash'], function (_export, _context) { + "use strict"; + + var _, _createClass, SUPPORTED_SQL_DS, defaultConfig, ZabbixDSConfigController; + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + return { + setters: [function (_lodash) { + _ = _lodash.default; + }], + execute: function () { + _createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + SUPPORTED_SQL_DS = ['mysql']; + defaultConfig = { + dbConnection: { + enable: false + } + }; + + _export('ZabbixDSConfigController', ZabbixDSConfigController = function () { + /** @ngInject */ + function ZabbixDSConfigController($scope, $injector, datasourceSrv) { + _classCallCheck(this, ZabbixDSConfigController); + + this.datasourceSrv = datasourceSrv; + + _.defaults(this.current.jsonData, defaultConfig); + this.sqlDataSources = this.getSupportedSQLDataSources(); + } + + _createClass(ZabbixDSConfigController, [{ + key: 'getSupportedSQLDataSources', + value: function getSupportedSQLDataSources() { + var datasources = this.datasourceSrv.getAll(); + return _.filter(datasources, function (ds) { + return _.includes(SUPPORTED_SQL_DS, ds.type); + }); + } + }]); + + return ZabbixDSConfigController; + }()); + + _export('ZabbixDSConfigController', ZabbixDSConfigController); + + ZabbixDSConfigController.templateUrl = 'datasource-zabbix/partials/config.html'; + } + }; +}); +//# sourceMappingURL=config.controller.js.map diff --git a/dist/datasource-zabbix/config.controller.js.map b/dist/datasource-zabbix/config.controller.js.map new file mode 100644 index 0000000..afc3a6b --- /dev/null +++ b/dist/datasource-zabbix/config.controller.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/datasource-zabbix/config.controller.js"],"names":["_","SUPPORTED_SQL_DS","defaultConfig","dbConnection","enable","ZabbixDSConfigController","$scope","$injector","datasourceSrv","defaults","current","jsonData","sqlDataSources","getSupportedSQLDataSources","datasources","getAll","filter","includes","ds","type","templateUrl"],"mappings":";;;;;;;;;;;;;;;AAAOA,O;;;;;;;;;;;;;;;;;;;;;AAEDC,sB,GAAmB,CAAC,OAAD,C;AAEnBC,mB,GAAgB;AACpBC,sBAAc;AACZC,kBAAQ;AADI;AADM,O;;0CAMTC,wB;AACX;AACA,0CAAYC,MAAZ,EAAoBC,SAApB,EAA+BC,aAA/B,EAA8C;AAAA;;AAC5C,eAAKA,aAAL,GAAqBA,aAArB;;AAEAR,YAAES,QAAF,CAAW,KAAKC,OAAL,CAAaC,QAAxB,EAAkCT,aAAlC;AACA,eAAKU,cAAL,GAAsB,KAAKC,0BAAL,EAAtB;AACD;;;;uDAE4B;AAC3B,gBAAIC,cAAc,KAAKN,aAAL,CAAmBO,MAAnB,EAAlB;AACA,mBAAOf,EAAEgB,MAAF,CAASF,WAAT,EAAsB,cAAM;AACjC,qBAAOd,EAAEiB,QAAF,CAAWhB,gBAAX,EAA6BiB,GAAGC,IAAhC,CAAP;AACD,aAFM,CAAP;AAGD;;;;;;;;AAGHd,+BAAyBe,WAAzB,GAAuC,wCAAvC","file":"config.controller.js","sourcesContent":["import _ from 'lodash';\n\nconst SUPPORTED_SQL_DS = ['mysql'];\n\nconst defaultConfig = {\n dbConnection: {\n enable: false,\n }\n};\n\nexport class ZabbixDSConfigController {\n /** @ngInject */\n constructor($scope, $injector, datasourceSrv) {\n this.datasourceSrv = datasourceSrv;\n\n _.defaults(this.current.jsonData, defaultConfig);\n this.sqlDataSources = this.getSupportedSQLDataSources();\n }\n\n getSupportedSQLDataSources() {\n let datasources = this.datasourceSrv.getAll();\n return _.filter(datasources, ds => {\n return _.includes(SUPPORTED_SQL_DS, ds.type);\n });\n }\n}\n\nZabbixDSConfigController.templateUrl = 'datasource-zabbix/partials/config.html';\n"]} \ No newline at end of file diff --git a/dist/datasource-zabbix/constants.js b/dist/datasource-zabbix/constants.js index 651f33a..f0f5916 100644 --- a/dist/datasource-zabbix/constants.js +++ b/dist/datasource-zabbix/constants.js @@ -3,7 +3,7 @@ System.register([], function (_export, _context) { "use strict"; - var MODE_METRICS, MODE_TEXT, MODE_ITSERVICE, SEV_NOT_CLASSIFIED, SEV_INFORMATION, SEV_WARNING, SEV_AVERAGE, SEV_HIGH, SEV_DISASTER, SHOW_ALL_TRIGGERS, SHOW_ALL_EVENTS, SHOW_OK_EVENTS, DATAPOINT_VALUE, DATAPOINT_TS; + var MODE_METRICS, MODE_ITSERVICE, MODE_TEXT, MODE_ITEMID, SEV_NOT_CLASSIFIED, SEV_INFORMATION, SEV_WARNING, SEV_AVERAGE, SEV_HIGH, SEV_DISASTER, SHOW_ALL_TRIGGERS, SHOW_ALL_EVENTS, SHOW_OK_EVENTS, DATAPOINT_VALUE, DATAPOINT_TS; return { setters: [], execute: function () { @@ -11,13 +11,17 @@ System.register([], function (_export, _context) { _export("MODE_METRICS", MODE_METRICS); + _export("MODE_ITSERVICE", MODE_ITSERVICE = 1); + + _export("MODE_ITSERVICE", MODE_ITSERVICE); + _export("MODE_TEXT", MODE_TEXT = 2); _export("MODE_TEXT", MODE_TEXT); - _export("MODE_ITSERVICE", MODE_ITSERVICE = 1); + _export("MODE_ITEMID", MODE_ITEMID = 3); - _export("MODE_ITSERVICE", MODE_ITSERVICE); + _export("MODE_ITEMID", MODE_ITEMID); _export("SEV_NOT_CLASSIFIED", SEV_NOT_CLASSIFIED = 0); diff --git a/dist/datasource-zabbix/constants.js.map b/dist/datasource-zabbix/constants.js.map index 710d7ff..427ad9d 100644 --- a/dist/datasource-zabbix/constants.js.map +++ b/dist/datasource-zabbix/constants.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/datasource-zabbix/constants.js"],"names":["MODE_METRICS","MODE_TEXT","MODE_ITSERVICE","SEV_NOT_CLASSIFIED","SEV_INFORMATION","SEV_WARNING","SEV_AVERAGE","SEV_HIGH","SEV_DISASTER","SHOW_ALL_TRIGGERS","SHOW_ALL_EVENTS","SHOW_OK_EVENTS","DATAPOINT_VALUE","DATAPOINT_TS"],"mappings":";;;;;;;;;8BACaA,Y,GAAe,C;;;;2BACfC,S,GAAY,C;;;;gCACZC,c,GAAiB,C;;;;oCAGjBC,kB,GAAqB,C;;;;iCACrBC,e,GAAkB,C;;;;6BAClBC,W,GAAc,C;;;;6BACdC,W,GAAc,C;;;;0BACdC,Q,GAAW,C;;;;8BACXC,Y,GAAe,C;;;;mCAEfC,iB,GAAoB,CAAC,CAAD,EAAI,CAAJ,C;;;;iCACpBC,e,GAAkB,CAAC,CAAD,EAAI,CAAJ,C;;;;gCAClBC,c,GAAiB,C;;;;iCAGjBC,e,GAAkB,C;;;;8BAClBC,Y,GAAe,C","file":"constants.js","sourcesContent":["// Editor modes\nexport const MODE_METRICS = 0;\nexport const MODE_TEXT = 2;\nexport const MODE_ITSERVICE = 1;\n\n// Triggers severity\nexport const SEV_NOT_CLASSIFIED = 0;\nexport const SEV_INFORMATION = 1;\nexport const SEV_WARNING = 2;\nexport const SEV_AVERAGE = 3;\nexport const SEV_HIGH = 4;\nexport const SEV_DISASTER = 5;\n\nexport const SHOW_ALL_TRIGGERS = [0, 1];\nexport const SHOW_ALL_EVENTS = [0, 1];\nexport const SHOW_OK_EVENTS = 1;\n\n// Data point\nexport const DATAPOINT_VALUE = 0;\nexport const DATAPOINT_TS = 1;\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/datasource-zabbix/constants.js"],"names":["MODE_METRICS","MODE_ITSERVICE","MODE_TEXT","MODE_ITEMID","SEV_NOT_CLASSIFIED","SEV_INFORMATION","SEV_WARNING","SEV_AVERAGE","SEV_HIGH","SEV_DISASTER","SHOW_ALL_TRIGGERS","SHOW_ALL_EVENTS","SHOW_OK_EVENTS","DATAPOINT_VALUE","DATAPOINT_TS"],"mappings":";;;;;;;;;8BACaA,Y,GAAe,C;;;;gCACfC,c,GAAiB,C;;;;2BACjBC,S,GAAY,C;;;;6BACZC,W,GAAc,C;;;;oCAGdC,kB,GAAqB,C;;;;iCACrBC,e,GAAkB,C;;;;6BAClBC,W,GAAc,C;;;;6BACdC,W,GAAc,C;;;;0BACdC,Q,GAAW,C;;;;8BACXC,Y,GAAe,C;;;;mCAEfC,iB,GAAoB,CAAC,CAAD,EAAI,CAAJ,C;;;;iCACpBC,e,GAAkB,CAAC,CAAD,EAAI,CAAJ,C;;;;gCAClBC,c,GAAiB,C;;;;iCAGjBC,e,GAAkB,C;;;;8BAClBC,Y,GAAe,C","file":"constants.js","sourcesContent":["// Editor modes\nexport const MODE_METRICS = 0;\nexport const MODE_ITSERVICE = 1;\nexport const MODE_TEXT = 2;\nexport const MODE_ITEMID = 3;\n\n// Triggers severity\nexport const SEV_NOT_CLASSIFIED = 0;\nexport const SEV_INFORMATION = 1;\nexport const SEV_WARNING = 2;\nexport const SEV_AVERAGE = 3;\nexport const SEV_HIGH = 4;\nexport const SEV_DISASTER = 5;\n\nexport const SHOW_ALL_TRIGGERS = [0, 1];\nexport const SHOW_ALL_EVENTS = [0, 1];\nexport const SHOW_OK_EVENTS = 1;\n\n// Data point\nexport const DATAPOINT_VALUE = 0;\nexport const DATAPOINT_TS = 1;\n"]} \ No newline at end of file diff --git a/dist/datasource-zabbix/datasource.js b/dist/datasource-zabbix/datasource.js index 8fc5db0..c03835c 100644 --- a/dist/datasource-zabbix/datasource.js +++ b/dist/datasource-zabbix/datasource.js @@ -23,10 +23,23 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', }); } + function getConsolidateBy(target) { + var consolidateBy = 'avg'; + var funcDef = _.find(target.functions, function (func) { + return func.def.name === 'consolidateBy'; + }); + if (funcDef && funcDef.params && funcDef.params.length) { + consolidateBy = funcDef.params[0]; + } + return consolidateBy; + } + function downsampleSeries(timeseries_data, options) { + var defaultAgg = dataProcessor.aggregationFunctions['avg']; + var consolidateByFunc = dataProcessor.aggregationFunctions[options.consolidateBy] || defaultAgg; return _.map(timeseries_data, function (timeseries) { if (timeseries.datapoints.length > options.maxDataPoints) { - timeseries.datapoints = dataProcessor.groupBy(options.interval, dataProcessor.AVERAGE, timeseries.datapoints); + timeseries.datapoints = dataProcessor.groupBy(options.interval, consolidateByFunc, timeseries.datapoints); } return timeseries; }); @@ -58,6 +71,13 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', return '(' + escapedValues.join('|') + ')'; } + function zabbixItemIdsTemplateFormat(value) { + if (typeof value === 'string') { + return value; + } + return value.join(','); + } + /** * If template variables are used in request, replace it using regex format * and wrap with '/' for proper multi-value work. Example: @@ -191,6 +211,9 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', this.dashboardSrv = dashboardSrv; this.zabbixAlertingSrv = zabbixAlertingSrv; + // Use custom format for template variables + this.replaceTemplateVars = _.partial(replaceTemplateVars, this.templateSrv); + // General data source settings this.name = instanceSettings.name; this.url = instanceSettings.url; @@ -215,10 +238,21 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', this.addThresholds = instanceSettings.jsonData.addThresholds; this.alertingMinSeverity = instanceSettings.jsonData.alertingMinSeverity || c.SEV_WARNING; - this.zabbix = new Zabbix(this.url, this.username, this.password, this.basicAuth, this.withCredentials, this.cacheTTL); + // Direct DB Connection options + this.enableDirectDBConnection = instanceSettings.jsonData.dbConnection.enable; + this.sqlDatasourceId = instanceSettings.jsonData.dbConnection.datasourceId; - // Use custom format for template variables - this.replaceTemplateVars = _.partial(replaceTemplateVars, this.templateSrv); + var zabbixOptions = { + username: this.username, + password: this.password, + basicAuth: this.basicAuth, + withCredentials: this.withCredentials, + cacheTTL: this.cacheTTL, + enableDirectDBConnection: this.enableDirectDBConnection, + sqlDatasourceId: this.sqlDatasourceId + }; + + this.zabbix = new Zabbix(this.url, zabbixOptions); } //////////////////////// @@ -253,6 +287,11 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', // Create request for each target var promises = _.map(options.targets, function (t) { + // Don't request undefined and hidden targets + if (t.hide) { + return []; + } + var timeFrom = Math.ceil(dateMath.parse(options.range.from) / 1000); var timeTo = Math.ceil(dateMath.parse(options.range.to) / 1000); @@ -276,7 +315,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', var useTrends = _this.isUseTrends(timeRange); // Metrics or Text query mode - if (target.mode !== c.MODE_ITSERVICE) { + if (target.mode === c.MODE_METRICS || target.mode === c.MODE_TEXT || target.mode === c.MODE_ITEMID) { // Migrate old targets target = migrations.migrate(target); @@ -289,20 +328,13 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', return _this.queryNumericData(target, timeRange, useTrends, options); } else if (target.mode === c.MODE_TEXT) { return _this.queryTextData(target, timeRange); + } else if (target.mode === c.MODE_ITEMID) { + return _this.queryItemIdData(target, timeRange, useTrends, options); } + } else if (target.mode === c.MODE_ITSERVICE) { + // IT services mode + return _this.queryITServiceData(target, timeRange, options); } - - // IT services mode - else if (target.mode === c.MODE_ITSERVICE) { - // Don't show undefined and hidden targets - if (target.hide || !target.itservice || !target.slaProperty) { - return []; - } - - return _this.zabbix.getSLA(target.itservice.serviceid, timeRange).then(function (slaObject) { - return responseHandler.handleSLAResponse(target.itservice, target.slaProperty, slaObject); - }); - } }); // Data for panel (all targets) @@ -315,19 +347,33 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', value: function queryNumericData(target, timeRange, useTrends, options) { var _this2 = this; - var _timeRange = _slicedToArray(timeRange, 2), - timeFrom = _timeRange[0], - timeTo = _timeRange[1]; - var getItemOptions = { itemtype: 'num' }; return this.zabbix.getItemsFromTarget(target, getItemOptions).then(function (items) { - var getHistoryPromise = void 0; + return _this2.queryNumericDataForItems(items, target, timeRange, useTrends, options); + }); + } + }, { + key: 'queryNumericDataForItems', + value: function queryNumericDataForItems(items, target, timeRange, useTrends, options) { + var _this3 = this; - if (useTrends) { - var valueType = _this2.getTrendValueType(target); - getHistoryPromise = _this2.zabbix.getTrend(items, timeFrom, timeTo).then(function (history) { + var _timeRange = _slicedToArray(timeRange, 2), + timeFrom = _timeRange[0], + timeTo = _timeRange[1]; + + var getHistoryPromise = void 0; + options.consolidateBy = getConsolidateBy(target); + + if (useTrends) { + if (this.enableDirectDBConnection) { + getHistoryPromise = this.zabbix.getTrendsDB(items, timeFrom, timeTo, options).then(function (history) { + return _this3.zabbix.dbConnector.handleGrafanaTSResponse(history, items); + }); + } else { + var valueType = this.getTrendValueType(target); + getHistoryPromise = this.zabbix.getTrend(items, timeFrom, timeTo).then(function (history) { return responseHandler.handleTrends(history, items, valueType); }).then(function (timeseries) { // Sort trend data, issue #202 @@ -336,19 +382,24 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', return point[c.DATAPOINT_TS]; }); }); - return timeseries; }); + } + } else { + // Use history + if (this.enableDirectDBConnection) { + getHistoryPromise = this.zabbix.getHistoryDB(items, timeFrom, timeTo, options).then(function (history) { + return _this3.zabbix.dbConnector.handleGrafanaTSResponse(history, items); + }); } else { - // Use history - getHistoryPromise = _this2.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) { + getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) { return responseHandler.handleHistory(history, items); }); } + } - return getHistoryPromise; - }).then(function (timeseries) { - return _this2.applyDataProcessingFunctions(timeseries, target); + return getHistoryPromise.then(function (timeseries) { + return _this3.applyDataProcessingFunctions(timeseries, target); }).then(function (timeseries) { return downsampleSeries(timeseries, options); }).catch(function (error) { @@ -427,7 +478,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', }, { key: 'queryTextData', value: function queryTextData(target, timeRange) { - var _this3 = this; + var _this4 = this; var _timeRange2 = _slicedToArray(timeRange, 2), timeFrom = _timeRange2[0], @@ -438,7 +489,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', }; return this.zabbix.getItemsFromTarget(target, options).then(function (items) { if (items.length) { - return _this3.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) { + return _this4.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) { return responseHandler.handleText(history, items, target); }); } else { @@ -446,15 +497,79 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', } }); } + }, { + key: 'queryItemIdData', + value: function queryItemIdData(target, timeRange, useTrends, options) { + var _this5 = this; + + var itemids = target.itemids; + itemids = this.templateSrv.replace(itemids, options.scopedVars, zabbixItemIdsTemplateFormat); + itemids = _.map(itemids.split(','), function (itemid) { + return itemid.trim(); + }); + + if (!itemids) { + return []; + } + + return this.zabbix.getItemsByIDs(itemids).then(function (items) { + return _this5.queryNumericDataForItems(items, target, timeRange, useTrends, options); + }); + } + }, { + key: 'queryITServiceData', + value: function queryITServiceData(target, timeRange, options) { + var _this6 = this; + + // Don't show undefined and hidden targets + if (target.hide || !target.itservice && !target.itServiceFilter || !target.slaProperty) { + return []; + } + + var itServiceIds = []; + var itServices = []; + var itServiceFilter = void 0; + var isOldVersion = target.itservice && !target.itServiceFilter; + + if (isOldVersion) { + // Backward compatibility + itServiceFilter = '/.*/'; + } else { + itServiceFilter = this.replaceTemplateVars(target.itServiceFilter, options.scopedVars); + } + + return this.zabbix.getITServices(itServiceFilter).then(function (itservices) { + itServices = itservices; + if (isOldVersion) { + itServices = _.filter(itServices, { 'serviceid': target.itservice.serviceid }); + } + + itServiceIds = _.map(itServices, 'serviceid'); + return itServiceIds; + }).then(function (serviceids) { + return _this6.zabbix.getSLA(serviceids, timeRange); + }).then(function (slaResponse) { + return _.map(itServiceIds, function (serviceid) { + var itservice = _.find(itServices, { 'serviceid': serviceid }); + return responseHandler.handleSLAResponse(itservice, target.slaProperty, slaResponse); + }); + }); + } }, { key: 'testDatasource', value: function testDatasource() { - var _this4 = this; + var _this7 = this; var zabbixVersion = void 0; return this.zabbix.getVersion().then(function (version) { zabbixVersion = version; - return _this4.zabbix.login(); + return _this7.zabbix.login(); + }).then(function () { + if (_this7.enableDirectDBConnection) { + return _this7.zabbix.dbConnector.testSQLDataSource(); + } else { + return Promise.resolve(); + } }).then(function () { return { status: "success", @@ -468,6 +583,12 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', title: error.message, message: error.data }; + } else if (error.data && error.data.message) { + return { + status: "error", + title: "Connection failed", + message: error.data.message + }; } else { return { status: "error", @@ -480,14 +601,14 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', }, { key: 'metricFindQuery', value: function metricFindQuery(query) { - var _this5 = this; + var _this8 = this; var result = void 0; var parts = []; // Split query. Query structure: group.host.app.item _.each(utils.splitTemplateQuery(query), function (part) { - part = _this5.replaceTemplateVars(part, {}); + part = _this8.replaceTemplateVars(part, {}); // Replace wildcard to regex if (part === '*') { @@ -524,7 +645,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', }, { key: 'annotationQuery', value: function annotationQuery(options) { - var _this6 = this; + var _this9 = this; var timeFrom = Math.ceil(dateMath.parse(options.rangeRaw.from) / 1000); var timeTo = Math.ceil(dateMath.parse(options.rangeRaw.to) / 1000); @@ -542,13 +663,14 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', return getTriggers.then(function (triggers) { // Filter triggers by description - if (utils.isRegex(annotation.trigger)) { + var triggerName = _this9.replaceTemplateVars(annotation.trigger, {}); + if (utils.isRegex(triggerName)) { triggers = _.filter(triggers, function (trigger) { - return utils.buildRegex(annotation.trigger).test(trigger.description); + return utils.buildRegex(triggerName).test(trigger.description); }); - } else if (annotation.trigger) { + } else if (triggerName) { triggers = _.filter(triggers, function (trigger) { - return trigger.description === annotation.trigger; + return trigger.description === triggerName; }); } @@ -558,7 +680,7 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', }); var objectids = _.map(triggers, 'triggerid'); - return _this6.zabbix.getEvents(objectids, timeFrom, timeTo, showOkEvents).then(function (events) { + return _this9.zabbix.getEvents(objectids, timeFrom, timeTo, showOkEvents).then(function (events) { var indexedTriggers = _.keyBy(triggers, 'triggerid'); // Hide acknowledged events if option enabled @@ -592,21 +714,23 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', }, { key: 'alertQuery', value: function alertQuery(options) { - var _this7 = this; + var _this10 = this; var enabled_targets = filterEnabledTargets(options.targets); - var getPanelItems = _.map(enabled_targets, function (target) { - return _this7.zabbix.getItemsFromTarget(target, { itemtype: 'num' }); + var getPanelItems = _.map(enabled_targets, function (t) { + var target = _.cloneDeep(t); + _this10.replaceTargetVariables(target, options); + return _this10.zabbix.getItemsFromTarget(target, { itemtype: 'num' }); }); return Promise.all(getPanelItems).then(function (results) { var items = _.flatten(results); var itemids = _.map(items, 'itemid'); - return _this7.zabbix.getAlerts(itemids); + return _this10.zabbix.getAlerts(itemids); }).then(function (triggers) { triggers = _.filter(triggers, function (trigger) { - return trigger.priority >= _this7.alertingMinSeverity; + return trigger.priority >= _this10.alertingMinSeverity; }); if (!triggers || triggers.length === 0) { @@ -634,12 +758,12 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', }, { key: 'replaceTargetVariables', value: function replaceTargetVariables(target, options) { - var _this8 = this; + var _this11 = this; var parts = ['group', 'host', 'application', 'item']; _.forEach(parts, function (p) { if (target[p] && target[p].filter) { - target[p].filter = _this8.replaceTemplateVars(target[p].filter, options.scopedVars); + target[p].filter = _this11.replaceTemplateVars(target[p].filter, options.scopedVars); } }); target.textFilter = this.replaceTemplateVars(target.textFilter, options.scopedVars); @@ -647,9 +771,9 @@ System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', _.forEach(target.functions, function (func) { func.params = _.map(func.params, function (param) { if (typeof param === 'number') { - return +_this8.templateSrv.replace(param.toString(), options.scopedVars); + return +_this11.templateSrv.replace(param.toString(), options.scopedVars); } else { - return _this8.templateSrv.replace(param, options.scopedVars); + return _this11.templateSrv.replace(param, options.scopedVars); } }); }); diff --git a/dist/datasource-zabbix/datasource.js.map b/dist/datasource-zabbix/datasource.js.map index 2379393..0565a60 100644 --- a/dist/datasource-zabbix/datasource.js.map +++ b/dist/datasource-zabbix/datasource.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/datasource-zabbix/datasource.js"],"names":["bindFunctionDefs","functionDefs","category","aggregationFunctions","_","map","metricFunctions","getCategories","aggFuncDefs","filter","func","includes","def","name","funcInstance","createFuncInstance","params","bindFunction","dataProcessor","downsampleSeries","timeseries_data","options","timeseries","datapoints","length","maxDataPoints","groupBy","interval","AVERAGE","formatMetric","metricObj","text","expandable","zabbixTemplateFormat","value","utils","escapeRegex","escapedValues","join","replaceTemplateVars","templateSrv","target","scopedVars","replacedTarget","replace","isRegex","sequence","funcsArray","result","i","call","filterEnabledTargets","targets","hide","group","host","item","getTriggerThreshold","expression","thresholdPattern","finded_thresholds","match","threshold","Number","dateMath","migrations","c","responseHandler","ZabbixAPIError","ZabbixAPIDatasource","instanceSettings","alertSrv","dashboardSrv","zabbixAlertingSrv","Zabbix","url","basicAuth","withCredentials","username","jsonData","password","trends","trendsFrom","trendsRange","ttl","cacheTTL","parseInterval","alertingEnabled","alerting","addThresholds","alertingMinSeverity","SEV_WARNING","zabbix","partial","alertQuery","then","setPanelAlertState","panelId","alert","state","removeZabbixThreshold","forEach","thresholds","setPanelThreshold","promises","timeFrom","Math","ceil","parse","range","from","timeTo","to","cloneDeep","t","replaceTargetVariables","timeFunctions","functions","time_from","time_to","timeRange","useTrends","isUseTrends","mode","MODE_ITSERVICE","migrate","MODE_METRICS","queryNumericData","MODE_TEXT","queryTextData","itservice","slaProperty","getSLA","serviceid","handleSLAResponse","slaObject","Promise","all","flatten","data","getItemOptions","itemtype","getItemsFromTarget","getHistoryPromise","valueType","getTrendValueType","getTrend","items","handleTrends","history","series","sortBy","point","DATAPOINT_TS","getHistory","handleHistory","applyDataProcessingFunctions","catch","console","log","error","trendFunctions","trendValueFunc","find","transformFunctions","filterFunctions","aliasFunctions","dp","aggFuncNames","lastAgg","findLast","applyTimeShiftFunction","timeShiftFunc","shift","unShiftTimeSeries","handleText","resolve","zabbixVersion","getVersion","version","login","status","title","message","query","parts","each","splitTemplateQuery","part","push","template","zipObject","app","getItems","getApps","getHosts","getGroups","metrics","rangeRaw","annotation","showOkEvents","SHOW_ALL_EVENTS","SHOW_OK_EVENTS","triggersOptions","showTriggers","SHOW_ALL_TRIGGERS","hideHostsInMaintenance","getTriggers","application","trigger","triggers","buildRegex","test","description","priority","minseverity","objectids","getEvents","indexedTriggers","keyBy","hideAcknowledged","events","event","acknowledges","tags","showHostname","hosts","formatted_acknowledges","formatAcknowledges","time","clock","objectid","enabled_targets","getPanelItems","results","itemids","getAlerts","firedTriggers","p","textFilter","param","toString","useTrendsFrom","useTrendsRange","contains","indexBy"],"mappings":"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","file":"datasource.js","sourcesContent":["import _ from 'lodash';\nimport * as dateMath from 'app/core/utils/datemath';\nimport * as utils from './utils';\nimport * as migrations from './migrations';\nimport * as metricFunctions from './metricFunctions';\nimport * as c from './constants';\nimport dataProcessor from './dataProcessor';\nimport responseHandler from './responseHandler';\nimport './zabbix.js';\nimport './zabbixAlerting.service.js';\nimport {ZabbixAPIError} from './zabbixAPICore.service.js';\n\nclass ZabbixAPIDatasource {\n\n /** @ngInject */\n constructor(instanceSettings, templateSrv, alertSrv, dashboardSrv, zabbixAlertingSrv, Zabbix) {\n this.templateSrv = templateSrv;\n this.alertSrv = alertSrv;\n this.dashboardSrv = dashboardSrv;\n this.zabbixAlertingSrv = zabbixAlertingSrv;\n\n // General data source settings\n this.name = instanceSettings.name;\n this.url = instanceSettings.url;\n this.basicAuth = instanceSettings.basicAuth;\n this.withCredentials = instanceSettings.withCredentials;\n\n // Zabbix API credentials\n this.username = instanceSettings.jsonData.username;\n this.password = instanceSettings.jsonData.password;\n\n // Use trends instead history since specified time\n this.trends = instanceSettings.jsonData.trends;\n this.trendsFrom = instanceSettings.jsonData.trendsFrom || '7d';\n this.trendsRange = instanceSettings.jsonData.trendsRange || '4d';\n\n // Set cache update interval\n var ttl = instanceSettings.jsonData.cacheTTL || '1h';\n this.cacheTTL = utils.parseInterval(ttl);\n\n // Alerting options\n this.alertingEnabled = instanceSettings.jsonData.alerting;\n this.addThresholds = instanceSettings.jsonData.addThresholds;\n this.alertingMinSeverity = instanceSettings.jsonData.alertingMinSeverity || c.SEV_WARNING;\n\n this.zabbix = new Zabbix(this.url, this.username, this.password, this.basicAuth, this.withCredentials, this.cacheTTL);\n\n // Use custom format for template variables\n this.replaceTemplateVars = _.partial(replaceTemplateVars, this.templateSrv);\n }\n\n ////////////////////////\n // Datasource methods //\n ////////////////////////\n\n /**\n * Query panel data. Calls for each panel in dashboard.\n * @param {Object} options Contains time range, targets and other info.\n * @return {Object} Grafana metrics object with timeseries data for each target.\n */\n query(options) {\n // Get alerts for current panel\n if (this.alertingEnabled) {\n this.alertQuery(options).then(alert => {\n this.zabbixAlertingSrv.setPanelAlertState(options.panelId, alert.state);\n\n this.zabbixAlertingSrv.removeZabbixThreshold(options.panelId);\n if (this.addThresholds) {\n _.forEach(alert.thresholds, threshold => {\n this.zabbixAlertingSrv.setPanelThreshold(options.panelId, threshold);\n });\n }\n });\n }\n\n // Create request for each target\n let promises = _.map(options.targets, t => {\n let timeFrom = Math.ceil(dateMath.parse(options.range.from) / 1000);\n let timeTo = Math.ceil(dateMath.parse(options.range.to) / 1000);\n\n // Prevent changes of original object\n let target = _.cloneDeep(t);\n this.replaceTargetVariables(target, options);\n\n // Apply Time-related functions (timeShift(), etc)\n let timeFunctions = bindFunctionDefs(target.functions, 'Time');\n if (timeFunctions.length) {\n const [time_from, time_to] = sequence(timeFunctions)([timeFrom, timeTo]);\n timeFrom = time_from;\n timeTo = time_to;\n }\n let timeRange = [timeFrom, timeTo];\n\n let useTrends = this.isUseTrends(timeRange);\n\n // Metrics or Text query mode\n if (target.mode !== c.MODE_ITSERVICE) {\n // Migrate old targets\n target = migrations.migrate(target);\n\n // Don't request undefined and hidden targets\n if (target.hide || !target.group || !target.host || !target.item) {\n return [];\n }\n\n if (!target.mode || target.mode === c.MODE_METRICS) {\n return this.queryNumericData(target, timeRange, useTrends, options);\n } else if (target.mode === c.MODE_TEXT) {\n return this.queryTextData(target, timeRange);\n }\n }\n\n // IT services mode\n else if (target.mode === c.MODE_ITSERVICE) {\n // Don't show undefined and hidden targets\n if (target.hide || !target.itservice || !target.slaProperty) {\n return [];\n }\n\n return this.zabbix.getSLA(target.itservice.serviceid, timeRange)\n .then(slaObject => {\n return responseHandler.handleSLAResponse(target.itservice, target.slaProperty, slaObject);\n });\n }\n });\n\n // Data for panel (all targets)\n return Promise.all(_.flatten(promises))\n .then(_.flatten)\n .then(data => {\n return { data: data };\n });\n }\n\n queryNumericData(target, timeRange, useTrends, options) {\n let [timeFrom, timeTo] = timeRange;\n let getItemOptions = {\n itemtype: 'num'\n };\n return this.zabbix.getItemsFromTarget(target, getItemOptions)\n .then(items => {\n let getHistoryPromise;\n\n if (useTrends) {\n let valueType = this.getTrendValueType(target);\n getHistoryPromise = this.zabbix.getTrend(items, timeFrom, timeTo)\n .then(history => {\n return responseHandler.handleTrends(history, items, valueType);\n })\n .then(timeseries => {\n // Sort trend data, issue #202\n _.forEach(timeseries, series => {\n series.datapoints = _.sortBy(series.datapoints, point => point[c.DATAPOINT_TS]);\n });\n\n return timeseries;\n });\n } else {\n // Use history\n getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo)\n .then(history => {\n return responseHandler.handleHistory(history, items);\n });\n }\n\n return getHistoryPromise;\n })\n .then(timeseries => this.applyDataProcessingFunctions(timeseries, target))\n .then(timeseries => downsampleSeries(timeseries, options))\n .catch(error => {\n console.log(error);\n return [];\n });\n }\n\n getTrendValueType(target) {\n // Find trendValue() function and get specified trend value\n var trendFunctions = _.map(metricFunctions.getCategories()['Trends'], 'name');\n var trendValueFunc = _.find(target.functions, func => {\n return _.includes(trendFunctions, func.def.name);\n });\n return trendValueFunc ? trendValueFunc.params[0] : \"avg\";\n }\n\n applyDataProcessingFunctions(timeseries_data, target) {\n let transformFunctions = bindFunctionDefs(target.functions, 'Transform');\n let aggregationFunctions = bindFunctionDefs(target.functions, 'Aggregate');\n let filterFunctions = bindFunctionDefs(target.functions, 'Filter');\n let aliasFunctions = bindFunctionDefs(target.functions, 'Alias');\n\n // Apply transformation functions\n timeseries_data = _.map(timeseries_data, timeseries => {\n timeseries.datapoints = sequence(transformFunctions)(timeseries.datapoints);\n return timeseries;\n });\n\n // Apply filter functions\n if (filterFunctions.length) {\n timeseries_data = sequence(filterFunctions)(timeseries_data);\n }\n\n // Apply aggregations\n if (aggregationFunctions.length) {\n let dp = _.map(timeseries_data, 'datapoints');\n dp = sequence(aggregationFunctions)(dp);\n\n let aggFuncNames = _.map(metricFunctions.getCategories()['Aggregate'], 'name');\n let lastAgg = _.findLast(target.functions, func => {\n return _.includes(aggFuncNames, func.def.name);\n });\n\n timeseries_data = [{\n target: lastAgg.text,\n datapoints: dp\n }];\n }\n\n // Apply alias functions\n _.forEach(timeseries_data, sequence(aliasFunctions));\n\n // Apply Time-related functions (timeShift(), etc)\n // Find timeShift() function and get specified trend value\n this.applyTimeShiftFunction(timeseries_data, target);\n\n return timeseries_data;\n }\n\n applyTimeShiftFunction(timeseries_data, target) {\n // Find timeShift() function and get specified interval\n let timeShiftFunc = _.find(target.functions, (func) => {\n return func.def.name === 'timeShift';\n });\n if (timeShiftFunc) {\n let shift = timeShiftFunc.params[0];\n _.forEach(timeseries_data, (series) => {\n series.datapoints = dataProcessor.unShiftTimeSeries(shift, series.datapoints);\n });\n }\n }\n\n queryTextData(target, timeRange) {\n let [timeFrom, timeTo] = timeRange;\n let options = {\n itemtype: 'text'\n };\n return this.zabbix.getItemsFromTarget(target, options)\n .then(items => {\n if (items.length) {\n return this.zabbix.getHistory(items, timeFrom, timeTo)\n .then(history => {\n return responseHandler.handleText(history, items, target);\n });\n } else {\n return Promise.resolve([]);\n }\n });\n }\n\n /**\n * Test connection to Zabbix API\n * @return {object} Connection status and Zabbix API version\n */\n testDatasource() {\n let zabbixVersion;\n return this.zabbix.getVersion()\n .then(version => {\n zabbixVersion = version;\n return this.zabbix.login();\n })\n .then(() => {\n return {\n status: \"success\",\n title: \"Success\",\n message: \"Zabbix API version: \" + zabbixVersion\n };\n })\n .catch(error => {\n if (error instanceof ZabbixAPIError) {\n return {\n status: \"error\",\n title: error.message,\n message: error.data\n };\n } else {\n return {\n status: \"error\",\n title: \"Connection failed\",\n message: \"Could not connect to given url\"\n };\n }\n });\n }\n\n ////////////////\n // Templating //\n ////////////////\n\n /**\n * Find metrics from templated request.\n *\n * @param {string} query Query from Templating\n * @return {string} Metric name - group, host, app or item or list\n * of metrics in \"{metric1,metcic2,...,metricN}\" format.\n */\n metricFindQuery(query) {\n let result;\n let parts = [];\n\n // Split query. Query structure: group.host.app.item\n _.each(utils.splitTemplateQuery(query), part => {\n part = this.replaceTemplateVars(part, {});\n\n // Replace wildcard to regex\n if (part === '*') {\n part = '/.*/';\n }\n parts.push(part);\n });\n let template = _.zipObject(['group', 'host', 'app', 'item'], parts);\n\n // Get items\n if (parts.length === 4) {\n // Search for all items, even it's not belong to any application\n if (template.app === '/.*/') {\n template.app = '';\n }\n result = this.zabbix.getItems(template.group, template.host, template.app, template.item);\n } else if (parts.length === 3) {\n // Get applications\n result = this.zabbix.getApps(template.group, template.host, template.app);\n } else if (parts.length === 2) {\n // Get hosts\n result = this.zabbix.getHosts(template.group, template.host);\n } else if (parts.length === 1) {\n // Get groups\n result = this.zabbix.getGroups(template.group);\n } else {\n result = Promise.resolve([]);\n }\n\n return result.then(metrics => {\n return _.map(metrics, formatMetric);\n });\n }\n\n /////////////////\n // Annotations //\n /////////////////\n\n annotationQuery(options) {\n var timeFrom = Math.ceil(dateMath.parse(options.rangeRaw.from) / 1000);\n var timeTo = Math.ceil(dateMath.parse(options.rangeRaw.to) / 1000);\n var annotation = options.annotation;\n var showOkEvents = annotation.showOkEvents ? c.SHOW_ALL_EVENTS : c.SHOW_OK_EVENTS;\n\n // Show all triggers\n let triggersOptions = {\n showTriggers: c.SHOW_ALL_TRIGGERS,\n hideHostsInMaintenance: false\n };\n\n var getTriggers = this.zabbix.getTriggers(this.replaceTemplateVars(annotation.group, {}),\n this.replaceTemplateVars(annotation.host, {}),\n this.replaceTemplateVars(annotation.application, {}),\n triggersOptions);\n\n return getTriggers.then(triggers => {\n\n // Filter triggers by description\n if (utils.isRegex(annotation.trigger)) {\n triggers = _.filter(triggers, trigger => {\n return utils.buildRegex(annotation.trigger).test(trigger.description);\n });\n } else if (annotation.trigger) {\n triggers = _.filter(triggers, trigger => {\n return trigger.description === annotation.trigger;\n });\n }\n\n // Remove events below the chose severity\n triggers = _.filter(triggers, trigger => {\n return Number(trigger.priority) >= Number(annotation.minseverity);\n });\n\n var objectids = _.map(triggers, 'triggerid');\n return this.zabbix\n .getEvents(objectids, timeFrom, timeTo, showOkEvents)\n .then(events => {\n var indexedTriggers = _.keyBy(triggers, 'triggerid');\n\n // Hide acknowledged events if option enabled\n if (annotation.hideAcknowledged) {\n events = _.filter(events, event => {\n return !event.acknowledges.length;\n });\n }\n\n return _.map(events, event => {\n let tags;\n if (annotation.showHostname) {\n tags = _.map(event.hosts, 'name');\n }\n\n // Show event type (OK or Problem)\n let title = Number(event.value) ? 'Problem' : 'OK';\n\n let formatted_acknowledges = utils.formatAcknowledges(event.acknowledges);\n return {\n annotation: annotation,\n time: event.clock * 1000,\n title: title,\n tags: tags,\n text: indexedTriggers[event.objectid].description + formatted_acknowledges\n };\n });\n });\n });\n }\n\n /**\n * Get triggers and its details for panel's targets\n * Returns alert state ('ok' if no fired triggers, or 'alerting' if at least 1 trigger is fired)\n * or empty object if no related triggers are finded.\n */\n alertQuery(options) {\n let enabled_targets = filterEnabledTargets(options.targets);\n let getPanelItems = _.map(enabled_targets, target => {\n return this.zabbix.getItemsFromTarget(target, {itemtype: 'num'});\n });\n\n return Promise.all(getPanelItems)\n .then(results => {\n let items = _.flatten(results);\n let itemids = _.map(items, 'itemid');\n\n return this.zabbix.getAlerts(itemids);\n })\n .then(triggers => {\n triggers = _.filter(triggers, trigger => {\n return trigger.priority >= this.alertingMinSeverity;\n });\n\n if (!triggers || triggers.length === 0) {\n return {};\n }\n\n let state = 'ok';\n\n let firedTriggers = _.filter(triggers, {value: '1'});\n if (firedTriggers.length) {\n state = 'alerting';\n }\n\n let thresholds = _.map(triggers, trigger => {\n return getTriggerThreshold(trigger.expression);\n });\n\n return {\n panelId: options.panelId,\n state: state,\n thresholds: thresholds\n };\n });\n }\n\n // Replace template variables\n replaceTargetVariables(target, options) {\n let parts = ['group', 'host', 'application', 'item'];\n _.forEach(parts, p => {\n if (target[p] && target[p].filter) {\n target[p].filter = this.replaceTemplateVars(target[p].filter, options.scopedVars);\n }\n });\n target.textFilter = this.replaceTemplateVars(target.textFilter, options.scopedVars);\n\n _.forEach(target.functions, func => {\n func.params = _.map(func.params, param => {\n if (typeof param === 'number') {\n return +this.templateSrv.replace(param.toString(), options.scopedVars);\n } else {\n return this.templateSrv.replace(param, options.scopedVars);\n }\n });\n });\n }\n\n isUseTrends(timeRange) {\n let [timeFrom, timeTo] = timeRange;\n let useTrendsFrom = Math.ceil(dateMath.parse('now-' + this.trendsFrom) / 1000);\n let useTrendsRange = Math.ceil(utils.parseInterval(this.trendsRange) / 1000);\n let useTrends = this.trends && (\n (timeFrom <= useTrendsFrom) ||\n (timeTo - timeFrom >= useTrendsRange)\n );\n return useTrends;\n }\n}\n\nfunction bindFunctionDefs(functionDefs, category) {\n var aggregationFunctions = _.map(metricFunctions.getCategories()[category], 'name');\n var aggFuncDefs = _.filter(functionDefs, function(func) {\n return _.includes(aggregationFunctions, func.def.name);\n });\n\n return _.map(aggFuncDefs, function(func) {\n var funcInstance = metricFunctions.createFuncInstance(func.def, func.params);\n return funcInstance.bindFunction(dataProcessor.metricFunctions);\n });\n}\n\nfunction downsampleSeries(timeseries_data, options) {\n return _.map(timeseries_data, timeseries => {\n if (timeseries.datapoints.length > options.maxDataPoints) {\n timeseries.datapoints = dataProcessor\n .groupBy(options.interval, dataProcessor.AVERAGE, timeseries.datapoints);\n }\n return timeseries;\n });\n}\n\nfunction formatMetric(metricObj) {\n return {\n text: metricObj.name,\n expandable: false\n };\n}\n\n/**\n * Custom formatter for template variables.\n * Default Grafana \"regex\" formatter returns\n * value1|value2\n * This formatter returns\n * (value1|value2)\n * This format needed for using in complex regex with\n * template variables, for example\n * /CPU $cpu_item.*time/ where $cpu_item is system,user,iowait\n */\nfunction zabbixTemplateFormat(value) {\n if (typeof value === 'string') {\n return utils.escapeRegex(value);\n }\n\n var escapedValues = _.map(value, utils.escapeRegex);\n return '(' + escapedValues.join('|') + ')';\n}\n\n/**\n * If template variables are used in request, replace it using regex format\n * and wrap with '/' for proper multi-value work. Example:\n * $variable selected as a, b, c\n * We use filter $variable\n * $variable -> a|b|c -> /a|b|c/\n * /$variable/ -> /a|b|c/ -> /a|b|c/\n */\nfunction replaceTemplateVars(templateSrv, target, scopedVars) {\n var replacedTarget = templateSrv.replace(target, scopedVars, zabbixTemplateFormat);\n if (target !== replacedTarget && !utils.isRegex(replacedTarget)) {\n replacedTarget = '/^' + replacedTarget + '$/';\n }\n return replacedTarget;\n}\n\n// Apply function one by one:\n// sequence([a(), b(), c()]) = c(b(a()));\nfunction sequence(funcsArray) {\n return function(result) {\n for (var i = 0; i < funcsArray.length; i++) {\n result = funcsArray[i].call(this, result);\n }\n return result;\n };\n}\n\nfunction filterEnabledTargets(targets) {\n return _.filter(targets, target => {\n return !(target.hide || !target.group || !target.host || !target.item);\n });\n}\n\nfunction getTriggerThreshold(expression) {\n let thresholdPattern = /.*[<>]([\\d\\.]+)/;\n let finded_thresholds = expression.match(thresholdPattern);\n if (finded_thresholds && finded_thresholds.length >= 2) {\n let threshold = finded_thresholds[1];\n threshold = Number(threshold);\n return threshold;\n } else {\n return null;\n }\n}\n\nexport {ZabbixAPIDatasource, zabbixTemplateFormat};\n\n// Fix for backward compatibility with lodash 2.4\nif (!_.includes) {_.includes = _.contains;}\nif (!_.keyBy) {_.keyBy = _.indexBy;}\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/datasource-zabbix/datasource.js"],"names":["bindFunctionDefs","functionDefs","category","aggregationFunctions","_","map","metricFunctions","getCategories","aggFuncDefs","filter","func","includes","def","name","funcInstance","createFuncInstance","params","bindFunction","dataProcessor","getConsolidateBy","target","consolidateBy","funcDef","find","functions","length","downsampleSeries","timeseries_data","options","defaultAgg","consolidateByFunc","timeseries","datapoints","maxDataPoints","groupBy","interval","formatMetric","metricObj","text","expandable","zabbixTemplateFormat","value","utils","escapeRegex","escapedValues","join","zabbixItemIdsTemplateFormat","replaceTemplateVars","templateSrv","scopedVars","replacedTarget","replace","isRegex","sequence","funcsArray","result","i","call","filterEnabledTargets","targets","hide","group","host","item","getTriggerThreshold","expression","thresholdPattern","finded_thresholds","match","threshold","Number","dateMath","migrations","c","responseHandler","ZabbixAPIError","ZabbixAPIDatasource","instanceSettings","alertSrv","dashboardSrv","zabbixAlertingSrv","Zabbix","partial","url","basicAuth","withCredentials","username","jsonData","password","trends","trendsFrom","trendsRange","ttl","cacheTTL","parseInterval","alertingEnabled","alerting","addThresholds","alertingMinSeverity","SEV_WARNING","enableDirectDBConnection","dbConnection","enable","sqlDatasourceId","datasourceId","zabbixOptions","zabbix","alertQuery","then","setPanelAlertState","panelId","alert","state","removeZabbixThreshold","forEach","thresholds","setPanelThreshold","promises","t","timeFrom","Math","ceil","parse","range","from","timeTo","to","cloneDeep","replaceTargetVariables","timeFunctions","time_from","time_to","timeRange","useTrends","isUseTrends","mode","MODE_METRICS","MODE_TEXT","MODE_ITEMID","migrate","queryNumericData","queryTextData","queryItemIdData","MODE_ITSERVICE","queryITServiceData","Promise","all","flatten","data","getItemOptions","itemtype","getItemsFromTarget","queryNumericDataForItems","items","getHistoryPromise","getTrendsDB","dbConnector","handleGrafanaTSResponse","history","valueType","getTrendValueType","getTrend","handleTrends","series","sortBy","point","DATAPOINT_TS","getHistoryDB","getHistory","handleHistory","applyDataProcessingFunctions","catch","console","log","error","trendFunctions","trendValueFunc","transformFunctions","filterFunctions","aliasFunctions","dp","aggFuncNames","lastAgg","findLast","applyTimeShiftFunction","timeShiftFunc","shift","unShiftTimeSeries","handleText","resolve","itemids","split","itemid","trim","getItemsByIDs","itservice","itServiceFilter","slaProperty","itServiceIds","itServices","isOldVersion","getITServices","itservices","serviceid","getSLA","serviceids","handleSLAResponse","slaResponse","zabbixVersion","getVersion","version","login","testSQLDataSource","status","title","message","query","parts","each","splitTemplateQuery","part","push","template","zipObject","app","getItems","getApps","getHosts","getGroups","metrics","rangeRaw","annotation","showOkEvents","SHOW_ALL_EVENTS","SHOW_OK_EVENTS","triggersOptions","showTriggers","SHOW_ALL_TRIGGERS","hideHostsInMaintenance","getTriggers","application","triggerName","trigger","triggers","buildRegex","test","description","priority","minseverity","objectids","getEvents","indexedTriggers","keyBy","hideAcknowledged","events","event","acknowledges","tags","showHostname","hosts","formatted_acknowledges","formatAcknowledges","time","clock","objectid","enabled_targets","getPanelItems","results","getAlerts","firedTriggers","p","textFilter","param","toString","useTrendsFrom","useTrendsRange","contains","indexBy"],"mappings":"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","file":"datasource.js","sourcesContent":["import _ from 'lodash';\nimport * as dateMath from 'app/core/utils/datemath';\nimport * as utils from './utils';\nimport * as migrations from './migrations';\nimport * as metricFunctions from './metricFunctions';\nimport * as c from './constants';\nimport dataProcessor from './dataProcessor';\nimport responseHandler from './responseHandler';\nimport './zabbix.js';\nimport './zabbixAlerting.service.js';\nimport {ZabbixAPIError} from './zabbixAPICore.service.js';\n\nclass ZabbixAPIDatasource {\n\n /** @ngInject */\n constructor(instanceSettings, templateSrv, alertSrv, dashboardSrv, zabbixAlertingSrv, Zabbix) {\n this.templateSrv = templateSrv;\n this.alertSrv = alertSrv;\n this.dashboardSrv = dashboardSrv;\n this.zabbixAlertingSrv = zabbixAlertingSrv;\n\n // Use custom format for template variables\n this.replaceTemplateVars = _.partial(replaceTemplateVars, this.templateSrv);\n\n // General data source settings\n this.name = instanceSettings.name;\n this.url = instanceSettings.url;\n this.basicAuth = instanceSettings.basicAuth;\n this.withCredentials = instanceSettings.withCredentials;\n\n // Zabbix API credentials\n this.username = instanceSettings.jsonData.username;\n this.password = instanceSettings.jsonData.password;\n\n // Use trends instead history since specified time\n this.trends = instanceSettings.jsonData.trends;\n this.trendsFrom = instanceSettings.jsonData.trendsFrom || '7d';\n this.trendsRange = instanceSettings.jsonData.trendsRange || '4d';\n\n // Set cache update interval\n var ttl = instanceSettings.jsonData.cacheTTL || '1h';\n this.cacheTTL = utils.parseInterval(ttl);\n\n // Alerting options\n this.alertingEnabled = instanceSettings.jsonData.alerting;\n this.addThresholds = instanceSettings.jsonData.addThresholds;\n this.alertingMinSeverity = instanceSettings.jsonData.alertingMinSeverity || c.SEV_WARNING;\n\n // Direct DB Connection options\n this.enableDirectDBConnection = instanceSettings.jsonData.dbConnection.enable;\n this.sqlDatasourceId = instanceSettings.jsonData.dbConnection.datasourceId;\n\n let zabbixOptions = {\n username: this.username,\n password: this.password,\n basicAuth: this.basicAuth,\n withCredentials: this.withCredentials,\n cacheTTL: this.cacheTTL,\n enableDirectDBConnection: this.enableDirectDBConnection,\n sqlDatasourceId: this.sqlDatasourceId\n };\n\n this.zabbix = new Zabbix(this.url, zabbixOptions);\n }\n\n ////////////////////////\n // Datasource methods //\n ////////////////////////\n\n /**\n * Query panel data. Calls for each panel in dashboard.\n * @param {Object} options Contains time range, targets and other info.\n * @return {Object} Grafana metrics object with timeseries data for each target.\n */\n query(options) {\n // Get alerts for current panel\n if (this.alertingEnabled) {\n this.alertQuery(options).then(alert => {\n this.zabbixAlertingSrv.setPanelAlertState(options.panelId, alert.state);\n\n this.zabbixAlertingSrv.removeZabbixThreshold(options.panelId);\n if (this.addThresholds) {\n _.forEach(alert.thresholds, threshold => {\n this.zabbixAlertingSrv.setPanelThreshold(options.panelId, threshold);\n });\n }\n });\n }\n\n // Create request for each target\n let promises = _.map(options.targets, t => {\n // Don't request undefined and hidden targets\n if (t.hide) {\n return [];\n }\n\n let timeFrom = Math.ceil(dateMath.parse(options.range.from) / 1000);\n let timeTo = Math.ceil(dateMath.parse(options.range.to) / 1000);\n\n // Prevent changes of original object\n let target = _.cloneDeep(t);\n this.replaceTargetVariables(target, options);\n\n // Apply Time-related functions (timeShift(), etc)\n let timeFunctions = bindFunctionDefs(target.functions, 'Time');\n if (timeFunctions.length) {\n const [time_from, time_to] = sequence(timeFunctions)([timeFrom, timeTo]);\n timeFrom = time_from;\n timeTo = time_to;\n }\n let timeRange = [timeFrom, timeTo];\n\n let useTrends = this.isUseTrends(timeRange);\n\n // Metrics or Text query mode\n if (target.mode === c.MODE_METRICS || target.mode === c.MODE_TEXT || target.mode === c.MODE_ITEMID) {\n // Migrate old targets\n target = migrations.migrate(target);\n\n // Don't request undefined and hidden targets\n if (target.hide || !target.group || !target.host || !target.item) {\n return [];\n }\n\n if (!target.mode || target.mode === c.MODE_METRICS) {\n return this.queryNumericData(target, timeRange, useTrends, options);\n } else if (target.mode === c.MODE_TEXT) {\n return this.queryTextData(target, timeRange);\n } else if (target.mode === c.MODE_ITEMID) {\n return this.queryItemIdData(target, timeRange, useTrends, options);\n }\n } else if (target.mode === c.MODE_ITSERVICE) {\n // IT services mode\n return this.queryITServiceData(target, timeRange, options);\n }\n });\n\n // Data for panel (all targets)\n return Promise.all(_.flatten(promises))\n .then(_.flatten)\n .then(data => {\n return { data: data };\n });\n }\n\n /**\n * Query target data for Metrics mode\n */\n queryNumericData(target, timeRange, useTrends, options) {\n let getItemOptions = {\n itemtype: 'num'\n };\n return this.zabbix.getItemsFromTarget(target, getItemOptions)\n .then(items => {\n return this.queryNumericDataForItems(items, target, timeRange, useTrends, options);\n });\n }\n\n /**\n * Query history for numeric items\n */\n queryNumericDataForItems(items, target, timeRange, useTrends, options) {\n let [timeFrom, timeTo] = timeRange;\n let getHistoryPromise;\n options.consolidateBy = getConsolidateBy(target);\n\n if (useTrends) {\n if (this.enableDirectDBConnection) {\n getHistoryPromise = this.zabbix.getTrendsDB(items, timeFrom, timeTo, options)\n .then(history => this.zabbix.dbConnector.handleGrafanaTSResponse(history, items));\n } else {\n let valueType = this.getTrendValueType(target);\n getHistoryPromise = this.zabbix.getTrend(items, timeFrom, timeTo)\n .then(history => responseHandler.handleTrends(history, items, valueType))\n .then(timeseries => {\n // Sort trend data, issue #202\n _.forEach(timeseries, series => {\n series.datapoints = _.sortBy(series.datapoints, point => point[c.DATAPOINT_TS]);\n });\n return timeseries;\n });\n }\n } else {\n // Use history\n if (this.enableDirectDBConnection) {\n getHistoryPromise = this.zabbix.getHistoryDB(items, timeFrom, timeTo, options)\n .then(history => this.zabbix.dbConnector.handleGrafanaTSResponse(history, items));\n } else {\n getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo)\n .then(history => responseHandler.handleHistory(history, items));\n }\n }\n\n return getHistoryPromise\n .then(timeseries => this.applyDataProcessingFunctions(timeseries, target))\n .then(timeseries => downsampleSeries(timeseries, options))\n .catch(error => {\n console.log(error);\n return [];\n });\n }\n\n getTrendValueType(target) {\n // Find trendValue() function and get specified trend value\n var trendFunctions = _.map(metricFunctions.getCategories()['Trends'], 'name');\n var trendValueFunc = _.find(target.functions, func => {\n return _.includes(trendFunctions, func.def.name);\n });\n return trendValueFunc ? trendValueFunc.params[0] : \"avg\";\n }\n\n applyDataProcessingFunctions(timeseries_data, target) {\n let transformFunctions = bindFunctionDefs(target.functions, 'Transform');\n let aggregationFunctions = bindFunctionDefs(target.functions, 'Aggregate');\n let filterFunctions = bindFunctionDefs(target.functions, 'Filter');\n let aliasFunctions = bindFunctionDefs(target.functions, 'Alias');\n\n // Apply transformation functions\n timeseries_data = _.map(timeseries_data, timeseries => {\n timeseries.datapoints = sequence(transformFunctions)(timeseries.datapoints);\n return timeseries;\n });\n\n // Apply filter functions\n if (filterFunctions.length) {\n timeseries_data = sequence(filterFunctions)(timeseries_data);\n }\n\n // Apply aggregations\n if (aggregationFunctions.length) {\n let dp = _.map(timeseries_data, 'datapoints');\n dp = sequence(aggregationFunctions)(dp);\n\n let aggFuncNames = _.map(metricFunctions.getCategories()['Aggregate'], 'name');\n let lastAgg = _.findLast(target.functions, func => {\n return _.includes(aggFuncNames, func.def.name);\n });\n\n timeseries_data = [{\n target: lastAgg.text,\n datapoints: dp\n }];\n }\n\n // Apply alias functions\n _.forEach(timeseries_data, sequence(aliasFunctions));\n\n // Apply Time-related functions (timeShift(), etc)\n // Find timeShift() function and get specified trend value\n this.applyTimeShiftFunction(timeseries_data, target);\n\n return timeseries_data;\n }\n\n applyTimeShiftFunction(timeseries_data, target) {\n // Find timeShift() function and get specified interval\n let timeShiftFunc = _.find(target.functions, (func) => {\n return func.def.name === 'timeShift';\n });\n if (timeShiftFunc) {\n let shift = timeShiftFunc.params[0];\n _.forEach(timeseries_data, (series) => {\n series.datapoints = dataProcessor.unShiftTimeSeries(shift, series.datapoints);\n });\n }\n }\n\n /**\n * Query target data for Text mode\n */\n queryTextData(target, timeRange) {\n let [timeFrom, timeTo] = timeRange;\n let options = {\n itemtype: 'text'\n };\n return this.zabbix.getItemsFromTarget(target, options)\n .then(items => {\n if (items.length) {\n return this.zabbix.getHistory(items, timeFrom, timeTo)\n .then(history => {\n return responseHandler.handleText(history, items, target);\n });\n } else {\n return Promise.resolve([]);\n }\n });\n }\n\n /**\n * Query target data for Item ID mode\n */\n queryItemIdData(target, timeRange, useTrends, options) {\n let itemids = target.itemids;\n itemids = this.templateSrv.replace(itemids, options.scopedVars, zabbixItemIdsTemplateFormat);\n itemids = _.map(itemids.split(','), itemid => itemid.trim());\n\n if (!itemids) {\n return [];\n }\n\n return this.zabbix.getItemsByIDs(itemids)\n .then(items => {\n return this.queryNumericDataForItems(items, target, timeRange, useTrends, options);\n });\n }\n\n /**\n * Query target data for IT Services mode\n */\n queryITServiceData(target, timeRange, options) {\n // Don't show undefined and hidden targets\n if (target.hide || (!target.itservice && !target.itServiceFilter) || !target.slaProperty) {\n return [];\n }\n\n let itServiceIds = [];\n let itServices = [];\n let itServiceFilter;\n let isOldVersion = target.itservice && !target.itServiceFilter;\n\n if (isOldVersion) {\n // Backward compatibility\n itServiceFilter = '/.*/';\n } else {\n itServiceFilter = this.replaceTemplateVars(target.itServiceFilter, options.scopedVars);\n }\n\n return this.zabbix.getITServices(itServiceFilter)\n .then(itservices => {\n itServices = itservices;\n if (isOldVersion) {\n itServices = _.filter(itServices, {'serviceid': target.itservice.serviceid});\n }\n\n itServiceIds = _.map(itServices, 'serviceid');\n return itServiceIds;\n })\n .then(serviceids => {\n return this.zabbix.getSLA(serviceids, timeRange);\n })\n .then(slaResponse => {\n return _.map(itServiceIds, serviceid => {\n let itservice = _.find(itServices, {'serviceid': serviceid});\n return responseHandler.handleSLAResponse(itservice, target.slaProperty, slaResponse);\n });\n });\n }\n\n /**\n * Test connection to Zabbix API\n * @return {object} Connection status and Zabbix API version\n */\n testDatasource() {\n let zabbixVersion;\n return this.zabbix.getVersion()\n .then(version => {\n zabbixVersion = version;\n return this.zabbix.login();\n })\n .then(() => {\n if (this.enableDirectDBConnection) {\n return this.zabbix.dbConnector.testSQLDataSource();\n } else {\n return Promise.resolve();\n }\n })\n .then(() => {\n return {\n status: \"success\",\n title: \"Success\",\n message: \"Zabbix API version: \" + zabbixVersion\n };\n })\n .catch(error => {\n if (error instanceof ZabbixAPIError) {\n return {\n status: \"error\",\n title: error.message,\n message: error.data\n };\n } else if (error.data && error.data.message) {\n return {\n status: \"error\",\n title: \"Connection failed\",\n message: error.data.message\n };\n } else {\n return {\n status: \"error\",\n title: \"Connection failed\",\n message: \"Could not connect to given url\"\n };\n }\n });\n }\n\n ////////////////\n // Templating //\n ////////////////\n\n /**\n * Find metrics from templated request.\n *\n * @param {string} query Query from Templating\n * @return {string} Metric name - group, host, app or item or list\n * of metrics in \"{metric1,metcic2,...,metricN}\" format.\n */\n metricFindQuery(query) {\n let result;\n let parts = [];\n\n // Split query. Query structure: group.host.app.item\n _.each(utils.splitTemplateQuery(query), part => {\n part = this.replaceTemplateVars(part, {});\n\n // Replace wildcard to regex\n if (part === '*') {\n part = '/.*/';\n }\n parts.push(part);\n });\n let template = _.zipObject(['group', 'host', 'app', 'item'], parts);\n\n // Get items\n if (parts.length === 4) {\n // Search for all items, even it's not belong to any application\n if (template.app === '/.*/') {\n template.app = '';\n }\n result = this.zabbix.getItems(template.group, template.host, template.app, template.item);\n } else if (parts.length === 3) {\n // Get applications\n result = this.zabbix.getApps(template.group, template.host, template.app);\n } else if (parts.length === 2) {\n // Get hosts\n result = this.zabbix.getHosts(template.group, template.host);\n } else if (parts.length === 1) {\n // Get groups\n result = this.zabbix.getGroups(template.group);\n } else {\n result = Promise.resolve([]);\n }\n\n return result.then(metrics => {\n return _.map(metrics, formatMetric);\n });\n }\n\n /////////////////\n // Annotations //\n /////////////////\n\n annotationQuery(options) {\n var timeFrom = Math.ceil(dateMath.parse(options.rangeRaw.from) / 1000);\n var timeTo = Math.ceil(dateMath.parse(options.rangeRaw.to) / 1000);\n var annotation = options.annotation;\n var showOkEvents = annotation.showOkEvents ? c.SHOW_ALL_EVENTS : c.SHOW_OK_EVENTS;\n\n // Show all triggers\n let triggersOptions = {\n showTriggers: c.SHOW_ALL_TRIGGERS,\n hideHostsInMaintenance: false\n };\n\n var getTriggers = this.zabbix.getTriggers(this.replaceTemplateVars(annotation.group, {}),\n this.replaceTemplateVars(annotation.host, {}),\n this.replaceTemplateVars(annotation.application, {}),\n triggersOptions);\n\n return getTriggers.then(triggers => {\n\n // Filter triggers by description\n let triggerName = this.replaceTemplateVars(annotation.trigger, {});\n if (utils.isRegex(triggerName)) {\n triggers = _.filter(triggers, trigger => {\n return utils.buildRegex(triggerName).test(trigger.description);\n });\n } else if (triggerName) {\n triggers = _.filter(triggers, trigger => {\n return trigger.description === triggerName;\n });\n }\n\n // Remove events below the chose severity\n triggers = _.filter(triggers, trigger => {\n return Number(trigger.priority) >= Number(annotation.minseverity);\n });\n\n var objectids = _.map(triggers, 'triggerid');\n return this.zabbix\n .getEvents(objectids, timeFrom, timeTo, showOkEvents)\n .then(events => {\n var indexedTriggers = _.keyBy(triggers, 'triggerid');\n\n // Hide acknowledged events if option enabled\n if (annotation.hideAcknowledged) {\n events = _.filter(events, event => {\n return !event.acknowledges.length;\n });\n }\n\n return _.map(events, event => {\n let tags;\n if (annotation.showHostname) {\n tags = _.map(event.hosts, 'name');\n }\n\n // Show event type (OK or Problem)\n let title = Number(event.value) ? 'Problem' : 'OK';\n\n let formatted_acknowledges = utils.formatAcknowledges(event.acknowledges);\n return {\n annotation: annotation,\n time: event.clock * 1000,\n title: title,\n tags: tags,\n text: indexedTriggers[event.objectid].description + formatted_acknowledges\n };\n });\n });\n });\n }\n\n /**\n * Get triggers and its details for panel's targets\n * Returns alert state ('ok' if no fired triggers, or 'alerting' if at least 1 trigger is fired)\n * or empty object if no related triggers are finded.\n */\n alertQuery(options) {\n let enabled_targets = filterEnabledTargets(options.targets);\n let getPanelItems = _.map(enabled_targets, t => {\n let target = _.cloneDeep(t);\n this.replaceTargetVariables(target, options);\n return this.zabbix.getItemsFromTarget(target, {itemtype: 'num'});\n });\n\n return Promise.all(getPanelItems)\n .then(results => {\n let items = _.flatten(results);\n let itemids = _.map(items, 'itemid');\n\n return this.zabbix.getAlerts(itemids);\n })\n .then(triggers => {\n triggers = _.filter(triggers, trigger => {\n return trigger.priority >= this.alertingMinSeverity;\n });\n\n if (!triggers || triggers.length === 0) {\n return {};\n }\n\n let state = 'ok';\n\n let firedTriggers = _.filter(triggers, {value: '1'});\n if (firedTriggers.length) {\n state = 'alerting';\n }\n\n let thresholds = _.map(triggers, trigger => {\n return getTriggerThreshold(trigger.expression);\n });\n\n return {\n panelId: options.panelId,\n state: state,\n thresholds: thresholds\n };\n });\n }\n\n // Replace template variables\n replaceTargetVariables(target, options) {\n let parts = ['group', 'host', 'application', 'item'];\n _.forEach(parts, p => {\n if (target[p] && target[p].filter) {\n target[p].filter = this.replaceTemplateVars(target[p].filter, options.scopedVars);\n }\n });\n target.textFilter = this.replaceTemplateVars(target.textFilter, options.scopedVars);\n\n _.forEach(target.functions, func => {\n func.params = _.map(func.params, param => {\n if (typeof param === 'number') {\n return +this.templateSrv.replace(param.toString(), options.scopedVars);\n } else {\n return this.templateSrv.replace(param, options.scopedVars);\n }\n });\n });\n }\n\n isUseTrends(timeRange) {\n let [timeFrom, timeTo] = timeRange;\n let useTrendsFrom = Math.ceil(dateMath.parse('now-' + this.trendsFrom) / 1000);\n let useTrendsRange = Math.ceil(utils.parseInterval(this.trendsRange) / 1000);\n let useTrends = this.trends && (\n (timeFrom <= useTrendsFrom) ||\n (timeTo - timeFrom >= useTrendsRange)\n );\n return useTrends;\n }\n}\n\nfunction bindFunctionDefs(functionDefs, category) {\n var aggregationFunctions = _.map(metricFunctions.getCategories()[category], 'name');\n var aggFuncDefs = _.filter(functionDefs, function(func) {\n return _.includes(aggregationFunctions, func.def.name);\n });\n\n return _.map(aggFuncDefs, function(func) {\n var funcInstance = metricFunctions.createFuncInstance(func.def, func.params);\n return funcInstance.bindFunction(dataProcessor.metricFunctions);\n });\n}\n\nfunction getConsolidateBy(target) {\n let consolidateBy = 'avg';\n let funcDef = _.find(target.functions, func => {\n return func.def.name === 'consolidateBy';\n });\n if (funcDef && funcDef.params && funcDef.params.length) {\n consolidateBy = funcDef.params[0];\n }\n return consolidateBy;\n}\n\nfunction downsampleSeries(timeseries_data, options) {\n let defaultAgg = dataProcessor.aggregationFunctions['avg'];\n let consolidateByFunc = dataProcessor.aggregationFunctions[options.consolidateBy] || defaultAgg;\n return _.map(timeseries_data, timeseries => {\n if (timeseries.datapoints.length > options.maxDataPoints) {\n timeseries.datapoints = dataProcessor\n .groupBy(options.interval, consolidateByFunc, timeseries.datapoints);\n }\n return timeseries;\n });\n}\n\nfunction formatMetric(metricObj) {\n return {\n text: metricObj.name,\n expandable: false\n };\n}\n\n/**\n * Custom formatter for template variables.\n * Default Grafana \"regex\" formatter returns\n * value1|value2\n * This formatter returns\n * (value1|value2)\n * This format needed for using in complex regex with\n * template variables, for example\n * /CPU $cpu_item.*time/ where $cpu_item is system,user,iowait\n */\nfunction zabbixTemplateFormat(value) {\n if (typeof value === 'string') {\n return utils.escapeRegex(value);\n }\n\n var escapedValues = _.map(value, utils.escapeRegex);\n return '(' + escapedValues.join('|') + ')';\n}\n\nfunction zabbixItemIdsTemplateFormat(value) {\n if (typeof value === 'string') {\n return value;\n }\n return value.join(',');\n}\n\n/**\n * If template variables are used in request, replace it using regex format\n * and wrap with '/' for proper multi-value work. Example:\n * $variable selected as a, b, c\n * We use filter $variable\n * $variable -> a|b|c -> /a|b|c/\n * /$variable/ -> /a|b|c/ -> /a|b|c/\n */\nfunction replaceTemplateVars(templateSrv, target, scopedVars) {\n var replacedTarget = templateSrv.replace(target, scopedVars, zabbixTemplateFormat);\n if (target !== replacedTarget && !utils.isRegex(replacedTarget)) {\n replacedTarget = '/^' + replacedTarget + '$/';\n }\n return replacedTarget;\n}\n\n// Apply function one by one:\n// sequence([a(), b(), c()]) = c(b(a()));\nfunction sequence(funcsArray) {\n return function(result) {\n for (var i = 0; i < funcsArray.length; i++) {\n result = funcsArray[i].call(this, result);\n }\n return result;\n };\n}\n\nfunction filterEnabledTargets(targets) {\n return _.filter(targets, target => {\n return !(target.hide || !target.group || !target.host || !target.item);\n });\n}\n\nfunction getTriggerThreshold(expression) {\n let thresholdPattern = /.*[<>]([\\d\\.]+)/;\n let finded_thresholds = expression.match(thresholdPattern);\n if (finded_thresholds && finded_thresholds.length >= 2) {\n let threshold = finded_thresholds[1];\n threshold = Number(threshold);\n return threshold;\n } else {\n return null;\n }\n}\n\nexport {ZabbixAPIDatasource, zabbixTemplateFormat};\n\n// Fix for backward compatibility with lodash 2.4\nif (!_.includes) {_.includes = _.contains;}\nif (!_.keyBy) {_.keyBy = _.indexBy;}\n"]} \ No newline at end of file diff --git a/dist/datasource-zabbix/module.js b/dist/datasource-zabbix/module.js index 2b772d3..32693a5 100644 --- a/dist/datasource-zabbix/module.js +++ b/dist/datasource-zabbix/module.js @@ -1,9 +1,9 @@ 'use strict'; -System.register(['./datasource', './query.controller'], function (_export, _context) { +System.register(['./datasource', './query.controller', './config.controller'], function (_export, _context) { "use strict"; - var ZabbixAPIDatasource, ZabbixQueryController, ZabbixConfigController, ZabbixQueryOptionsController, ZabbixAnnotationsQueryController; + var ZabbixAPIDatasource, ZabbixQueryController, ZabbixDSConfigController, ZabbixQueryOptionsController, ZabbixAnnotationsQueryController; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { @@ -16,14 +16,10 @@ System.register(['./datasource', './query.controller'], function (_export, _cont ZabbixAPIDatasource = _datasource.ZabbixAPIDatasource; }, function (_queryController) { ZabbixQueryController = _queryController.ZabbixQueryController; + }, function (_configController) { + ZabbixDSConfigController = _configController.ZabbixDSConfigController; }], execute: function () { - _export('ConfigCtrl', ZabbixConfigController = function ZabbixConfigController() { - _classCallCheck(this, ZabbixConfigController); - }); - - ZabbixConfigController.templateUrl = 'datasource-zabbix/partials/config.html'; - _export('QueryOptionsCtrl', ZabbixQueryOptionsController = function ZabbixQueryOptionsController() { _classCallCheck(this, ZabbixQueryOptionsController); }); @@ -38,7 +34,7 @@ System.register(['./datasource', './query.controller'], function (_export, _cont _export('Datasource', ZabbixAPIDatasource); - _export('ConfigCtrl', ZabbixConfigController); + _export('ConfigCtrl', ZabbixDSConfigController); _export('QueryCtrl', ZabbixQueryController); diff --git a/dist/datasource-zabbix/module.js.map b/dist/datasource-zabbix/module.js.map index 776f7e4..bf4adfe 100644 --- a/dist/datasource-zabbix/module.js.map +++ b/dist/datasource-zabbix/module.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/datasource-zabbix/module.js"],"names":["ZabbixAPIDatasource","ZabbixQueryController","ZabbixConfigController","templateUrl","ZabbixQueryOptionsController","ZabbixAnnotationsQueryController"],"mappings":";;;;;;;;;;;;;;;AAAQA,yB,eAAAA,mB;;AACAC,2B,oBAAAA,qB;;;4BAEFC,sB;;;;AACNA,6BAAuBC,WAAvB,GAAqC,wCAArC;;kCAEMC,4B;;;;AACNA,mCAA6BD,WAA7B,GAA2C,+CAA3C;;sCAEME,gC;;;;AACNA,uCAAiCF,WAAjC,GAA+C,oDAA/C;;4BAGEH,mB;;4BACAE,sB;;2BACAD,qB;;kCACAG,4B;;sCACAC,gC","file":"module.js","sourcesContent":["import {ZabbixAPIDatasource} from './datasource';\nimport {ZabbixQueryController} from './query.controller';\n\nclass ZabbixConfigController {}\nZabbixConfigController.templateUrl = 'datasource-zabbix/partials/config.html';\n\nclass ZabbixQueryOptionsController {}\nZabbixQueryOptionsController.templateUrl = 'datasource-zabbix/partials/query.options.html';\n\nclass ZabbixAnnotationsQueryController {}\nZabbixAnnotationsQueryController.templateUrl = 'datasource-zabbix/partials/annotations.editor.html';\n\nexport {\n ZabbixAPIDatasource as Datasource,\n ZabbixConfigController as ConfigCtrl,\n ZabbixQueryController as QueryCtrl,\n ZabbixQueryOptionsController as QueryOptionsCtrl,\n ZabbixAnnotationsQueryController as AnnotationsQueryCtrl\n};\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/datasource-zabbix/module.js"],"names":["ZabbixAPIDatasource","ZabbixQueryController","ZabbixDSConfigController","ZabbixQueryOptionsController","templateUrl","ZabbixAnnotationsQueryController"],"mappings":";;;;;;;;;;;;;;;AAAQA,yB,eAAAA,mB;;AACAC,2B,oBAAAA,qB;;AACAC,8B,qBAAAA,wB;;;kCAEFC,4B;;;;AACNA,mCAA6BC,WAA7B,GAA2C,+CAA3C;;sCAEMC,gC;;;;AACNA,uCAAiCD,WAAjC,GAA+C,oDAA/C;;4BAGEJ,mB;;4BACAE,wB;;2BACAD,qB;;kCACAE,4B;;sCACAE,gC","file":"module.js","sourcesContent":["import {ZabbixAPIDatasource} from './datasource';\nimport {ZabbixQueryController} from './query.controller';\nimport {ZabbixDSConfigController} from './config.controller';\n\nclass ZabbixQueryOptionsController {}\nZabbixQueryOptionsController.templateUrl = 'datasource-zabbix/partials/query.options.html';\n\nclass ZabbixAnnotationsQueryController {}\nZabbixAnnotationsQueryController.templateUrl = 'datasource-zabbix/partials/annotations.editor.html';\n\nexport {\n ZabbixAPIDatasource as Datasource,\n ZabbixDSConfigController as ConfigCtrl,\n ZabbixQueryController as QueryCtrl,\n ZabbixQueryOptionsController as QueryOptionsCtrl,\n ZabbixAnnotationsQueryController as AnnotationsQueryCtrl\n};\n"]} \ No newline at end of file diff --git a/dist/datasource-zabbix/partials/config.html b/dist/datasource-zabbix/partials/config.html index 49e18b8..7f626c2 100644 --- a/dist/datasource-zabbix/partials/config.html +++ b/dist/datasource-zabbix/partials/config.html @@ -76,24 +76,53 @@
-

Alerting

- +

Direct DB Connection

+ - - -
- Min severity +
+
+ + SQL Data Source + + Select SQL Data Source for Zabbix database. + In order to use this feature you should create and + configure it first. Zabbix plugin uses this data source for querying history data directly from database. + This way usually faster than pulling data from Zabbix API, especially on the wide time ranges, and reduces + amount of data transfered. + +
-
+
+
+ +
+

Alerting

+ + +
+ + +
+ Min severity +
+ +
+
+
diff --git a/dist/datasource-zabbix/partials/query.editor.html b/dist/datasource-zabbix/partials/query.editor.html index 5a7df44..f583102 100644 --- a/dist/datasource-zabbix/partials/query.editor.html +++ b/dist/datasource-zabbix/partials/query.editor.html @@ -7,7 +7,7 @@
@@ -17,27 +17,29 @@ -
+
-
- -
+ +
- +
@@ -46,7 +48,7 @@
-
+
@@ -83,7 +85,7 @@
-
+
@@ -129,7 +131,7 @@
- @@ -137,8 +139,30 @@
+ +
+
+ + + +
+
+
+
+
+ -
+
@@ -151,7 +175,7 @@
-
+
@@ -165,6 +189,8 @@ +
+
+
- diff --git a/dist/datasource-zabbix/query.controller.js b/dist/datasource-zabbix/query.controller.js index 17e65a4..87ad8f9 100644 --- a/dist/datasource-zabbix/query.controller.js +++ b/dist/datasource-zabbix/query.controller.js @@ -1,9 +1,9 @@ 'use strict'; -System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils', './metricFunctions', './migrations', './add-metric-function.directive', './metric-function-editor.directive', './css/query-editor.css!'], function (_export, _context) { +System.register(['app/plugins/sdk', 'lodash', './constants', './utils', './metricFunctions', './migrations', './add-metric-function.directive', './metric-function-editor.directive', './css/query-editor.css!'], function (_export, _context) { "use strict"; - var QueryCtrl, angular, _, c, utils, metricFunctions, migrations, _createClass, ZabbixQueryController; + var QueryCtrl, _, c, utils, metricFunctions, migrations, _createClass, ZabbixQueryController; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { @@ -38,8 +38,6 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils return { setters: [function (_appPluginsSdk) { QueryCtrl = _appPluginsSdk.QueryCtrl; - }, function (_angular) { - angular = _angular.default; }, function (_lodash) { _ = _lodash.default; }, function (_constants) { @@ -85,17 +83,24 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils _this.replaceTemplateVars = _this.datasource.replaceTemplateVars; _this.templateSrv = templateSrv; - _this.editorModes = { - 0: { value: 'num', text: 'Metrics', mode: c.MODE_METRICS }, - 1: { value: 'itservice', text: 'IT Services', mode: c.MODE_ITSERVICE }, - 2: { value: 'text', text: 'Text', mode: c.MODE_TEXT } + _this.editorModes = [{ value: 'num', text: 'Metrics', mode: c.MODE_METRICS }, { value: 'text', text: 'Text', mode: c.MODE_TEXT }, { value: 'itservice', text: 'IT Services', mode: c.MODE_ITSERVICE }, { value: 'itemid', text: 'Item ID', mode: c.MODE_ITEMID }]; + + _this.$scope.editorMode = { + METRICS: c.MODE_METRICS, + TEXT: c.MODE_TEXT, + ITSERVICE: c.MODE_ITSERVICE, + ITEMID: c.MODE_ITEMID }; + _this.slaPropertyList = [{ name: "Status", property: "status" }, { name: "SLA", property: "sla" }, { name: "OK time", property: "okTime" }, { name: "Problem time", property: "problemTime" }, { name: "Down time", property: "downtimeTime" }]; + // Map functions for bs-typeahead _this.getGroupNames = _.bind(_this.getMetricNames, _this, 'groupList'); _this.getHostNames = _.bind(_this.getMetricNames, _this, 'hostList', true); _this.getApplicationNames = _.bind(_this.getMetricNames, _this, 'appList'); _this.getItemNames = _.bind(_this.getMetricNames, _this, 'itemList'); + _this.getITServices = _.bind(_this.getMetricNames, _this, 'itServiceList'); + _this.getVariables = _.bind(_this.getTemplateVariables, _this); // Update metric suggestion when template variable was changed $rootScope.$on('template-variable-value-updated', function () { @@ -122,14 +127,14 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils // Load default values var targetDefaults = { - mode: c.MODE_METRICS, - group: { filter: "" }, - host: { filter: "" }, - application: { filter: "" }, - item: { filter: "" }, - functions: [], - options: { - showDisabledItems: false + 'mode': c.MODE_METRICS, + 'group': { 'filter': "" }, + 'host': { 'filter': "" }, + 'application': { 'filter': "" }, + 'item': { 'filter': "" }, + 'functions': [], + 'options': { + 'showDisabledItems': false } }; _.defaults(target, targetDefaults); @@ -141,13 +146,10 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils if (target.mode === c.MODE_METRICS || target.mode === c.MODE_TEXT) { - this.downsampleFunctionList = [{ name: "avg", value: "avg" }, { name: "min", value: "min" }, { name: "max", value: "max" }, { name: "sum", value: "sum" }, { name: "count", value: "count" }]; - this.initFilters(); } else if (target.mode === c.MODE_ITSERVICE) { - this.slaPropertyList = [{ name: "Status", property: "status" }, { name: "SLA", property: "sla" }, { name: "OK time", property: "okTime" }, { name: "Problem time", property: "problemTime" }, { name: "Down time", property: "downtimeTime" }]; - this.itserviceList = [{ name: "test" }]; - this.updateITServiceList(); + _.defaults(target, { slaProperty: { name: "SLA", property: "sla" } }); + this.suggestITServices(); } }; @@ -158,7 +160,8 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils _createClass(ZabbixQueryController, [{ key: 'initFilters', value: function initFilters() { - var itemtype = this.editorModes[this.target.mode].value; + var itemtype = _.find(this.editorModes, { 'mode': this.target.mode }); + itemtype = itemtype ? itemtype.value : null; return Promise.all([this.suggestGroups(), this.suggestHosts(), this.suggestApps(), this.suggestItems(itemtype)]); } }, { @@ -177,6 +180,13 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils return metrics; } + }, { + key: 'getTemplateVariables', + value: function getTemplateVariables() { + return _.map(this.templateSrv.variables, function (variable) { + return '$' + variable.name; + }); + } }, { key: 'suggestGroups', value: function suggestGroups() { @@ -230,6 +240,16 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils return items; }); } + }, { + key: 'suggestITServices', + value: function suggestITServices() { + var _this6 = this; + + return this.zabbix.getITService().then(function (itservices) { + _this6.metric.itServiceList = itservices; + return itservices; + }); + } }, { key: 'isRegex', value: function isRegex(str) { @@ -259,11 +279,11 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils }, { key: 'isContainsVariables', value: function isContainsVariables() { - var _this6 = this; + var _this7 = this; return _.some(['group', 'host', 'application'], function (field) { - if (_this6.target[field] && _this6.target[field].filter) { - return utils.isTemplateVariable(_this6.target[field].filter, _this6.templateSrv.variables); + if (_this7.target[field] && _this7.target[field].filter) { + return utils.isTemplateVariable(_this7.target[field].filter, _this7.templateSrv.variables); } else { return false; } @@ -356,24 +376,7 @@ System.register(['app/plugins/sdk', 'angular', 'lodash', './constants', './utils value: function switchEditorMode(mode) { this.target.mode = mode; this.init(); - } - }, { - key: 'updateITServiceList', - value: function updateITServiceList() { - var _this7 = this; - - this.zabbix.getITService().then(function (iteservices) { - _this7.itserviceList = []; - _this7.itserviceList = _this7.itserviceList.concat(iteservices); - }); - } - }, { - key: 'selectITService', - value: function selectITService() { - if (!_.isEqual(this.oldTarget, this.target) && _.isEmpty(this.target.errors)) { - this.oldTarget = angular.copy(this.target); - this.panelCtrl.refresh(); - } + this.targetChanged(); } }]); diff --git a/dist/datasource-zabbix/query.controller.js.map b/dist/datasource-zabbix/query.controller.js.map index a281820..0f74835 100644 --- a/dist/datasource-zabbix/query.controller.js.map +++ b/dist/datasource-zabbix/query.controller.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/datasource-zabbix/query.controller.js"],"names":["QueryCtrl","angular","_","c","utils","metricFunctions","migrations","ZabbixQueryController","$scope","$injector","$rootScope","$sce","templateSrv","zabbix","datasource","replaceTemplateVars","editorModes","value","text","mode","MODE_METRICS","MODE_ITSERVICE","MODE_TEXT","getGroupNames","bind","getMetricNames","getHostNames","getApplicationNames","getItemNames","$on","onVariableChange","onTargetBlur","init","target","migrate","scopeDefaults","metric","oldTarget","cloneDeep","queryOptionsText","renderQueryOptionsText","defaults","targetDefaults","group","filter","host","application","item","functions","options","showDisabledItems","map","func","createFuncInstance","def","params","downsampleFunctionList","name","initFilters","slaPropertyList","property","itserviceList","updateITServiceList","itemtype","Promise","all","suggestGroups","suggestHosts","suggestApps","suggestItems","metricList","addAllValue","metrics","uniq","forEach","variables","unshift","variable","getAllGroups","then","groupList","groups","groupFilter","getAllHosts","hostList","hosts","hostFilter","getAllApps","appList","apps","appFilter","getAllItems","itemList","items","str","isRegex","isTemplateVariable","newTarget","isEqual","targetChanged","isContainsVariables","some","field","parseTarget","panelCtrl","refresh","funcDef","newFunc","added","push","moveAliasFuncLast","length","without","aliasFunc","find","showQueryOptions","optionsMap","forOwn","key","join","getITService","iteservices","concat","isEmpty","errors","copy","templateUrl"],"mappings":"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","file":"query.controller.js","sourcesContent":["import {QueryCtrl} from 'app/plugins/sdk';\nimport angular from 'angular';\nimport _ from 'lodash';\nimport * as c from './constants';\nimport * as utils from './utils';\nimport * as metricFunctions from './metricFunctions';\nimport * as migrations from './migrations';\n\nimport './add-metric-function.directive';\nimport './metric-function-editor.directive';\n\nimport './css/query-editor.css!';\n\nexport class ZabbixQueryController extends QueryCtrl {\n\n // ZabbixQueryCtrl constructor\n constructor($scope, $injector, $rootScope, $sce, templateSrv) {\n super($scope, $injector);\n this.zabbix = this.datasource.zabbix;\n\n // Use custom format for template variables\n this.replaceTemplateVars = this.datasource.replaceTemplateVars;\n this.templateSrv = templateSrv;\n\n this.editorModes = {\n 0: {value: 'num', text: 'Metrics', mode: c.MODE_METRICS},\n 1: {value: 'itservice', text: 'IT Services', mode: c.MODE_ITSERVICE},\n 2: {value: 'text', text: 'Text', mode: c.MODE_TEXT}\n };\n\n // Map functions for bs-typeahead\n this.getGroupNames = _.bind(this.getMetricNames, this, 'groupList');\n this.getHostNames = _.bind(this.getMetricNames, this, 'hostList', true);\n this.getApplicationNames = _.bind(this.getMetricNames, this, 'appList');\n this.getItemNames = _.bind(this.getMetricNames, this, 'itemList');\n\n // Update metric suggestion when template variable was changed\n $rootScope.$on('template-variable-value-updated', () => this.onVariableChange());\n\n // Update metrics when item selected from dropdown\n $scope.$on('typeahead-updated', () => {\n this.onTargetBlur();\n });\n\n this.init = function() {\n var target = this.target;\n\n // Migrate old targets\n target = migrations.migrate(target);\n\n var scopeDefaults = {\n metric: {},\n oldTarget: _.cloneDeep(this.target),\n queryOptionsText: this.renderQueryOptionsText()\n };\n _.defaults(this, scopeDefaults);\n\n // Load default values\n var targetDefaults = {\n mode: c.MODE_METRICS,\n group: { filter: \"\" },\n host: { filter: \"\" },\n application: { filter: \"\" },\n item: { filter: \"\" },\n functions: [],\n options: {\n showDisabledItems: false\n }\n };\n _.defaults(target, targetDefaults);\n\n // Create function instances from saved JSON\n target.functions = _.map(target.functions, function(func) {\n return metricFunctions.createFuncInstance(func.def, func.params);\n });\n\n if (target.mode === c.MODE_METRICS ||\n target.mode === c.MODE_TEXT) {\n\n this.downsampleFunctionList = [\n {name: \"avg\", value: \"avg\"},\n {name: \"min\", value: \"min\"},\n {name: \"max\", value: \"max\"},\n {name: \"sum\", value: \"sum\"},\n {name: \"count\", value: \"count\"}\n ];\n\n this.initFilters();\n }\n else if (target.mode === c.MODE_ITSERVICE) {\n this.slaPropertyList = [\n {name: \"Status\", property: \"status\"},\n {name: \"SLA\", property: \"sla\"},\n {name: \"OK time\", property: \"okTime\"},\n {name: \"Problem time\", property: \"problemTime\"},\n {name: \"Down time\", property: \"downtimeTime\"}\n ];\n this.itserviceList = [{name: \"test\"}];\n this.updateITServiceList();\n }\n };\n\n this.init();\n }\n\n initFilters() {\n let itemtype = this.editorModes[this.target.mode].value;\n return Promise.all([\n this.suggestGroups(),\n this.suggestHosts(),\n this.suggestApps(),\n this.suggestItems(itemtype)\n ]);\n }\n\n // Get list of metric names for bs-typeahead directive\n getMetricNames(metricList, addAllValue) {\n let metrics = _.uniq(_.map(this.metric[metricList], 'name'));\n\n // Add template variables\n _.forEach(this.templateSrv.variables, variable => {\n metrics.unshift('$' + variable.name);\n });\n\n if (addAllValue) {\n metrics.unshift('/.*/');\n }\n\n return metrics;\n }\n\n suggestGroups() {\n return this.zabbix.getAllGroups()\n .then(groups => {\n this.metric.groupList = groups;\n return groups;\n });\n }\n\n suggestHosts() {\n let groupFilter = this.replaceTemplateVars(this.target.group.filter);\n return this.zabbix.getAllHosts(groupFilter)\n .then(hosts => {\n this.metric.hostList = hosts;\n return hosts;\n });\n }\n\n suggestApps() {\n let groupFilter = this.replaceTemplateVars(this.target.group.filter);\n let hostFilter = this.replaceTemplateVars(this.target.host.filter);\n return this.zabbix.getAllApps(groupFilter, hostFilter)\n .then(apps => {\n this.metric.appList = apps;\n return apps;\n });\n }\n\n suggestItems(itemtype = 'num') {\n let groupFilter = this.replaceTemplateVars(this.target.group.filter);\n let hostFilter = this.replaceTemplateVars(this.target.host.filter);\n let appFilter = this.replaceTemplateVars(this.target.application.filter);\n let options = {\n itemtype: itemtype,\n showDisabledItems: this.target.options.showDisabledItems\n };\n\n return this.zabbix\n .getAllItems(groupFilter, hostFilter, appFilter, options)\n .then(items => {\n this.metric.itemList = items;\n return items;\n });\n }\n\n isRegex(str) {\n return utils.isRegex(str);\n }\n\n isVariable(str) {\n return utils.isTemplateVariable(str, this.templateSrv.variables);\n }\n\n onTargetBlur() {\n var newTarget = _.cloneDeep(this.target);\n if (!_.isEqual(this.oldTarget, this.target)) {\n this.oldTarget = newTarget;\n this.targetChanged();\n }\n }\n\n onVariableChange() {\n if (this.isContainsVariables()) {\n this.targetChanged();\n }\n }\n\n /**\n * Check query for template variables\n */\n isContainsVariables() {\n return _.some(['group', 'host', 'application'], field => {\n if (this.target[field] && this.target[field].filter) {\n return utils.isTemplateVariable(this.target[field].filter, this.templateSrv.variables);\n } else {\n return false;\n }\n });\n }\n\n parseTarget() {\n // Parse target\n }\n\n // Validate target and set validation info\n validateTarget() {\n // validate\n }\n\n targetChanged() {\n this.initFilters();\n this.parseTarget();\n this.panelCtrl.refresh();\n }\n\n addFunction(funcDef) {\n var newFunc = metricFunctions.createFuncInstance(funcDef);\n newFunc.added = true;\n this.target.functions.push(newFunc);\n\n this.moveAliasFuncLast();\n\n if (newFunc.params.length && newFunc.added ||\n newFunc.def.params.length === 0) {\n this.targetChanged();\n }\n }\n\n removeFunction(func) {\n this.target.functions = _.without(this.target.functions, func);\n this.targetChanged();\n }\n\n moveAliasFuncLast() {\n var aliasFunc = _.find(this.target.functions, function(func) {\n return func.def.name === 'alias' ||\n func.def.name === 'aliasByNode' ||\n func.def.name === 'aliasByMetric';\n });\n\n if (aliasFunc) {\n this.target.functions = _.without(this.target.functions, aliasFunc);\n this.target.functions.push(aliasFunc);\n }\n }\n\n toggleQueryOptions() {\n this.showQueryOptions = !this.showQueryOptions;\n }\n\n onQueryOptionChange() {\n this.queryOptionsText = this.renderQueryOptionsText();\n this.onTargetBlur();\n }\n\n renderQueryOptionsText() {\n var optionsMap = {\n showDisabledItems: \"Show disabled items\"\n };\n var options = [];\n _.forOwn(this.target.options, (value, key) => {\n if (value) {\n if (value === true) {\n // Show only option name (if enabled) for boolean options\n options.push(optionsMap[key]);\n } else {\n // Show \"option = value\" for another options\n options.push(optionsMap[key] + \" = \" + value);\n }\n }\n });\n return \"Options: \" + options.join(', ');\n }\n\n /**\n * Switch query editor to specified mode.\n * Modes:\n * 0 - items\n * 1 - IT services\n * 2 - Text metrics\n */\n switchEditorMode(mode) {\n this.target.mode = mode;\n this.init();\n }\n\n /////////////////\n // IT Services //\n /////////////////\n\n /**\n * Update list of IT services\n */\n updateITServiceList() {\n this.zabbix.getITService().then((iteservices) => {\n this.itserviceList = [];\n this.itserviceList = this.itserviceList.concat(iteservices);\n });\n }\n\n /**\n * Call when IT service is selected.\n */\n selectITService() {\n if (!_.isEqual(this.oldTarget, this.target) && _.isEmpty(this.target.errors)) {\n this.oldTarget = angular.copy(this.target);\n this.panelCtrl.refresh();\n }\n }\n}\n\n// Set templateUrl as static property\nZabbixQueryController.templateUrl = 'datasource-zabbix/partials/query.editor.html';\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/datasource-zabbix/query.controller.js"],"names":["QueryCtrl","_","c","utils","metricFunctions","migrations","ZabbixQueryController","$scope","$injector","$rootScope","$sce","templateSrv","zabbix","datasource","replaceTemplateVars","editorModes","value","text","mode","MODE_METRICS","MODE_TEXT","MODE_ITSERVICE","MODE_ITEMID","editorMode","METRICS","TEXT","ITSERVICE","ITEMID","slaPropertyList","name","property","getGroupNames","bind","getMetricNames","getHostNames","getApplicationNames","getItemNames","getITServices","getVariables","getTemplateVariables","$on","onVariableChange","onTargetBlur","init","target","migrate","scopeDefaults","metric","oldTarget","cloneDeep","queryOptionsText","renderQueryOptionsText","defaults","targetDefaults","functions","map","func","createFuncInstance","def","params","initFilters","slaProperty","suggestITServices","itemtype","find","Promise","all","suggestGroups","suggestHosts","suggestApps","suggestItems","metricList","addAllValue","metrics","uniq","forEach","variables","unshift","variable","getAllGroups","then","groupList","groups","groupFilter","group","filter","getAllHosts","hostList","hosts","hostFilter","host","getAllApps","appList","apps","appFilter","application","options","showDisabledItems","getAllItems","itemList","items","getITService","itServiceList","itservices","str","isRegex","isTemplateVariable","newTarget","isEqual","targetChanged","isContainsVariables","some","field","parseTarget","panelCtrl","refresh","funcDef","newFunc","added","push","moveAliasFuncLast","length","without","aliasFunc","showQueryOptions","optionsMap","forOwn","key","join","templateUrl"],"mappings":"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","file":"query.controller.js","sourcesContent":["import {QueryCtrl} from 'app/plugins/sdk';\nimport _ from 'lodash';\nimport * as c from './constants';\nimport * as utils from './utils';\nimport * as metricFunctions from './metricFunctions';\nimport * as migrations from './migrations';\n\nimport './add-metric-function.directive';\nimport './metric-function-editor.directive';\n\nimport './css/query-editor.css!';\n\nexport class ZabbixQueryController extends QueryCtrl {\n\n // ZabbixQueryCtrl constructor\n constructor($scope, $injector, $rootScope, $sce, templateSrv) {\n super($scope, $injector);\n this.zabbix = this.datasource.zabbix;\n\n // Use custom format for template variables\n this.replaceTemplateVars = this.datasource.replaceTemplateVars;\n this.templateSrv = templateSrv;\n\n this.editorModes = [\n {value: 'num', text: 'Metrics', mode: c.MODE_METRICS},\n {value: 'text', text: 'Text', mode: c.MODE_TEXT},\n {value: 'itservice', text: 'IT Services', mode: c.MODE_ITSERVICE},\n {value: 'itemid', text: 'Item ID', mode: c.MODE_ITEMID}\n ];\n\n this.$scope.editorMode = {\n METRICS: c.MODE_METRICS,\n TEXT: c.MODE_TEXT,\n ITSERVICE: c.MODE_ITSERVICE,\n ITEMID: c.MODE_ITEMID\n };\n\n this.slaPropertyList = [\n {name: \"Status\", property: \"status\"},\n {name: \"SLA\", property: \"sla\"},\n {name: \"OK time\", property: \"okTime\"},\n {name: \"Problem time\", property: \"problemTime\"},\n {name: \"Down time\", property: \"downtimeTime\"}\n ];\n\n // Map functions for bs-typeahead\n this.getGroupNames = _.bind(this.getMetricNames, this, 'groupList');\n this.getHostNames = _.bind(this.getMetricNames, this, 'hostList', true);\n this.getApplicationNames = _.bind(this.getMetricNames, this, 'appList');\n this.getItemNames = _.bind(this.getMetricNames, this, 'itemList');\n this.getITServices = _.bind(this.getMetricNames, this, 'itServiceList');\n this.getVariables = _.bind(this.getTemplateVariables, this);\n\n // Update metric suggestion when template variable was changed\n $rootScope.$on('template-variable-value-updated', () => this.onVariableChange());\n\n // Update metrics when item selected from dropdown\n $scope.$on('typeahead-updated', () => {\n this.onTargetBlur();\n });\n\n this.init = function() {\n var target = this.target;\n\n // Migrate old targets\n target = migrations.migrate(target);\n\n var scopeDefaults = {\n metric: {},\n oldTarget: _.cloneDeep(this.target),\n queryOptionsText: this.renderQueryOptionsText()\n };\n _.defaults(this, scopeDefaults);\n\n // Load default values\n var targetDefaults = {\n 'mode': c.MODE_METRICS,\n 'group': { 'filter': \"\" },\n 'host': { 'filter': \"\" },\n 'application': { 'filter': \"\" },\n 'item': { 'filter': \"\" },\n 'functions': [],\n 'options': {\n 'showDisabledItems': false\n }\n };\n _.defaults(target, targetDefaults);\n\n // Create function instances from saved JSON\n target.functions = _.map(target.functions, function(func) {\n return metricFunctions.createFuncInstance(func.def, func.params);\n });\n\n if (target.mode === c.MODE_METRICS ||\n target.mode === c.MODE_TEXT) {\n\n this.initFilters();\n }\n else if (target.mode === c.MODE_ITSERVICE) {\n _.defaults(target, {slaProperty: {name: \"SLA\", property: \"sla\"}});\n this.suggestITServices();\n }\n };\n\n this.init();\n }\n\n initFilters() {\n let itemtype = _.find(this.editorModes, {'mode': this.target.mode});\n itemtype = itemtype ? itemtype.value : null;\n return Promise.all([\n this.suggestGroups(),\n this.suggestHosts(),\n this.suggestApps(),\n this.suggestItems(itemtype)\n ]);\n }\n\n // Get list of metric names for bs-typeahead directive\n getMetricNames(metricList, addAllValue) {\n let metrics = _.uniq(_.map(this.metric[metricList], 'name'));\n\n // Add template variables\n _.forEach(this.templateSrv.variables, variable => {\n metrics.unshift('$' + variable.name);\n });\n\n if (addAllValue) {\n metrics.unshift('/.*/');\n }\n\n return metrics;\n }\n\n getTemplateVariables() {\n return _.map(this.templateSrv.variables, variable => {\n return '$' + variable.name;\n });\n }\n\n suggestGroups() {\n return this.zabbix.getAllGroups()\n .then(groups => {\n this.metric.groupList = groups;\n return groups;\n });\n }\n\n suggestHosts() {\n let groupFilter = this.replaceTemplateVars(this.target.group.filter);\n return this.zabbix.getAllHosts(groupFilter)\n .then(hosts => {\n this.metric.hostList = hosts;\n return hosts;\n });\n }\n\n suggestApps() {\n let groupFilter = this.replaceTemplateVars(this.target.group.filter);\n let hostFilter = this.replaceTemplateVars(this.target.host.filter);\n return this.zabbix.getAllApps(groupFilter, hostFilter)\n .then(apps => {\n this.metric.appList = apps;\n return apps;\n });\n }\n\n suggestItems(itemtype = 'num') {\n let groupFilter = this.replaceTemplateVars(this.target.group.filter);\n let hostFilter = this.replaceTemplateVars(this.target.host.filter);\n let appFilter = this.replaceTemplateVars(this.target.application.filter);\n let options = {\n itemtype: itemtype,\n showDisabledItems: this.target.options.showDisabledItems\n };\n\n return this.zabbix\n .getAllItems(groupFilter, hostFilter, appFilter, options)\n .then(items => {\n this.metric.itemList = items;\n return items;\n });\n }\n\n suggestITServices() {\n return this.zabbix.getITService()\n .then(itservices => {\n this.metric.itServiceList = itservices;\n return itservices;\n });\n }\n\n isRegex(str) {\n return utils.isRegex(str);\n }\n\n isVariable(str) {\n return utils.isTemplateVariable(str, this.templateSrv.variables);\n }\n\n onTargetBlur() {\n var newTarget = _.cloneDeep(this.target);\n if (!_.isEqual(this.oldTarget, this.target)) {\n this.oldTarget = newTarget;\n this.targetChanged();\n }\n }\n\n onVariableChange() {\n if (this.isContainsVariables()) {\n this.targetChanged();\n }\n }\n\n /**\n * Check query for template variables\n */\n isContainsVariables() {\n return _.some(['group', 'host', 'application'], field => {\n if (this.target[field] && this.target[field].filter) {\n return utils.isTemplateVariable(this.target[field].filter, this.templateSrv.variables);\n } else {\n return false;\n }\n });\n }\n\n parseTarget() {\n // Parse target\n }\n\n // Validate target and set validation info\n validateTarget() {\n // validate\n }\n\n targetChanged() {\n this.initFilters();\n this.parseTarget();\n this.panelCtrl.refresh();\n }\n\n addFunction(funcDef) {\n var newFunc = metricFunctions.createFuncInstance(funcDef);\n newFunc.added = true;\n this.target.functions.push(newFunc);\n\n this.moveAliasFuncLast();\n\n if (newFunc.params.length && newFunc.added ||\n newFunc.def.params.length === 0) {\n this.targetChanged();\n }\n }\n\n removeFunction(func) {\n this.target.functions = _.without(this.target.functions, func);\n this.targetChanged();\n }\n\n moveAliasFuncLast() {\n var aliasFunc = _.find(this.target.functions, function(func) {\n return func.def.name === 'alias' ||\n func.def.name === 'aliasByNode' ||\n func.def.name === 'aliasByMetric';\n });\n\n if (aliasFunc) {\n this.target.functions = _.without(this.target.functions, aliasFunc);\n this.target.functions.push(aliasFunc);\n }\n }\n\n toggleQueryOptions() {\n this.showQueryOptions = !this.showQueryOptions;\n }\n\n onQueryOptionChange() {\n this.queryOptionsText = this.renderQueryOptionsText();\n this.onTargetBlur();\n }\n\n renderQueryOptionsText() {\n var optionsMap = {\n showDisabledItems: \"Show disabled items\"\n };\n var options = [];\n _.forOwn(this.target.options, (value, key) => {\n if (value) {\n if (value === true) {\n // Show only option name (if enabled) for boolean options\n options.push(optionsMap[key]);\n } else {\n // Show \"option = value\" for another options\n options.push(optionsMap[key] + \" = \" + value);\n }\n }\n });\n return \"Options: \" + options.join(', ');\n }\n\n /**\n * Switch query editor to specified mode.\n * Modes:\n * 0 - items\n * 1 - IT services\n * 2 - Text metrics\n */\n switchEditorMode(mode) {\n this.target.mode = mode;\n this.init();\n this.targetChanged();\n }\n}\n\n// Set templateUrl as static property\nZabbixQueryController.templateUrl = 'datasource-zabbix/partials/query.editor.html';\n"]} \ No newline at end of file diff --git a/dist/datasource-zabbix/specs/datasource_specs.js b/dist/datasource-zabbix/specs/datasource_specs.js index 295f4fd..dec10a2 100644 --- a/dist/datasource-zabbix/specs/datasource_specs.js +++ b/dist/datasource-zabbix/specs/datasource_specs.js @@ -15,7 +15,10 @@ describe('ZabbixDatasource', () => { password: 'zabbix', trends: true, trendsFrom: '14d', - trendsRange: '7d' + trendsRange: '7d', + dbConnection: { + enabled: false + } } }; ctx.templateSrv = {}; diff --git a/dist/datasource-zabbix/specs/utils_specs.js b/dist/datasource-zabbix/specs/utils_specs.js index 41ab76c..c540db2 100644 --- a/dist/datasource-zabbix/specs/utils_specs.js +++ b/dist/datasource-zabbix/specs/utils_specs.js @@ -88,4 +88,54 @@ describe('Utils', () => { done(); }); }); + + describe('splitTemplateQuery()', () => { + + // Backward compatibility + it('should properly split query in old format', (done) => { + let test_cases = [ + { + query: `/alu/./tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9{2}/`, + expected: ['/alu/', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9{2}/'] + }, + { + query: `a.b.c.d`, + expected: ['a', 'b', 'c', 'd'] + } + ]; + + _.each(test_cases, test_case => { + let splitQuery = utils.splitTemplateQuery(test_case.query); + expect(splitQuery).to.eql(test_case.expected); + }); + done(); + }); + + it('should properly split query', (done) => { + let test_cases = [ + { + query: `{alu}{/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]*/}`, + expected: ['alu', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]*/'] + }, + { + query: `{alu}{/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]{2}/}`, + expected: ['alu', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]{2}/'] + }, + { + query: `{a}{b}{c}{d}`, + expected: ['a', 'b', 'c', 'd'] + }, + { + query: `{a}{b.c.d}`, + expected: ['a', 'b.c.d'] + } + ]; + + _.each(test_cases, test_case => { + let splitQuery = utils.splitTemplateQuery(test_case.query); + expect(splitQuery).to.eql(test_case.expected); + }); + done(); + }); + }); }); diff --git a/dist/datasource-zabbix/utils.js b/dist/datasource-zabbix/utils.js index d634a22..9f370a1 100644 --- a/dist/datasource-zabbix/utils.js +++ b/dist/datasource-zabbix/utils.js @@ -28,6 +28,16 @@ System.register(['lodash', 'moment'], function (_export, _context) { _export('expandItemName', expandItemName); + function expandItems(items) { + _.forEach(items, function (item) { + item.item = item.name; + item.name = expandItemName(item.item, item.key_); + return item; + }); + return items; + } + _export('expandItems', expandItems); + function splitKeyParams(paramStr) { var params = []; var quoted = false; @@ -56,7 +66,9 @@ System.register(['lodash', 'moment'], function (_export, _context) { params.push(param); return params; - }function containsMacro(itemName) { + } + + function containsMacro(itemName) { return MACRO_PATTERN.test(itemName); } @@ -99,7 +111,7 @@ System.register(['lodash', 'moment'], function (_export, _context) { * {group}{host.com} -> [group, host.com] */ function splitTemplateQuery(query) { - var splitPattern = /{[^{}]*}/g; + var splitPattern = /\{[^\{\}]*\}|\{\/.*\/\}/g; var split = void 0; if (isContainsBraces(query)) { @@ -117,7 +129,8 @@ System.register(['lodash', 'moment'], function (_export, _context) { _export('splitTemplateQuery', splitTemplateQuery); function isContainsBraces(query) { - return query.includes('{') && query.includes('}'); + var bracesPattern = /^\{.+\}$/; + return bracesPattern.test(query); } // Pattern for testing regex diff --git a/dist/datasource-zabbix/utils.js.map b/dist/datasource-zabbix/utils.js.map index b0d851e..94c6f0a 100644 --- a/dist/datasource-zabbix/utils.js.map +++ b/dist/datasource-zabbix/utils.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/datasource-zabbix/utils.js"],"names":["expandItemName","name","key","key_params_str","substring","indexOf","lastIndexOf","key_params","splitKeyParams","i","length","replace","paramStr","params","quoted","in_array","split_symbol","param","_","forEach","symbol","push","containsMacro","itemName","MACRO_PATTERN","test","replaceMacro","item","macros","item_macros","match","host_macros","filter","m","hostid","macro_def","find","macro","value","macro_value","macro_regex","RegExp","escapeMacro","splitTemplateQuery","query","splitPattern","split","isContainsBraces","result","map","trim","part","includes","isRegex","str","regexPattern","isTemplateVariable","templateVariables","variablePattern","variables","variable","buildRegex","matches","pattern","flags","undefined","escapeRegex","parseInterval","interval","intervalPattern","momentInterval","exec","moment","duration","Number","valueOf","parseTimeShiftInterval","formatAcknowledges","acknowledges","formatted_acknowledges","each","ack","timestamp","unix","clock","format","alias","surname","message","concat","convertToZabbixAPIUrl","url","zabbixAPIUrlPattern","trimSlashPattern","callOnce","func","promiseKeeper","Promise","resolve","apply","arguments","then","contains"],"mappings":"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","file":"utils.js","sourcesContent":["import _ from 'lodash';\nimport moment from 'moment';\n\n/**\n * Expand Zabbix item name\n *\n * @param {string} name item name, ie \"CPU $2 time\"\n * @param {string} key item key, ie system.cpu.util[,system,avg1]\n * @return {string} expanded name, ie \"CPU system time\"\n */\nexport function expandItemName(name, key) {\n\n // extract params from key:\n // \"system.cpu.util[,system,avg1]\" --> [\"\", \"system\", \"avg1\"]\n let key_params_str = key.substring(key.indexOf('[') + 1, key.lastIndexOf(']'));\n let key_params = splitKeyParams(key_params_str);\n\n // replace item parameters\n for (let i = key_params.length; i >= 1; i--) {\n name = name.replace('$' + i, key_params[i - 1]);\n }\n return name;\n}\n\nfunction splitKeyParams(paramStr) {\n let params = [];\n let quoted = false;\n let in_array = false;\n let split_symbol = ',';\n let param = '';\n\n _.forEach(paramStr, symbol => {\n if (symbol === '\"' && in_array) {\n param += symbol;\n } else if (symbol === '\"' && quoted) {\n quoted = false;\n } else if (symbol === '\"' && !quoted) {\n quoted = true;\n } else if (symbol === '[' && !quoted) {\n in_array = true;\n } else if (symbol === ']' && !quoted) {\n in_array = false;\n } else if (symbol === split_symbol && !quoted && !in_array) {\n params.push(param);\n param = '';\n } else {\n param += symbol;\n }\n });\n\n params.push(param);\n return params;\n}\n\nconst MACRO_PATTERN = /{\\$[A-Z0-9_\\.]+}/g;\n\nexport function containsMacro(itemName) {\n return MACRO_PATTERN.test(itemName);\n}\n\nexport function replaceMacro(item, macros) {\n let itemName = item.name;\n let item_macros = itemName.match(MACRO_PATTERN);\n _.forEach(item_macros, macro => {\n let host_macros = _.filter(macros, m => {\n if (m.hostid) {\n return m.hostid === item.hostid;\n } else {\n // Add global macros\n return true;\n }\n });\n\n let macro_def = _.find(host_macros, { macro: macro });\n if (macro_def && macro_def.value) {\n let macro_value = macro_def.value;\n let macro_regex = new RegExp(escapeMacro(macro));\n itemName = itemName.replace(macro_regex, macro_value);\n }\n });\n\n return itemName;\n}\n\nfunction escapeMacro(macro) {\n macro = macro.replace(/\\$/, '\\\\\\$');\n return macro;\n}\n\n/**\n * Split template query to parts of zabbix entities\n * group.host.app.item -> [group, host, app, item]\n * {group}{host.com} -> [group, host.com]\n */\nexport function splitTemplateQuery(query) {\n let splitPattern = /{[^{}]*}/g;\n let split;\n\n if (isContainsBraces(query)) {\n let result = query.match(splitPattern);\n split = _.map(result, part => {\n return _.trim(part, '{}');\n });\n } else {\n split = query.split('.');\n }\n\n return split;\n}\n\nfunction isContainsBraces(query) {\n return query.includes('{') && query.includes('}');\n}\n\n// Pattern for testing regex\nexport const regexPattern = /^\\/(.*)\\/([gmi]*)$/m;\n\nexport function isRegex(str) {\n return regexPattern.test(str);\n}\n\nexport function isTemplateVariable(str, templateVariables) {\n var variablePattern = /^\\$\\w+/;\n if (variablePattern.test(str)) {\n var variables = _.map(templateVariables, variable => {\n return '$' + variable.name;\n });\n return _.includes(variables, str);\n } else {\n return false;\n }\n}\n\nexport function buildRegex(str) {\n var matches = str.match(regexPattern);\n var pattern = matches[1];\n var flags = matches[2] !== \"\" ? matches[2] : undefined;\n return new RegExp(pattern, flags);\n}\n\n// Need for template variables replace\n// From Grafana's templateSrv.js\nexport function escapeRegex(value) {\n return value.replace(/[\\\\^$*+?.()|[\\]{}\\/]/g, '\\\\$&');\n}\n\nexport function parseInterval(interval) {\n var intervalPattern = /(^[\\d]+)(y|M|w|d|h|m|s)/g;\n var momentInterval = intervalPattern.exec(interval);\n return moment.duration(Number(momentInterval[1]), momentInterval[2]).valueOf();\n}\n\nexport function parseTimeShiftInterval(interval) {\n let intervalPattern = /^([\\+\\-]*)([\\d]+)(y|M|w|d|h|m|s)/g;\n let momentInterval = intervalPattern.exec(interval);\n let duration = 0;\n\n if (momentInterval[1] === '+') {\n duration = 0 - moment.duration(Number(momentInterval[2]), momentInterval[3]).valueOf();\n } else {\n duration = moment.duration(Number(momentInterval[2]), momentInterval[3]).valueOf();\n }\n\n return duration;\n}\n\n/**\n * Format acknowledges.\n *\n * @param {array} acknowledges array of Zabbix acknowledge objects\n * @return {string} HTML-formatted table\n */\nexport function formatAcknowledges(acknowledges) {\n if (acknowledges.length) {\n var formatted_acknowledges = '

Acknowledges:
'\n + '';\n _.each(_.map(acknowledges, function (ack) {\n var timestamp = moment.unix(ack.clock);\n return '';\n }), function (ack) {\n formatted_acknowledges = formatted_acknowledges.concat(ack);\n });\n formatted_acknowledges = formatted_acknowledges.concat('
TimeUserComments
' + timestamp.format(\"DD MMM YYYY HH:mm:ss\") + '' + ack.alias\n + ' (' + ack.name + ' ' + ack.surname + ')' + '' + ack.message + '
');\n return formatted_acknowledges;\n } else {\n return '';\n }\n}\n\nexport function convertToZabbixAPIUrl(url) {\n var zabbixAPIUrlPattern = /.*api_jsonrpc.php$/;\n var trimSlashPattern = /(.*?)[\\/]*$/;\n if (url.match(zabbixAPIUrlPattern)) {\n return url;\n } else {\n return url.replace(trimSlashPattern, \"$1\");\n }\n}\n\n/**\n * Wrap function to prevent multiple calls\n * when waiting for result.\n */\nexport function callOnce(func, promiseKeeper) {\n return function() {\n if (!promiseKeeper) {\n promiseKeeper = Promise.resolve(\n func.apply(this, arguments)\n .then(result => {\n promiseKeeper = null;\n return result;\n })\n );\n }\n return promiseKeeper;\n };\n}\n\n// Fix for backward compatibility with lodash 2.4\nif (!_.includes) {\n _.includes = _.contains;\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/datasource-zabbix/utils.js"],"names":["expandItemName","name","key","key_params_str","substring","indexOf","lastIndexOf","key_params","splitKeyParams","i","length","replace","expandItems","items","_","forEach","item","key_","paramStr","params","quoted","in_array","split_symbol","param","symbol","push","containsMacro","itemName","MACRO_PATTERN","test","replaceMacro","macros","item_macros","match","host_macros","filter","m","hostid","macro_def","find","macro","value","macro_value","macro_regex","RegExp","escapeMacro","splitTemplateQuery","query","splitPattern","split","isContainsBraces","result","map","trim","part","bracesPattern","isRegex","str","regexPattern","isTemplateVariable","templateVariables","variablePattern","variables","variable","includes","buildRegex","matches","pattern","flags","undefined","escapeRegex","parseInterval","interval","intervalPattern","momentInterval","exec","moment","duration","Number","valueOf","parseTimeShiftInterval","formatAcknowledges","acknowledges","formatted_acknowledges","each","ack","timestamp","unix","clock","format","alias","surname","message","concat","convertToZabbixAPIUrl","url","zabbixAPIUrlPattern","trimSlashPattern","callOnce","func","promiseKeeper","Promise","resolve","apply","arguments","then","contains"],"mappings":"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","file":"utils.js","sourcesContent":["import _ from 'lodash';\nimport moment from 'moment';\n\n/**\n * Expand Zabbix item name\n *\n * @param {string} name item name, ie \"CPU $2 time\"\n * @param {string} key item key, ie system.cpu.util[,system,avg1]\n * @return {string} expanded name, ie \"CPU system time\"\n */\nexport function expandItemName(name, key) {\n\n // extract params from key:\n // \"system.cpu.util[,system,avg1]\" --> [\"\", \"system\", \"avg1\"]\n let key_params_str = key.substring(key.indexOf('[') + 1, key.lastIndexOf(']'));\n let key_params = splitKeyParams(key_params_str);\n\n // replace item parameters\n for (let i = key_params.length; i >= 1; i--) {\n name = name.replace('$' + i, key_params[i - 1]);\n }\n return name;\n}\n\nexport function expandItems(items) {\n _.forEach(items, item => {\n item.item = item.name;\n item.name = expandItemName(item.item, item.key_);\n return item;\n });\n return items;\n}\n\nfunction splitKeyParams(paramStr) {\n let params = [];\n let quoted = false;\n let in_array = false;\n let split_symbol = ',';\n let param = '';\n\n _.forEach(paramStr, symbol => {\n if (symbol === '\"' && in_array) {\n param += symbol;\n } else if (symbol === '\"' && quoted) {\n quoted = false;\n } else if (symbol === '\"' && !quoted) {\n quoted = true;\n } else if (symbol === '[' && !quoted) {\n in_array = true;\n } else if (symbol === ']' && !quoted) {\n in_array = false;\n } else if (symbol === split_symbol && !quoted && !in_array) {\n params.push(param);\n param = '';\n } else {\n param += symbol;\n }\n });\n\n params.push(param);\n return params;\n}\n\nconst MACRO_PATTERN = /{\\$[A-Z0-9_\\.]+}/g;\n\nexport function containsMacro(itemName) {\n return MACRO_PATTERN.test(itemName);\n}\n\nexport function replaceMacro(item, macros) {\n let itemName = item.name;\n let item_macros = itemName.match(MACRO_PATTERN);\n _.forEach(item_macros, macro => {\n let host_macros = _.filter(macros, m => {\n if (m.hostid) {\n return m.hostid === item.hostid;\n } else {\n // Add global macros\n return true;\n }\n });\n\n let macro_def = _.find(host_macros, { macro: macro });\n if (macro_def && macro_def.value) {\n let macro_value = macro_def.value;\n let macro_regex = new RegExp(escapeMacro(macro));\n itemName = itemName.replace(macro_regex, macro_value);\n }\n });\n\n return itemName;\n}\n\nfunction escapeMacro(macro) {\n macro = macro.replace(/\\$/, '\\\\\\$');\n return macro;\n}\n\n/**\n * Split template query to parts of zabbix entities\n * group.host.app.item -> [group, host, app, item]\n * {group}{host.com} -> [group, host.com]\n */\nexport function splitTemplateQuery(query) {\n let splitPattern = /\\{[^\\{\\}]*\\}|\\{\\/.*\\/\\}/g;\n let split;\n\n if (isContainsBraces(query)) {\n let result = query.match(splitPattern);\n split = _.map(result, part => {\n return _.trim(part, '{}');\n });\n } else {\n split = query.split('.');\n }\n\n return split;\n}\n\nfunction isContainsBraces(query) {\n let bracesPattern = /^\\{.+\\}$/;\n return bracesPattern.test(query);\n}\n\n// Pattern for testing regex\nexport const regexPattern = /^\\/(.*)\\/([gmi]*)$/m;\n\nexport function isRegex(str) {\n return regexPattern.test(str);\n}\n\nexport function isTemplateVariable(str, templateVariables) {\n var variablePattern = /^\\$\\w+/;\n if (variablePattern.test(str)) {\n var variables = _.map(templateVariables, variable => {\n return '$' + variable.name;\n });\n return _.includes(variables, str);\n } else {\n return false;\n }\n}\n\nexport function buildRegex(str) {\n var matches = str.match(regexPattern);\n var pattern = matches[1];\n var flags = matches[2] !== \"\" ? matches[2] : undefined;\n return new RegExp(pattern, flags);\n}\n\n// Need for template variables replace\n// From Grafana's templateSrv.js\nexport function escapeRegex(value) {\n return value.replace(/[\\\\^$*+?.()|[\\]{}\\/]/g, '\\\\$&');\n}\n\nexport function parseInterval(interval) {\n var intervalPattern = /(^[\\d]+)(y|M|w|d|h|m|s)/g;\n var momentInterval = intervalPattern.exec(interval);\n return moment.duration(Number(momentInterval[1]), momentInterval[2]).valueOf();\n}\n\nexport function parseTimeShiftInterval(interval) {\n let intervalPattern = /^([\\+\\-]*)([\\d]+)(y|M|w|d|h|m|s)/g;\n let momentInterval = intervalPattern.exec(interval);\n let duration = 0;\n\n if (momentInterval[1] === '+') {\n duration = 0 - moment.duration(Number(momentInterval[2]), momentInterval[3]).valueOf();\n } else {\n duration = moment.duration(Number(momentInterval[2]), momentInterval[3]).valueOf();\n }\n\n return duration;\n}\n\n/**\n * Format acknowledges.\n *\n * @param {array} acknowledges array of Zabbix acknowledge objects\n * @return {string} HTML-formatted table\n */\nexport function formatAcknowledges(acknowledges) {\n if (acknowledges.length) {\n var formatted_acknowledges = '

Acknowledges:
'\n + '';\n _.each(_.map(acknowledges, function (ack) {\n var timestamp = moment.unix(ack.clock);\n return '';\n }), function (ack) {\n formatted_acknowledges = formatted_acknowledges.concat(ack);\n });\n formatted_acknowledges = formatted_acknowledges.concat('
TimeUserComments
' + timestamp.format(\"DD MMM YYYY HH:mm:ss\") + '' + ack.alias\n + ' (' + ack.name + ' ' + ack.surname + ')' + '' + ack.message + '
');\n return formatted_acknowledges;\n } else {\n return '';\n }\n}\n\nexport function convertToZabbixAPIUrl(url) {\n var zabbixAPIUrlPattern = /.*api_jsonrpc.php$/;\n var trimSlashPattern = /(.*?)[\\/]*$/;\n if (url.match(zabbixAPIUrlPattern)) {\n return url;\n } else {\n return url.replace(trimSlashPattern, \"$1\");\n }\n}\n\n/**\n * Wrap function to prevent multiple calls\n * when waiting for result.\n */\nexport function callOnce(func, promiseKeeper) {\n return function() {\n if (!promiseKeeper) {\n promiseKeeper = Promise.resolve(\n func.apply(this, arguments)\n .then(result => {\n promiseKeeper = null;\n return result;\n })\n );\n }\n return promiseKeeper;\n };\n}\n\n// Fix for backward compatibility with lodash 2.4\nif (!_.includes) {\n _.includes = _.contains;\n}\n"]} \ No newline at end of file diff --git a/dist/datasource-zabbix/zabbix.js b/dist/datasource-zabbix/zabbix.js index 51e6fd5..fb1cb12 100644 --- a/dist/datasource-zabbix/zabbix.js +++ b/dist/datasource-zabbix/zabbix.js @@ -1,6 +1,6 @@ 'use strict'; -System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './zabbixCachingProxy.service.js'], function (_export, _context) { +System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './zabbixCachingProxy.service.js', './zabbixDBConnector'], function (_export, _context) { "use strict"; var angular, _, utils, _createClass; @@ -27,25 +27,44 @@ System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './za // Each Zabbix data source instance should initialize its own API instance. /** @ngInject */ - function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy) { + function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy, ZabbixDBConnector) { var Zabbix = function () { - function Zabbix(url, username, password, basicAuth, withCredentials, cacheTTL) { + function Zabbix(url, options) { _classCallCheck(this, Zabbix); + var username = options.username, + password = options.password, + basicAuth = options.basicAuth, + withCredentials = options.withCredentials, + cacheTTL = options.cacheTTL, + enableDirectDBConnection = options.enableDirectDBConnection, + sqlDatasourceId = options.sqlDatasourceId; + + // Initialize Zabbix API var ZabbixAPI = zabbixAPIService; this.zabbixAPI = new ZabbixAPI(url, username, password, basicAuth, withCredentials); + if (enableDirectDBConnection) { + this.dbConnector = new ZabbixDBConnector(sqlDatasourceId); + } + // Initialize caching proxy for requests var cacheOptions = { enabled: true, ttl: cacheTTL }; - this.cachingProxy = new ZabbixCachingProxy(this.zabbixAPI, cacheOptions); + this.cachingProxy = new ZabbixCachingProxy(this.zabbixAPI, this.dbConnector, cacheOptions); // Proxy methods this.getHistory = this.cachingProxy.getHistory.bind(this.cachingProxy); this.getMacros = this.cachingProxy.getMacros.bind(this.cachingProxy); + this.getItemsByIDs = this.cachingProxy.getItemsByIDs.bind(this.cachingProxy); + + if (enableDirectDBConnection) { + this.getHistoryDB = this.cachingProxy.getHistoryDB.bind(this.cachingProxy); + this.getTrendsDB = this.cachingProxy.getTrendsDB.bind(this.cachingProxy); + } this.getTrend = this.zabbixAPI.getTrend.bind(this.zabbixAPI); this.getEvents = this.zabbixAPI.getEvents.bind(this.zabbixAPI); @@ -168,6 +187,13 @@ System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './za return filterByQuery(items, itemFilter); }); } + }, { + key: 'getITServices', + value: function getITServices(itServiceFilter) { + return this.cachingProxy.getITServices().then(function (itServices) { + return findByFilter(itServices, itServiceFilter); + }); + } }, { key: 'getTriggers', value: function getTriggers(groupFilter, hostFilter, appFilter, options) { @@ -274,7 +300,7 @@ System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './za _ = _lodash.default; }, function (_utils) { utils = _utils; - }, function (_zabbixAPIServiceJs) {}, function (_zabbixCachingProxyServiceJs) {}], + }, function (_zabbixAPIServiceJs) {}, function (_zabbixCachingProxyServiceJs) {}, function (_zabbixDBConnector) {}], execute: function () { _createClass = function () { function defineProperties(target, props) { diff --git a/dist/datasource-zabbix/zabbix.js.map b/dist/datasource-zabbix/zabbix.js.map index da87230..54358d9 100644 --- a/dist/datasource-zabbix/zabbix.js.map +++ b/dist/datasource-zabbix/zabbix.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/datasource-zabbix/zabbix.js"],"names":["ZabbixFactory","zabbixAPIService","ZabbixCachingProxy","Zabbix","url","username","password","basicAuth","withCredentials","cacheTTL","ZabbixAPI","zabbixAPI","cacheOptions","enabled","ttl","cachingProxy","getHistory","bind","getMacros","getTrend","getEvents","getAlerts","getAcknowledges","getITService","getSLA","getVersion","login","target","options","parts","filters","_","map","p","filter","getItems","getGroups","groupFilter","getAllGroups","then","findByFilter","groups","groupids","getHosts","hostFilter","getAllHosts","hosts","hostids","getApps","appFilter","filterByQuery","apps","appFilterEmpty","undefined","itemtype","appids","showDisabledItems","items","expandUserMacro","getHostIds","forEach","utils","containsMacro","item","name","replaceMacro","macros","itemFilter","getAllItems","promises","Promise","all","filteredGroups","results","filteredHosts","filteredApps","query","applicationids","flatten","getTriggers","findByName","list","finded","find","filterByName","filterByRegex","regex","filterPattern","buildRegex","zbx_obj","test","isRegex","hostIds","uniq","angular","module","factory"],"mappings":"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","file":"zabbix.js","sourcesContent":["import angular from 'angular';\nimport _ from 'lodash';\nimport * as utils from './utils';\nimport './zabbixAPI.service.js';\nimport './zabbixCachingProxy.service.js';\n\n// Use factory() instead service() for multiple data sources support.\n// Each Zabbix data source instance should initialize its own API instance.\n\n/** @ngInject */\nfunction ZabbixFactory(zabbixAPIService, ZabbixCachingProxy) {\n\n class Zabbix {\n constructor(url, username, password, basicAuth, withCredentials, cacheTTL) {\n\n // Initialize Zabbix API\n var ZabbixAPI = zabbixAPIService;\n this.zabbixAPI = new ZabbixAPI(url, username, password, basicAuth, withCredentials);\n\n // Initialize caching proxy for requests\n let cacheOptions = {\n enabled: true,\n ttl: cacheTTL\n };\n this.cachingProxy = new ZabbixCachingProxy(this.zabbixAPI, cacheOptions);\n\n // Proxy methods\n this.getHistory = this.cachingProxy.getHistory.bind(this.cachingProxy);\n this.getMacros = this.cachingProxy.getMacros.bind(this.cachingProxy);\n\n this.getTrend = this.zabbixAPI.getTrend.bind(this.zabbixAPI);\n this.getEvents = this.zabbixAPI.getEvents.bind(this.zabbixAPI);\n this.getAlerts = this.zabbixAPI.getAlerts.bind(this.zabbixAPI);\n this.getAcknowledges = this.zabbixAPI.getAcknowledges.bind(this.zabbixAPI);\n this.getITService = this.zabbixAPI.getITService.bind(this.zabbixAPI);\n this.getSLA = this.zabbixAPI.getSLA.bind(this.zabbixAPI);\n this.getVersion = this.zabbixAPI.getVersion.bind(this.zabbixAPI);\n this.login = this.zabbixAPI.login.bind(this.zabbixAPI);\n }\n\n getItemsFromTarget(target, options) {\n let parts = ['group', 'host', 'application', 'item'];\n let filters = _.map(parts, p => target[p].filter);\n return this.getItems(...filters, options);\n }\n\n getAllGroups() {\n return this.cachingProxy.getGroups();\n }\n\n getGroups(groupFilter) {\n return this.getAllGroups()\n .then(groups => findByFilter(groups, groupFilter));\n }\n\n /**\n * Get list of host belonging to given groups.\n */\n getAllHosts(groupFilter) {\n return this.getGroups(groupFilter)\n .then(groups => {\n let groupids = _.map(groups, 'groupid');\n return this.cachingProxy.getHosts(groupids);\n });\n }\n\n getHosts(groupFilter, hostFilter) {\n return this.getAllHosts(groupFilter)\n .then(hosts => findByFilter(hosts, hostFilter));\n }\n\n /**\n * Get list of applications belonging to given groups and hosts.\n */\n getAllApps(groupFilter, hostFilter) {\n return this.getHosts(groupFilter, hostFilter)\n .then(hosts => {\n let hostids = _.map(hosts, 'hostid');\n return this.cachingProxy.getApps(hostids);\n });\n }\n\n getApps(groupFilter, hostFilter, appFilter) {\n return this.getHosts(groupFilter, hostFilter)\n .then(hosts => {\n let hostids = _.map(hosts, 'hostid');\n if (appFilter) {\n return this.cachingProxy.getApps(hostids)\n .then(apps => filterByQuery(apps, appFilter));\n } else {\n return {\n appFilterEmpty: true,\n hostids: hostids\n };\n }\n });\n }\n\n getAllItems(groupFilter, hostFilter, appFilter, options = {}) {\n return this.getApps(groupFilter, hostFilter, appFilter)\n .then(apps => {\n if (apps.appFilterEmpty) {\n return this.cachingProxy.getItems(apps.hostids, undefined, options.itemtype);\n } else {\n let appids = _.map(apps, 'applicationid');\n return this.cachingProxy.getItems(undefined, appids, options.itemtype);\n }\n })\n .then(items => {\n if (!options.showDisabledItems) {\n items = _.filter(items, {'status': '0'});\n }\n\n return items;\n })\n .then(this.expandUserMacro.bind(this));\n }\n\n expandUserMacro(items) {\n let hostids = getHostIds(items);\n return this.getMacros(hostids)\n .then(macros => {\n _.forEach(items, item => {\n if (utils.containsMacro(item.name)) {\n item.name = utils.replaceMacro(item, macros);\n }\n });\n return items;\n });\n }\n\n getItems(groupFilter, hostFilter, appFilter, itemFilter, options = {}) {\n return this.getAllItems(groupFilter, hostFilter, appFilter, options)\n .then(items => filterByQuery(items, itemFilter));\n }\n\n /**\n * Build query - convert target filters to array of Zabbix items\n */\n getTriggers(groupFilter, hostFilter, appFilter, options) {\n let promises = [\n this.getGroups(groupFilter),\n this.getHosts(groupFilter, hostFilter),\n this.getApps(groupFilter, hostFilter, appFilter)\n ];\n\n return Promise.all(promises)\n .then(results => {\n let filteredGroups = results[0];\n let filteredHosts = results[1];\n let filteredApps = results[2];\n let query = {};\n\n if (appFilter) {\n query.applicationids = _.flatten(_.map(filteredApps, 'applicationid'));\n }\n if (hostFilter) {\n query.hostids = _.map(filteredHosts, 'hostid');\n }\n if (groupFilter) {\n query.groupids = _.map(filteredGroups, 'groupid');\n }\n\n return query;\n }).then(query => {\n return this.zabbixAPI.getTriggers(query.groupids, query.hostids, query.applicationids, options);\n });\n }\n }\n\n return Zabbix;\n}\n\nangular\n .module('grafana.services')\n .factory('Zabbix', ZabbixFactory);\n\n///////////////////////////////////////////////////////////////////////////////\n\n/**\n * Find group, host, app or item by given name.\n * @param list list of groups, apps or other\n * @param name visible name\n * @return array with finded element or empty array\n */\nfunction findByName(list, name) {\n var finded = _.find(list, {'name': name});\n if (finded) {\n return [finded];\n } else {\n return [];\n }\n}\n\n/**\n * Different hosts can contains applications and items with same name.\n * For this reason use _.filter, which return all elements instead _.find,\n * which return only first finded.\n * @param {[type]} list list of elements\n * @param {[type]} name app name\n * @return {[type]} array with finded element or empty array\n */\nfunction filterByName(list, name) {\n var finded = _.filter(list, {'name': name});\n if (finded) {\n return finded;\n } else {\n return [];\n }\n}\n\nfunction filterByRegex(list, regex) {\n var filterPattern = utils.buildRegex(regex);\n return _.filter(list, function (zbx_obj) {\n return filterPattern.test(zbx_obj.name);\n });\n}\n\nfunction findByFilter(list, filter) {\n if (utils.isRegex(filter)) {\n return filterByRegex(list, filter);\n } else {\n return findByName(list, filter);\n }\n}\n\nfunction filterByQuery(list, filter) {\n if (utils.isRegex(filter)) {\n return filterByRegex(list, filter);\n } else {\n return filterByName(list, filter);\n }\n}\n\nfunction getHostIds(items) {\n let hostIds = _.map(items, item => {\n return _.map(item.hosts, 'hostid');\n });\n return _.uniq(_.flatten(hostIds));\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/datasource-zabbix/zabbix.js"],"names":["ZabbixFactory","zabbixAPIService","ZabbixCachingProxy","ZabbixDBConnector","Zabbix","url","options","username","password","basicAuth","withCredentials","cacheTTL","enableDirectDBConnection","sqlDatasourceId","ZabbixAPI","zabbixAPI","dbConnector","cacheOptions","enabled","ttl","cachingProxy","getHistory","bind","getMacros","getItemsByIDs","getHistoryDB","getTrendsDB","getTrend","getEvents","getAlerts","getAcknowledges","getITService","getSLA","getVersion","login","target","parts","filters","_","map","p","filter","getItems","getGroups","groupFilter","getAllGroups","then","findByFilter","groups","groupids","getHosts","hostFilter","getAllHosts","hosts","hostids","getApps","appFilter","filterByQuery","apps","appFilterEmpty","undefined","itemtype","appids","showDisabledItems","items","expandUserMacro","getHostIds","forEach","utils","containsMacro","item","name","replaceMacro","macros","itemFilter","getAllItems","itServiceFilter","getITServices","itServices","promises","Promise","all","filteredGroups","results","filteredHosts","filteredApps","query","applicationids","flatten","getTriggers","findByName","list","finded","find","filterByName","filterByRegex","regex","filterPattern","buildRegex","zbx_obj","test","isRegex","hostIds","uniq","angular","module","factory"],"mappings":"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","file":"zabbix.js","sourcesContent":["import angular from 'angular';\nimport _ from 'lodash';\nimport * as utils from './utils';\nimport './zabbixAPI.service.js';\nimport './zabbixCachingProxy.service.js';\nimport './zabbixDBConnector';\n\n// Use factory() instead service() for multiple data sources support.\n// Each Zabbix data source instance should initialize its own API instance.\n\n/** @ngInject */\nfunction ZabbixFactory(zabbixAPIService, ZabbixCachingProxy, ZabbixDBConnector) {\n\n class Zabbix {\n constructor(url, options) {\n let {\n username, password, basicAuth, withCredentials, cacheTTL,\n enableDirectDBConnection, sqlDatasourceId\n } = options;\n\n // Initialize Zabbix API\n var ZabbixAPI = zabbixAPIService;\n this.zabbixAPI = new ZabbixAPI(url, username, password, basicAuth, withCredentials);\n\n if (enableDirectDBConnection) {\n this.dbConnector = new ZabbixDBConnector(sqlDatasourceId);\n }\n\n // Initialize caching proxy for requests\n let cacheOptions = {\n enabled: true,\n ttl: cacheTTL\n };\n this.cachingProxy = new ZabbixCachingProxy(this.zabbixAPI, this.dbConnector, cacheOptions);\n\n // Proxy methods\n this.getHistory = this.cachingProxy.getHistory.bind(this.cachingProxy);\n this.getMacros = this.cachingProxy.getMacros.bind(this.cachingProxy);\n this.getItemsByIDs = this.cachingProxy.getItemsByIDs.bind(this.cachingProxy);\n\n if (enableDirectDBConnection) {\n this.getHistoryDB = this.cachingProxy.getHistoryDB.bind(this.cachingProxy);\n this.getTrendsDB = this.cachingProxy.getTrendsDB.bind(this.cachingProxy);\n }\n\n this.getTrend = this.zabbixAPI.getTrend.bind(this.zabbixAPI);\n this.getEvents = this.zabbixAPI.getEvents.bind(this.zabbixAPI);\n this.getAlerts = this.zabbixAPI.getAlerts.bind(this.zabbixAPI);\n this.getAcknowledges = this.zabbixAPI.getAcknowledges.bind(this.zabbixAPI);\n this.getITService = this.zabbixAPI.getITService.bind(this.zabbixAPI);\n this.getSLA = this.zabbixAPI.getSLA.bind(this.zabbixAPI);\n this.getVersion = this.zabbixAPI.getVersion.bind(this.zabbixAPI);\n this.login = this.zabbixAPI.login.bind(this.zabbixAPI);\n }\n\n getItemsFromTarget(target, options) {\n let parts = ['group', 'host', 'application', 'item'];\n let filters = _.map(parts, p => target[p].filter);\n return this.getItems(...filters, options);\n }\n\n getAllGroups() {\n return this.cachingProxy.getGroups();\n }\n\n getGroups(groupFilter) {\n return this.getAllGroups()\n .then(groups => findByFilter(groups, groupFilter));\n }\n\n /**\n * Get list of host belonging to given groups.\n */\n getAllHosts(groupFilter) {\n return this.getGroups(groupFilter)\n .then(groups => {\n let groupids = _.map(groups, 'groupid');\n return this.cachingProxy.getHosts(groupids);\n });\n }\n\n getHosts(groupFilter, hostFilter) {\n return this.getAllHosts(groupFilter)\n .then(hosts => findByFilter(hosts, hostFilter));\n }\n\n /**\n * Get list of applications belonging to given groups and hosts.\n */\n getAllApps(groupFilter, hostFilter) {\n return this.getHosts(groupFilter, hostFilter)\n .then(hosts => {\n let hostids = _.map(hosts, 'hostid');\n return this.cachingProxy.getApps(hostids);\n });\n }\n\n getApps(groupFilter, hostFilter, appFilter) {\n return this.getHosts(groupFilter, hostFilter)\n .then(hosts => {\n let hostids = _.map(hosts, 'hostid');\n if (appFilter) {\n return this.cachingProxy.getApps(hostids)\n .then(apps => filterByQuery(apps, appFilter));\n } else {\n return {\n appFilterEmpty: true,\n hostids: hostids\n };\n }\n });\n }\n\n getAllItems(groupFilter, hostFilter, appFilter, options = {}) {\n return this.getApps(groupFilter, hostFilter, appFilter)\n .then(apps => {\n if (apps.appFilterEmpty) {\n return this.cachingProxy.getItems(apps.hostids, undefined, options.itemtype);\n } else {\n let appids = _.map(apps, 'applicationid');\n return this.cachingProxy.getItems(undefined, appids, options.itemtype);\n }\n })\n .then(items => {\n if (!options.showDisabledItems) {\n items = _.filter(items, {'status': '0'});\n }\n\n return items;\n })\n .then(this.expandUserMacro.bind(this));\n }\n\n expandUserMacro(items) {\n let hostids = getHostIds(items);\n return this.getMacros(hostids)\n .then(macros => {\n _.forEach(items, item => {\n if (utils.containsMacro(item.name)) {\n item.name = utils.replaceMacro(item, macros);\n }\n });\n return items;\n });\n }\n\n getItems(groupFilter, hostFilter, appFilter, itemFilter, options = {}) {\n return this.getAllItems(groupFilter, hostFilter, appFilter, options)\n .then(items => filterByQuery(items, itemFilter));\n }\n\n getITServices(itServiceFilter) {\n return this.cachingProxy.getITServices()\n .then(itServices => findByFilter(itServices, itServiceFilter));\n }\n\n /**\n * Build query - convert target filters to array of Zabbix items\n */\n getTriggers(groupFilter, hostFilter, appFilter, options) {\n let promises = [\n this.getGroups(groupFilter),\n this.getHosts(groupFilter, hostFilter),\n this.getApps(groupFilter, hostFilter, appFilter)\n ];\n\n return Promise.all(promises)\n .then(results => {\n let filteredGroups = results[0];\n let filteredHosts = results[1];\n let filteredApps = results[2];\n let query = {};\n\n if (appFilter) {\n query.applicationids = _.flatten(_.map(filteredApps, 'applicationid'));\n }\n if (hostFilter) {\n query.hostids = _.map(filteredHosts, 'hostid');\n }\n if (groupFilter) {\n query.groupids = _.map(filteredGroups, 'groupid');\n }\n\n return query;\n }).then(query => {\n return this.zabbixAPI.getTriggers(query.groupids, query.hostids, query.applicationids, options);\n });\n }\n }\n\n return Zabbix;\n}\n\nangular\n .module('grafana.services')\n .factory('Zabbix', ZabbixFactory);\n\n///////////////////////////////////////////////////////////////////////////////\n\n/**\n * Find group, host, app or item by given name.\n * @param list list of groups, apps or other\n * @param name visible name\n * @return array with finded element or empty array\n */\nfunction findByName(list, name) {\n var finded = _.find(list, {'name': name});\n if (finded) {\n return [finded];\n } else {\n return [];\n }\n}\n\n/**\n * Different hosts can contains applications and items with same name.\n * For this reason use _.filter, which return all elements instead _.find,\n * which return only first finded.\n * @param {[type]} list list of elements\n * @param {[type]} name app name\n * @return {[type]} array with finded element or empty array\n */\nfunction filterByName(list, name) {\n var finded = _.filter(list, {'name': name});\n if (finded) {\n return finded;\n } else {\n return [];\n }\n}\n\nfunction filterByRegex(list, regex) {\n var filterPattern = utils.buildRegex(regex);\n return _.filter(list, function (zbx_obj) {\n return filterPattern.test(zbx_obj.name);\n });\n}\n\nfunction findByFilter(list, filter) {\n if (utils.isRegex(filter)) {\n return filterByRegex(list, filter);\n } else {\n return findByName(list, filter);\n }\n}\n\nfunction filterByQuery(list, filter) {\n if (utils.isRegex(filter)) {\n return filterByRegex(list, filter);\n } else {\n return filterByName(list, filter);\n }\n}\n\nfunction getHostIds(items) {\n let hostIds = _.map(items, item => {\n return _.map(item.hosts, 'hostid');\n });\n return _.uniq(_.flatten(hostIds));\n}\n"]} \ No newline at end of file diff --git a/dist/datasource-zabbix/zabbixAPI.service.js b/dist/datasource-zabbix/zabbixAPI.service.js index b48bb91..29f7b90 100644 --- a/dist/datasource-zabbix/zabbixAPI.service.js +++ b/dist/datasource-zabbix/zabbixAPI.service.js @@ -166,16 +166,19 @@ System.register(['angular', 'lodash', './utils', './zabbixAPICore.service'], fun params.filter.value_type = [1, 2, 4]; } - return this.request('item.get', params).then(expandItems); + return this.request('item.get', params).then(utils.expandItems); + } + }, { + key: 'getItemsByIDs', + value: function getItemsByIDs(itemids) { + var params = { + itemids: itemids, + output: ['name', 'key_', 'value_type', 'hostid', 'status', 'state'], + webitems: true, + selectHosts: ['hostid', 'name'] + }; - function expandItems(items) { - _.forEach(items, function (item) { - item.item = item.name; - item.name = utils.expandItemName(item.item, item.key_); - return item; - }); - return items; - } + return this.request('item.get', params).then(utils.expandItems); } }, { key: 'getMacros', diff --git a/dist/datasource-zabbix/zabbixAPI.service.js.map b/dist/datasource-zabbix/zabbixAPI.service.js.map index 629d0fb..654eab3 100644 --- a/dist/datasource-zabbix/zabbixAPI.service.js.map +++ b/dist/datasource-zabbix/zabbixAPI.service.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/datasource-zabbix/zabbixAPI.service.js"],"names":["ZabbixAPIServiceFactory","alertSrv","zabbixAPICoreService","ZabbixAPI","api_url","username","password","basicAuth","withCredentials","url","auth","requestOptions","loginPromise","loginErrorCount","maxLoginAttempts","zabbixAPICore","getTrend","getTrend_ZBXNEXT1193","method","params","request","catch","isNotAuthorized","error","data","loginOnce","then","message","statusText","alertAPIError","timeout","set","Promise","resolve","login","getVersion","eventid","eventids","output","sortfield","real_hosts","groupids","hostids","appids","itemtype","webitems","filter","selectHosts","applicationids","value_type","expandItems","items","_","forEach","item","name","utils","expandItemName","key_","globalmacro","itemid","itemids","length","lastvalue","timeFrom","timeTill","grouped_items","groupBy","promises","map","history","sortorder","time_from","time_till","all","flatten","trend","self","serviceids","timeRange","timeTo","intervals","from","to","options","showTriggers","hideHostsInMaintenance","expandDescription","expandData","expandComment","monitored","skipDependent","value","selectGroups","selectItems","selectLastEvent","maintenance","lastChangeSince","lastChangeTill","objectids","showEvents","select_acknowledges","preservekeys","events","event","acknowledges","angular","module","factory"],"mappings":"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","file":"zabbixAPI.service.js","sourcesContent":["import angular from 'angular';\nimport _ from 'lodash';\nimport * as utils from './utils';\nimport './zabbixAPICore.service';\n\n/** @ngInject */\nfunction ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) {\n\n /**\n * Zabbix API Wrapper.\n * Creates Zabbix API instance with given parameters (url, credentials and other).\n * Wraps API calls and provides high-level methods.\n */\n class ZabbixAPI {\n\n constructor(api_url, username, password, basicAuth, withCredentials) {\n this.url = api_url;\n this.username = username;\n this.password = password;\n this.auth = \"\";\n\n this.requestOptions = {\n basicAuth: basicAuth,\n withCredentials: withCredentials\n };\n\n this.loginPromise = null;\n this.loginErrorCount = 0;\n this.maxLoginAttempts = 3;\n\n this.alertSrv = alertSrv;\n this.zabbixAPICore = zabbixAPICoreService;\n\n this.getTrend = this.getTrend_ZBXNEXT1193;\n //getTrend = getTrend_30;\n }\n\n //////////////////////////\n // Core method wrappers //\n //////////////////////////\n\n request(method, params) {\n return this.zabbixAPICore.request(this.url, method, params, this.requestOptions, this.auth)\n .catch(error => {\n if (isNotAuthorized(error.data)) {\n // Handle auth errors\n this.loginErrorCount++;\n if (this.loginErrorCount > this.maxLoginAttempts) {\n this.loginErrorCount = 0;\n return null;\n } else {\n return this.loginOnce()\n .then(() => this.request(method, params));\n }\n } else {\n // Handle API errors\n let message = error.data ? error.data : error.statusText;\n this.alertAPIError(message);\n }\n });\n }\n\n alertAPIError(message, timeout = 5000) {\n this.alertSrv.set(\n \"Zabbix API Error\",\n message,\n 'error',\n timeout\n );\n }\n\n /**\n * When API unauthenticated or auth token expired each request produce login()\n * call. But auth token is common to all requests. This function wraps login() method\n * and call it once. If login() already called just wait for it (return its promise).\n * @return login promise\n */\n loginOnce() {\n if (!this.loginPromise) {\n this.loginPromise = Promise.resolve(\n this.login().then(auth => {\n this.auth = auth;\n this.loginPromise = null;\n return auth;\n })\n );\n }\n return this.loginPromise;\n }\n\n /**\n * Get authentication token.\n */\n login() {\n return this.zabbixAPICore.login(this.url, this.username, this.password, this.requestOptions);\n }\n\n /**\n * Get Zabbix API version\n */\n getVersion() {\n return this.zabbixAPICore.getVersion(this.url, this.requestOptions);\n }\n\n ////////////////////////////////\n // Zabbix API method wrappers //\n ////////////////////////////////\n\n acknowledgeEvent(eventid, message) {\n var params = {\n eventids: eventid,\n message: message\n };\n\n return this.request('event.acknowledge', params);\n }\n\n getGroups() {\n var params = {\n output: ['name'],\n sortfield: 'name',\n real_hosts: true\n };\n\n return this.request('hostgroup.get', params);\n }\n\n getHosts(groupids) {\n var params = {\n output: ['name', 'host'],\n sortfield: 'name'\n };\n if (groupids) {\n params.groupids = groupids;\n }\n\n return this.request('host.get', params);\n }\n\n getApps(hostids) {\n var params = {\n output: ['applicationid', 'name'],\n hostids: hostids\n };\n\n return this.request('application.get', params);\n }\n\n /**\n * Get Zabbix items\n * @param {[type]} hostids host ids\n * @param {[type]} appids application ids\n * @param {String} itemtype 'num' or 'text'\n * @return {[type]} array of items\n */\n getItems(hostids, appids, itemtype) {\n var params = {\n output: [\n 'name', 'key_',\n 'value_type',\n 'hostid',\n 'status',\n 'state'\n ],\n sortfield: 'name',\n webitems: true,\n filter: {},\n selectHosts: [\n 'hostid',\n 'name'\n ]\n };\n if (hostids) {\n params.hostids = hostids;\n }\n if (appids) {\n params.applicationids = appids;\n }\n if (itemtype === 'num') {\n // Return only numeric metrics\n params.filter.value_type = [0, 3];\n }\n if (itemtype === 'text') {\n // Return only text metrics\n params.filter.value_type = [1, 2, 4];\n }\n\n return this.request('item.get', params)\n .then(expandItems);\n\n function expandItems(items) {\n _.forEach(items, item => {\n item.item = item.name;\n item.name = utils.expandItemName(item.item, item.key_);\n return item;\n });\n return items;\n }\n }\n\n getMacros(hostids) {\n var params = {\n output: 'extend',\n hostids: hostids\n };\n\n return this.request('usermacro.get', params);\n }\n\n getGlobalMacros() {\n var params = {\n output: 'extend',\n globalmacro: true\n };\n\n return this.request('usermacro.get', params);\n }\n\n getLastValue(itemid) {\n var params = {\n output: ['lastvalue'],\n itemids: itemid\n };\n return this.request('item.get', params)\n .then(items => items.length ? items[0].lastvalue : null);\n }\n\n /**\n * Perform history query from Zabbix API\n *\n * @param {Array} items Array of Zabbix item objects\n * @param {Number} timeFrom Time in seconds\n * @param {Number} timeTill Time in seconds\n * @return {Array} Array of Zabbix history objects\n */\n getHistory(items, timeFrom, timeTill) {\n\n // Group items by value type and perform request for each value type\n let grouped_items = _.groupBy(items, 'value_type');\n let promises = _.map(grouped_items, (items, value_type) => {\n let itemids = _.map(items, 'itemid');\n let params = {\n output: 'extend',\n history: value_type,\n itemids: itemids,\n sortfield: 'clock',\n sortorder: 'ASC',\n time_from: timeFrom\n };\n\n // Relative queries (e.g. last hour) don't include an end time\n if (timeTill) {\n params.time_till = timeTill;\n }\n\n return this.request('history.get', params);\n });\n\n return Promise.all(promises).then(_.flatten);\n }\n\n /**\n * Perform trends query from Zabbix API\n * Use trends api extension from ZBXNEXT-1193 patch.\n *\n * @param {Array} items Array of Zabbix item objects\n * @param {Number} time_from Time in seconds\n * @param {Number} time_till Time in seconds\n * @return {Array} Array of Zabbix trend objects\n */\n getTrend_ZBXNEXT1193(items, timeFrom, timeTill) {\n\n // Group items by value type and perform request for each value type\n let grouped_items = _.groupBy(items, 'value_type');\n let promises = _.map(grouped_items, (items, value_type) => {\n let itemids = _.map(items, 'itemid');\n let params = {\n output: 'extend',\n trend: value_type,\n itemids: itemids,\n sortfield: 'clock',\n sortorder: 'ASC',\n time_from: timeFrom\n };\n\n // Relative queries (e.g. last hour) don't include an end time\n if (timeTill) {\n params.time_till = timeTill;\n }\n\n return this.request('trend.get', params);\n });\n\n return Promise.all(promises).then(_.flatten);\n }\n\n getTrend_30(items, time_from, time_till, value_type) {\n var self = this;\n var itemids = _.map(items, 'itemid');\n\n var params = {\n output: [\"itemid\",\n \"clock\",\n value_type\n ],\n itemids: itemids,\n time_from: time_from\n };\n\n // Relative queries (e.g. last hour) don't include an end time\n if (time_till) {\n params.time_till = time_till;\n }\n\n return self.request('trend.get', params);\n }\n\n getITService(serviceids) {\n var params = {\n output: 'extend',\n serviceids: serviceids\n };\n return this.request('service.get', params);\n }\n\n getSLA(serviceids, timeRange) {\n let [timeFrom, timeTo] = timeRange;\n var params = {\n serviceids: serviceids,\n intervals: [{\n from: timeFrom,\n to: timeTo\n }]\n };\n return this.request('service.getsla', params);\n }\n\n getTriggers(groupids, hostids, applicationids, options) {\n let {showTriggers, hideHostsInMaintenance, timeFrom, timeTo} = options;\n\n let params = {\n output: 'extend',\n groupids: groupids,\n hostids: hostids,\n applicationids: applicationids,\n expandDescription: true,\n expandData: true,\n expandComment: true,\n monitored: true,\n skipDependent: true,\n //only_true: true,\n filter: {\n value: 1\n },\n selectGroups: ['name'],\n selectHosts: ['name', 'host'],\n selectItems: ['name', 'key_', 'lastvalue'],\n selectLastEvent: 'extend'\n };\n\n if (showTriggers) {\n params.filter.value = showTriggers;\n }\n\n if (hideHostsInMaintenance) {\n params.maintenance = false;\n }\n\n if (timeFrom || timeTo) {\n params.lastChangeSince = timeFrom;\n params.lastChangeTill = timeTo;\n }\n\n return this.request('trigger.get', params);\n }\n\n getEvents(objectids, timeFrom, timeTo, showEvents) {\n var params = {\n output: 'extend',\n time_from: timeFrom,\n time_till: timeTo,\n objectids: objectids,\n select_acknowledges: 'extend',\n selectHosts: 'extend',\n value: showEvents\n };\n\n return this.request('event.get', params);\n }\n\n getAcknowledges(eventids) {\n var params = {\n output: 'extend',\n eventids: eventids,\n preservekeys: true,\n select_acknowledges: 'extend',\n sortfield: 'clock',\n sortorder: 'DESC'\n };\n\n return this.request('event.get', params)\n .then(events => {\n return _.filter(events, (event) => event.acknowledges.length);\n });\n }\n\n getAlerts(itemids, timeFrom, timeTo) {\n var params = {\n output: 'extend',\n itemids: itemids,\n expandDescription: true,\n expandData: true,\n expandComment: true,\n monitored: true,\n skipDependent: true,\n //only_true: true,\n // filter: {\n // value: 1\n // },\n selectLastEvent: 'extend'\n };\n\n if (timeFrom || timeTo) {\n params.lastChangeSince = timeFrom;\n params.lastChangeTill = timeTo;\n }\n\n return this.request('trigger.get', params);\n }\n }\n\n return ZabbixAPI;\n}\n\nfunction isNotAuthorized(message) {\n return (\n message === \"Session terminated, re-login, please.\" ||\n message === \"Not authorised.\" ||\n message === \"Not authorized.\"\n );\n}\n\nangular\n .module('grafana.services')\n .factory('zabbixAPIService', ZabbixAPIServiceFactory);\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/datasource-zabbix/zabbixAPI.service.js"],"names":["ZabbixAPIServiceFactory","alertSrv","zabbixAPICoreService","ZabbixAPI","api_url","username","password","basicAuth","withCredentials","url","auth","requestOptions","loginPromise","loginErrorCount","maxLoginAttempts","zabbixAPICore","getTrend","getTrend_ZBXNEXT1193","method","params","request","catch","isNotAuthorized","error","data","loginOnce","then","message","statusText","alertAPIError","timeout","set","Promise","resolve","login","getVersion","eventid","eventids","output","sortfield","real_hosts","groupids","hostids","appids","itemtype","webitems","filter","selectHosts","applicationids","value_type","utils","expandItems","itemids","globalmacro","itemid","items","length","lastvalue","timeFrom","timeTill","grouped_items","_","groupBy","promises","map","history","sortorder","time_from","time_till","all","flatten","trend","self","serviceids","timeRange","timeTo","intervals","from","to","options","showTriggers","hideHostsInMaintenance","expandDescription","expandData","expandComment","monitored","skipDependent","value","selectGroups","selectItems","selectLastEvent","maintenance","lastChangeSince","lastChangeTill","objectids","showEvents","select_acknowledges","preservekeys","events","event","acknowledges","angular","module","factory"],"mappings":"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","file":"zabbixAPI.service.js","sourcesContent":["import angular from 'angular';\nimport _ from 'lodash';\nimport * as utils from './utils';\nimport './zabbixAPICore.service';\n\n/** @ngInject */\nfunction ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) {\n\n /**\n * Zabbix API Wrapper.\n * Creates Zabbix API instance with given parameters (url, credentials and other).\n * Wraps API calls and provides high-level methods.\n */\n class ZabbixAPI {\n\n constructor(api_url, username, password, basicAuth, withCredentials) {\n this.url = api_url;\n this.username = username;\n this.password = password;\n this.auth = \"\";\n\n this.requestOptions = {\n basicAuth: basicAuth,\n withCredentials: withCredentials\n };\n\n this.loginPromise = null;\n this.loginErrorCount = 0;\n this.maxLoginAttempts = 3;\n\n this.alertSrv = alertSrv;\n this.zabbixAPICore = zabbixAPICoreService;\n\n this.getTrend = this.getTrend_ZBXNEXT1193;\n //getTrend = getTrend_30;\n }\n\n //////////////////////////\n // Core method wrappers //\n //////////////////////////\n\n request(method, params) {\n return this.zabbixAPICore.request(this.url, method, params, this.requestOptions, this.auth)\n .catch(error => {\n if (isNotAuthorized(error.data)) {\n // Handle auth errors\n this.loginErrorCount++;\n if (this.loginErrorCount > this.maxLoginAttempts) {\n this.loginErrorCount = 0;\n return null;\n } else {\n return this.loginOnce()\n .then(() => this.request(method, params));\n }\n } else {\n // Handle API errors\n let message = error.data ? error.data : error.statusText;\n this.alertAPIError(message);\n }\n });\n }\n\n alertAPIError(message, timeout = 5000) {\n this.alertSrv.set(\n \"Zabbix API Error\",\n message,\n 'error',\n timeout\n );\n }\n\n /**\n * When API unauthenticated or auth token expired each request produce login()\n * call. But auth token is common to all requests. This function wraps login() method\n * and call it once. If login() already called just wait for it (return its promise).\n * @return login promise\n */\n loginOnce() {\n if (!this.loginPromise) {\n this.loginPromise = Promise.resolve(\n this.login().then(auth => {\n this.auth = auth;\n this.loginPromise = null;\n return auth;\n })\n );\n }\n return this.loginPromise;\n }\n\n /**\n * Get authentication token.\n */\n login() {\n return this.zabbixAPICore.login(this.url, this.username, this.password, this.requestOptions);\n }\n\n /**\n * Get Zabbix API version\n */\n getVersion() {\n return this.zabbixAPICore.getVersion(this.url, this.requestOptions);\n }\n\n ////////////////////////////////\n // Zabbix API method wrappers //\n ////////////////////////////////\n\n acknowledgeEvent(eventid, message) {\n var params = {\n eventids: eventid,\n message: message\n };\n\n return this.request('event.acknowledge', params);\n }\n\n getGroups() {\n var params = {\n output: ['name'],\n sortfield: 'name',\n real_hosts: true\n };\n\n return this.request('hostgroup.get', params);\n }\n\n getHosts(groupids) {\n var params = {\n output: ['name', 'host'],\n sortfield: 'name'\n };\n if (groupids) {\n params.groupids = groupids;\n }\n\n return this.request('host.get', params);\n }\n\n getApps(hostids) {\n var params = {\n output: ['applicationid', 'name'],\n hostids: hostids\n };\n\n return this.request('application.get', params);\n }\n\n /**\n * Get Zabbix items\n * @param {[type]} hostids host ids\n * @param {[type]} appids application ids\n * @param {String} itemtype 'num' or 'text'\n * @return {[type]} array of items\n */\n getItems(hostids, appids, itemtype) {\n var params = {\n output: [\n 'name', 'key_',\n 'value_type',\n 'hostid',\n 'status',\n 'state'\n ],\n sortfield: 'name',\n webitems: true,\n filter: {},\n selectHosts: ['hostid', 'name']\n };\n if (hostids) {\n params.hostids = hostids;\n }\n if (appids) {\n params.applicationids = appids;\n }\n if (itemtype === 'num') {\n // Return only numeric metrics\n params.filter.value_type = [0, 3];\n }\n if (itemtype === 'text') {\n // Return only text metrics\n params.filter.value_type = [1, 2, 4];\n }\n\n return this.request('item.get', params)\n .then(utils.expandItems);\n }\n\n getItemsByIDs(itemids) {\n var params = {\n itemids: itemids,\n output: [\n 'name', 'key_',\n 'value_type',\n 'hostid',\n 'status',\n 'state'\n ],\n webitems: true,\n selectHosts: ['hostid', 'name']\n };\n\n return this.request('item.get', params)\n .then(utils.expandItems);\n }\n\n getMacros(hostids) {\n var params = {\n output: 'extend',\n hostids: hostids\n };\n\n return this.request('usermacro.get', params);\n }\n\n getGlobalMacros() {\n var params = {\n output: 'extend',\n globalmacro: true\n };\n\n return this.request('usermacro.get', params);\n }\n\n getLastValue(itemid) {\n var params = {\n output: ['lastvalue'],\n itemids: itemid\n };\n return this.request('item.get', params)\n .then(items => items.length ? items[0].lastvalue : null);\n }\n\n /**\n * Perform history query from Zabbix API\n *\n * @param {Array} items Array of Zabbix item objects\n * @param {Number} timeFrom Time in seconds\n * @param {Number} timeTill Time in seconds\n * @return {Array} Array of Zabbix history objects\n */\n getHistory(items, timeFrom, timeTill) {\n\n // Group items by value type and perform request for each value type\n let grouped_items = _.groupBy(items, 'value_type');\n let promises = _.map(grouped_items, (items, value_type) => {\n let itemids = _.map(items, 'itemid');\n let params = {\n output: 'extend',\n history: value_type,\n itemids: itemids,\n sortfield: 'clock',\n sortorder: 'ASC',\n time_from: timeFrom\n };\n\n // Relative queries (e.g. last hour) don't include an end time\n if (timeTill) {\n params.time_till = timeTill;\n }\n\n return this.request('history.get', params);\n });\n\n return Promise.all(promises).then(_.flatten);\n }\n\n /**\n * Perform trends query from Zabbix API\n * Use trends api extension from ZBXNEXT-1193 patch.\n *\n * @param {Array} items Array of Zabbix item objects\n * @param {Number} time_from Time in seconds\n * @param {Number} time_till Time in seconds\n * @return {Array} Array of Zabbix trend objects\n */\n getTrend_ZBXNEXT1193(items, timeFrom, timeTill) {\n\n // Group items by value type and perform request for each value type\n let grouped_items = _.groupBy(items, 'value_type');\n let promises = _.map(grouped_items, (items, value_type) => {\n let itemids = _.map(items, 'itemid');\n let params = {\n output: 'extend',\n trend: value_type,\n itemids: itemids,\n sortfield: 'clock',\n sortorder: 'ASC',\n time_from: timeFrom\n };\n\n // Relative queries (e.g. last hour) don't include an end time\n if (timeTill) {\n params.time_till = timeTill;\n }\n\n return this.request('trend.get', params);\n });\n\n return Promise.all(promises).then(_.flatten);\n }\n\n getTrend_30(items, time_from, time_till, value_type) {\n var self = this;\n var itemids = _.map(items, 'itemid');\n\n var params = {\n output: [\"itemid\",\n \"clock\",\n value_type\n ],\n itemids: itemids,\n time_from: time_from\n };\n\n // Relative queries (e.g. last hour) don't include an end time\n if (time_till) {\n params.time_till = time_till;\n }\n\n return self.request('trend.get', params);\n }\n\n getITService(serviceids) {\n var params = {\n output: 'extend',\n serviceids: serviceids\n };\n return this.request('service.get', params);\n }\n\n getSLA(serviceids, timeRange) {\n let [timeFrom, timeTo] = timeRange;\n var params = {\n serviceids: serviceids,\n intervals: [{\n from: timeFrom,\n to: timeTo\n }]\n };\n return this.request('service.getsla', params);\n }\n\n getTriggers(groupids, hostids, applicationids, options) {\n let {showTriggers, hideHostsInMaintenance, timeFrom, timeTo} = options;\n\n let params = {\n output: 'extend',\n groupids: groupids,\n hostids: hostids,\n applicationids: applicationids,\n expandDescription: true,\n expandData: true,\n expandComment: true,\n monitored: true,\n skipDependent: true,\n //only_true: true,\n filter: {\n value: 1\n },\n selectGroups: ['name'],\n selectHosts: ['name', 'host'],\n selectItems: ['name', 'key_', 'lastvalue'],\n selectLastEvent: 'extend'\n };\n\n if (showTriggers) {\n params.filter.value = showTriggers;\n }\n\n if (hideHostsInMaintenance) {\n params.maintenance = false;\n }\n\n if (timeFrom || timeTo) {\n params.lastChangeSince = timeFrom;\n params.lastChangeTill = timeTo;\n }\n\n return this.request('trigger.get', params);\n }\n\n getEvents(objectids, timeFrom, timeTo, showEvents) {\n var params = {\n output: 'extend',\n time_from: timeFrom,\n time_till: timeTo,\n objectids: objectids,\n select_acknowledges: 'extend',\n selectHosts: 'extend',\n value: showEvents\n };\n\n return this.request('event.get', params);\n }\n\n getAcknowledges(eventids) {\n var params = {\n output: 'extend',\n eventids: eventids,\n preservekeys: true,\n select_acknowledges: 'extend',\n sortfield: 'clock',\n sortorder: 'DESC'\n };\n\n return this.request('event.get', params)\n .then(events => {\n return _.filter(events, (event) => event.acknowledges.length);\n });\n }\n\n getAlerts(itemids, timeFrom, timeTo) {\n var params = {\n output: 'extend',\n itemids: itemids,\n expandDescription: true,\n expandData: true,\n expandComment: true,\n monitored: true,\n skipDependent: true,\n //only_true: true,\n // filter: {\n // value: 1\n // },\n selectLastEvent: 'extend'\n };\n\n if (timeFrom || timeTo) {\n params.lastChangeSince = timeFrom;\n params.lastChangeTill = timeTo;\n }\n\n return this.request('trigger.get', params);\n }\n }\n\n return ZabbixAPI;\n}\n\nfunction isNotAuthorized(message) {\n return (\n message === \"Session terminated, re-login, please.\" ||\n message === \"Not authorised.\" ||\n message === \"Not authorized.\"\n );\n}\n\nangular\n .module('grafana.services')\n .factory('zabbixAPIService', ZabbixAPIServiceFactory);\n"]} \ No newline at end of file diff --git a/dist/datasource-zabbix/zabbixCachingProxy.service.js b/dist/datasource-zabbix/zabbixCachingProxy.service.js index 9ccf0f1..5e657ec 100644 --- a/dist/datasource-zabbix/zabbixCachingProxy.service.js +++ b/dist/datasource-zabbix/zabbixCachingProxy.service.js @@ -29,10 +29,11 @@ System.register(['angular', 'lodash'], function (_export, _context) { /** @ngInject */ function ZabbixCachingProxyFactory() { var ZabbixCachingProxy = function () { - function ZabbixCachingProxy(zabbixAPI, cacheOptions) { + function ZabbixCachingProxy(zabbixAPI, zabbixDBConnector, cacheOptions) { _classCallCheck(this, ZabbixCachingProxy); this.zabbixAPI = zabbixAPI; + this.dbConnector = zabbixDBConnector; this.cacheEnabled = cacheOptions.enabled; this.ttl = cacheOptions.ttl || 600000; // 10 minutes by default @@ -45,7 +46,8 @@ System.register(['angular', 'lodash'], function (_export, _context) { history: {}, trends: {}, macros: {}, - globalMacros: {} + globalMacros: {}, + itServices: {} }; this.historyPromises = {}; @@ -53,6 +55,11 @@ System.register(['angular', 'lodash'], function (_export, _context) { // Don't run duplicated history requests this.getHistory = callAPIRequestOnce(_.bind(this.zabbixAPI.getHistory, this.zabbixAPI), this.historyPromises, getHistoryRequestHash); + if (this.dbConnector) { + this.getHistoryDB = callAPIRequestOnce(_.bind(this.dbConnector.getHistory, this.dbConnector), this.historyPromises, getDBQueryHash); + this.getTrendsDB = callAPIRequestOnce(_.bind(this.dbConnector.getTrends, this.dbConnector), this.historyPromises, getDBQueryHash); + } + // Don't run duplicated requests this.groupPromises = {}; this.getGroupsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getGroups, this.zabbixAPI), this.groupPromises, getRequestHash); @@ -66,6 +73,12 @@ System.register(['angular', 'lodash'], function (_export, _context) { this.itemPromises = {}; this.getItemsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getItems, this.zabbixAPI), this.itemPromises, getRequestHash); + this.itemByIdPromises = {}; + this.getItemsByIdOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getItemsByIDs, this.zabbixAPI), this.itemPromises, getRequestHash); + + this.itServicesPromises = {}; + this.getITServicesOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getITService, this.zabbixAPI), this.itServicesPromises, getRequestHash); + this.macroPromises = {}; this.getMacrosOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getMacros, this.zabbixAPI), this.macroPromises, getRequestHash); @@ -120,6 +133,17 @@ System.register(['angular', 'lodash'], function (_export, _context) { var params = [hostids, appids, itemtype]; return this.proxyRequest(this.getItemsOnce, params, this.cache.items); } + }, { + key: 'getItemsByIDs', + value: function getItemsByIDs(itemids) { + var params = [itemids]; + return this.proxyRequest(this.getItemsByIdOnce, params, this.cache.items); + } + }, { + key: 'getITServices', + value: function getITServices() { + return this.proxyRequest(this.getITServicesOnce, [], this.cache.itServices); + } }, { key: 'getMacros', value: function getMacros(hostids) { @@ -209,6 +233,14 @@ System.register(['angular', 'lodash'], function (_export, _context) { return stamp.getHash(); } + function getDBQueryHash(args) { + var itemids = _.map(args[0], 'itemid'); + var consolidateBy = args[3].consolidateBy; + var intervalMs = args[3].intervalMs; + var stamp = itemids.join() + args[1] + args[2] + consolidateBy + intervalMs; + return stamp.getHash(); + } + return { setters: [function (_angular) { angular = _angular.default; diff --git a/dist/datasource-zabbix/zabbixCachingProxy.service.js.map b/dist/datasource-zabbix/zabbixCachingProxy.service.js.map index 9eda30f..5edd381 100644 --- a/dist/datasource-zabbix/zabbixCachingProxy.service.js.map +++ b/dist/datasource-zabbix/zabbixCachingProxy.service.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/datasource-zabbix/zabbixCachingProxy.service.js"],"names":["ZabbixCachingProxyFactory","ZabbixCachingProxy","zabbixAPI","cacheOptions","cacheEnabled","enabled","ttl","cache","groups","hosts","applications","items","history","trends","macros","globalMacros","historyPromises","getHistory","callAPIRequestOnce","_","bind","getHistoryRequestHash","groupPromises","getGroupsOnce","getGroups","getRequestHash","hostPromises","getHostsOnce","getHosts","appPromises","getAppsOnce","getApps","itemPromises","getItemsOnce","getItems","macroPromises","getMacrosOnce","getMacros","globalMacroPromises","getGlobalMacrosOnce","getGlobalMacros","cacheObject","object_age","Date","now","timestamp","request","params","hash","isExpired","Promise","resolve","value","then","result","proxyRequest","groupids","hostids","appids","itemtype","promises","all","flatten","time_from","time_till","historyStorage","full_history","expired","filter","keyBy","item","itemid","length","grouped_history","groupBy","forEach","map","func","promiseKeeper","argsHashFunc","arguments","apply","args","requestStamp","arg","undefined","isArray","sort","toString","join","getHash","itemids","stamp","angular","module","factory","String","prototype","i","chr","len","charCodeAt","indexBy"],"mappings":"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","file":"zabbixCachingProxy.service.js","sourcesContent":["import angular from 'angular';\nimport _ from 'lodash';\n\n// Use factory() instead service() for multiple datasources support.\n// Each datasource instance must initialize its own cache.\n\n/** @ngInject */\nfunction ZabbixCachingProxyFactory() {\n\n class ZabbixCachingProxy {\n constructor(zabbixAPI, cacheOptions) {\n this.zabbixAPI = zabbixAPI;\n this.cacheEnabled = cacheOptions.enabled;\n this.ttl = cacheOptions.ttl || 600000; // 10 minutes by default\n\n // Internal objects for data storing\n this.cache = {\n groups: {},\n hosts: {},\n applications: {},\n items: {},\n history: {},\n trends: {},\n macros: {},\n globalMacros: {}\n };\n\n this.historyPromises = {};\n\n // Don't run duplicated history requests\n this.getHistory = callAPIRequestOnce(_.bind(this.zabbixAPI.getHistory, this.zabbixAPI),\n this.historyPromises, getHistoryRequestHash);\n\n // Don't run duplicated requests\n this.groupPromises = {};\n this.getGroupsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getGroups, this.zabbixAPI),\n this.groupPromises, getRequestHash);\n\n this.hostPromises = {};\n this.getHostsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getHosts, this.zabbixAPI),\n this.hostPromises, getRequestHash);\n\n this.appPromises = {};\n this.getAppsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getApps, this.zabbixAPI),\n this.appPromises, getRequestHash);\n\n this.itemPromises = {};\n this.getItemsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getItems, this.zabbixAPI),\n this.itemPromises, getRequestHash);\n\n this.macroPromises = {};\n this.getMacrosOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getMacros, this.zabbixAPI),\n this.macroPromises, getRequestHash);\n\n this.globalMacroPromises = {};\n this.getGlobalMacrosOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getGlobalMacros, this.zabbixAPI),\n this.globalMacroPromises, getRequestHash);\n }\n\n isExpired(cacheObject) {\n if (cacheObject) {\n let object_age = Date.now() - cacheObject.timestamp;\n return !(cacheObject.timestamp && object_age < this.ttl);\n } else {\n return true;\n }\n }\n\n /**\n * Check that result is present in cache and up to date\n * or send request to API.\n */\n proxyRequest(request, params, cacheObject) {\n let hash = getRequestHash(params);\n if (this.cacheEnabled && !this.isExpired(cacheObject[hash])) {\n return Promise.resolve(cacheObject[hash].value);\n } else {\n return request(...params)\n .then(result => {\n cacheObject[hash] = {\n value: result,\n timestamp: Date.now()\n };\n return result;\n });\n }\n }\n\n getGroups() {\n return this.proxyRequest(this.getGroupsOnce, [], this.cache.groups);\n }\n\n getHosts(groupids) {\n return this.proxyRequest(this.getHostsOnce, [groupids], this.cache.hosts);\n }\n\n getApps(hostids) {\n return this.proxyRequest(this.getAppsOnce, [hostids], this.cache.applications);\n }\n\n getItems(hostids, appids, itemtype) {\n let params = [hostids, appids, itemtype];\n return this.proxyRequest(this.getItemsOnce, params, this.cache.items);\n }\n\n getMacros(hostids) {\n // Merge global macros and host macros\n let promises = [\n this.proxyRequest(this.getMacrosOnce, [hostids], this.cache.macros),\n this.proxyRequest(this.getGlobalMacrosOnce, [], this.cache.globalMacros)\n ];\n\n return Promise.all(promises).then(_.flatten);\n }\n\n getHistoryFromCache(items, time_from, time_till) {\n var historyStorage = this.cache.history;\n var full_history;\n var expired = _.filter(_.keyBy(items, 'itemid'), (item, itemid) => {\n return !historyStorage[itemid];\n });\n if (expired.length) {\n return this.zabbixAPI.getHistory(expired, time_from, time_till).then(function(history) {\n var grouped_history = _.groupBy(history, 'itemid');\n _.forEach(expired, item => {\n var itemid = item.itemid;\n historyStorage[itemid] = item;\n historyStorage[itemid].time_from = time_from;\n historyStorage[itemid].time_till = time_till;\n historyStorage[itemid].history = grouped_history[itemid];\n });\n full_history = _.map(items, item => {\n return historyStorage[item.itemid].history;\n });\n return _.flatten(full_history, true);\n });\n } else {\n full_history = _.map(items, function(item) {\n return historyStorage[item.itemid].history;\n });\n return Promise.resolve(_.flatten(full_history, true));\n }\n }\n\n getHistoryFromAPI(items, time_from, time_till) {\n return this.zabbixAPI.getHistory(items, time_from, time_till);\n }\n }\n\n return ZabbixCachingProxy;\n}\n\nangular\n .module('grafana.services')\n .factory('ZabbixCachingProxy', ZabbixCachingProxyFactory);\n\n/**\n * Wrap zabbix API request to prevent multiple calls\n * with same params when waiting for result.\n */\nfunction callAPIRequestOnce(func, promiseKeeper, argsHashFunc) {\n return function() {\n var hash = argsHashFunc(arguments);\n if (!promiseKeeper[hash]) {\n promiseKeeper[hash] = Promise.resolve(\n func.apply(this, arguments)\n .then(result => {\n promiseKeeper[hash] = null;\n return result;\n })\n );\n }\n return promiseKeeper[hash];\n };\n}\n\nfunction getRequestHash(args) {\n var requestStamp = _.map(args, arg => {\n if (arg === undefined) {\n return 'undefined';\n } else {\n if (_.isArray(arg)) {\n return arg.sort().toString();\n } else {\n return arg.toString();\n }\n }\n }).join();\n return requestStamp.getHash();\n}\n\nfunction getHistoryRequestHash(args) {\n let itemids = _.map(args[0], 'itemid');\n let stamp = itemids.join() + args[1] + args[2];\n return stamp.getHash();\n}\n\nString.prototype.getHash = function() {\n var hash = 0, i, chr, len;\n if (this.length !== 0) {\n for (i = 0, len = this.length; i < len; i++) {\n chr = this.charCodeAt(i);\n hash = ((hash << 5) - hash) + chr;\n hash |= 0; // Convert to 32bit integer\n }\n }\n return hash;\n};\n\n// Fix for backward compatibility with lodash 2.4\nif (!_.keyBy) {_.keyBy = _.indexBy;}\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/datasource-zabbix/zabbixCachingProxy.service.js"],"names":["ZabbixCachingProxyFactory","ZabbixCachingProxy","zabbixAPI","zabbixDBConnector","cacheOptions","dbConnector","cacheEnabled","enabled","ttl","cache","groups","hosts","applications","items","history","trends","macros","globalMacros","itServices","historyPromises","getHistory","callAPIRequestOnce","_","bind","getHistoryRequestHash","getHistoryDB","getDBQueryHash","getTrendsDB","getTrends","groupPromises","getGroupsOnce","getGroups","getRequestHash","hostPromises","getHostsOnce","getHosts","appPromises","getAppsOnce","getApps","itemPromises","getItemsOnce","getItems","itemByIdPromises","getItemsByIdOnce","getItemsByIDs","itServicesPromises","getITServicesOnce","getITService","macroPromises","getMacrosOnce","getMacros","globalMacroPromises","getGlobalMacrosOnce","getGlobalMacros","cacheObject","object_age","Date","now","timestamp","request","params","hash","isExpired","Promise","resolve","value","then","result","proxyRequest","groupids","hostids","appids","itemtype","itemids","promises","all","flatten","time_from","time_till","historyStorage","full_history","expired","filter","keyBy","item","itemid","length","grouped_history","groupBy","forEach","map","func","promiseKeeper","argsHashFunc","arguments","apply","args","requestStamp","arg","undefined","isArray","sort","toString","join","getHash","stamp","consolidateBy","intervalMs","angular","module","factory","String","prototype","i","chr","len","charCodeAt","indexBy"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAGA;AACA;;AAEA;AACA,WAASA,yBAAT,GAAqC;AAAA,QAE7BC,kBAF6B;AAGjC,kCAAYC,SAAZ,EAAuBC,iBAAvB,EAA0CC,YAA1C,EAAwD;AAAA;;AACtD,aAAKF,SAAL,GAAiBA,SAAjB;AACA,aAAKG,WAAL,GAAmBF,iBAAnB;AACA,aAAKG,YAAL,GAAoBF,aAAaG,OAAjC;AACA,aAAKC,GAAL,GAAoBJ,aAAaI,GAAb,IAAoB,MAAxC,CAJsD,CAIN;;AAEhD;AACA,aAAKC,KAAL,GAAa;AACXC,kBAAQ,EADG;AAEXC,iBAAO,EAFI;AAGXC,wBAAc,EAHH;AAIXC,iBAAO,EAJI;AAKXC,mBAAS,EALE;AAMXC,kBAAQ,EANG;AAOXC,kBAAQ,EAPG;AAQXC,wBAAc,EARH;AASXC,sBAAY;AATD,SAAb;;AAYA,aAAKC,eAAL,GAAuB,EAAvB;;AAEA;AACA,aAAKC,UAAL,GAAkBC,mBAAmBC,EAAEC,IAAF,CAAO,KAAKrB,SAAL,CAAekB,UAAtB,EAAkC,KAAKlB,SAAvC,CAAnB,EACmB,KAAKiB,eADxB,EACyCK,qBADzC,CAAlB;;AAGA,YAAI,KAAKnB,WAAT,EAAsB;AACpB,eAAKoB,YAAL,GAAoBJ,mBAAmBC,EAAEC,IAAF,CAAO,KAAKlB,WAAL,CAAiBe,UAAxB,EAAoC,KAAKf,WAAzC,CAAnB,EACmB,KAAKc,eADxB,EACyCO,cADzC,CAApB;AAEA,eAAKC,WAAL,GAAmBN,mBAAmBC,EAAEC,IAAF,CAAO,KAAKlB,WAAL,CAAiBuB,SAAxB,EAAmC,KAAKvB,WAAxC,CAAnB,EACmB,KAAKc,eADxB,EACyCO,cADzC,CAAnB;AAED;;AAED;AACA,aAAKG,aAAL,GAAqB,EAArB;AACA,aAAKC,aAAL,GAAqBT,mBAAmBC,EAAEC,IAAF,CAAO,KAAKrB,SAAL,CAAe6B,SAAtB,EAAiC,KAAK7B,SAAtC,CAAnB,EACmB,KAAK2B,aADxB,EACuCG,cADvC,CAArB;;AAGA,aAAKC,YAAL,GAAoB,EAApB;AACA,aAAKC,YAAL,GAAoBb,mBAAmBC,EAAEC,IAAF,CAAO,KAAKrB,SAAL,CAAeiC,QAAtB,EAAgC,KAAKjC,SAArC,CAAnB,EACmB,KAAK+B,YADxB,EACsCD,cADtC,CAApB;;AAGA,aAAKI,WAAL,GAAmB,EAAnB;AACA,aAAKC,WAAL,GAAmBhB,mBAAmBC,EAAEC,IAAF,CAAO,KAAKrB,SAAL,CAAeoC,OAAtB,EAA+B,KAAKpC,SAApC,CAAnB,EACmB,KAAKkC,WADxB,EACqCJ,cADrC,CAAnB;;AAGA,aAAKO,YAAL,GAAoB,EAApB;AACA,aAAKC,YAAL,GAAoBnB,mBAAmBC,EAAEC,IAAF,CAAO,KAAKrB,SAAL,CAAeuC,QAAtB,EAAgC,KAAKvC,SAArC,CAAnB,EACmB,KAAKqC,YADxB,EACsCP,cADtC,CAApB;;AAGA,aAAKU,gBAAL,GAAwB,EAAxB;AACA,aAAKC,gBAAL,GAAwBtB,mBAAmBC,EAAEC,IAAF,CAAO,KAAKrB,SAAL,CAAe0C,aAAtB,EAAqC,KAAK1C,SAA1C,CAAnB,EACmB,KAAKqC,YADxB,EACsCP,cADtC,CAAxB;;AAGA,aAAKa,kBAAL,GAA0B,EAA1B;AACA,aAAKC,iBAAL,GAAyBzB,mBAAmBC,EAAEC,IAAF,CAAO,KAAKrB,SAAL,CAAe6C,YAAtB,EAAoC,KAAK7C,SAAzC,CAAnB,EACmB,KAAK2C,kBADxB,EAC4Cb,cAD5C,CAAzB;;AAGA,aAAKgB,aAAL,GAAqB,EAArB;AACA,aAAKC,aAAL,GAAqB5B,mBAAmBC,EAAEC,IAAF,CAAO,KAAKrB,SAAL,CAAegD,SAAtB,EAAiC,KAAKhD,SAAtC,CAAnB,EACkB,KAAK8C,aADvB,EACsChB,cADtC,CAArB;;AAGA,aAAKmB,mBAAL,GAA2B,EAA3B;AACA,aAAKC,mBAAL,GAA2B/B,mBAAmBC,EAAEC,IAAF,CAAO,KAAKrB,SAAL,CAAemD,eAAtB,EAAuC,KAAKnD,SAA5C,CAAnB,EACmB,KAAKiD,mBADxB,EAC6CnB,cAD7C,CAA3B;AAED;;AAnEgC;AAAA;AAAA,kCAqEvBsB,WArEuB,EAqEV;AACrB,cAAIA,WAAJ,EAAiB;AACf,gBAAIC,aAAaC,KAAKC,GAAL,KAAaH,YAAYI,SAA1C;AACA,mBAAO,EAAEJ,YAAYI,SAAZ,IAAyBH,aAAa,KAAK/C,GAA7C,CAAP;AACD,WAHD,MAGO;AACL,mBAAO,IAAP;AACD;AACF;AA5EgC;AAAA;AAAA,qCAkFpBmD,OAlFoB,EAkFXC,MAlFW,EAkFHN,WAlFG,EAkFU;AACzC,cAAIO,OAAO7B,eAAe4B,MAAf,CAAX;AACA,cAAI,KAAKtD,YAAL,IAAqB,CAAC,KAAKwD,SAAL,CAAeR,YAAYO,IAAZ,CAAf,CAA1B,EAA6D;AAC3D,mBAAOE,QAAQC,OAAR,CAAgBV,YAAYO,IAAZ,EAAkBI,KAAlC,CAAP;AACD,WAFD,MAEO;AACL,mBAAON,4CAAWC,MAAX,GACNM,IADM,CACD,kBAAU;AACdZ,0BAAYO,IAAZ,IAAoB;AAClBI,uBAAOE,MADW;AAElBT,2BAAWF,KAAKC,GAAL;AAFO,eAApB;AAIA,qBAAOU,MAAP;AACD,aAPM,CAAP;AAQD;AACF;AAhGgC;AAAA;AAAA,oCAkGrB;AACV,iBAAO,KAAKC,YAAL,CAAkB,KAAKtC,aAAvB,EAAsC,EAAtC,EAA0C,KAAKrB,KAAL,CAAWC,MAArD,CAAP;AACD;AApGgC;AAAA;AAAA,iCAsGxB2D,QAtGwB,EAsGd;AACjB,iBAAO,KAAKD,YAAL,CAAkB,KAAKlC,YAAvB,EAAqC,CAACmC,QAAD,CAArC,EAAiD,KAAK5D,KAAL,CAAWE,KAA5D,CAAP;AACD;AAxGgC;AAAA;AAAA,gCA0GzB2D,OA1GyB,EA0GhB;AACf,iBAAO,KAAKF,YAAL,CAAkB,KAAK/B,WAAvB,EAAoC,CAACiC,OAAD,CAApC,EAA+C,KAAK7D,KAAL,CAAWG,YAA1D,CAAP;AACD;AA5GgC;AAAA;AAAA,iCA8GxB0D,OA9GwB,EA8GfC,MA9Ge,EA8GPC,QA9GO,EA8GG;AAClC,cAAIZ,SAAS,CAACU,OAAD,EAAUC,MAAV,EAAkBC,QAAlB,CAAb;AACA,iBAAO,KAAKJ,YAAL,CAAkB,KAAK5B,YAAvB,EAAqCoB,MAArC,EAA6C,KAAKnD,KAAL,CAAWI,KAAxD,CAAP;AACD;AAjHgC;AAAA;AAAA,sCAmHnB4D,OAnHmB,EAmHV;AACrB,cAAIb,SAAS,CAACa,OAAD,CAAb;AACA,iBAAO,KAAKL,YAAL,CAAkB,KAAKzB,gBAAvB,EAAyCiB,MAAzC,EAAiD,KAAKnD,KAAL,CAAWI,KAA5D,CAAP;AACD;AAtHgC;AAAA;AAAA,wCAwHjB;AACd,iBAAO,KAAKuD,YAAL,CAAkB,KAAKtB,iBAAvB,EAA0C,EAA1C,EAA8C,KAAKrC,KAAL,CAAWS,UAAzD,CAAP;AACD;AA1HgC;AAAA;AAAA,kCA4HvBoD,OA5HuB,EA4Hd;AACjB;AACA,cAAII,WAAW,CACb,KAAKN,YAAL,CAAkB,KAAKnB,aAAvB,EAAsC,CAACqB,OAAD,CAAtC,EAAiD,KAAK7D,KAAL,CAAWO,MAA5D,CADa,EAEb,KAAKoD,YAAL,CAAkB,KAAKhB,mBAAvB,EAA4C,EAA5C,EAAgD,KAAK3C,KAAL,CAAWQ,YAA3D,CAFa,CAAf;;AAKA,iBAAO8C,QAAQY,GAAR,CAAYD,QAAZ,EAAsBR,IAAtB,CAA2B5C,EAAEsD,OAA7B,CAAP;AACD;AApIgC;AAAA;AAAA,4CAsIb/D,KAtIa,EAsINgE,SAtIM,EAsIKC,SAtIL,EAsIgB;AAC/C,cAAIC,iBAAiB,KAAKtE,KAAL,CAAWK,OAAhC;AACA,cAAIkE,YAAJ;AACA,cAAIC,UAAU3D,EAAE4D,MAAF,CAAS5D,EAAE6D,KAAF,CAAQtE,KAAR,EAAe,QAAf,CAAT,EAAmC,UAACuE,IAAD,EAAOC,MAAP,EAAkB;AACjE,mBAAO,CAACN,eAAeM,MAAf,CAAR;AACD,WAFa,CAAd;AAGA,cAAIJ,QAAQK,MAAZ,EAAoB;AAClB,mBAAO,KAAKpF,SAAL,CAAekB,UAAf,CAA0B6D,OAA1B,EAAmCJ,SAAnC,EAA8CC,SAA9C,EAAyDZ,IAAzD,CAA8D,UAASpD,OAAT,EAAkB;AACrF,kBAAIyE,kBAAkBjE,EAAEkE,OAAF,CAAU1E,OAAV,EAAmB,QAAnB,CAAtB;AACAQ,gBAAEmE,OAAF,CAAUR,OAAV,EAAmB,gBAAQ;AACzB,oBAAII,SAASD,KAAKC,MAAlB;AACAN,+BAAeM,MAAf,IAAyBD,IAAzB;AACAL,+BAAeM,MAAf,EAAuBR,SAAvB,GAAmCA,SAAnC;AACAE,+BAAeM,MAAf,EAAuBP,SAAvB,GAAmCA,SAAnC;AACAC,+BAAeM,MAAf,EAAuBvE,OAAvB,GAAiCyE,gBAAgBF,MAAhB,CAAjC;AACD,eAND;AAOAL,6BAAe1D,EAAEoE,GAAF,CAAM7E,KAAN,EAAa,gBAAQ;AAClC,uBAAOkE,eAAeK,KAAKC,MAApB,EAA4BvE,OAAnC;AACD,eAFc,CAAf;AAGA,qBAAOQ,EAAEsD,OAAF,CAAUI,YAAV,EAAwB,IAAxB,CAAP;AACD,aAbM,CAAP;AAcD,WAfD,MAeO;AACLA,2BAAe1D,EAAEoE,GAAF,CAAM7E,KAAN,EAAa,UAASuE,IAAT,EAAe;AACzC,qBAAOL,eAAeK,KAAKC,MAApB,EAA4BvE,OAAnC;AACD,aAFc,CAAf;AAGA,mBAAOiD,QAAQC,OAAR,CAAgB1C,EAAEsD,OAAF,CAAUI,YAAV,EAAwB,IAAxB,CAAhB,CAAP;AACD;AACF;AAjKgC;AAAA;AAAA,0CAmKfnE,KAnKe,EAmKRgE,SAnKQ,EAmKGC,SAnKH,EAmKc;AAC7C,iBAAO,KAAK5E,SAAL,CAAekB,UAAf,CAA0BP,KAA1B,EAAiCgE,SAAjC,EAA4CC,SAA5C,CAAP;AACD;AArKgC;;AAAA;AAAA;;AAwKnC,WAAO7E,kBAAP;AACD;;AAMD;;;;AAIA,WAASoB,kBAAT,CAA4BsE,IAA5B,EAAkCC,aAAlC,EAAiDC,YAAjD,EAA+D;AAC7D,WAAO,YAAW;AAChB,UAAIhC,OAAOgC,aAAaC,SAAb,CAAX;AACA,UAAI,CAACF,cAAc/B,IAAd,CAAL,EAA0B;AACxB+B,sBAAc/B,IAAd,IAAsBE,QAAQC,OAAR,CACpB2B,KAAKI,KAAL,CAAW,IAAX,EAAiBD,SAAjB,EACC5B,IADD,CACM,kBAAU;AACd0B,wBAAc/B,IAAd,IAAsB,IAAtB;AACA,iBAAOM,MAAP;AACD,SAJD,CADoB,CAAtB;AAOD;AACD,aAAOyB,cAAc/B,IAAd,CAAP;AACD,KAZD;AAaD;;AAED,WAAS7B,cAAT,CAAwBgE,IAAxB,EAA8B;AAC5B,QAAIC,eAAe3E,EAAEoE,GAAF,CAAMM,IAAN,EAAY,eAAO;AACpC,UAAIE,QAAQC,SAAZ,EAAuB;AACrB,eAAO,WAAP;AACD,OAFD,MAEO;AACL,YAAI7E,EAAE8E,OAAF,CAAUF,GAAV,CAAJ,EAAoB;AAClB,iBAAOA,IAAIG,IAAJ,GAAWC,QAAX,EAAP;AACD,SAFD,MAEO;AACL,iBAAOJ,IAAII,QAAJ,EAAP;AACD;AACF;AACF,KAVkB,EAUhBC,IAVgB,EAAnB;AAWA,WAAON,aAAaO,OAAb,EAAP;AACD;;AAED,WAAShF,qBAAT,CAA+BwE,IAA/B,EAAqC;AACnC,QAAIvB,UAAUnD,EAAEoE,GAAF,CAAMM,KAAK,CAAL,CAAN,EAAe,QAAf,CAAd;AACA,QAAIS,QAAQhC,QAAQ8B,IAAR,KAAiBP,KAAK,CAAL,CAAjB,GAA2BA,KAAK,CAAL,CAAvC;AACA,WAAOS,MAAMD,OAAN,EAAP;AACD;;AAED,WAAS9E,cAAT,CAAwBsE,IAAxB,EAA8B;AAC5B,QAAIvB,UAAUnD,EAAEoE,GAAF,CAAMM,KAAK,CAAL,CAAN,EAAe,QAAf,CAAd;AACA,QAAIU,gBAAgBV,KAAK,CAAL,EAAQU,aAA5B;AACA,QAAIC,aAAaX,KAAK,CAAL,EAAQW,UAAzB;AACA,QAAIF,QAAQhC,QAAQ8B,IAAR,KAAiBP,KAAK,CAAL,CAAjB,GAA2BA,KAAK,CAAL,CAA3B,GAAqCU,aAArC,GAAqDC,UAAjE;AACA,WAAOF,MAAMD,OAAN,EAAP;AACD;;;;AArOMI,a;;AACAtF,O;;;;;;;;;;;;;;;;;;;;;AAiLPsF,cACGC,MADH,CACU,kBADV,EAEGC,OAFH,CAEW,oBAFX,EAEiC9G,yBAFjC,EAqDA+G,OAAOC,SAAP,CAAiBR,OAAjB,GAA2B,YAAW;AACpC,YAAI3C,OAAO,CAAX;AAAA,YAAcoD,CAAd;AAAA,YAAiBC,GAAjB;AAAA,YAAsBC,GAAtB;AACA,YAAI,KAAK7B,MAAL,KAAgB,CAApB,EAAuB;AACrB,eAAK2B,IAAI,CAAJ,EAAOE,MAAM,KAAK7B,MAAvB,EAA+B2B,IAAIE,GAAnC,EAAwCF,GAAxC,EAA6C;AAC3CC,kBAAQ,KAAKE,UAAL,CAAgBH,CAAhB,CAAR;AACApD,mBAAS,CAACA,QAAQ,CAAT,IAAcA,IAAf,GAAuBqD,GAA/B;AACArD,oBAAQ,CAAR,CAH2C,CAGhC;AACZ;AACF;AACD,eAAOA,IAAP;AACD,OAVD;;AAYA;AACA,UAAI,CAACvC,EAAE6D,KAAP,EAAc;AAAC7D,UAAE6D,KAAF,GAAU7D,EAAE+F,OAAZ;AAAqB","file":"zabbixCachingProxy.service.js","sourcesContent":["import angular from 'angular';\nimport _ from 'lodash';\n\n// Use factory() instead service() for multiple datasources support.\n// Each datasource instance must initialize its own cache.\n\n/** @ngInject */\nfunction ZabbixCachingProxyFactory() {\n\n class ZabbixCachingProxy {\n constructor(zabbixAPI, zabbixDBConnector, cacheOptions) {\n this.zabbixAPI = zabbixAPI;\n this.dbConnector = zabbixDBConnector;\n this.cacheEnabled = cacheOptions.enabled;\n this.ttl = cacheOptions.ttl || 600000; // 10 minutes by default\n\n // Internal objects for data storing\n this.cache = {\n groups: {},\n hosts: {},\n applications: {},\n items: {},\n history: {},\n trends: {},\n macros: {},\n globalMacros: {},\n itServices: {}\n };\n\n this.historyPromises = {};\n\n // Don't run duplicated history requests\n this.getHistory = callAPIRequestOnce(_.bind(this.zabbixAPI.getHistory, this.zabbixAPI),\n this.historyPromises, getHistoryRequestHash);\n\n if (this.dbConnector) {\n this.getHistoryDB = callAPIRequestOnce(_.bind(this.dbConnector.getHistory, this.dbConnector),\n this.historyPromises, getDBQueryHash);\n this.getTrendsDB = callAPIRequestOnce(_.bind(this.dbConnector.getTrends, this.dbConnector),\n this.historyPromises, getDBQueryHash);\n }\n\n // Don't run duplicated requests\n this.groupPromises = {};\n this.getGroupsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getGroups, this.zabbixAPI),\n this.groupPromises, getRequestHash);\n\n this.hostPromises = {};\n this.getHostsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getHosts, this.zabbixAPI),\n this.hostPromises, getRequestHash);\n\n this.appPromises = {};\n this.getAppsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getApps, this.zabbixAPI),\n this.appPromises, getRequestHash);\n\n this.itemPromises = {};\n this.getItemsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getItems, this.zabbixAPI),\n this.itemPromises, getRequestHash);\n\n this.itemByIdPromises = {};\n this.getItemsByIdOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getItemsByIDs, this.zabbixAPI),\n this.itemPromises, getRequestHash);\n\n this.itServicesPromises = {};\n this.getITServicesOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getITService, this.zabbixAPI),\n this.itServicesPromises, getRequestHash);\n\n this.macroPromises = {};\n this.getMacrosOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getMacros, this.zabbixAPI),\n this.macroPromises, getRequestHash);\n\n this.globalMacroPromises = {};\n this.getGlobalMacrosOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getGlobalMacros, this.zabbixAPI),\n this.globalMacroPromises, getRequestHash);\n }\n\n isExpired(cacheObject) {\n if (cacheObject) {\n let object_age = Date.now() - cacheObject.timestamp;\n return !(cacheObject.timestamp && object_age < this.ttl);\n } else {\n return true;\n }\n }\n\n /**\n * Check that result is present in cache and up to date\n * or send request to API.\n */\n proxyRequest(request, params, cacheObject) {\n let hash = getRequestHash(params);\n if (this.cacheEnabled && !this.isExpired(cacheObject[hash])) {\n return Promise.resolve(cacheObject[hash].value);\n } else {\n return request(...params)\n .then(result => {\n cacheObject[hash] = {\n value: result,\n timestamp: Date.now()\n };\n return result;\n });\n }\n }\n\n getGroups() {\n return this.proxyRequest(this.getGroupsOnce, [], this.cache.groups);\n }\n\n getHosts(groupids) {\n return this.proxyRequest(this.getHostsOnce, [groupids], this.cache.hosts);\n }\n\n getApps(hostids) {\n return this.proxyRequest(this.getAppsOnce, [hostids], this.cache.applications);\n }\n\n getItems(hostids, appids, itemtype) {\n let params = [hostids, appids, itemtype];\n return this.proxyRequest(this.getItemsOnce, params, this.cache.items);\n }\n\n getItemsByIDs(itemids) {\n let params = [itemids];\n return this.proxyRequest(this.getItemsByIdOnce, params, this.cache.items);\n }\n\n getITServices() {\n return this.proxyRequest(this.getITServicesOnce, [], this.cache.itServices);\n }\n\n getMacros(hostids) {\n // Merge global macros and host macros\n let promises = [\n this.proxyRequest(this.getMacrosOnce, [hostids], this.cache.macros),\n this.proxyRequest(this.getGlobalMacrosOnce, [], this.cache.globalMacros)\n ];\n\n return Promise.all(promises).then(_.flatten);\n }\n\n getHistoryFromCache(items, time_from, time_till) {\n var historyStorage = this.cache.history;\n var full_history;\n var expired = _.filter(_.keyBy(items, 'itemid'), (item, itemid) => {\n return !historyStorage[itemid];\n });\n if (expired.length) {\n return this.zabbixAPI.getHistory(expired, time_from, time_till).then(function(history) {\n var grouped_history = _.groupBy(history, 'itemid');\n _.forEach(expired, item => {\n var itemid = item.itemid;\n historyStorage[itemid] = item;\n historyStorage[itemid].time_from = time_from;\n historyStorage[itemid].time_till = time_till;\n historyStorage[itemid].history = grouped_history[itemid];\n });\n full_history = _.map(items, item => {\n return historyStorage[item.itemid].history;\n });\n return _.flatten(full_history, true);\n });\n } else {\n full_history = _.map(items, function(item) {\n return historyStorage[item.itemid].history;\n });\n return Promise.resolve(_.flatten(full_history, true));\n }\n }\n\n getHistoryFromAPI(items, time_from, time_till) {\n return this.zabbixAPI.getHistory(items, time_from, time_till);\n }\n }\n\n return ZabbixCachingProxy;\n}\n\nangular\n .module('grafana.services')\n .factory('ZabbixCachingProxy', ZabbixCachingProxyFactory);\n\n/**\n * Wrap zabbix API request to prevent multiple calls\n * with same params when waiting for result.\n */\nfunction callAPIRequestOnce(func, promiseKeeper, argsHashFunc) {\n return function() {\n var hash = argsHashFunc(arguments);\n if (!promiseKeeper[hash]) {\n promiseKeeper[hash] = Promise.resolve(\n func.apply(this, arguments)\n .then(result => {\n promiseKeeper[hash] = null;\n return result;\n })\n );\n }\n return promiseKeeper[hash];\n };\n}\n\nfunction getRequestHash(args) {\n var requestStamp = _.map(args, arg => {\n if (arg === undefined) {\n return 'undefined';\n } else {\n if (_.isArray(arg)) {\n return arg.sort().toString();\n } else {\n return arg.toString();\n }\n }\n }).join();\n return requestStamp.getHash();\n}\n\nfunction getHistoryRequestHash(args) {\n let itemids = _.map(args[0], 'itemid');\n let stamp = itemids.join() + args[1] + args[2];\n return stamp.getHash();\n}\n\nfunction getDBQueryHash(args) {\n let itemids = _.map(args[0], 'itemid');\n let consolidateBy = args[3].consolidateBy;\n let intervalMs = args[3].intervalMs;\n let stamp = itemids.join() + args[1] + args[2] + consolidateBy + intervalMs;\n return stamp.getHash();\n}\n\nString.prototype.getHash = function() {\n var hash = 0, i, chr, len;\n if (this.length !== 0) {\n for (i = 0, len = this.length; i < len; i++) {\n chr = this.charCodeAt(i);\n hash = ((hash << 5) - hash) + chr;\n hash |= 0; // Convert to 32bit integer\n }\n }\n return hash;\n};\n\n// Fix for backward compatibility with lodash 2.4\nif (!_.keyBy) {_.keyBy = _.indexBy;}\n"]} \ No newline at end of file diff --git a/dist/datasource-zabbix/zabbixDBConnector.js b/dist/datasource-zabbix/zabbixDBConnector.js new file mode 100644 index 0000000..1d46ef7 --- /dev/null +++ b/dist/datasource-zabbix/zabbixDBConnector.js @@ -0,0 +1,233 @@ +'use strict'; + +System.register(['angular', 'lodash'], function (_export, _context) { + "use strict"; + + var angular, _, _createClass, DEFAULT_QUERY_LIMIT, HISTORY_TO_TABLE_MAP, TREND_TO_TABLE_MAP, consolidateByFunc, consolidateByTrendColumns; + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + /** @ngInject */ + function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) { + var ZabbixDBConnector = function () { + function ZabbixDBConnector(sqlDataSourceId) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + _classCallCheck(this, ZabbixDBConnector); + + var limit = options.limit; + + + this.sqlDataSourceId = sqlDataSourceId; + this.limit = limit || DEFAULT_QUERY_LIMIT; + } + + /** + * Try to load DS with given id to check it's exist. + * @param {*} datasourceId ID of SQL data source + */ + + + _createClass(ZabbixDBConnector, [{ + key: 'loadSQLDataSource', + value: function loadSQLDataSource(datasourceId) { + var ds = _.find(datasourceSrv.getAll(), { 'id': datasourceId }); + if (ds) { + return datasourceSrv.loadDatasource(ds.name).then(function (ds) { + console.log('SQL data source loaded', ds); + }); + } else { + return Promise.reject('SQL Data Source with ID ' + datasourceId + ' not found'); + } + } + }, { + key: 'testSQLDataSource', + value: function testSQLDataSource() { + var testQuery = 'SELECT itemid AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1'; + return this.invokeSQLQuery(testQuery); + } + }, { + key: 'getHistory', + value: function getHistory(items, timeFrom, timeTill, options) { + var _this = this; + + var intervalMs = options.intervalMs, + consolidateBy = options.consolidateBy; + + var intervalSec = Math.ceil(intervalMs / 1000); + + consolidateBy = consolidateBy || 'avg'; + var aggFunction = consolidateByFunc[consolidateBy]; + + // Group items by value type and perform request for each value type + var grouped_items = _.groupBy(items, 'value_type'); + var promises = _.map(grouped_items, function (items, value_type) { + var itemids = _.map(items, 'itemid').join(', '); + var table = HISTORY_TO_TABLE_MAP[value_type]; + + var query = '\n SELECT itemid AS metric, clock AS time_sec, ' + aggFunction + '(value) AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY time_sec DIV ' + intervalSec + ', metric\n '; + + query = compactSQLQuery(query); + return _this.invokeSQLQuery(query); + }); + + return Promise.all(promises).then(function (results) { + return _.flatten(results); + }); + } + }, { + key: 'getTrends', + value: function getTrends(items, timeFrom, timeTill, options) { + var _this2 = this; + + var intervalMs = options.intervalMs, + consolidateBy = options.consolidateBy; + + var intervalSec = Math.ceil(intervalMs / 1000); + + consolidateBy = consolidateBy || 'avg'; + var aggFunction = consolidateByFunc[consolidateBy]; + + // Group items by value type and perform request for each value type + var grouped_items = _.groupBy(items, 'value_type'); + var promises = _.map(grouped_items, function (items, value_type) { + var itemids = _.map(items, 'itemid').join(', '); + var table = TREND_TO_TABLE_MAP[value_type]; + var valueColumn = _.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg'; + valueColumn = consolidateByTrendColumns[valueColumn]; + + var query = '\n SELECT itemid AS metric, clock AS time_sec, ' + aggFunction + '(' + valueColumn + ') AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY time_sec DIV ' + intervalSec + ', metric\n '; + + query = compactSQLQuery(query); + return _this2.invokeSQLQuery(query); + }); + + return Promise.all(promises).then(function (results) { + return _.flatten(results); + }); + } + }, { + key: 'handleGrafanaTSResponse', + value: function handleGrafanaTSResponse(history, items) { + var addHostName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; + + return convertGrafanaTSResponse(history, items, addHostName); + } + }, { + key: 'invokeSQLQuery', + value: function invokeSQLQuery(query) { + var queryDef = { + refId: 'A', + format: 'time_series', + datasourceId: this.sqlDataSourceId, + rawSql: query, + maxDataPoints: this.limit + }; + + return backendSrv.datasourceRequest({ + url: '/api/tsdb/query', + method: 'POST', + data: { + queries: [queryDef] + } + }).then(function (response) { + var results = response.data.results; + if (results['A']) { + return results['A'].series; + } else { + return null; + } + }); + } + }]); + + return ZabbixDBConnector; + }(); + + return ZabbixDBConnector; + } + + /////////////////////////////////////////////////////////////////////////////// + + function convertGrafanaTSResponse(time_series, items, addHostName) { + var hosts = _.uniqBy(_.flatten(_.map(items, 'hosts')), 'hostid'); //uniqBy is needed to deduplicate + var grafanaSeries = _.map(time_series, function (series) { + var itemid = series.name; + var datapoints = series.points; + var item = _.find(items, { 'itemid': itemid }); + var alias = item.name; + if (_.keys(hosts).length > 1 && addHostName) { + //only when actual multi hosts selected + var host = _.find(hosts, { 'hostid': item.hostid }); + alias = host.name + ": " + alias; + } + return { + target: alias, + datapoints: datapoints + }; + }); + + return _.sortBy(grafanaSeries, 'target'); + } + + function compactSQLQuery(query) { + return query.replace(/\s+/g, ' '); + } + return { + setters: [function (_angular) { + angular = _angular.default; + }, function (_lodash) { + _ = _lodash.default; + }], + execute: function () { + _createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + DEFAULT_QUERY_LIMIT = 10000; + HISTORY_TO_TABLE_MAP = { + '0': 'history', + '1': 'history_str', + '2': 'history_log', + '3': 'history_uint', + '4': 'history_text' + }; + TREND_TO_TABLE_MAP = { + '0': 'trends', + '3': 'trends_uint' + }; + consolidateByFunc = { + 'avg': 'AVG', + 'min': 'MIN', + 'max': 'MAX', + 'sum': 'SUM', + 'count': 'COUNT' + }; + consolidateByTrendColumns = { + 'avg': 'value_avg', + 'min': 'value_min', + 'max': 'value_max' + }; + angular.module('grafana.services').factory('ZabbixDBConnector', ZabbixDBConnectorFactory); + } + }; +}); +//# sourceMappingURL=zabbixDBConnector.js.map diff --git a/dist/datasource-zabbix/zabbixDBConnector.js.map b/dist/datasource-zabbix/zabbixDBConnector.js.map new file mode 100644 index 0000000..66e923b --- /dev/null +++ b/dist/datasource-zabbix/zabbixDBConnector.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/datasource-zabbix/zabbixDBConnector.js"],"names":["ZabbixDBConnectorFactory","datasourceSrv","backendSrv","ZabbixDBConnector","sqlDataSourceId","options","limit","DEFAULT_QUERY_LIMIT","datasourceId","ds","_","find","getAll","loadDatasource","name","then","console","log","Promise","reject","testQuery","invokeSQLQuery","items","timeFrom","timeTill","intervalMs","consolidateBy","intervalSec","Math","ceil","aggFunction","consolidateByFunc","grouped_items","groupBy","promises","map","value_type","itemids","join","table","HISTORY_TO_TABLE_MAP","query","compactSQLQuery","all","flatten","results","TREND_TO_TABLE_MAP","valueColumn","includes","consolidateByTrendColumns","history","addHostName","convertGrafanaTSResponse","queryDef","refId","format","rawSql","maxDataPoints","datasourceRequest","url","method","data","queries","response","series","time_series","hosts","uniqBy","grafanaSeries","itemid","datapoints","points","item","alias","keys","length","host","hostid","target","sortBy","replace","angular","module","factory"],"mappings":"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","file":"zabbixDBConnector.js","sourcesContent":["import angular from 'angular';\nimport _ from 'lodash';\n\nconst DEFAULT_QUERY_LIMIT = 10000;\nconst HISTORY_TO_TABLE_MAP = {\n '0': 'history',\n '1': 'history_str',\n '2': 'history_log',\n '3': 'history_uint',\n '4': 'history_text'\n};\n\nconst TREND_TO_TABLE_MAP = {\n '0': 'trends',\n '3': 'trends_uint'\n};\n\nconst consolidateByFunc = {\n 'avg': 'AVG',\n 'min': 'MIN',\n 'max': 'MAX',\n 'sum': 'SUM',\n 'count': 'COUNT'\n};\n\nconst consolidateByTrendColumns = {\n 'avg': 'value_avg',\n 'min': 'value_min',\n 'max': 'value_max'\n};\n\n/** @ngInject */\nfunction ZabbixDBConnectorFactory(datasourceSrv, backendSrv) {\n\n class ZabbixDBConnector {\n\n constructor(sqlDataSourceId, options = {}) {\n let {limit} = options;\n\n this.sqlDataSourceId = sqlDataSourceId;\n this.limit = limit || DEFAULT_QUERY_LIMIT;\n }\n\n /**\n * Try to load DS with given id to check it's exist.\n * @param {*} datasourceId ID of SQL data source\n */\n loadSQLDataSource(datasourceId) {\n let ds = _.find(datasourceSrv.getAll(), {'id': datasourceId});\n if (ds) {\n return datasourceSrv.loadDatasource(ds.name)\n .then(ds => {\n console.log('SQL data source loaded', ds);\n });\n } else {\n return Promise.reject(`SQL Data Source with ID ${datasourceId} not found`);\n }\n }\n\n /**\n * Try to invoke test query for one of Zabbix database tables.\n */\n testSQLDataSource() {\n let testQuery = `SELECT itemid AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1`;\n return this.invokeSQLQuery(testQuery);\n }\n\n getHistory(items, timeFrom, timeTill, options) {\n let {intervalMs, consolidateBy} = options;\n let intervalSec = Math.ceil(intervalMs / 1000);\n\n consolidateBy = consolidateBy || 'avg';\n let aggFunction = consolidateByFunc[consolidateBy];\n\n // Group items by value type and perform request for each value type\n let grouped_items = _.groupBy(items, 'value_type');\n let promises = _.map(grouped_items, (items, value_type) => {\n let itemids = _.map(items, 'itemid').join(', ');\n let table = HISTORY_TO_TABLE_MAP[value_type];\n\n let query = `\n SELECT itemid AS metric, clock AS time_sec, ${aggFunction}(value) AS value\n FROM ${table}\n WHERE itemid IN (${itemids})\n AND clock > ${timeFrom} AND clock < ${timeTill}\n GROUP BY time_sec DIV ${intervalSec}, metric\n `;\n\n query = compactSQLQuery(query);\n return this.invokeSQLQuery(query);\n });\n\n return Promise.all(promises).then(results => {\n return _.flatten(results);\n });\n }\n\n getTrends(items, timeFrom, timeTill, options) {\n let {intervalMs, consolidateBy} = options;\n let intervalSec = Math.ceil(intervalMs / 1000);\n\n consolidateBy = consolidateBy || 'avg';\n let aggFunction = consolidateByFunc[consolidateBy];\n\n // Group items by value type and perform request for each value type\n let grouped_items = _.groupBy(items, 'value_type');\n let promises = _.map(grouped_items, (items, value_type) => {\n let itemids = _.map(items, 'itemid').join(', ');\n let table = TREND_TO_TABLE_MAP[value_type];\n let valueColumn = _.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg';\n valueColumn = consolidateByTrendColumns[valueColumn];\n\n let query = `\n SELECT itemid AS metric, clock AS time_sec, ${aggFunction}(${valueColumn}) AS value\n FROM ${table}\n WHERE itemid IN (${itemids})\n AND clock > ${timeFrom} AND clock < ${timeTill}\n GROUP BY time_sec DIV ${intervalSec}, metric\n `;\n\n query = compactSQLQuery(query);\n return this.invokeSQLQuery(query);\n });\n\n return Promise.all(promises).then(results => {\n return _.flatten(results);\n });\n }\n\n handleGrafanaTSResponse(history, items, addHostName = true) {\n return convertGrafanaTSResponse(history, items, addHostName);\n }\n\n invokeSQLQuery(query) {\n let queryDef = {\n refId: 'A',\n format: 'time_series',\n datasourceId: this.sqlDataSourceId,\n rawSql: query,\n maxDataPoints: this.limit\n };\n\n return backendSrv.datasourceRequest({\n url: '/api/tsdb/query',\n method: 'POST',\n data: {\n queries: [queryDef],\n }\n })\n .then(response => {\n let results = response.data.results;\n if (results['A']) {\n return results['A'].series;\n } else {\n return null;\n }\n });\n }\n }\n\n return ZabbixDBConnector;\n}\n\nangular\n .module('grafana.services')\n .factory('ZabbixDBConnector', ZabbixDBConnectorFactory);\n\n///////////////////////////////////////////////////////////////////////////////\n\nfunction convertGrafanaTSResponse(time_series, items, addHostName) {\n var hosts = _.uniqBy(_.flatten(_.map(items, 'hosts')), 'hostid'); //uniqBy is needed to deduplicate\n let grafanaSeries = _.map(time_series, series => {\n let itemid = series.name;\n let datapoints = series.points;\n var item = _.find(items, {'itemid': itemid});\n var alias = item.name;\n if (_.keys(hosts).length > 1 && addHostName) { //only when actual multi hosts selected\n var host = _.find(hosts, {'hostid': item.hostid});\n alias = host.name + \": \" + alias;\n }\n return {\n target: alias,\n datapoints: datapoints\n };\n });\n\n return _.sortBy(grafanaSeries, 'target');\n}\n\nfunction compactSQLQuery(query) {\n return query.replace(/\\s+/g, ' ');\n}\n"]} \ No newline at end of file diff --git a/dist/panel-triggers/editor.html b/dist/panel-triggers/editor.html index aa60aea..af58a83 100644 --- a/dist/panel-triggers/editor.html +++ b/dist/panel-triggers/editor.html @@ -55,6 +55,10 @@ placeholder="trigger name" class="gf-form-input" ng-style="editor.panel.triggers.trigger.style" + ng-class="{ + 'zbx-variable': editor.isVariable(editor.panel.triggers.trigger.filter), + 'zbx-regex': editor.isRegex(editor.panel.triggers.trigger.filter) + }" empty-to-null>
diff --git a/dist/panel-triggers/module.js b/dist/panel-triggers/module.js index bf5d433..781e711 100644 --- a/dist/panel-triggers/module.js +++ b/dist/panel-triggers/module.js @@ -206,6 +206,7 @@ System.register(['lodash', 'jquery', 'moment', 'app/plugins/sdk', '../datasource return this.datasourceSrv.get(this.panel.datasource).then(function (datasource) { var zabbix = datasource.zabbix; _this3.zabbix = zabbix; + _this3.datasource = datasource; var showEvents = _this3.panel.showEvents.value; var triggerFilter = _this3.panel.triggers; var hideHostsInMaintenance = _this3.panel.hideHostsInMaintenance; @@ -219,10 +220,10 @@ System.register(['lodash', 'jquery', 'moment', 'app/plugins/sdk', '../datasource showTriggers: showEvents, hideHostsInMaintenance: hideHostsInMaintenance }; - var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, triggersOptions); - return getTriggers.then(function (triggers) { - return _.map(triggers, _this3.formatTrigger.bind(_this3)); - }); + + return zabbix.getTriggers(groupFilter, hostFilter, appFilter, triggersOptions); + }).then(function (triggers) { + return _.map(triggers, _this3.formatTrigger.bind(_this3)); }); } }, { @@ -272,6 +273,7 @@ System.register(['lodash', 'jquery', 'moment', 'app/plugins/sdk', '../datasource // Filter triggers by description var triggerFilter = this.panel.triggers.trigger.filter; + triggerFilter = this.datasource.replaceTemplateVars(triggerFilter); if (triggerFilter) { triggerList = _filterTriggers(triggerList, triggerFilter); } diff --git a/dist/panel-triggers/module.js.map b/dist/panel-triggers/module.js.map index 9c568ee..baf236d 100644 --- a/dist/panel-triggers/module.js.map +++ b/dist/panel-triggers/module.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/panel-triggers/module.js"],"names":["filterTriggers","triggers","triggerFilter","utils","isRegex","_","filter","trigger","buildRegex","test","description","$","moment","loadPluginCss","PanelCtrl","triggerPanelEditor","dark","light","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","hideHostsInMaintenance","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","scroll","pageSize","fontSize","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","dashboardSrv","pageIndex","triggerList","currentTriggersPage","defaults","panel","cloneDeep","events","on","onInitEditMode","bind","onRefresh","addEditorTab","otherPanelInFullscreenMode","error","loading","refreshData","then","slice","getCurrentTriggersPage","render","getTriggers","getAcknowledges","get","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","triggersOptions","map","formatTrigger","eventids","lastEvent","eventid","each","event","find","acknowledges","timestamp","unix","ack","clock","customLastChangeFormat","time","format","lastChangeFormat","user","alias","name","surname","markAckEvents","length","sortBy","reverse","triggerObj","lastchangeUnix","Number","lastchange","age","fromNow","hosts","hostTechName","showComment","message","grafana_user","ack_message","zabbixAPI","acknowledgeEvent","startPos","endPos","Math","min","scope","elem","attrs","ctrl","data","pageCount","getTableHeight","panelHeight","height","switchPage","e","el","currentTarget","parseInt","$apply","renderPanel","appendPaginationControls","footerElem","empty","ceil","startPage","max","endPage","paginationList","i","activeClass","pageLinkElem","append","panelElem","parents","rootElem","css","addClass","unbindDestroy","$on","off","renderData","renderingCompleted","templateUrl"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2WA,WAASA,eAAT,CAAwBC,QAAxB,EAAkCC,aAAlC,EAAiD;AAC/C,QAAIC,MAAMC,OAAN,CAAcF,aAAd,CAAJ,EAAkC;AAChC,aAAOG,EAAEC,MAAF,CAASL,QAAT,EAAmB,UAASM,OAAT,EAAkB;AAC1C,eAAOJ,MAAMK,UAAN,CAAiBN,aAAjB,EAAgCO,IAAhC,CAAqCF,QAAQG,WAA7C,CAAP;AACD,OAFM,CAAP;AAGD,KAJD,MAIO;AACL,aAAOL,EAAEC,MAAF,CAASL,QAAT,EAAmB,UAASM,OAAT,EAAkB;AAC1C,eAAOA,QAAQG,WAAR,KAAwBR,aAA/B;AACD,OAFM,CAAP;AAGD;AACF;;;;AAxWMG,O;;AACAM,O;;AACAC,Y;;AACCC,mB,kBAAAA,a;AAEAC,e,kBAAAA,S;;AADIX,W;;AAEJY,wB,WAAAA,kB;;;;;;;;;;;;;;;;;;;;;AAnBR;;;;;;;;;;;;;AAsBAF,oBAAc;AACZG,cAAM,gEADM;AAEZC,eAAO;AAFK,OAAd;;AAKIC,qB,GAAkB,CACpB,EAAEC,UAAU,CAAZ,EAAeC,UAAU,gBAAzB,EAA4CC,OAAO,SAAnD,EAA8DC,MAAM,IAApE,EADoB,EAEpB,EAAEH,UAAU,CAAZ,EAAeC,UAAU,aAAzB,EAA4CC,OAAO,SAAnD,EAA8DC,MAAM,IAApE,EAFoB,EAGpB,EAAEH,UAAU,CAAZ,EAAeC,UAAU,SAAzB,EAA4CC,OAAO,SAAnD,EAA8DC,MAAM,IAApE,EAHoB,EAIpB,EAAEH,UAAU,CAAZ,EAAeC,UAAU,SAAzB,EAA4CC,OAAO,SAAnD,EAA8DC,MAAM,IAApE,EAJoB,EAKpB,EAAEH,UAAU,CAAZ,EAAeC,UAAU,MAAzB,EAA4CC,OAAO,SAAnD,EAA8DC,MAAM,IAApE,EALoB,EAMpB,EAAEH,UAAU,CAAZ,EAAeC,UAAU,UAAzB,EAA4CC,OAAO,SAAnD,EAA8DC,MAAM,IAApE,EANoB,C;AASlBC,mB,GAAgB;AAClBC,oBAAY,IADM;AAElBvB,kBAAU;AACRwB,iBAAO,EAACnB,QAAQ,EAAT,EADC;AAERoB,gBAAM,EAACpB,QAAQ,EAAT,EAFE;AAGRqB,uBAAa,EAACrB,QAAQ,EAAT,EAHL;AAIRC,mBAAS,EAACD,QAAQ,EAAT;AAJD,SAFQ;AAQlBsB,mBAAW,IARO;AASlBC,qBAAa,KATK;AAUlBC,uBAAe,KAVG;AAWlBC,yBAAiB,IAXC;AAYlBC,kBAAU,IAZQ;AAalBC,mBAAW,IAbO;AAclBC,eAAO,EAdW;AAelBC,sBAAc,cAfI;AAgBlBC,gCAAwB,KAhBN;AAiBlBC,wBAAgB,EAAEC,MAAM,aAAR,EAAuBC,OAAO,YAA9B,EAjBE;AAkBlBC,oBAAY,EAAEF,MAAM,UAAR,EAAoBC,OAAO,GAA3B,EAlBM;AAmBlBE,yBAAiBvB,eAnBC;AAoBlBwB,sBAAc,yBApBI;AAqBlBC,uBAAe,kBArBG;AAsBlBC,gBAAQ,IAtBU;AAuBlBC,kBAAU,EAvBQ;AAwBlBC,kBAAU;AAxBQ,O;AA2BhBC,sB,GAAmB;AACrB,aAAK,IADgB;AAErB,aAAK;AAFgB,O;AAKnBC,uB,GAAoB,sB;;uDAElBC,gB;;;AAEJ;AACA,kCAAYC,MAAZ,EAAoBC,SAApB,EAA+BC,QAA/B,EAAyCC,aAAzC,EAAwDC,WAAxD,EAAqEC,UAArE,EAAiFC,YAAjF,EAA+F;AAAA;;AAAA,0IACvFN,MADuF,EAC/EC,SAD+E;;AAE7F,gBAAKE,aAAL,GAAqBA,aAArB;AACA,gBAAKC,WAAL,GAAmBA,WAAnB;AACA,gBAAKC,UAAL,GAAkBA,UAAlB;AACA,gBAAKC,YAAL,GAAoBA,YAApB;;AAEA,gBAAKT,gBAAL,GAAwBA,gBAAxB;AACA,gBAAKC,iBAAL,GAAyBA,iBAAzB;AACA,gBAAKS,SAAL,GAAiB,CAAjB;AACA,gBAAKC,WAAL,GAAmB,EAAnB;AACA,gBAAKC,mBAAL,GAA2B,EAA3B;;AAEA;AACA;AACA;AACAtD,YAAEuD,QAAF,CAAW,MAAKC,KAAhB,EAAuBxD,EAAEyD,SAAF,CAAYvC,aAAZ,CAAvB;;AAEA,gBAAKwC,MAAL,CAAYC,EAAZ,CAAe,gBAAf,EAAiC,MAAKC,cAAL,CAAoBC,IAApB,OAAjC;AACA,gBAAKH,MAAL,CAAYC,EAAZ,CAAe,SAAf,EAA0B,MAAKG,SAAL,CAAeD,IAAf,OAA1B;AAnB6F;AAoB9F;;;;2CAEgB;AACf,iBAAKE,YAAL,CAAkB,SAAlB,EAA6BrD,kBAA7B,EAAiD,CAAjD;AACD;;;sCAEW;AAAA;;AACV;AACA,gBAAI,KAAKsD,0BAAL,EAAJ,EAAuC;AAAE;AAAS;;AAElD;AACA,mBAAO,KAAKC,KAAZ;AACA,iBAAKC,OAAL,GAAe,IAAf;;AAEA,mBAAO,KAAKC,WAAL,GACNC,IADM,CACD,uBAAe;AACnB;AACA,qBAAKf,WAAL,GAAoBA,YAAYgB,KAAZ,CAAkB,CAAlB,EAAqB,OAAKb,KAAL,CAAW3B,KAAhC,CAApB;;AAEA,qBAAKyC,sBAAL;;AAEA;AACA,qBAAKJ,OAAL,GAAe,KAAf;;AAEA,qBAAKK,MAAL,CAAY,OAAKlB,WAAjB;AACD,aAXM,CAAP;AAYD;;;wCAEa;AACZ,mBAAO,KAAKmB,WAAL,GACNJ,IADM,CACD,KAAKK,eAAL,CAAqBZ,IAArB,CAA0B,IAA1B,CADC,EAENO,IAFM,CAED,KAAKzE,cAAL,CAAoBkE,IAApB,CAAyB,IAAzB,CAFC,CAAP;AAGD;;;wCAEa;AAAA;;AACZ,mBAAO,KAAKb,aAAL,CAAmB0B,GAAnB,CAAuB,KAAKlB,KAAL,CAAWrC,UAAlC,EACNiD,IADM,CACD,sBAAc;AAClB,kBAAIO,SAASxD,WAAWwD,MAAxB;AACA,qBAAKA,MAAL,GAAcA,MAAd;AACA,kBAAIxC,aAAa,OAAKqB,KAAL,CAAWrB,UAAX,CAAsBD,KAAvC;AACA,kBAAIrC,gBAAgB,OAAK2D,KAAL,CAAW5D,QAA/B;AACA,kBAAImC,yBAAyB,OAAKyB,KAAL,CAAWzB,sBAAxC;;AAEA;AACA,kBAAI6C,cAAczD,WAAW0D,mBAAX,CAA+BhF,cAAcuB,KAAd,CAAoBnB,MAAnD,CAAlB;AACA,kBAAI6E,aAAa3D,WAAW0D,mBAAX,CAA+BhF,cAAcwB,IAAd,CAAmBpB,MAAlD,CAAjB;AACA,kBAAI8E,YAAY5D,WAAW0D,mBAAX,CAA+BhF,cAAcyB,WAAd,CAA0BrB,MAAzD,CAAhB;;AAEA,kBAAI+E,kBAAkB;AACpBlD,8BAAcK,UADM;AAEpBJ,wCAAwBA;AAFJ,eAAtB;AAIA,kBAAIyC,cAAcG,OAAOH,WAAP,CAAmBI,WAAnB,EAAgCE,UAAhC,EAA4CC,SAA5C,EAAuDC,eAAvD,CAAlB;AACA,qBAAOR,YAAYJ,IAAZ,CAAiB,oBAAY;AAClC,uBAAOpE,EAAEiF,GAAF,CAAMrF,QAAN,EAAgB,OAAKsF,aAAL,CAAmBrB,IAAnB,QAAhB,CAAP;AACD,eAFM,CAAP;AAGD,aArBM,CAAP;AAsBD;;;0CAEeR,W,EAAa;AAAA;;AAC3B;AACA,gBAAI8B,WAAWnF,EAAEiF,GAAF,CAAM5B,WAAN,EAAmB,mBAAW;AAC3C,qBAAOnD,QAAQkF,SAAR,CAAkBC,OAAzB;AACD,aAFc,CAAf;;AAIA,mBAAO,KAAKV,MAAL,CAAYF,eAAZ,CAA4BU,QAA5B,EACNf,IADM,CACD,kBAAU;;AAEd;AACApE,gBAAEsF,IAAF,CAAOjC,WAAP,EAAoB,mBAAW;AAC7B,oBAAIkC,QAAQvF,EAAEwF,IAAF,CAAO9B,MAAP,EAAe,iBAAS;AAClC,yBAAO6B,MAAMF,OAAN,KAAkBnF,QAAQkF,SAAR,CAAkBC,OAA3C;AACD,iBAFW,CAAZ;;AAIA,oBAAIE,KAAJ,EAAW;AACTrF,0BAAQuF,YAAR,GAAuBzF,EAAEiF,GAAF,CAAMM,MAAME,YAAZ,EAA0B,eAAO;AACtD,wBAAIC,YAAYnF,OAAOoF,IAAP,CAAYC,IAAIC,KAAhB,CAAhB;AACA,wBAAI,OAAKrC,KAAL,CAAWsC,sBAAf,EAAuC;AACrCF,0BAAIG,IAAJ,GAAWL,UAAUM,MAAV,CAAiB,OAAKxC,KAAL,CAAWyC,gBAA5B,CAAX;AACD,qBAFD,MAEO;AACLL,0BAAIG,IAAJ,GAAWL,UAAUM,MAAV,CAAiB,OAAKrD,iBAAtB,CAAX;AACD;AACDiD,wBAAIM,IAAJ,GAAWN,IAAIO,KAAJ,GAAY,IAAZ,GAAmBP,IAAIQ,IAAvB,GAA8B,GAA9B,GAAoCR,IAAIS,OAAxC,GAAkD,GAA7D;AACA,2BAAOT,GAAP;AACD,mBATsB,CAAvB;;AAWA;AACA,sBAAI,OAAKpC,KAAL,CAAW8C,aAAX,IAA4BpG,QAAQuF,YAAR,CAAqBc,MAArD,EAA6D;AAC3DrG,4BAAQc,KAAR,GAAgB,OAAKwC,KAAL,CAAWlB,aAA3B;AACD;AACF;AACF,eAtBD;;AAwBA,qBAAOe,WAAP;AACD,aA7BM,CAAP;AA8BD;;;yCAEcA,W,EAAa;AAAA;;AAC1B;AACA,gBAAIxD,gBAAgB,KAAK2D,KAAL,CAAW5D,QAAX,CAAoBM,OAApB,CAA4BD,MAAhD;AACA,gBAAIJ,aAAJ,EAAmB;AACjBwD,4BAAc1D,gBAAe0D,WAAf,EAA4BxD,aAA5B,CAAd;AACD;;AAED;AACA,gBAAI,KAAK2D,KAAL,CAAW1B,YAAX,KAA4B,gBAAhC,EAAkD;AAChDuB,4BAAcrD,EAAEC,MAAF,CAASoD,WAAT,EAAsB,mBAAW;AAC7C,uBAAO,CAACnD,QAAQuF,YAAhB;AACD,eAFa,CAAd;AAGD,aAJD,MAIO,IAAI,KAAKjC,KAAL,CAAW1B,YAAX,KAA4B,cAAhC,EAAgD;AACrDuB,4BAAcrD,EAAEC,MAAF,CAASoD,WAAT,EAAsB,cAAtB,CAAd;AACD,aAFM,MAEA;AACLA,4BAAcA,WAAd;AACD;;AAED;AACAA,0BAAcrD,EAAEC,MAAF,CAASoD,WAAT,EAAsB,mBAAW;AAC7C,qBAAO,OAAKG,KAAL,CAAWpB,eAAX,CAA2BlC,QAAQY,QAAnC,EAA6CG,IAApD;AACD,aAFa,CAAd;;AAIA;AACA,gBAAI,KAAKuC,KAAL,CAAWxB,cAAX,CAA0BE,KAA1B,KAAoC,UAAxC,EAAoD;AAClDmB,4BAAcrD,EAAEwG,MAAF,CAASnD,WAAT,EAAsB,UAAtB,EAAkCoD,OAAlC,EAAd;AACD,aAFD,MAEO;AACLpD,4BAAcrD,EAAEwG,MAAF,CAASnD,WAAT,EAAsB,gBAAtB,EAAwCoD,OAAxC,EAAd;AACD;;AAED,mBAAOpD,WAAP;AACD;;;wCAEanD,O,EAAS;AACrB,gBAAIwG,aAAaxG,OAAjB;;AAEA;AACAA,oBAAQyG,cAAR,GAAyBC,OAAO1G,QAAQ2G,UAAf,CAAzB;AACA,gBAAInB,YAAYnF,OAAOoF,IAAP,CAAYzF,QAAQyG,cAApB,CAAhB;AACA,gBAAI,KAAKnD,KAAL,CAAWsC,sBAAf,EAAuC;AACrC;AACAY,yBAAWG,UAAX,GAAwBnB,UAAUM,MAAV,CAAiB,KAAKxC,KAAL,CAAWyC,gBAA5B,CAAxB;AACD,aAHD,MAGO;AACLS,yBAAWG,UAAX,GAAwBnB,UAAUM,MAAV,CAAiB,KAAKrD,iBAAtB,CAAxB;AACD;AACD+D,uBAAWI,GAAX,GAAiBpB,UAAUqB,OAAV,CAAkB,IAAlB,CAAjB;;AAEA;AACA,gBAAI7G,QAAQ8G,KAAR,CAAcT,MAAlB,EAA0B;AACxBG,yBAAWrF,IAAX,GAAkBnB,QAAQ8G,KAAR,CAAc,CAAd,EAAiBZ,IAAnC;AACAM,yBAAWO,YAAX,GAA0B/G,QAAQ8G,KAAR,CAAc,CAAd,EAAiB3F,IAA3C;AACD;;AAED;AACA,gBAAInB,QAAQgC,KAAR,KAAkB,GAAtB,EAA2B;AACzB;AACAwE,yBAAW1F,KAAX,GAAmB,KAAKwC,KAAL,CAAWpB,eAAX,CAA2BlC,QAAQY,QAAnC,EAA6CE,KAAhE;AACD,aAHD,MAGO;AACL;AACA0F,yBAAW1F,KAAX,GAAmB,KAAKwC,KAAL,CAAWnB,YAA9B;AACD;;AAEDqE,uBAAW3F,QAAX,GAAsB,KAAKyC,KAAL,CAAWpB,eAAX,CAA2BlC,QAAQY,QAAnC,EAA6CC,QAAnE;AACA,mBAAO2F,UAAP;AACD;;;wCAEaxG,O,EAAS;AACrBA,oBAAQgH,WAAR,GAAsB,CAAChH,QAAQgH,WAA/B;AACD;;;6CAEkBhH,O,EAASiH,O,EAAS;AACnC,gBAAI9B,UAAUnF,QAAQkF,SAAR,CAAkBC,OAAhC;AACA,gBAAI+B,eAAe,KAAKlE,UAAL,CAAgBgD,IAAhB,CAAqBE,IAAxC;AACA,gBAAIiB,cAAcD,eAAe,cAAf,GAAgCD,OAAlD;AACA,mBAAO,KAAKnE,aAAL,CAAmB0B,GAAnB,CAAuB,KAAKlB,KAAL,CAAWrC,UAAlC,EACNiD,IADM,CACD,sBAAc;AAClB,kBAAIkD,YAAYnG,WAAWwD,MAAX,CAAkB2C,SAAlC;AACA,qBAAOA,UAAUC,gBAAV,CAA2BlC,OAA3B,EAAoCgC,WAApC,CAAP;AACD,aAJM,EAKNjD,IALM,CAKD,KAAKN,SAAL,CAAeD,IAAf,CAAoB,IAApB,CALC,CAAP;AAMD;;;mDAEwB;AACvB,gBAAIrB,WAAW,KAAKgB,KAAL,CAAWhB,QAAX,IAAuB,EAAtC;AACA,gBAAIgF,WAAW,KAAKpE,SAAL,GAAiBZ,QAAhC;AACA,gBAAIiF,SAASC,KAAKC,GAAL,CAASH,WAAWhF,QAApB,EAA8B,KAAKa,WAAL,CAAiBkD,MAA/C,CAAb;AACA,iBAAKjD,mBAAL,GAA2B,KAAKD,WAAL,CAAiBgB,KAAjB,CAAuBmD,QAAvB,EAAiCC,MAAjC,CAA3B;AACA,mBAAO,KAAKnE,mBAAZ;AACD;;;+BAEIsE,K,EAAOC,I,EAAMC,K,EAAOC,I,EAAM;AAC7B,gBAAIC,IAAJ;AACA,gBAAIxE,QAAQuE,KAAKvE,KAAjB;AACA,gBAAIyE,YAAY,CAAhB;AACAD,mBAAOD,KAAK1E,WAAZ;;AAEA,qBAAS6E,cAAT,GAA0B;AACxB,kBAAIC,cAAcJ,KAAKK,MAAvB;;AAEA,kBAAIH,YAAY,CAAhB,EAAmB;AACjBE,+BAAe,EAAf;AACD;;AAED,qBAAQA,cAAc,EAAf,GAAqB,IAA5B;AACD;;AAED,qBAASE,UAAT,CAAoBC,CAApB,EAAuB;AACrB,kBAAIC,KAAKjI,EAAEgI,EAAEE,aAAJ,CAAT;AACAT,mBAAK3E,SAAL,GAAkBqF,SAASF,GAAGtG,IAAH,EAAT,EAAoB,EAApB,IAAwB,CAA1C;;AAEA,kBAAIO,WAAWuF,KAAKvE,KAAL,CAAWhB,QAAX,IAAuB,EAAtC;AACA,kBAAIgF,WAAWO,KAAK3E,SAAL,GAAiBZ,QAAhC;AACA,kBAAIiF,SAASC,KAAKC,GAAL,CAASH,WAAWhF,QAApB,EAA8BuF,KAAK1E,WAAL,CAAiBkD,MAA/C,CAAb;AACAwB,mBAAKzE,mBAAL,GAA2ByE,KAAK1E,WAAL,CAAiBgB,KAAjB,CAAuBmD,QAAvB,EAAiCC,MAAjC,CAA3B;;AAEAG,oBAAMc,MAAN;AACAC;AACD;;AAED,qBAASC,wBAAT,CAAkCC,UAAlC,EAA8C;AAC5CA,yBAAWC,KAAX;;AAEA,kBAAItG,WAAWuF,KAAKvE,KAAL,CAAWhB,QAAX,IAAuB,CAAtC;AACAyF,0BAAYP,KAAKqB,IAAL,CAAUf,KAAKzB,MAAL,GAAc/D,QAAxB,CAAZ;AACA,kBAAIyF,cAAc,CAAlB,EAAqB;AACnB;AACD;;AAED,kBAAIe,YAAYtB,KAAKuB,GAAL,CAASlB,KAAK3E,SAAL,GAAiB,CAA1B,EAA6B,CAA7B,CAAhB;AACA,kBAAI8F,UAAUxB,KAAKC,GAAL,CAASM,SAAT,EAAoBe,YAAY,CAAhC,CAAd;;AAEA,kBAAIG,iBAAiB7I,EAAE,WAAF,CAArB;;AAEA,mBAAK,IAAI8I,IAAIJ,SAAb,EAAwBI,IAAIF,OAA5B,EAAqCE,GAArC,EAA0C;AACxC,oBAAIC,cAAcD,MAAMrB,KAAK3E,SAAX,GAAuB,QAAvB,GAAkC,EAApD;AACA,oBAAIkG,eAAehJ,EAAE,oDAAoD+I,WAApD,GAAkE,IAAlE,IAA0ED,IAAE,CAA5E,IAAiF,WAAnF,CAAnB;AACAD,+BAAeI,MAAf,CAAsBD,YAAtB;AACD;;AAEDT,yBAAWU,MAAX,CAAkBJ,cAAlB;AACD;;AAED,qBAASR,WAAT,GAAuB;AACrB,kBAAIa,YAAY3B,KAAK4B,OAAL,CAAa,QAAb,CAAhB;AACA,kBAAIC,WAAW7B,KAAKrC,IAAL,CAAU,wBAAV,CAAf;AACA,kBAAIqD,aAAahB,KAAKrC,IAAL,CAAU,wBAAV,CAAjB;;AAEAqC,mBAAK8B,GAAL,CAAS,EAAC,aAAanG,MAAMf,QAApB,EAAT;AACA+G,wBAAUI,QAAV,CAAmB,wBAAnB;AACAhB,uCAAyBC,UAAzB;;AAEAa,uBAASC,GAAT,CAAa,EAAC,cAAcnG,MAAMjB,MAAN,GAAe2F,gBAAf,GAAkC,EAAjD,EAAb;AACD;;AAEDL,iBAAKlE,EAAL,CAAQ,OAAR,EAAiB,2BAAjB,EAA8C0E,UAA9C;;AAEA,gBAAIwB,gBAAgBjC,MAAMkC,GAAN,CAAU,UAAV,EAAsB,YAAW;AACnDjC,mBAAKkC,GAAL,CAAS,OAAT,EAAkB,2BAAlB;AACAF;AACD,aAHmB,CAApB;;AAKA9B,iBAAKrE,MAAL,CAAYC,EAAZ,CAAe,QAAf,EAAyB,UAACqG,UAAD,EAAgB;AACvChC,qBAAOgC,cAAchC,IAArB;AACA,kBAAIA,IAAJ,EAAU;AACRW;AACD;AACDZ,mBAAKkC,kBAAL;AACD,aAND;AAOD;;;;QAhS4BxJ,S;;AAmS/BmC,uBAAiBsH,WAAjB,GAA+B,4BAA/B;kCAeEtH,gB;;2BACAA,gB","file":"module.js","sourcesContent":["/**\n * Grafana-Zabbix\n * Zabbix plugin for Grafana.\n * http://github.com/alexanderzobnin/grafana-zabbix\n *\n * Trigger panel.\n * This feature sponsored by CORE IT\n * http://www.coreit.fr\n *\n * Copyright 2015 Alexander Zobnin alexanderzobnin@gmail.com\n * Licensed under the Apache License, Version 2.0\n */\n\nimport _ from 'lodash';\nimport $ from 'jquery';\nimport moment from 'moment';\nimport {loadPluginCss} from 'app/plugins/sdk';\nimport * as utils from '../datasource-zabbix/utils';\nimport {PanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\n\nloadPluginCss({\n dark: 'plugins/alexanderzobnin-zabbix-app/css/grafana-zabbix.dark.css',\n light: 'plugins/alexanderzobnin-zabbix-app/css/grafana-zabbix.light.css'\n});\n\nvar defaultSeverity = [\n { priority: 0, severity: 'Not classified', color: '#B7DBAB', show: true },\n { priority: 1, severity: 'Information', color: '#82B5D8', show: true },\n { priority: 2, severity: 'Warning', color: '#E5AC0E', show: true },\n { priority: 3, severity: 'Average', color: '#C15C17', show: true },\n { priority: 4, severity: 'High', color: '#BF1B00', show: true },\n { priority: 5, severity: 'Disaster', color: '#890F02', show: true }\n];\n\nvar panelDefaults = {\n datasource: null,\n triggers: {\n group: {filter: \"\"},\n host: {filter: \"\"},\n application: {filter: \"\"},\n trigger: {filter: \"\"}\n },\n hostField: true,\n statusField: false,\n severityField: false,\n lastChangeField: true,\n ageField: true,\n infoField: true,\n limit: 10,\n showTriggers: 'all triggers',\n hideHostsInMaintenance: false,\n sortTriggersBy: { text: 'last change', value: 'lastchange' },\n showEvents: { text: 'Problems', value: '1' },\n triggerSeverity: defaultSeverity,\n okEventColor: 'rgba(0, 245, 153, 0.45)',\n ackEventColor: 'rgba(0, 0, 0, 0)',\n scroll: true,\n pageSize: 10,\n fontSize: '100%',\n};\n\nvar triggerStatusMap = {\n '0': 'OK',\n '1': 'Problem'\n};\n\nvar defaultTimeFormat = \"DD MMM YYYY HH:mm:ss\";\n\nclass TriggerPanelCtrl extends PanelCtrl {\n\n /** @ngInject */\n constructor($scope, $injector, $element, datasourceSrv, templateSrv, contextSrv, dashboardSrv) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\n this.dashboardSrv = dashboardSrv;\n\n this.triggerStatusMap = triggerStatusMap;\n this.defaultTimeFormat = defaultTimeFormat;\n this.pageIndex = 0;\n this.triggerList = [];\n this.currentTriggersPage = [];\n\n // Load panel defaults\n // _.cloneDeep() need for prevent changing shared defaultSeverity.\n // Load object \"by value\" istead \"by reference\".\n _.defaults(this.panel, _.cloneDeep(panelDefaults));\n\n this.events.on('init-edit-mode', this.onInitEditMode.bind(this));\n this.events.on('refresh', this.onRefresh.bind(this));\n }\n\n onInitEditMode() {\n this.addEditorTab('Options', triggerPanelEditor, 2);\n }\n\n onRefresh() {\n // ignore fetching data if another panel is in fullscreen\n if (this.otherPanelInFullscreenMode()) { return; }\n\n // clear loading/error state\n delete this.error;\n this.loading = true;\n\n return this.refreshData()\n .then(triggerList => {\n // Limit triggers number\n this.triggerList = triggerList.slice(0, this.panel.limit);\n\n this.getCurrentTriggersPage();\n\n // Notify panel that request is finished\n this.loading = false;\n\n this.render(this.triggerList);\n });\n }\n\n refreshData() {\n return this.getTriggers()\n .then(this.getAcknowledges.bind(this))\n .then(this.filterTriggers.bind(this));\n }\n\n getTriggers() {\n return this.datasourceSrv.get(this.panel.datasource)\n .then(datasource => {\n var zabbix = datasource.zabbix;\n this.zabbix = zabbix;\n var showEvents = this.panel.showEvents.value;\n var triggerFilter = this.panel.triggers;\n var hideHostsInMaintenance = this.panel.hideHostsInMaintenance;\n\n // Replace template variables\n var groupFilter = datasource.replaceTemplateVars(triggerFilter.group.filter);\n var hostFilter = datasource.replaceTemplateVars(triggerFilter.host.filter);\n var appFilter = datasource.replaceTemplateVars(triggerFilter.application.filter);\n\n let triggersOptions = {\n showTriggers: showEvents,\n hideHostsInMaintenance: hideHostsInMaintenance\n };\n let getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, triggersOptions);\n return getTriggers.then(triggers => {\n return _.map(triggers, this.formatTrigger.bind(this));\n });\n });\n }\n\n getAcknowledges(triggerList) {\n // Request acknowledges for trigger\n var eventids = _.map(triggerList, trigger => {\n return trigger.lastEvent.eventid;\n });\n\n return this.zabbix.getAcknowledges(eventids)\n .then(events => {\n\n // Map events to triggers\n _.each(triggerList, trigger => {\n var event = _.find(events, event => {\n return event.eventid === trigger.lastEvent.eventid;\n });\n\n if (event) {\n trigger.acknowledges = _.map(event.acknowledges, ack => {\n let timestamp = moment.unix(ack.clock);\n if (this.panel.customLastChangeFormat) {\n ack.time = timestamp.format(this.panel.lastChangeFormat);\n } else {\n ack.time = timestamp.format(this.defaultTimeFormat);\n }\n ack.user = ack.alias + ' (' + ack.name + ' ' + ack.surname + ')';\n return ack;\n });\n\n // Mark acknowledged triggers with different color\n if (this.panel.markAckEvents && trigger.acknowledges.length) {\n trigger.color = this.panel.ackEventColor;\n }\n }\n });\n\n return triggerList;\n });\n }\n\n filterTriggers(triggerList) {\n // Filter triggers by description\n var triggerFilter = this.panel.triggers.trigger.filter;\n if (triggerFilter) {\n triggerList = filterTriggers(triggerList, triggerFilter);\n }\n\n // Filter acknowledged triggers\n if (this.panel.showTriggers === 'unacknowledged') {\n triggerList = _.filter(triggerList, trigger => {\n return !trigger.acknowledges;\n });\n } else if (this.panel.showTriggers === 'acknowledged') {\n triggerList = _.filter(triggerList, 'acknowledges');\n } else {\n triggerList = triggerList;\n }\n\n // Filter triggers by severity\n triggerList = _.filter(triggerList, trigger => {\n return this.panel.triggerSeverity[trigger.priority].show;\n });\n\n // Sort triggers\n if (this.panel.sortTriggersBy.value === 'priority') {\n triggerList = _.sortBy(triggerList, 'priority').reverse();\n } else {\n triggerList = _.sortBy(triggerList, 'lastchangeUnix').reverse();\n }\n\n return triggerList;\n }\n\n formatTrigger(trigger) {\n let triggerObj = trigger;\n\n // Format last change and age\n trigger.lastchangeUnix = Number(trigger.lastchange);\n let timestamp = moment.unix(trigger.lastchangeUnix);\n if (this.panel.customLastChangeFormat) {\n // User defined format\n triggerObj.lastchange = timestamp.format(this.panel.lastChangeFormat);\n } else {\n triggerObj.lastchange = timestamp.format(this.defaultTimeFormat);\n }\n triggerObj.age = timestamp.fromNow(true);\n\n // Set host that the trigger belongs\n if (trigger.hosts.length) {\n triggerObj.host = trigger.hosts[0].name;\n triggerObj.hostTechName = trigger.hosts[0].host;\n }\n\n // Set color\n if (trigger.value === '1') {\n // Problem state\n triggerObj.color = this.panel.triggerSeverity[trigger.priority].color;\n } else {\n // OK state\n triggerObj.color = this.panel.okEventColor;\n }\n\n triggerObj.severity = this.panel.triggerSeverity[trigger.priority].severity;\n return triggerObj;\n }\n\n switchComment(trigger) {\n trigger.showComment = !trigger.showComment;\n }\n\n acknowledgeTrigger(trigger, message) {\n let eventid = trigger.lastEvent.eventid;\n let grafana_user = this.contextSrv.user.name;\n let ack_message = grafana_user + ' (Grafana): ' + message;\n return this.datasourceSrv.get(this.panel.datasource)\n .then(datasource => {\n let zabbixAPI = datasource.zabbix.zabbixAPI;\n return zabbixAPI.acknowledgeEvent(eventid, ack_message);\n })\n .then(this.onRefresh.bind(this));\n }\n\n getCurrentTriggersPage() {\n let pageSize = this.panel.pageSize || 10;\n let startPos = this.pageIndex * pageSize;\n let endPos = Math.min(startPos + pageSize, this.triggerList.length);\n this.currentTriggersPage = this.triggerList.slice(startPos, endPos);\n return this.currentTriggersPage;\n }\n\n link(scope, elem, attrs, ctrl) {\n var data;\n var panel = ctrl.panel;\n var pageCount = 0;\n data = ctrl.triggerList;\n\n function getTableHeight() {\n var panelHeight = ctrl.height;\n\n if (pageCount > 1) {\n panelHeight -= 26;\n }\n\n return (panelHeight - 31) + 'px';\n }\n\n function switchPage(e) {\n let el = $(e.currentTarget);\n ctrl.pageIndex = (parseInt(el.text(), 10)-1);\n\n let pageSize = ctrl.panel.pageSize || 10;\n let startPos = ctrl.pageIndex * pageSize;\n let endPos = Math.min(startPos + pageSize, ctrl.triggerList.length);\n ctrl.currentTriggersPage = ctrl.triggerList.slice(startPos, endPos);\n\n scope.$apply();\n renderPanel();\n }\n\n function appendPaginationControls(footerElem) {\n footerElem.empty();\n\n var pageSize = ctrl.panel.pageSize || 5;\n pageCount = Math.ceil(data.length / pageSize);\n if (pageCount === 1) {\n return;\n }\n\n var startPage = Math.max(ctrl.pageIndex - 3, 0);\n var endPage = Math.min(pageCount, startPage + 9);\n\n var paginationList = $('
    ');\n\n for (var i = startPage; i < endPage; i++) {\n var activeClass = i === ctrl.pageIndex ? 'active' : '';\n var pageLinkElem = $('
  • ' + (i+1) + '
  • ');\n paginationList.append(pageLinkElem);\n }\n\n footerElem.append(paginationList);\n }\n\n function renderPanel() {\n var panelElem = elem.parents('.panel');\n var rootElem = elem.find('.triggers-panel-scroll');\n var footerElem = elem.find('.triggers-panel-footer');\n\n elem.css({'font-size': panel.fontSize});\n panelElem.addClass('triggers-panel-wrapper');\n appendPaginationControls(footerElem);\n\n rootElem.css({'max-height': panel.scroll ? getTableHeight() : '' });\n }\n\n elem.on('click', '.triggers-panel-page-link', switchPage);\n\n var unbindDestroy = scope.$on('$destroy', function() {\n elem.off('click', '.triggers-panel-page-link');\n unbindDestroy();\n });\n\n ctrl.events.on('render', (renderData) => {\n data = renderData || data;\n if (data) {\n renderPanel();\n }\n ctrl.renderingCompleted();\n });\n }\n}\n\nTriggerPanelCtrl.templateUrl = 'panel-triggers/module.html';\n\nfunction filterTriggers(triggers, triggerFilter) {\n if (utils.isRegex(triggerFilter)) {\n return _.filter(triggers, function(trigger) {\n return utils.buildRegex(triggerFilter).test(trigger.description);\n });\n } else {\n return _.filter(triggers, function(trigger) {\n return trigger.description === triggerFilter;\n });\n }\n}\n\nexport {\n TriggerPanelCtrl,\n TriggerPanelCtrl as PanelCtrl\n};\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/panel-triggers/module.js"],"names":["filterTriggers","triggers","triggerFilter","utils","isRegex","_","filter","trigger","buildRegex","test","description","$","moment","loadPluginCss","PanelCtrl","triggerPanelEditor","dark","light","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","hideHostsInMaintenance","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","scroll","pageSize","fontSize","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","dashboardSrv","pageIndex","triggerList","currentTriggersPage","defaults","panel","cloneDeep","events","on","onInitEditMode","bind","onRefresh","addEditorTab","otherPanelInFullscreenMode","error","loading","refreshData","then","slice","getCurrentTriggersPage","render","getTriggers","getAcknowledges","get","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","triggersOptions","map","formatTrigger","eventids","lastEvent","eventid","each","event","find","acknowledges","timestamp","unix","ack","clock","customLastChangeFormat","time","format","lastChangeFormat","user","alias","name","surname","markAckEvents","length","sortBy","reverse","triggerObj","lastchangeUnix","Number","lastchange","age","fromNow","hosts","hostTechName","showComment","message","grafana_user","ack_message","zabbixAPI","acknowledgeEvent","startPos","endPos","Math","min","scope","elem","attrs","ctrl","data","pageCount","getTableHeight","panelHeight","height","switchPage","e","el","currentTarget","parseInt","$apply","renderPanel","appendPaginationControls","footerElem","empty","ceil","startPage","max","endPage","paginationList","i","activeClass","pageLinkElem","append","panelElem","parents","rootElem","css","addClass","unbindDestroy","$on","off","renderData","renderingCompleted","templateUrl"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8WA,WAASA,eAAT,CAAwBC,QAAxB,EAAkCC,aAAlC,EAAiD;AAC/C,QAAIC,MAAMC,OAAN,CAAcF,aAAd,CAAJ,EAAkC;AAChC,aAAOG,EAAEC,MAAF,CAASL,QAAT,EAAmB,UAASM,OAAT,EAAkB;AAC1C,eAAOJ,MAAMK,UAAN,CAAiBN,aAAjB,EAAgCO,IAAhC,CAAqCF,QAAQG,WAA7C,CAAP;AACD,OAFM,CAAP;AAGD,KAJD,MAIO;AACL,aAAOL,EAAEC,MAAF,CAASL,QAAT,EAAmB,UAASM,OAAT,EAAkB;AAC1C,eAAOA,QAAQG,WAAR,KAAwBR,aAA/B;AACD,OAFM,CAAP;AAGD;AACF;;;;AA3WMG,O;;AACAM,O;;AACAC,Y;;AACCC,mB,kBAAAA,a;AAEAC,e,kBAAAA,S;;AADIX,W;;AAEJY,wB,WAAAA,kB;;;;;;;;;;;;;;;;;;;;;AAnBR;;;;;;;;;;;;;AAsBAF,oBAAc;AACZG,cAAM,gEADM;AAEZC,eAAO;AAFK,OAAd;;AAKIC,qB,GAAkB,CACpB,EAAEC,UAAU,CAAZ,EAAeC,UAAU,gBAAzB,EAA4CC,OAAO,SAAnD,EAA8DC,MAAM,IAApE,EADoB,EAEpB,EAAEH,UAAU,CAAZ,EAAeC,UAAU,aAAzB,EAA4CC,OAAO,SAAnD,EAA8DC,MAAM,IAApE,EAFoB,EAGpB,EAAEH,UAAU,CAAZ,EAAeC,UAAU,SAAzB,EAA4CC,OAAO,SAAnD,EAA8DC,MAAM,IAApE,EAHoB,EAIpB,EAAEH,UAAU,CAAZ,EAAeC,UAAU,SAAzB,EAA4CC,OAAO,SAAnD,EAA8DC,MAAM,IAApE,EAJoB,EAKpB,EAAEH,UAAU,CAAZ,EAAeC,UAAU,MAAzB,EAA4CC,OAAO,SAAnD,EAA8DC,MAAM,IAApE,EALoB,EAMpB,EAAEH,UAAU,CAAZ,EAAeC,UAAU,UAAzB,EAA4CC,OAAO,SAAnD,EAA8DC,MAAM,IAApE,EANoB,C;AASlBC,mB,GAAgB;AAClBC,oBAAY,IADM;AAElBvB,kBAAU;AACRwB,iBAAO,EAACnB,QAAQ,EAAT,EADC;AAERoB,gBAAM,EAACpB,QAAQ,EAAT,EAFE;AAGRqB,uBAAa,EAACrB,QAAQ,EAAT,EAHL;AAIRC,mBAAS,EAACD,QAAQ,EAAT;AAJD,SAFQ;AAQlBsB,mBAAW,IARO;AASlBC,qBAAa,KATK;AAUlBC,uBAAe,KAVG;AAWlBC,yBAAiB,IAXC;AAYlBC,kBAAU,IAZQ;AAalBC,mBAAW,IAbO;AAclBC,eAAO,EAdW;AAelBC,sBAAc,cAfI;AAgBlBC,gCAAwB,KAhBN;AAiBlBC,wBAAgB,EAAEC,MAAM,aAAR,EAAuBC,OAAO,YAA9B,EAjBE;AAkBlBC,oBAAY,EAAEF,MAAM,UAAR,EAAoBC,OAAO,GAA3B,EAlBM;AAmBlBE,yBAAiBvB,eAnBC;AAoBlBwB,sBAAc,yBApBI;AAqBlBC,uBAAe,kBArBG;AAsBlBC,gBAAQ,IAtBU;AAuBlBC,kBAAU,EAvBQ;AAwBlBC,kBAAU;AAxBQ,O;AA2BhBC,sB,GAAmB;AACrB,aAAK,IADgB;AAErB,aAAK;AAFgB,O;AAKnBC,uB,GAAoB,sB;;uDAElBC,gB;;;AAEJ;AACA,kCAAYC,MAAZ,EAAoBC,SAApB,EAA+BC,QAA/B,EAAyCC,aAAzC,EAAwDC,WAAxD,EAAqEC,UAArE,EAAiFC,YAAjF,EAA+F;AAAA;;AAAA,0IACvFN,MADuF,EAC/EC,SAD+E;;AAE7F,gBAAKE,aAAL,GAAqBA,aAArB;AACA,gBAAKC,WAAL,GAAmBA,WAAnB;AACA,gBAAKC,UAAL,GAAkBA,UAAlB;AACA,gBAAKC,YAAL,GAAoBA,YAApB;;AAEA,gBAAKT,gBAAL,GAAwBA,gBAAxB;AACA,gBAAKC,iBAAL,GAAyBA,iBAAzB;AACA,gBAAKS,SAAL,GAAiB,CAAjB;AACA,gBAAKC,WAAL,GAAmB,EAAnB;AACA,gBAAKC,mBAAL,GAA2B,EAA3B;;AAEA;AACA;AACA;AACAtD,YAAEuD,QAAF,CAAW,MAAKC,KAAhB,EAAuBxD,EAAEyD,SAAF,CAAYvC,aAAZ,CAAvB;;AAEA,gBAAKwC,MAAL,CAAYC,EAAZ,CAAe,gBAAf,EAAiC,MAAKC,cAAL,CAAoBC,IAApB,OAAjC;AACA,gBAAKH,MAAL,CAAYC,EAAZ,CAAe,SAAf,EAA0B,MAAKG,SAAL,CAAeD,IAAf,OAA1B;AAnB6F;AAoB9F;;;;2CAEgB;AACf,iBAAKE,YAAL,CAAkB,SAAlB,EAA6BrD,kBAA7B,EAAiD,CAAjD;AACD;;;sCAEW;AAAA;;AACV;AACA,gBAAI,KAAKsD,0BAAL,EAAJ,EAAuC;AAAE;AAAS;;AAElD;AACA,mBAAO,KAAKC,KAAZ;AACA,iBAAKC,OAAL,GAAe,IAAf;;AAEA,mBAAO,KAAKC,WAAL,GACNC,IADM,CACD,uBAAe;AACnB;AACA,qBAAKf,WAAL,GAAoBA,YAAYgB,KAAZ,CAAkB,CAAlB,EAAqB,OAAKb,KAAL,CAAW3B,KAAhC,CAApB;;AAEA,qBAAKyC,sBAAL;;AAEA;AACA,qBAAKJ,OAAL,GAAe,KAAf;;AAEA,qBAAKK,MAAL,CAAY,OAAKlB,WAAjB;AACD,aAXM,CAAP;AAYD;;;wCAEa;AACZ,mBAAO,KAAKmB,WAAL,GACNJ,IADM,CACD,KAAKK,eAAL,CAAqBZ,IAArB,CAA0B,IAA1B,CADC,EAENO,IAFM,CAED,KAAKzE,cAAL,CAAoBkE,IAApB,CAAyB,IAAzB,CAFC,CAAP;AAGD;;;wCAEa;AAAA;;AACZ,mBAAO,KAAKb,aAAL,CAAmB0B,GAAnB,CAAuB,KAAKlB,KAAL,CAAWrC,UAAlC,EACNiD,IADM,CACD,sBAAc;AAClB,kBAAIO,SAASxD,WAAWwD,MAAxB;AACA,qBAAKA,MAAL,GAAcA,MAAd;AACA,qBAAKxD,UAAL,GAAkBA,UAAlB;AACA,kBAAIgB,aAAa,OAAKqB,KAAL,CAAWrB,UAAX,CAAsBD,KAAvC;AACA,kBAAIrC,gBAAgB,OAAK2D,KAAL,CAAW5D,QAA/B;AACA,kBAAImC,yBAAyB,OAAKyB,KAAL,CAAWzB,sBAAxC;;AAEA;AACA,kBAAI6C,cAAczD,WAAW0D,mBAAX,CAA+BhF,cAAcuB,KAAd,CAAoBnB,MAAnD,CAAlB;AACA,kBAAI6E,aAAa3D,WAAW0D,mBAAX,CAA+BhF,cAAcwB,IAAd,CAAmBpB,MAAlD,CAAjB;AACA,kBAAI8E,YAAY5D,WAAW0D,mBAAX,CAA+BhF,cAAcyB,WAAd,CAA0BrB,MAAzD,CAAhB;;AAEA,kBAAI+E,kBAAkB;AACpBlD,8BAAcK,UADM;AAEpBJ,wCAAwBA;AAFJ,eAAtB;;AAKA,qBAAO4C,OAAOH,WAAP,CAAmBI,WAAnB,EAAgCE,UAAhC,EAA4CC,SAA5C,EAAuDC,eAAvD,CAAP;AACD,aApBM,EAqBNZ,IArBM,CAqBD,oBAAY;AAChB,qBAAOpE,EAAEiF,GAAF,CAAMrF,QAAN,EAAgB,OAAKsF,aAAL,CAAmBrB,IAAnB,QAAhB,CAAP;AACD,aAvBM,CAAP;AAwBD;;;0CAEeR,W,EAAa;AAAA;;AAC3B;AACA,gBAAI8B,WAAWnF,EAAEiF,GAAF,CAAM5B,WAAN,EAAmB,mBAAW;AAC3C,qBAAOnD,QAAQkF,SAAR,CAAkBC,OAAzB;AACD,aAFc,CAAf;;AAIA,mBAAO,KAAKV,MAAL,CAAYF,eAAZ,CAA4BU,QAA5B,EACNf,IADM,CACD,kBAAU;;AAEd;AACApE,gBAAEsF,IAAF,CAAOjC,WAAP,EAAoB,mBAAW;AAC7B,oBAAIkC,QAAQvF,EAAEwF,IAAF,CAAO9B,MAAP,EAAe,iBAAS;AAClC,yBAAO6B,MAAMF,OAAN,KAAkBnF,QAAQkF,SAAR,CAAkBC,OAA3C;AACD,iBAFW,CAAZ;;AAIA,oBAAIE,KAAJ,EAAW;AACTrF,0BAAQuF,YAAR,GAAuBzF,EAAEiF,GAAF,CAAMM,MAAME,YAAZ,EAA0B,eAAO;AACtD,wBAAIC,YAAYnF,OAAOoF,IAAP,CAAYC,IAAIC,KAAhB,CAAhB;AACA,wBAAI,OAAKrC,KAAL,CAAWsC,sBAAf,EAAuC;AACrCF,0BAAIG,IAAJ,GAAWL,UAAUM,MAAV,CAAiB,OAAKxC,KAAL,CAAWyC,gBAA5B,CAAX;AACD,qBAFD,MAEO;AACLL,0BAAIG,IAAJ,GAAWL,UAAUM,MAAV,CAAiB,OAAKrD,iBAAtB,CAAX;AACD;AACDiD,wBAAIM,IAAJ,GAAWN,IAAIO,KAAJ,GAAY,IAAZ,GAAmBP,IAAIQ,IAAvB,GAA8B,GAA9B,GAAoCR,IAAIS,OAAxC,GAAkD,GAA7D;AACA,2BAAOT,GAAP;AACD,mBATsB,CAAvB;;AAWA;AACA,sBAAI,OAAKpC,KAAL,CAAW8C,aAAX,IAA4BpG,QAAQuF,YAAR,CAAqBc,MAArD,EAA6D;AAC3DrG,4BAAQc,KAAR,GAAgB,OAAKwC,KAAL,CAAWlB,aAA3B;AACD;AACF;AACF,eAtBD;;AAwBA,qBAAOe,WAAP;AACD,aA7BM,CAAP;AA8BD;;;yCAEcA,W,EAAa;AAAA;;AAC1B;AACA,gBAAIxD,gBAAgB,KAAK2D,KAAL,CAAW5D,QAAX,CAAoBM,OAApB,CAA4BD,MAAhD;AACAJ,4BAAgB,KAAKsB,UAAL,CAAgB0D,mBAAhB,CAAoChF,aAApC,CAAhB;AACA,gBAAIA,aAAJ,EAAmB;AACjBwD,4BAAc1D,gBAAe0D,WAAf,EAA4BxD,aAA5B,CAAd;AACD;;AAED;AACA,gBAAI,KAAK2D,KAAL,CAAW1B,YAAX,KAA4B,gBAAhC,EAAkD;AAChDuB,4BAAcrD,EAAEC,MAAF,CAASoD,WAAT,EAAsB,mBAAW;AAC7C,uBAAO,CAACnD,QAAQuF,YAAhB;AACD,eAFa,CAAd;AAGD,aAJD,MAIO,IAAI,KAAKjC,KAAL,CAAW1B,YAAX,KAA4B,cAAhC,EAAgD;AACrDuB,4BAAcrD,EAAEC,MAAF,CAASoD,WAAT,EAAsB,cAAtB,CAAd;AACD,aAFM,MAEA;AACLA,4BAAcA,WAAd;AACD;;AAED;AACAA,0BAAcrD,EAAEC,MAAF,CAASoD,WAAT,EAAsB,mBAAW;AAC7C,qBAAO,OAAKG,KAAL,CAAWpB,eAAX,CAA2BlC,QAAQY,QAAnC,EAA6CG,IAApD;AACD,aAFa,CAAd;;AAIA;AACA,gBAAI,KAAKuC,KAAL,CAAWxB,cAAX,CAA0BE,KAA1B,KAAoC,UAAxC,EAAoD;AAClDmB,4BAAcrD,EAAEwG,MAAF,CAASnD,WAAT,EAAsB,UAAtB,EAAkCoD,OAAlC,EAAd;AACD,aAFD,MAEO;AACLpD,4BAAcrD,EAAEwG,MAAF,CAASnD,WAAT,EAAsB,gBAAtB,EAAwCoD,OAAxC,EAAd;AACD;;AAED,mBAAOpD,WAAP;AACD;;;wCAEanD,O,EAAS;AACrB,gBAAIwG,aAAaxG,OAAjB;;AAEA;AACAA,oBAAQyG,cAAR,GAAyBC,OAAO1G,QAAQ2G,UAAf,CAAzB;AACA,gBAAInB,YAAYnF,OAAOoF,IAAP,CAAYzF,QAAQyG,cAApB,CAAhB;AACA,gBAAI,KAAKnD,KAAL,CAAWsC,sBAAf,EAAuC;AACrC;AACAY,yBAAWG,UAAX,GAAwBnB,UAAUM,MAAV,CAAiB,KAAKxC,KAAL,CAAWyC,gBAA5B,CAAxB;AACD,aAHD,MAGO;AACLS,yBAAWG,UAAX,GAAwBnB,UAAUM,MAAV,CAAiB,KAAKrD,iBAAtB,CAAxB;AACD;AACD+D,uBAAWI,GAAX,GAAiBpB,UAAUqB,OAAV,CAAkB,IAAlB,CAAjB;;AAEA;AACA,gBAAI7G,QAAQ8G,KAAR,CAAcT,MAAlB,EAA0B;AACxBG,yBAAWrF,IAAX,GAAkBnB,QAAQ8G,KAAR,CAAc,CAAd,EAAiBZ,IAAnC;AACAM,yBAAWO,YAAX,GAA0B/G,QAAQ8G,KAAR,CAAc,CAAd,EAAiB3F,IAA3C;AACD;;AAED;AACA,gBAAInB,QAAQgC,KAAR,KAAkB,GAAtB,EAA2B;AACzB;AACAwE,yBAAW1F,KAAX,GAAmB,KAAKwC,KAAL,CAAWpB,eAAX,CAA2BlC,QAAQY,QAAnC,EAA6CE,KAAhE;AACD,aAHD,MAGO;AACL;AACA0F,yBAAW1F,KAAX,GAAmB,KAAKwC,KAAL,CAAWnB,YAA9B;AACD;;AAEDqE,uBAAW3F,QAAX,GAAsB,KAAKyC,KAAL,CAAWpB,eAAX,CAA2BlC,QAAQY,QAAnC,EAA6CC,QAAnE;AACA,mBAAO2F,UAAP;AACD;;;wCAEaxG,O,EAAS;AACrBA,oBAAQgH,WAAR,GAAsB,CAAChH,QAAQgH,WAA/B;AACD;;;6CAEkBhH,O,EAASiH,O,EAAS;AACnC,gBAAI9B,UAAUnF,QAAQkF,SAAR,CAAkBC,OAAhC;AACA,gBAAI+B,eAAe,KAAKlE,UAAL,CAAgBgD,IAAhB,CAAqBE,IAAxC;AACA,gBAAIiB,cAAcD,eAAe,cAAf,GAAgCD,OAAlD;AACA,mBAAO,KAAKnE,aAAL,CAAmB0B,GAAnB,CAAuB,KAAKlB,KAAL,CAAWrC,UAAlC,EACNiD,IADM,CACD,sBAAc;AAClB,kBAAIkD,YAAYnG,WAAWwD,MAAX,CAAkB2C,SAAlC;AACA,qBAAOA,UAAUC,gBAAV,CAA2BlC,OAA3B,EAAoCgC,WAApC,CAAP;AACD,aAJM,EAKNjD,IALM,CAKD,KAAKN,SAAL,CAAeD,IAAf,CAAoB,IAApB,CALC,CAAP;AAMD;;;mDAEwB;AACvB,gBAAIrB,WAAW,KAAKgB,KAAL,CAAWhB,QAAX,IAAuB,EAAtC;AACA,gBAAIgF,WAAW,KAAKpE,SAAL,GAAiBZ,QAAhC;AACA,gBAAIiF,SAASC,KAAKC,GAAL,CAASH,WAAWhF,QAApB,EAA8B,KAAKa,WAAL,CAAiBkD,MAA/C,CAAb;AACA,iBAAKjD,mBAAL,GAA2B,KAAKD,WAAL,CAAiBgB,KAAjB,CAAuBmD,QAAvB,EAAiCC,MAAjC,CAA3B;AACA,mBAAO,KAAKnE,mBAAZ;AACD;;;+BAEIsE,K,EAAOC,I,EAAMC,K,EAAOC,I,EAAM;AAC7B,gBAAIC,IAAJ;AACA,gBAAIxE,QAAQuE,KAAKvE,KAAjB;AACA,gBAAIyE,YAAY,CAAhB;AACAD,mBAAOD,KAAK1E,WAAZ;;AAEA,qBAAS6E,cAAT,GAA0B;AACxB,kBAAIC,cAAcJ,KAAKK,MAAvB;;AAEA,kBAAIH,YAAY,CAAhB,EAAmB;AACjBE,+BAAe,EAAf;AACD;;AAED,qBAAQA,cAAc,EAAf,GAAqB,IAA5B;AACD;;AAED,qBAASE,UAAT,CAAoBC,CAApB,EAAuB;AACrB,kBAAIC,KAAKjI,EAAEgI,EAAEE,aAAJ,CAAT;AACAT,mBAAK3E,SAAL,GAAkBqF,SAASF,GAAGtG,IAAH,EAAT,EAAoB,EAApB,IAAwB,CAA1C;;AAEA,kBAAIO,WAAWuF,KAAKvE,KAAL,CAAWhB,QAAX,IAAuB,EAAtC;AACA,kBAAIgF,WAAWO,KAAK3E,SAAL,GAAiBZ,QAAhC;AACA,kBAAIiF,SAASC,KAAKC,GAAL,CAASH,WAAWhF,QAApB,EAA8BuF,KAAK1E,WAAL,CAAiBkD,MAA/C,CAAb;AACAwB,mBAAKzE,mBAAL,GAA2ByE,KAAK1E,WAAL,CAAiBgB,KAAjB,CAAuBmD,QAAvB,EAAiCC,MAAjC,CAA3B;;AAEAG,oBAAMc,MAAN;AACAC;AACD;;AAED,qBAASC,wBAAT,CAAkCC,UAAlC,EAA8C;AAC5CA,yBAAWC,KAAX;;AAEA,kBAAItG,WAAWuF,KAAKvE,KAAL,CAAWhB,QAAX,IAAuB,CAAtC;AACAyF,0BAAYP,KAAKqB,IAAL,CAAUf,KAAKzB,MAAL,GAAc/D,QAAxB,CAAZ;AACA,kBAAIyF,cAAc,CAAlB,EAAqB;AACnB;AACD;;AAED,kBAAIe,YAAYtB,KAAKuB,GAAL,CAASlB,KAAK3E,SAAL,GAAiB,CAA1B,EAA6B,CAA7B,CAAhB;AACA,kBAAI8F,UAAUxB,KAAKC,GAAL,CAASM,SAAT,EAAoBe,YAAY,CAAhC,CAAd;;AAEA,kBAAIG,iBAAiB7I,EAAE,WAAF,CAArB;;AAEA,mBAAK,IAAI8I,IAAIJ,SAAb,EAAwBI,IAAIF,OAA5B,EAAqCE,GAArC,EAA0C;AACxC,oBAAIC,cAAcD,MAAMrB,KAAK3E,SAAX,GAAuB,QAAvB,GAAkC,EAApD;AACA,oBAAIkG,eAAehJ,EAAE,oDAAoD+I,WAApD,GAAkE,IAAlE,IAA0ED,IAAE,CAA5E,IAAiF,WAAnF,CAAnB;AACAD,+BAAeI,MAAf,CAAsBD,YAAtB;AACD;;AAEDT,yBAAWU,MAAX,CAAkBJ,cAAlB;AACD;;AAED,qBAASR,WAAT,GAAuB;AACrB,kBAAIa,YAAY3B,KAAK4B,OAAL,CAAa,QAAb,CAAhB;AACA,kBAAIC,WAAW7B,KAAKrC,IAAL,CAAU,wBAAV,CAAf;AACA,kBAAIqD,aAAahB,KAAKrC,IAAL,CAAU,wBAAV,CAAjB;;AAEAqC,mBAAK8B,GAAL,CAAS,EAAC,aAAanG,MAAMf,QAApB,EAAT;AACA+G,wBAAUI,QAAV,CAAmB,wBAAnB;AACAhB,uCAAyBC,UAAzB;;AAEAa,uBAASC,GAAT,CAAa,EAAC,cAAcnG,MAAMjB,MAAN,GAAe2F,gBAAf,GAAkC,EAAjD,EAAb;AACD;;AAEDL,iBAAKlE,EAAL,CAAQ,OAAR,EAAiB,2BAAjB,EAA8C0E,UAA9C;;AAEA,gBAAIwB,gBAAgBjC,MAAMkC,GAAN,CAAU,UAAV,EAAsB,YAAW;AACnDjC,mBAAKkC,GAAL,CAAS,OAAT,EAAkB,2BAAlB;AACAF;AACD,aAHmB,CAApB;;AAKA9B,iBAAKrE,MAAL,CAAYC,EAAZ,CAAe,QAAf,EAAyB,UAACqG,UAAD,EAAgB;AACvChC,qBAAOgC,cAAchC,IAArB;AACA,kBAAIA,IAAJ,EAAU;AACRW;AACD;AACDZ,mBAAKkC,kBAAL;AACD,aAND;AAOD;;;;QAnS4BxJ,S;;AAsS/BmC,uBAAiBsH,WAAjB,GAA+B,4BAA/B;kCAeEtH,gB;;2BACAA,gB","file":"module.js","sourcesContent":["/**\n * Grafana-Zabbix\n * Zabbix plugin for Grafana.\n * http://github.com/alexanderzobnin/grafana-zabbix\n *\n * Trigger panel.\n * This feature sponsored by CORE IT\n * http://www.coreit.fr\n *\n * Copyright 2015 Alexander Zobnin alexanderzobnin@gmail.com\n * Licensed under the Apache License, Version 2.0\n */\n\nimport _ from 'lodash';\nimport $ from 'jquery';\nimport moment from 'moment';\nimport {loadPluginCss} from 'app/plugins/sdk';\nimport * as utils from '../datasource-zabbix/utils';\nimport {PanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\n\nloadPluginCss({\n dark: 'plugins/alexanderzobnin-zabbix-app/css/grafana-zabbix.dark.css',\n light: 'plugins/alexanderzobnin-zabbix-app/css/grafana-zabbix.light.css'\n});\n\nvar defaultSeverity = [\n { priority: 0, severity: 'Not classified', color: '#B7DBAB', show: true },\n { priority: 1, severity: 'Information', color: '#82B5D8', show: true },\n { priority: 2, severity: 'Warning', color: '#E5AC0E', show: true },\n { priority: 3, severity: 'Average', color: '#C15C17', show: true },\n { priority: 4, severity: 'High', color: '#BF1B00', show: true },\n { priority: 5, severity: 'Disaster', color: '#890F02', show: true }\n];\n\nvar panelDefaults = {\n datasource: null,\n triggers: {\n group: {filter: \"\"},\n host: {filter: \"\"},\n application: {filter: \"\"},\n trigger: {filter: \"\"}\n },\n hostField: true,\n statusField: false,\n severityField: false,\n lastChangeField: true,\n ageField: true,\n infoField: true,\n limit: 10,\n showTriggers: 'all triggers',\n hideHostsInMaintenance: false,\n sortTriggersBy: { text: 'last change', value: 'lastchange' },\n showEvents: { text: 'Problems', value: '1' },\n triggerSeverity: defaultSeverity,\n okEventColor: 'rgba(0, 245, 153, 0.45)',\n ackEventColor: 'rgba(0, 0, 0, 0)',\n scroll: true,\n pageSize: 10,\n fontSize: '100%',\n};\n\nvar triggerStatusMap = {\n '0': 'OK',\n '1': 'Problem'\n};\n\nvar defaultTimeFormat = \"DD MMM YYYY HH:mm:ss\";\n\nclass TriggerPanelCtrl extends PanelCtrl {\n\n /** @ngInject */\n constructor($scope, $injector, $element, datasourceSrv, templateSrv, contextSrv, dashboardSrv) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\n this.dashboardSrv = dashboardSrv;\n\n this.triggerStatusMap = triggerStatusMap;\n this.defaultTimeFormat = defaultTimeFormat;\n this.pageIndex = 0;\n this.triggerList = [];\n this.currentTriggersPage = [];\n\n // Load panel defaults\n // _.cloneDeep() need for prevent changing shared defaultSeverity.\n // Load object \"by value\" istead \"by reference\".\n _.defaults(this.panel, _.cloneDeep(panelDefaults));\n\n this.events.on('init-edit-mode', this.onInitEditMode.bind(this));\n this.events.on('refresh', this.onRefresh.bind(this));\n }\n\n onInitEditMode() {\n this.addEditorTab('Options', triggerPanelEditor, 2);\n }\n\n onRefresh() {\n // ignore fetching data if another panel is in fullscreen\n if (this.otherPanelInFullscreenMode()) { return; }\n\n // clear loading/error state\n delete this.error;\n this.loading = true;\n\n return this.refreshData()\n .then(triggerList => {\n // Limit triggers number\n this.triggerList = triggerList.slice(0, this.panel.limit);\n\n this.getCurrentTriggersPage();\n\n // Notify panel that request is finished\n this.loading = false;\n\n this.render(this.triggerList);\n });\n }\n\n refreshData() {\n return this.getTriggers()\n .then(this.getAcknowledges.bind(this))\n .then(this.filterTriggers.bind(this));\n }\n\n getTriggers() {\n return this.datasourceSrv.get(this.panel.datasource)\n .then(datasource => {\n var zabbix = datasource.zabbix;\n this.zabbix = zabbix;\n this.datasource = datasource;\n var showEvents = this.panel.showEvents.value;\n var triggerFilter = this.panel.triggers;\n var hideHostsInMaintenance = this.panel.hideHostsInMaintenance;\n\n // Replace template variables\n var groupFilter = datasource.replaceTemplateVars(triggerFilter.group.filter);\n var hostFilter = datasource.replaceTemplateVars(triggerFilter.host.filter);\n var appFilter = datasource.replaceTemplateVars(triggerFilter.application.filter);\n\n let triggersOptions = {\n showTriggers: showEvents,\n hideHostsInMaintenance: hideHostsInMaintenance\n };\n\n return zabbix.getTriggers(groupFilter, hostFilter, appFilter, triggersOptions);\n })\n .then(triggers => {\n return _.map(triggers, this.formatTrigger.bind(this));\n });\n }\n\n getAcknowledges(triggerList) {\n // Request acknowledges for trigger\n var eventids = _.map(triggerList, trigger => {\n return trigger.lastEvent.eventid;\n });\n\n return this.zabbix.getAcknowledges(eventids)\n .then(events => {\n\n // Map events to triggers\n _.each(triggerList, trigger => {\n var event = _.find(events, event => {\n return event.eventid === trigger.lastEvent.eventid;\n });\n\n if (event) {\n trigger.acknowledges = _.map(event.acknowledges, ack => {\n let timestamp = moment.unix(ack.clock);\n if (this.panel.customLastChangeFormat) {\n ack.time = timestamp.format(this.panel.lastChangeFormat);\n } else {\n ack.time = timestamp.format(this.defaultTimeFormat);\n }\n ack.user = ack.alias + ' (' + ack.name + ' ' + ack.surname + ')';\n return ack;\n });\n\n // Mark acknowledged triggers with different color\n if (this.panel.markAckEvents && trigger.acknowledges.length) {\n trigger.color = this.panel.ackEventColor;\n }\n }\n });\n\n return triggerList;\n });\n }\n\n filterTriggers(triggerList) {\n // Filter triggers by description\n var triggerFilter = this.panel.triggers.trigger.filter;\n triggerFilter = this.datasource.replaceTemplateVars(triggerFilter);\n if (triggerFilter) {\n triggerList = filterTriggers(triggerList, triggerFilter);\n }\n\n // Filter acknowledged triggers\n if (this.panel.showTriggers === 'unacknowledged') {\n triggerList = _.filter(triggerList, trigger => {\n return !trigger.acknowledges;\n });\n } else if (this.panel.showTriggers === 'acknowledged') {\n triggerList = _.filter(triggerList, 'acknowledges');\n } else {\n triggerList = triggerList;\n }\n\n // Filter triggers by severity\n triggerList = _.filter(triggerList, trigger => {\n return this.panel.triggerSeverity[trigger.priority].show;\n });\n\n // Sort triggers\n if (this.panel.sortTriggersBy.value === 'priority') {\n triggerList = _.sortBy(triggerList, 'priority').reverse();\n } else {\n triggerList = _.sortBy(triggerList, 'lastchangeUnix').reverse();\n }\n\n return triggerList;\n }\n\n formatTrigger(trigger) {\n let triggerObj = trigger;\n\n // Format last change and age\n trigger.lastchangeUnix = Number(trigger.lastchange);\n let timestamp = moment.unix(trigger.lastchangeUnix);\n if (this.panel.customLastChangeFormat) {\n // User defined format\n triggerObj.lastchange = timestamp.format(this.panel.lastChangeFormat);\n } else {\n triggerObj.lastchange = timestamp.format(this.defaultTimeFormat);\n }\n triggerObj.age = timestamp.fromNow(true);\n\n // Set host that the trigger belongs\n if (trigger.hosts.length) {\n triggerObj.host = trigger.hosts[0].name;\n triggerObj.hostTechName = trigger.hosts[0].host;\n }\n\n // Set color\n if (trigger.value === '1') {\n // Problem state\n triggerObj.color = this.panel.triggerSeverity[trigger.priority].color;\n } else {\n // OK state\n triggerObj.color = this.panel.okEventColor;\n }\n\n triggerObj.severity = this.panel.triggerSeverity[trigger.priority].severity;\n return triggerObj;\n }\n\n switchComment(trigger) {\n trigger.showComment = !trigger.showComment;\n }\n\n acknowledgeTrigger(trigger, message) {\n let eventid = trigger.lastEvent.eventid;\n let grafana_user = this.contextSrv.user.name;\n let ack_message = grafana_user + ' (Grafana): ' + message;\n return this.datasourceSrv.get(this.panel.datasource)\n .then(datasource => {\n let zabbixAPI = datasource.zabbix.zabbixAPI;\n return zabbixAPI.acknowledgeEvent(eventid, ack_message);\n })\n .then(this.onRefresh.bind(this));\n }\n\n getCurrentTriggersPage() {\n let pageSize = this.panel.pageSize || 10;\n let startPos = this.pageIndex * pageSize;\n let endPos = Math.min(startPos + pageSize, this.triggerList.length);\n this.currentTriggersPage = this.triggerList.slice(startPos, endPos);\n return this.currentTriggersPage;\n }\n\n link(scope, elem, attrs, ctrl) {\n var data;\n var panel = ctrl.panel;\n var pageCount = 0;\n data = ctrl.triggerList;\n\n function getTableHeight() {\n var panelHeight = ctrl.height;\n\n if (pageCount > 1) {\n panelHeight -= 26;\n }\n\n return (panelHeight - 31) + 'px';\n }\n\n function switchPage(e) {\n let el = $(e.currentTarget);\n ctrl.pageIndex = (parseInt(el.text(), 10)-1);\n\n let pageSize = ctrl.panel.pageSize || 10;\n let startPos = ctrl.pageIndex * pageSize;\n let endPos = Math.min(startPos + pageSize, ctrl.triggerList.length);\n ctrl.currentTriggersPage = ctrl.triggerList.slice(startPos, endPos);\n\n scope.$apply();\n renderPanel();\n }\n\n function appendPaginationControls(footerElem) {\n footerElem.empty();\n\n var pageSize = ctrl.panel.pageSize || 5;\n pageCount = Math.ceil(data.length / pageSize);\n if (pageCount === 1) {\n return;\n }\n\n var startPage = Math.max(ctrl.pageIndex - 3, 0);\n var endPage = Math.min(pageCount, startPage + 9);\n\n var paginationList = $('
      ');\n\n for (var i = startPage; i < endPage; i++) {\n var activeClass = i === ctrl.pageIndex ? 'active' : '';\n var pageLinkElem = $('
    • ' + (i+1) + '
    • ');\n paginationList.append(pageLinkElem);\n }\n\n footerElem.append(paginationList);\n }\n\n function renderPanel() {\n var panelElem = elem.parents('.panel');\n var rootElem = elem.find('.triggers-panel-scroll');\n var footerElem = elem.find('.triggers-panel-footer');\n\n elem.css({'font-size': panel.fontSize});\n panelElem.addClass('triggers-panel-wrapper');\n appendPaginationControls(footerElem);\n\n rootElem.css({'max-height': panel.scroll ? getTableHeight() : '' });\n }\n\n elem.on('click', '.triggers-panel-page-link', switchPage);\n\n var unbindDestroy = scope.$on('$destroy', function() {\n elem.off('click', '.triggers-panel-page-link');\n unbindDestroy();\n });\n\n ctrl.events.on('render', (renderData) => {\n data = renderData || data;\n if (data) {\n renderPanel();\n }\n ctrl.renderingCompleted();\n });\n }\n}\n\nTriggerPanelCtrl.templateUrl = 'panel-triggers/module.html';\n\nfunction filterTriggers(triggers, triggerFilter) {\n if (utils.isRegex(triggerFilter)) {\n return _.filter(triggers, function(trigger) {\n return utils.buildRegex(triggerFilter).test(trigger.description);\n });\n } else {\n return _.filter(triggers, function(trigger) {\n return trigger.description === triggerFilter;\n });\n }\n}\n\nexport {\n TriggerPanelCtrl,\n TriggerPanelCtrl as PanelCtrl\n};\n"]} \ No newline at end of file diff --git a/dist/plugin.json b/dist/plugin.json index 6bbab7e..9f15b89 100644 --- a/dist/plugin.json +++ b/dist/plugin.json @@ -26,8 +26,8 @@ {"name": "Metric Editor", "path": "img/screenshot-metric_editor.png"}, {"name": "Triggers", "path": "img/screenshot-triggers.png"} ], - "version": "3.4.0", - "updated": "2017-05-17" + "version": "3.5.1", + "updated": "2017-07-10" }, "includes": [ diff --git a/dist/test/datasource-zabbix/config.controller.js b/dist/test/datasource-zabbix/config.controller.js new file mode 100644 index 0000000..4cf0090 --- /dev/null +++ b/dist/test/datasource-zabbix/config.controller.js @@ -0,0 +1,50 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ZabbixDSConfigController = undefined; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var SUPPORTED_SQL_DS = ['mysql']; + +var defaultConfig = { + dbConnection: { + enable: false + } +}; + +var ZabbixDSConfigController = exports.ZabbixDSConfigController = function () { + /** @ngInject */ + function ZabbixDSConfigController($scope, $injector, datasourceSrv) { + _classCallCheck(this, ZabbixDSConfigController); + + this.datasourceSrv = datasourceSrv; + + _lodash2.default.defaults(this.current.jsonData, defaultConfig); + this.sqlDataSources = this.getSupportedSQLDataSources(); + } + + _createClass(ZabbixDSConfigController, [{ + key: 'getSupportedSQLDataSources', + value: function getSupportedSQLDataSources() { + var datasources = this.datasourceSrv.getAll(); + return _lodash2.default.filter(datasources, function (ds) { + return _lodash2.default.includes(SUPPORTED_SQL_DS, ds.type); + }); + } + }]); + + return ZabbixDSConfigController; +}(); + +ZabbixDSConfigController.templateUrl = 'datasource-zabbix/partials/config.html'; diff --git a/dist/test/datasource-zabbix/constants.js b/dist/test/datasource-zabbix/constants.js index 1c985cd..1670215 100644 --- a/dist/test/datasource-zabbix/constants.js +++ b/dist/test/datasource-zabbix/constants.js @@ -5,8 +5,9 @@ Object.defineProperty(exports, "__esModule", { }); // Editor modes var MODE_METRICS = exports.MODE_METRICS = 0; -var MODE_TEXT = exports.MODE_TEXT = 2; var MODE_ITSERVICE = exports.MODE_ITSERVICE = 1; +var MODE_TEXT = exports.MODE_TEXT = 2; +var MODE_ITEMID = exports.MODE_ITEMID = 3; // Triggers severity var SEV_NOT_CLASSIFIED = exports.SEV_NOT_CLASSIFIED = 0; diff --git a/dist/test/datasource-zabbix/datasource.js b/dist/test/datasource-zabbix/datasource.js index 5723da5..e11af3e 100644 --- a/dist/test/datasource-zabbix/datasource.js +++ b/dist/test/datasource-zabbix/datasource.js @@ -64,6 +64,9 @@ var ZabbixAPIDatasource = function () { this.dashboardSrv = dashboardSrv; this.zabbixAlertingSrv = zabbixAlertingSrv; + // Use custom format for template variables + this.replaceTemplateVars = _lodash2.default.partial(replaceTemplateVars, this.templateSrv); + // General data source settings this.name = instanceSettings.name; this.url = instanceSettings.url; @@ -88,10 +91,21 @@ var ZabbixAPIDatasource = function () { this.addThresholds = instanceSettings.jsonData.addThresholds; this.alertingMinSeverity = instanceSettings.jsonData.alertingMinSeverity || c.SEV_WARNING; - this.zabbix = new Zabbix(this.url, this.username, this.password, this.basicAuth, this.withCredentials, this.cacheTTL); + // Direct DB Connection options + this.enableDirectDBConnection = instanceSettings.jsonData.dbConnection.enable; + this.sqlDatasourceId = instanceSettings.jsonData.dbConnection.datasourceId; - // Use custom format for template variables - this.replaceTemplateVars = _lodash2.default.partial(replaceTemplateVars, this.templateSrv); + var zabbixOptions = { + username: this.username, + password: this.password, + basicAuth: this.basicAuth, + withCredentials: this.withCredentials, + cacheTTL: this.cacheTTL, + enableDirectDBConnection: this.enableDirectDBConnection, + sqlDatasourceId: this.sqlDatasourceId + }; + + this.zabbix = new Zabbix(this.url, zabbixOptions); } //////////////////////// @@ -126,6 +140,11 @@ var ZabbixAPIDatasource = function () { // Create request for each target var promises = _lodash2.default.map(options.targets, function (t) { + // Don't request undefined and hidden targets + if (t.hide) { + return []; + } + var timeFrom = Math.ceil(dateMath.parse(options.range.from) / 1000); var timeTo = Math.ceil(dateMath.parse(options.range.to) / 1000); @@ -149,7 +168,7 @@ var ZabbixAPIDatasource = function () { var useTrends = _this.isUseTrends(timeRange); // Metrics or Text query mode - if (target.mode !== c.MODE_ITSERVICE) { + if (target.mode === c.MODE_METRICS || target.mode === c.MODE_TEXT || target.mode === c.MODE_ITEMID) { // Migrate old targets target = migrations.migrate(target); @@ -162,20 +181,13 @@ var ZabbixAPIDatasource = function () { return _this.queryNumericData(target, timeRange, useTrends, options); } else if (target.mode === c.MODE_TEXT) { return _this.queryTextData(target, timeRange); + } else if (target.mode === c.MODE_ITEMID) { + return _this.queryItemIdData(target, timeRange, useTrends, options); } + } else if (target.mode === c.MODE_ITSERVICE) { + // IT services mode + return _this.queryITServiceData(target, timeRange, options); } - - // IT services mode - else if (target.mode === c.MODE_ITSERVICE) { - // Don't show undefined and hidden targets - if (target.hide || !target.itservice || !target.slaProperty) { - return []; - } - - return _this.zabbix.getSLA(target.itservice.serviceid, timeRange).then(function (slaObject) { - return _responseHandler2.default.handleSLAResponse(target.itservice, target.slaProperty, slaObject); - }); - } }); // Data for panel (all targets) @@ -183,24 +195,48 @@ var ZabbixAPIDatasource = function () { return { data: data }; }); } + + /** + * Query target data for Metrics mode + */ + }, { key: 'queryNumericData', value: function queryNumericData(target, timeRange, useTrends, options) { var _this2 = this; - var _timeRange = _slicedToArray(timeRange, 2), - timeFrom = _timeRange[0], - timeTo = _timeRange[1]; - var getItemOptions = { itemtype: 'num' }; return this.zabbix.getItemsFromTarget(target, getItemOptions).then(function (items) { - var getHistoryPromise = void 0; + return _this2.queryNumericDataForItems(items, target, timeRange, useTrends, options); + }); + } - if (useTrends) { - var valueType = _this2.getTrendValueType(target); - getHistoryPromise = _this2.zabbix.getTrend(items, timeFrom, timeTo).then(function (history) { + /** + * Query history for numeric items + */ + + }, { + key: 'queryNumericDataForItems', + value: function queryNumericDataForItems(items, target, timeRange, useTrends, options) { + var _this3 = this; + + var _timeRange = _slicedToArray(timeRange, 2), + timeFrom = _timeRange[0], + timeTo = _timeRange[1]; + + var getHistoryPromise = void 0; + options.consolidateBy = getConsolidateBy(target); + + if (useTrends) { + if (this.enableDirectDBConnection) { + getHistoryPromise = this.zabbix.getTrendsDB(items, timeFrom, timeTo, options).then(function (history) { + return _this3.zabbix.dbConnector.handleGrafanaTSResponse(history, items); + }); + } else { + var valueType = this.getTrendValueType(target); + getHistoryPromise = this.zabbix.getTrend(items, timeFrom, timeTo).then(function (history) { return _responseHandler2.default.handleTrends(history, items, valueType); }).then(function (timeseries) { // Sort trend data, issue #202 @@ -209,19 +245,24 @@ var ZabbixAPIDatasource = function () { return point[c.DATAPOINT_TS]; }); }); - return timeseries; }); + } + } else { + // Use history + if (this.enableDirectDBConnection) { + getHistoryPromise = this.zabbix.getHistoryDB(items, timeFrom, timeTo, options).then(function (history) { + return _this3.zabbix.dbConnector.handleGrafanaTSResponse(history, items); + }); } else { - // Use history - getHistoryPromise = _this2.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) { + getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) { return _responseHandler2.default.handleHistory(history, items); }); } + } - return getHistoryPromise; - }).then(function (timeseries) { - return _this2.applyDataProcessingFunctions(timeseries, target); + return getHistoryPromise.then(function (timeseries) { + return _this3.applyDataProcessingFunctions(timeseries, target); }).then(function (timeseries) { return downsampleSeries(timeseries, options); }).catch(function (error) { @@ -297,10 +338,15 @@ var ZabbixAPIDatasource = function () { }); } } + + /** + * Query target data for Text mode + */ + }, { key: 'queryTextData', value: function queryTextData(target, timeRange) { - var _this3 = this; + var _this4 = this; var _timeRange2 = _slicedToArray(timeRange, 2), timeFrom = _timeRange2[0], @@ -311,7 +357,7 @@ var ZabbixAPIDatasource = function () { }; return this.zabbix.getItemsFromTarget(target, options).then(function (items) { if (items.length) { - return _this3.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) { + return _this4.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) { return _responseHandler2.default.handleText(history, items, target); }); } else { @@ -320,6 +366,74 @@ var ZabbixAPIDatasource = function () { }); } + /** + * Query target data for Item ID mode + */ + + }, { + key: 'queryItemIdData', + value: function queryItemIdData(target, timeRange, useTrends, options) { + var _this5 = this; + + var itemids = target.itemids; + itemids = this.templateSrv.replace(itemids, options.scopedVars, zabbixItemIdsTemplateFormat); + itemids = _lodash2.default.map(itemids.split(','), function (itemid) { + return itemid.trim(); + }); + + if (!itemids) { + return []; + } + + return this.zabbix.getItemsByIDs(itemids).then(function (items) { + return _this5.queryNumericDataForItems(items, target, timeRange, useTrends, options); + }); + } + + /** + * Query target data for IT Services mode + */ + + }, { + key: 'queryITServiceData', + value: function queryITServiceData(target, timeRange, options) { + var _this6 = this; + + // Don't show undefined and hidden targets + if (target.hide || !target.itservice && !target.itServiceFilter || !target.slaProperty) { + return []; + } + + var itServiceIds = []; + var itServices = []; + var itServiceFilter = void 0; + var isOldVersion = target.itservice && !target.itServiceFilter; + + if (isOldVersion) { + // Backward compatibility + itServiceFilter = '/.*/'; + } else { + itServiceFilter = this.replaceTemplateVars(target.itServiceFilter, options.scopedVars); + } + + return this.zabbix.getITServices(itServiceFilter).then(function (itservices) { + itServices = itservices; + if (isOldVersion) { + itServices = _lodash2.default.filter(itServices, { 'serviceid': target.itservice.serviceid }); + } + + itServiceIds = _lodash2.default.map(itServices, 'serviceid'); + return itServiceIds; + }).then(function (serviceids) { + return _this6.zabbix.getSLA(serviceids, timeRange); + }).then(function (slaResponse) { + return _lodash2.default.map(itServiceIds, function (serviceid) { + var itservice = _lodash2.default.find(itServices, { 'serviceid': serviceid }); + return _responseHandler2.default.handleSLAResponse(itservice, target.slaProperty, slaResponse); + }); + }); + } + /** * Test connection to Zabbix API * @return {object} Connection status and Zabbix API version @@ -328,12 +442,18 @@ var ZabbixAPIDatasource = function () { }, { key: 'testDatasource', value: function testDatasource() { - var _this4 = this; + var _this7 = this; var zabbixVersion = void 0; return this.zabbix.getVersion().then(function (version) { zabbixVersion = version; - return _this4.zabbix.login(); + return _this7.zabbix.login(); + }).then(function () { + if (_this7.enableDirectDBConnection) { + return _this7.zabbix.dbConnector.testSQLDataSource(); + } else { + return Promise.resolve(); + } }).then(function () { return { status: "success", @@ -347,6 +467,12 @@ var ZabbixAPIDatasource = function () { title: error.message, message: error.data }; + } else if (error.data && error.data.message) { + return { + status: "error", + title: "Connection failed", + message: error.data.message + }; } else { return { status: "error", @@ -372,14 +498,14 @@ var ZabbixAPIDatasource = function () { }, { key: 'metricFindQuery', value: function metricFindQuery(query) { - var _this5 = this; + var _this8 = this; var result = void 0; var parts = []; // Split query. Query structure: group.host.app.item _lodash2.default.each(utils.splitTemplateQuery(query), function (part) { - part = _this5.replaceTemplateVars(part, {}); + part = _this8.replaceTemplateVars(part, {}); // Replace wildcard to regex if (part === '*') { @@ -421,7 +547,7 @@ var ZabbixAPIDatasource = function () { }, { key: 'annotationQuery', value: function annotationQuery(options) { - var _this6 = this; + var _this9 = this; var timeFrom = Math.ceil(dateMath.parse(options.rangeRaw.from) / 1000); var timeTo = Math.ceil(dateMath.parse(options.rangeRaw.to) / 1000); @@ -439,13 +565,14 @@ var ZabbixAPIDatasource = function () { return getTriggers.then(function (triggers) { // Filter triggers by description - if (utils.isRegex(annotation.trigger)) { + var triggerName = _this9.replaceTemplateVars(annotation.trigger, {}); + if (utils.isRegex(triggerName)) { triggers = _lodash2.default.filter(triggers, function (trigger) { - return utils.buildRegex(annotation.trigger).test(trigger.description); + return utils.buildRegex(triggerName).test(trigger.description); }); - } else if (annotation.trigger) { + } else if (triggerName) { triggers = _lodash2.default.filter(triggers, function (trigger) { - return trigger.description === annotation.trigger; + return trigger.description === triggerName; }); } @@ -455,7 +582,7 @@ var ZabbixAPIDatasource = function () { }); var objectids = _lodash2.default.map(triggers, 'triggerid'); - return _this6.zabbix.getEvents(objectids, timeFrom, timeTo, showOkEvents).then(function (events) { + return _this9.zabbix.getEvents(objectids, timeFrom, timeTo, showOkEvents).then(function (events) { var indexedTriggers = _lodash2.default.keyBy(triggers, 'triggerid'); // Hide acknowledged events if option enabled @@ -496,21 +623,23 @@ var ZabbixAPIDatasource = function () { }, { key: 'alertQuery', value: function alertQuery(options) { - var _this7 = this; + var _this10 = this; var enabled_targets = filterEnabledTargets(options.targets); - var getPanelItems = _lodash2.default.map(enabled_targets, function (target) { - return _this7.zabbix.getItemsFromTarget(target, { itemtype: 'num' }); + var getPanelItems = _lodash2.default.map(enabled_targets, function (t) { + var target = _lodash2.default.cloneDeep(t); + _this10.replaceTargetVariables(target, options); + return _this10.zabbix.getItemsFromTarget(target, { itemtype: 'num' }); }); return Promise.all(getPanelItems).then(function (results) { var items = _lodash2.default.flatten(results); var itemids = _lodash2.default.map(items, 'itemid'); - return _this7.zabbix.getAlerts(itemids); + return _this10.zabbix.getAlerts(itemids); }).then(function (triggers) { triggers = _lodash2.default.filter(triggers, function (trigger) { - return trigger.priority >= _this7.alertingMinSeverity; + return trigger.priority >= _this10.alertingMinSeverity; }); if (!triggers || triggers.length === 0) { @@ -541,12 +670,12 @@ var ZabbixAPIDatasource = function () { }, { key: 'replaceTargetVariables', value: function replaceTargetVariables(target, options) { - var _this8 = this; + var _this11 = this; var parts = ['group', 'host', 'application', 'item']; _lodash2.default.forEach(parts, function (p) { if (target[p] && target[p].filter) { - target[p].filter = _this8.replaceTemplateVars(target[p].filter, options.scopedVars); + target[p].filter = _this11.replaceTemplateVars(target[p].filter, options.scopedVars); } }); target.textFilter = this.replaceTemplateVars(target.textFilter, options.scopedVars); @@ -554,9 +683,9 @@ var ZabbixAPIDatasource = function () { _lodash2.default.forEach(target.functions, function (func) { func.params = _lodash2.default.map(func.params, function (param) { if (typeof param === 'number') { - return +_this8.templateSrv.replace(param.toString(), options.scopedVars); + return +_this11.templateSrv.replace(param.toString(), options.scopedVars); } else { - return _this8.templateSrv.replace(param, options.scopedVars); + return _this11.templateSrv.replace(param, options.scopedVars); } }); }); @@ -590,10 +719,23 @@ function bindFunctionDefs(functionDefs, category) { }); } +function getConsolidateBy(target) { + var consolidateBy = 'avg'; + var funcDef = _lodash2.default.find(target.functions, function (func) { + return func.def.name === 'consolidateBy'; + }); + if (funcDef && funcDef.params && funcDef.params.length) { + consolidateBy = funcDef.params[0]; + } + return consolidateBy; +} + function downsampleSeries(timeseries_data, options) { + var defaultAgg = _dataProcessor2.default.aggregationFunctions['avg']; + var consolidateByFunc = _dataProcessor2.default.aggregationFunctions[options.consolidateBy] || defaultAgg; return _lodash2.default.map(timeseries_data, function (timeseries) { if (timeseries.datapoints.length > options.maxDataPoints) { - timeseries.datapoints = _dataProcessor2.default.groupBy(options.interval, _dataProcessor2.default.AVERAGE, timeseries.datapoints); + timeseries.datapoints = _dataProcessor2.default.groupBy(options.interval, consolidateByFunc, timeseries.datapoints); } return timeseries; }); @@ -625,6 +767,13 @@ function zabbixTemplateFormat(value) { return '(' + escapedValues.join('|') + ')'; } +function zabbixItemIdsTemplateFormat(value) { + if (typeof value === 'string') { + return value; + } + return value.join(','); +} + /** * If template variables are used in request, replace it using regex format * and wrap with '/' for proper multi-value work. Example: diff --git a/dist/test/datasource-zabbix/module.js b/dist/test/datasource-zabbix/module.js index 10f88d0..6a44f8d 100644 --- a/dist/test/datasource-zabbix/module.js +++ b/dist/test/datasource-zabbix/module.js @@ -9,14 +9,10 @@ var _datasource = require('./datasource'); var _query = require('./query.controller'); +var _config = require('./config.controller'); + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -var ZabbixConfigController = function ZabbixConfigController() { - _classCallCheck(this, ZabbixConfigController); -}; - -ZabbixConfigController.templateUrl = 'datasource-zabbix/partials/config.html'; - var ZabbixQueryOptionsController = function ZabbixQueryOptionsController() { _classCallCheck(this, ZabbixQueryOptionsController); }; @@ -30,7 +26,7 @@ var ZabbixAnnotationsQueryController = function ZabbixAnnotationsQueryController ZabbixAnnotationsQueryController.templateUrl = 'datasource-zabbix/partials/annotations.editor.html'; exports.Datasource = _datasource.ZabbixAPIDatasource; -exports.ConfigCtrl = ZabbixConfigController; +exports.ConfigCtrl = _config.ZabbixDSConfigController; exports.QueryCtrl = _query.ZabbixQueryController; exports.QueryOptionsCtrl = ZabbixQueryOptionsController; exports.AnnotationsQueryCtrl = ZabbixAnnotationsQueryController; diff --git a/dist/test/datasource-zabbix/query.controller.js b/dist/test/datasource-zabbix/query.controller.js index 729b8b9..a0e9914 100644 --- a/dist/test/datasource-zabbix/query.controller.js +++ b/dist/test/datasource-zabbix/query.controller.js @@ -9,10 +9,6 @@ var _createClass = function () { function defineProperties(target, props) { for var _sdk = require('app/plugins/sdk'); -var _angular = require('angular'); - -var _angular2 = _interopRequireDefault(_angular); - var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); @@ -64,17 +60,24 @@ var ZabbixQueryController = exports.ZabbixQueryController = function (_QueryCtrl _this.replaceTemplateVars = _this.datasource.replaceTemplateVars; _this.templateSrv = templateSrv; - _this.editorModes = { - 0: { value: 'num', text: 'Metrics', mode: c.MODE_METRICS }, - 1: { value: 'itservice', text: 'IT Services', mode: c.MODE_ITSERVICE }, - 2: { value: 'text', text: 'Text', mode: c.MODE_TEXT } + _this.editorModes = [{ value: 'num', text: 'Metrics', mode: c.MODE_METRICS }, { value: 'text', text: 'Text', mode: c.MODE_TEXT }, { value: 'itservice', text: 'IT Services', mode: c.MODE_ITSERVICE }, { value: 'itemid', text: 'Item ID', mode: c.MODE_ITEMID }]; + + _this.$scope.editorMode = { + METRICS: c.MODE_METRICS, + TEXT: c.MODE_TEXT, + ITSERVICE: c.MODE_ITSERVICE, + ITEMID: c.MODE_ITEMID }; + _this.slaPropertyList = [{ name: "Status", property: "status" }, { name: "SLA", property: "sla" }, { name: "OK time", property: "okTime" }, { name: "Problem time", property: "problemTime" }, { name: "Down time", property: "downtimeTime" }]; + // Map functions for bs-typeahead _this.getGroupNames = _lodash2.default.bind(_this.getMetricNames, _this, 'groupList'); _this.getHostNames = _lodash2.default.bind(_this.getMetricNames, _this, 'hostList', true); _this.getApplicationNames = _lodash2.default.bind(_this.getMetricNames, _this, 'appList'); _this.getItemNames = _lodash2.default.bind(_this.getMetricNames, _this, 'itemList'); + _this.getITServices = _lodash2.default.bind(_this.getMetricNames, _this, 'itServiceList'); + _this.getVariables = _lodash2.default.bind(_this.getTemplateVariables, _this); // Update metric suggestion when template variable was changed $rootScope.$on('template-variable-value-updated', function () { @@ -101,14 +104,14 @@ var ZabbixQueryController = exports.ZabbixQueryController = function (_QueryCtrl // Load default values var targetDefaults = { - mode: c.MODE_METRICS, - group: { filter: "" }, - host: { filter: "" }, - application: { filter: "" }, - item: { filter: "" }, - functions: [], - options: { - showDisabledItems: false + 'mode': c.MODE_METRICS, + 'group': { 'filter': "" }, + 'host': { 'filter': "" }, + 'application': { 'filter': "" }, + 'item': { 'filter': "" }, + 'functions': [], + 'options': { + 'showDisabledItems': false } }; _lodash2.default.defaults(target, targetDefaults); @@ -120,13 +123,10 @@ var ZabbixQueryController = exports.ZabbixQueryController = function (_QueryCtrl if (target.mode === c.MODE_METRICS || target.mode === c.MODE_TEXT) { - this.downsampleFunctionList = [{ name: "avg", value: "avg" }, { name: "min", value: "min" }, { name: "max", value: "max" }, { name: "sum", value: "sum" }, { name: "count", value: "count" }]; - this.initFilters(); } else if (target.mode === c.MODE_ITSERVICE) { - this.slaPropertyList = [{ name: "Status", property: "status" }, { name: "SLA", property: "sla" }, { name: "OK time", property: "okTime" }, { name: "Problem time", property: "problemTime" }, { name: "Down time", property: "downtimeTime" }]; - this.itserviceList = [{ name: "test" }]; - this.updateITServiceList(); + _lodash2.default.defaults(target, { slaProperty: { name: "SLA", property: "sla" } }); + this.suggestITServices(); } }; @@ -137,7 +137,8 @@ var ZabbixQueryController = exports.ZabbixQueryController = function (_QueryCtrl _createClass(ZabbixQueryController, [{ key: 'initFilters', value: function initFilters() { - var itemtype = this.editorModes[this.target.mode].value; + var itemtype = _lodash2.default.find(this.editorModes, { 'mode': this.target.mode }); + itemtype = itemtype ? itemtype.value : null; return Promise.all([this.suggestGroups(), this.suggestHosts(), this.suggestApps(), this.suggestItems(itemtype)]); } @@ -159,6 +160,13 @@ var ZabbixQueryController = exports.ZabbixQueryController = function (_QueryCtrl return metrics; } + }, { + key: 'getTemplateVariables', + value: function getTemplateVariables() { + return _lodash2.default.map(this.templateSrv.variables, function (variable) { + return '$' + variable.name; + }); + } }, { key: 'suggestGroups', value: function suggestGroups() { @@ -212,6 +220,16 @@ var ZabbixQueryController = exports.ZabbixQueryController = function (_QueryCtrl return items; }); } + }, { + key: 'suggestITServices', + value: function suggestITServices() { + var _this6 = this; + + return this.zabbix.getITService().then(function (itservices) { + _this6.metric.itServiceList = itservices; + return itservices; + }); + } }, { key: 'isRegex', value: function isRegex(str) { @@ -246,11 +264,11 @@ var ZabbixQueryController = exports.ZabbixQueryController = function (_QueryCtrl }, { key: 'isContainsVariables', value: function isContainsVariables() { - var _this6 = this; + var _this7 = this; return _lodash2.default.some(['group', 'host', 'application'], function (field) { - if (_this6.target[field] && _this6.target[field].filter) { - return utils.isTemplateVariable(_this6.target[field].filter, _this6.templateSrv.variables); + if (_this7.target[field] && _this7.target[field].filter) { + return utils.isTemplateVariable(_this7.target[field].filter, _this7.templateSrv.variables); } else { return false; } @@ -352,38 +370,7 @@ var ZabbixQueryController = exports.ZabbixQueryController = function (_QueryCtrl value: function switchEditorMode(mode) { this.target.mode = mode; this.init(); - } - - ///////////////// - // IT Services // - ///////////////// - - /** - * Update list of IT services - */ - - }, { - key: 'updateITServiceList', - value: function updateITServiceList() { - var _this7 = this; - - this.zabbix.getITService().then(function (iteservices) { - _this7.itserviceList = []; - _this7.itserviceList = _this7.itserviceList.concat(iteservices); - }); - } - - /** - * Call when IT service is selected. - */ - - }, { - key: 'selectITService', - value: function selectITService() { - if (!_lodash2.default.isEqual(this.oldTarget, this.target) && _lodash2.default.isEmpty(this.target.errors)) { - this.oldTarget = _angular2.default.copy(this.target); - this.panelCtrl.refresh(); - } + this.targetChanged(); } }]); diff --git a/dist/test/datasource-zabbix/specs/datasource_specs.js b/dist/test/datasource-zabbix/specs/datasource_specs.js index b4c1fee..89e19ca 100644 --- a/dist/test/datasource-zabbix/specs/datasource_specs.js +++ b/dist/test/datasource-zabbix/specs/datasource_specs.js @@ -29,7 +29,10 @@ describe('ZabbixDatasource', function () { password: 'zabbix', trends: true, trendsFrom: '14d', - trendsRange: '7d' + trendsRange: '7d', + dbConnection: { + enabled: false + } } }; ctx.templateSrv = {}; diff --git a/dist/test/datasource-zabbix/specs/utils_specs.js b/dist/test/datasource-zabbix/specs/utils_specs.js index 01147dc..c381ca8 100644 --- a/dist/test/datasource-zabbix/specs/utils_specs.js +++ b/dist/test/datasource-zabbix/specs/utils_specs.js @@ -86,4 +86,46 @@ describe('Utils', function () { done(); }); }); + + describe('splitTemplateQuery()', function () { + + // Backward compatibility + it('should properly split query in old format', function (done) { + var test_cases = [{ + query: '/alu/./tw-(nyc|que|brx|dwt|brk)-sta_(w|d)*-alu-[0-9{2}/', + expected: ['/alu/', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9{2}/'] + }, { + query: 'a.b.c.d', + expected: ['a', 'b', 'c', 'd'] + }]; + + _lodash2.default.each(test_cases, function (test_case) { + var splitQuery = utils.splitTemplateQuery(test_case.query); + expect(splitQuery).to.eql(test_case.expected); + }); + done(); + }); + + it('should properly split query', function (done) { + var test_cases = [{ + query: '{alu}{/tw-(nyc|que|brx|dwt|brk)-sta_(w|d)*-alu-[0-9]*/}', + expected: ['alu', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]*/'] + }, { + query: '{alu}{/tw-(nyc|que|brx|dwt|brk)-sta_(w|d)*-alu-[0-9]{2}/}', + expected: ['alu', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]{2}/'] + }, { + query: '{a}{b}{c}{d}', + expected: ['a', 'b', 'c', 'd'] + }, { + query: '{a}{b.c.d}', + expected: ['a', 'b.c.d'] + }]; + + _lodash2.default.each(test_cases, function (test_case) { + var splitQuery = utils.splitTemplateQuery(test_case.query); + expect(splitQuery).to.eql(test_case.expected); + }); + done(); + }); + }); }); diff --git a/dist/test/datasource-zabbix/utils.js b/dist/test/datasource-zabbix/utils.js index 432ca98..6ca5c96 100644 --- a/dist/test/datasource-zabbix/utils.js +++ b/dist/test/datasource-zabbix/utils.js @@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", { }); exports.regexPattern = undefined; exports.expandItemName = expandItemName; +exports.expandItems = expandItems; exports.containsMacro = containsMacro; exports.replaceMacro = replaceMacro; exports.splitTemplateQuery = splitTemplateQuery; @@ -49,6 +50,15 @@ function expandItemName(name, key) { return name; } +function expandItems(items) { + _lodash2.default.forEach(items, function (item) { + item.item = item.name; + item.name = expandItemName(item.item, item.key_); + return item; + }); + return items; +} + function splitKeyParams(paramStr) { var params = []; var quoted = false; @@ -120,7 +130,7 @@ function escapeMacro(macro) { * {group}{host.com} -> [group, host.com] */ function splitTemplateQuery(query) { - var splitPattern = /{[^{}]*}/g; + var splitPattern = /\{[^\{\}]*\}|\{\/.*\/\}/g; var split = void 0; if (isContainsBraces(query)) { @@ -136,7 +146,8 @@ function splitTemplateQuery(query) { } function isContainsBraces(query) { - return query.includes('{') && query.includes('}'); + var bracesPattern = /^\{.+\}$/; + return bracesPattern.test(query); } // Pattern for testing regex diff --git a/dist/test/datasource-zabbix/zabbix.js b/dist/test/datasource-zabbix/zabbix.js index 3875006..6335b92 100644 --- a/dist/test/datasource-zabbix/zabbix.js +++ b/dist/test/datasource-zabbix/zabbix.js @@ -18,6 +18,8 @@ require('./zabbixAPI.service.js'); require('./zabbixCachingProxy.service.js'); +require('./zabbixDBConnector'); + function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -30,25 +32,44 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons // Each Zabbix data source instance should initialize its own API instance. /** @ngInject */ -function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy) { +function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy, ZabbixDBConnector) { var Zabbix = function () { - function Zabbix(url, username, password, basicAuth, withCredentials, cacheTTL) { + function Zabbix(url, options) { _classCallCheck(this, Zabbix); + var username = options.username, + password = options.password, + basicAuth = options.basicAuth, + withCredentials = options.withCredentials, + cacheTTL = options.cacheTTL, + enableDirectDBConnection = options.enableDirectDBConnection, + sqlDatasourceId = options.sqlDatasourceId; + // Initialize Zabbix API + var ZabbixAPI = zabbixAPIService; this.zabbixAPI = new ZabbixAPI(url, username, password, basicAuth, withCredentials); + if (enableDirectDBConnection) { + this.dbConnector = new ZabbixDBConnector(sqlDatasourceId); + } + // Initialize caching proxy for requests var cacheOptions = { enabled: true, ttl: cacheTTL }; - this.cachingProxy = new ZabbixCachingProxy(this.zabbixAPI, cacheOptions); + this.cachingProxy = new ZabbixCachingProxy(this.zabbixAPI, this.dbConnector, cacheOptions); // Proxy methods this.getHistory = this.cachingProxy.getHistory.bind(this.cachingProxy); this.getMacros = this.cachingProxy.getMacros.bind(this.cachingProxy); + this.getItemsByIDs = this.cachingProxy.getItemsByIDs.bind(this.cachingProxy); + + if (enableDirectDBConnection) { + this.getHistoryDB = this.cachingProxy.getHistoryDB.bind(this.cachingProxy); + this.getTrendsDB = this.cachingProxy.getTrendsDB.bind(this.cachingProxy); + } this.getTrend = this.zabbixAPI.getTrend.bind(this.zabbixAPI); this.getEvents = this.zabbixAPI.getEvents.bind(this.zabbixAPI); @@ -181,6 +202,13 @@ function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy) { return filterByQuery(items, itemFilter); }); } + }, { + key: 'getITServices', + value: function getITServices(itServiceFilter) { + return this.cachingProxy.getITServices().then(function (itServices) { + return findByFilter(itServices, itServiceFilter); + }); + } /** * Build query - convert target filters to array of Zabbix items diff --git a/dist/test/datasource-zabbix/zabbixAPI.service.js b/dist/test/datasource-zabbix/zabbixAPI.service.js index f28827c..7e43167 100644 --- a/dist/test/datasource-zabbix/zabbixAPI.service.js +++ b/dist/test/datasource-zabbix/zabbixAPI.service.js @@ -217,16 +217,19 @@ function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) { params.filter.value_type = [1, 2, 4]; } - return this.request('item.get', params).then(expandItems); + return this.request('item.get', params).then(utils.expandItems); + } + }, { + key: 'getItemsByIDs', + value: function getItemsByIDs(itemids) { + var params = { + itemids: itemids, + output: ['name', 'key_', 'value_type', 'hostid', 'status', 'state'], + webitems: true, + selectHosts: ['hostid', 'name'] + }; - function expandItems(items) { - _lodash2.default.forEach(items, function (item) { - item.item = item.name; - item.name = utils.expandItemName(item.item, item.key_); - return item; - }); - return items; - } + return this.request('item.get', params).then(utils.expandItems); } }, { key: 'getMacros', diff --git a/dist/test/datasource-zabbix/zabbixCachingProxy.service.js b/dist/test/datasource-zabbix/zabbixCachingProxy.service.js index 353d9cc..a3b12f5 100644 --- a/dist/test/datasource-zabbix/zabbixCachingProxy.service.js +++ b/dist/test/datasource-zabbix/zabbixCachingProxy.service.js @@ -22,10 +22,11 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons /** @ngInject */ function ZabbixCachingProxyFactory() { var ZabbixCachingProxy = function () { - function ZabbixCachingProxy(zabbixAPI, cacheOptions) { + function ZabbixCachingProxy(zabbixAPI, zabbixDBConnector, cacheOptions) { _classCallCheck(this, ZabbixCachingProxy); this.zabbixAPI = zabbixAPI; + this.dbConnector = zabbixDBConnector; this.cacheEnabled = cacheOptions.enabled; this.ttl = cacheOptions.ttl || 600000; // 10 minutes by default @@ -38,7 +39,8 @@ function ZabbixCachingProxyFactory() { history: {}, trends: {}, macros: {}, - globalMacros: {} + globalMacros: {}, + itServices: {} }; this.historyPromises = {}; @@ -46,6 +48,11 @@ function ZabbixCachingProxyFactory() { // Don't run duplicated history requests this.getHistory = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getHistory, this.zabbixAPI), this.historyPromises, getHistoryRequestHash); + if (this.dbConnector) { + this.getHistoryDB = callAPIRequestOnce(_lodash2.default.bind(this.dbConnector.getHistory, this.dbConnector), this.historyPromises, getDBQueryHash); + this.getTrendsDB = callAPIRequestOnce(_lodash2.default.bind(this.dbConnector.getTrends, this.dbConnector), this.historyPromises, getDBQueryHash); + } + // Don't run duplicated requests this.groupPromises = {}; this.getGroupsOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getGroups, this.zabbixAPI), this.groupPromises, getRequestHash); @@ -59,6 +66,12 @@ function ZabbixCachingProxyFactory() { this.itemPromises = {}; this.getItemsOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getItems, this.zabbixAPI), this.itemPromises, getRequestHash); + this.itemByIdPromises = {}; + this.getItemsByIdOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getItemsByIDs, this.zabbixAPI), this.itemPromises, getRequestHash); + + this.itServicesPromises = {}; + this.getITServicesOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getITService, this.zabbixAPI), this.itServicesPromises, getRequestHash); + this.macroPromises = {}; this.getMacrosOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getMacros, this.zabbixAPI), this.macroPromises, getRequestHash); @@ -119,6 +132,17 @@ function ZabbixCachingProxyFactory() { var params = [hostids, appids, itemtype]; return this.proxyRequest(this.getItemsOnce, params, this.cache.items); } + }, { + key: 'getItemsByIDs', + value: function getItemsByIDs(itemids) { + var params = [itemids]; + return this.proxyRequest(this.getItemsByIdOnce, params, this.cache.items); + } + }, { + key: 'getITServices', + value: function getITServices() { + return this.proxyRequest(this.getITServicesOnce, [], this.cache.itServices); + } }, { key: 'getMacros', value: function getMacros(hostids) { @@ -210,6 +234,14 @@ function getHistoryRequestHash(args) { return stamp.getHash(); } +function getDBQueryHash(args) { + var itemids = _lodash2.default.map(args[0], 'itemid'); + var consolidateBy = args[3].consolidateBy; + var intervalMs = args[3].intervalMs; + var stamp = itemids.join() + args[1] + args[2] + consolidateBy + intervalMs; + return stamp.getHash(); +} + String.prototype.getHash = function () { var hash = 0, i, diff --git a/dist/test/datasource-zabbix/zabbixDBConnector.js b/dist/test/datasource-zabbix/zabbixDBConnector.js new file mode 100644 index 0000000..54dd854 --- /dev/null +++ b/dist/test/datasource-zabbix/zabbixDBConnector.js @@ -0,0 +1,217 @@ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _angular = require('angular'); + +var _angular2 = _interopRequireDefault(_angular); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var DEFAULT_QUERY_LIMIT = 10000; +var HISTORY_TO_TABLE_MAP = { + '0': 'history', + '1': 'history_str', + '2': 'history_log', + '3': 'history_uint', + '4': 'history_text' +}; + +var TREND_TO_TABLE_MAP = { + '0': 'trends', + '3': 'trends_uint' +}; + +var consolidateByFunc = { + 'avg': 'AVG', + 'min': 'MIN', + 'max': 'MAX', + 'sum': 'SUM', + 'count': 'COUNT' +}; + +var consolidateByTrendColumns = { + 'avg': 'value_avg', + 'min': 'value_min', + 'max': 'value_max' +}; + +/** @ngInject */ +function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) { + var ZabbixDBConnector = function () { + function ZabbixDBConnector(sqlDataSourceId) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + _classCallCheck(this, ZabbixDBConnector); + + var limit = options.limit; + + + this.sqlDataSourceId = sqlDataSourceId; + this.limit = limit || DEFAULT_QUERY_LIMIT; + } + + /** + * Try to load DS with given id to check it's exist. + * @param {*} datasourceId ID of SQL data source + */ + + + _createClass(ZabbixDBConnector, [{ + key: 'loadSQLDataSource', + value: function loadSQLDataSource(datasourceId) { + var ds = _lodash2.default.find(datasourceSrv.getAll(), { 'id': datasourceId }); + if (ds) { + return datasourceSrv.loadDatasource(ds.name).then(function (ds) { + console.log('SQL data source loaded', ds); + }); + } else { + return Promise.reject('SQL Data Source with ID ' + datasourceId + ' not found'); + } + } + + /** + * Try to invoke test query for one of Zabbix database tables. + */ + + }, { + key: 'testSQLDataSource', + value: function testSQLDataSource() { + var testQuery = 'SELECT itemid AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1'; + return this.invokeSQLQuery(testQuery); + } + }, { + key: 'getHistory', + value: function getHistory(items, timeFrom, timeTill, options) { + var _this = this; + + var intervalMs = options.intervalMs, + consolidateBy = options.consolidateBy; + + var intervalSec = Math.ceil(intervalMs / 1000); + + consolidateBy = consolidateBy || 'avg'; + var aggFunction = consolidateByFunc[consolidateBy]; + + // Group items by value type and perform request for each value type + var grouped_items = _lodash2.default.groupBy(items, 'value_type'); + var promises = _lodash2.default.map(grouped_items, function (items, value_type) { + var itemids = _lodash2.default.map(items, 'itemid').join(', '); + var table = HISTORY_TO_TABLE_MAP[value_type]; + + var query = '\n SELECT itemid AS metric, clock AS time_sec, ' + aggFunction + '(value) AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY time_sec DIV ' + intervalSec + ', metric\n '; + + query = compactSQLQuery(query); + return _this.invokeSQLQuery(query); + }); + + return Promise.all(promises).then(function (results) { + return _lodash2.default.flatten(results); + }); + } + }, { + key: 'getTrends', + value: function getTrends(items, timeFrom, timeTill, options) { + var _this2 = this; + + var intervalMs = options.intervalMs, + consolidateBy = options.consolidateBy; + + var intervalSec = Math.ceil(intervalMs / 1000); + + consolidateBy = consolidateBy || 'avg'; + var aggFunction = consolidateByFunc[consolidateBy]; + + // Group items by value type and perform request for each value type + var grouped_items = _lodash2.default.groupBy(items, 'value_type'); + var promises = _lodash2.default.map(grouped_items, function (items, value_type) { + var itemids = _lodash2.default.map(items, 'itemid').join(', '); + var table = TREND_TO_TABLE_MAP[value_type]; + var valueColumn = _lodash2.default.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg'; + valueColumn = consolidateByTrendColumns[valueColumn]; + + var query = '\n SELECT itemid AS metric, clock AS time_sec, ' + aggFunction + '(' + valueColumn + ') AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY time_sec DIV ' + intervalSec + ', metric\n '; + + query = compactSQLQuery(query); + return _this2.invokeSQLQuery(query); + }); + + return Promise.all(promises).then(function (results) { + return _lodash2.default.flatten(results); + }); + } + }, { + key: 'handleGrafanaTSResponse', + value: function handleGrafanaTSResponse(history, items) { + var addHostName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; + + return convertGrafanaTSResponse(history, items, addHostName); + } + }, { + key: 'invokeSQLQuery', + value: function invokeSQLQuery(query) { + var queryDef = { + refId: 'A', + format: 'time_series', + datasourceId: this.sqlDataSourceId, + rawSql: query, + maxDataPoints: this.limit + }; + + return backendSrv.datasourceRequest({ + url: '/api/tsdb/query', + method: 'POST', + data: { + queries: [queryDef] + } + }).then(function (response) { + var results = response.data.results; + if (results['A']) { + return results['A'].series; + } else { + return null; + } + }); + } + }]); + + return ZabbixDBConnector; + }(); + + return ZabbixDBConnector; +} + +_angular2.default.module('grafana.services').factory('ZabbixDBConnector', ZabbixDBConnectorFactory); + +/////////////////////////////////////////////////////////////////////////////// + +function convertGrafanaTSResponse(time_series, items, addHostName) { + var hosts = _lodash2.default.uniqBy(_lodash2.default.flatten(_lodash2.default.map(items, 'hosts')), 'hostid'); //uniqBy is needed to deduplicate + var grafanaSeries = _lodash2.default.map(time_series, function (series) { + var itemid = series.name; + var datapoints = series.points; + var item = _lodash2.default.find(items, { 'itemid': itemid }); + var alias = item.name; + if (_lodash2.default.keys(hosts).length > 1 && addHostName) { + //only when actual multi hosts selected + var host = _lodash2.default.find(hosts, { 'hostid': item.hostid }); + alias = host.name + ": " + alias; + } + return { + target: alias, + datapoints: datapoints + }; + }); + + return _lodash2.default.sortBy(grafanaSeries, 'target'); +} + +function compactSQLQuery(query) { + return query.replace(/\s+/g, ' '); +} diff --git a/dist/test/panel-triggers/module.js b/dist/test/panel-triggers/module.js index e5da3c4..e22f1ca 100644 --- a/dist/test/panel-triggers/module.js +++ b/dist/test/panel-triggers/module.js @@ -165,6 +165,7 @@ var TriggerPanelCtrl = function (_PanelCtrl) { return this.datasourceSrv.get(this.panel.datasource).then(function (datasource) { var zabbix = datasource.zabbix; _this3.zabbix = zabbix; + _this3.datasource = datasource; var showEvents = _this3.panel.showEvents.value; var triggerFilter = _this3.panel.triggers; var hideHostsInMaintenance = _this3.panel.hideHostsInMaintenance; @@ -178,10 +179,10 @@ var TriggerPanelCtrl = function (_PanelCtrl) { showTriggers: showEvents, hideHostsInMaintenance: hideHostsInMaintenance }; - var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, triggersOptions); - return getTriggers.then(function (triggers) { - return _lodash2.default.map(triggers, _this3.formatTrigger.bind(_this3)); - }); + + return zabbix.getTriggers(groupFilter, hostFilter, appFilter, triggersOptions); + }).then(function (triggers) { + return _lodash2.default.map(triggers, _this3.formatTrigger.bind(_this3)); }); } }, { @@ -231,6 +232,7 @@ var TriggerPanelCtrl = function (_PanelCtrl) { // Filter triggers by description var triggerFilter = this.panel.triggers.trigger.filter; + triggerFilter = this.datasource.replaceTemplateVars(triggerFilter); if (triggerFilter) { triggerList = _filterTriggers(triggerList, triggerFilter); } diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index b98283b..1666dad 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -18,6 +18,7 @@ pages: - Installation: - 'Installation': 'installation/index.md' - 'Configuration': 'installation/configuration.md' + - 'SQL Data Source Configuration': 'installation/configuration-sql.md' - 'Upgrade': 'installation/upgrade.md' - 'Troubleshooting': 'installation/troubleshooting.md' - User Guides: @@ -28,5 +29,6 @@ pages: - 'Triggers Panel': 'reference/panel-triggers.md' - 'Functions': 'reference/functions.md' - 'Alerting': 'reference/alerting.md' + - 'Direct DB Connection': 'reference/direct-db-connection.md' # - Tutorials: # - 'Building Host Dashboard': 'tutorials/host_dashboard.md' diff --git a/docs/sources/features.md b/docs/sources/features.md index 9f91a5a..e61732a 100644 --- a/docs/sources/features.md +++ b/docs/sources/features.md @@ -6,6 +6,12 @@ page_description: Grafana-Zabbix Feature Highlights. Grafana in couple with Grafana-Zabbix plugin allows to create great dashboards. There is some features: -- Rich graphing with Grafana -- Template variables allow to create reusable dashboards - +- Rich graphing features +- Create interactive and reusable dashboards with [template variables](http://docs.grafana-zabbix.org/guides/templating/) +- Show events on graphs with [Annotations](http://docs.grafana.org/reference/annotations/) +- Select multiple metrics [by using Regex](http://docs.grafana-zabbix.org/guides/gettingstarted/#multiple-items-on-one-graph) +- Display active problems with Triggers panel +- Transform and shape your data with [metric processing functions](http://docs.grafana-zabbix.org/reference/functions/) (Avg, Median, Min, Max, Multiply, Summarize, Time shift, Alias) +- Find problems faster with [Alerting](http://docs.grafana-zabbix.org/reference/alerting/) feature +- Mix metrics from multiple data sources in the same dashboard or even graph +- Discover and share [dashboards](https://grafana.com/dashboards) in the official library diff --git a/docs/sources/img/.gitattributes b/docs/sources/img/.gitattributes index 257c15f..8dce774 100644 --- a/docs/sources/img/.gitattributes +++ b/docs/sources/img/.gitattributes @@ -1,3 +1,4 @@ *.png filter=lfs diff=lfs merge=lfs -text *.jpg filter=lfs diff=lfs merge=lfs -text *.psd filter=lfs diff=lfs merge=lfs -text +*.svg filter=lfs diff=lfs merge=lfs -text diff --git a/docs/sources/img/installation-datasource_config.png b/docs/sources/img/installation-datasource_config.png index f5ee615..ab3648d 100644 --- a/docs/sources/img/installation-datasource_config.png +++ b/docs/sources/img/installation-datasource_config.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b58742637f58519a5fab038db0c15b5525d1d330fe5e4a1de954b72f4f1cc3e -size 225446 +oid sha256:367b5fa51e9d05eb87afedd4ef6ed8ea1ce0e095f94bfdc58ebe6744fbaca71c +size 131343 diff --git a/docs/sources/img/installation-mysql_ds_config.png b/docs/sources/img/installation-mysql_ds_config.png new file mode 100644 index 0000000..3c8d221 --- /dev/null +++ b/docs/sources/img/installation-mysql_ds_config.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0bac25f3d28c74f1f309476120bc67275e15f420e3343f0ff9668ead3a1e6170 +size 227988 diff --git a/docs/sources/img/reference-direct-db-connection.svg b/docs/sources/img/reference-direct-db-connection.svg new file mode 100644 index 0000000..a48702c --- /dev/null +++ b/docs/sources/img/reference-direct-db-connection.svg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0b942ebdeec31f98ae800c78223fb96ec077e8396e2f33a71e29d4d6d096661 +size 200108 diff --git a/docs/sources/installation/configuration-sql.md b/docs/sources/installation/configuration-sql.md new file mode 100644 index 0000000..a1cf37a --- /dev/null +++ b/docs/sources/installation/configuration-sql.md @@ -0,0 +1,22 @@ +# SQL Data Source Configuration + +In order to use _Direct DB Connection_ feature you should configure SQL data source first. + +![Configure MySQL data source](../img/installation-mysql_ds_config.png) + +Select _MySQL_ data source type and provide your database host address and port (3306 is default for MySQL). Fill +database name (usually, `zabbix`) and specify credentials. + +## Security notes + +As you can see in _User Permission_ note, Grafana doesn't restrict any queries to the database. So you should be careful +and create a special user with limited access to Zabbix database. Grafana-Zabbix plugin uses only `SELECT` queries to +`history`, `history_uint`, `trends` and `trends_uint` tables. So it's reasonable to grant only SELECT privileges to +these tables for grafana user. But if you want to use this MySQL data source for querying another data, you can +grant SELECT privileges to entire zabbix database. + +Also, all queries are invoked by grafana-server, so you can restrict connection to only grafana host. + +```sql +GRANT SELECT ON zabbix.* TO 'grafana'@'grafana-host' identified by 'password'; +``` diff --git a/docs/sources/installation/configuration.md b/docs/sources/installation/configuration.md index ae4f78d..9d7135e 100644 --- a/docs/sources/installation/configuration.md +++ b/docs/sources/installation/configuration.md @@ -52,7 +52,23 @@ Direct access is still supported because in some cases it may be useful to acces - **Cache TTL**: plugin caches some api requests for increasing performance. Set this value to desired cache lifetime (this option affect data like items list). +### Direct DB Connection + +Direct DB Connection allows plugin to use existing SQL data source for querying history data directly from Zabbix +database. This way usually faster than pulling data from Zabbix API, especially on the wide time ranges, and reduces +amount of data transfered. + +Read [how to configure](/installation/configuration-sql) SQL data source in Grafana. + +- **Enable**: enable Direct DB Connection. +- **SQL Data Source**: Select SQL Data Source for Zabbix database. + +#### Supported databases + +Now only **MySQL** is supported by Grafana. + ### Alerting + - **Enable alerting**: enable limited alerting support. - **Add thresholds**: get thresholds info from zabbix triggers and add it to graphs. For example, if you have trigger `{Zabbix server:system.cpu.util[,iowait].avg(5m)}>20`, threshold will be set to 20. @@ -65,10 +81,12 @@ or password, wrong api url. ![Test Connection](../img/installation-test_connection.png) ## Import example dashboards + You can import dashboard examples from _Dashboards_ tab in plugin config. ![Import dashboards](../img/installation-plugin-dashboards.png) ## Note about Zabbix 2.2 or less + Zabbix API (api_jsonrpc.php) before zabbix 2.4 don't allow cross-domain requests (CORS). And you can get HTTP error 412 (Precondition Failed). To fix it add this code to api_jsonrpc.php immediately after the copyright: @@ -83,17 +101,20 @@ if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { return; } ``` + before ```php require_once dirname(__FILE__).'/include/func.inc.php'; require_once dirname(__FILE__).'/include/classes/core/CHttpRequest.php'; ``` + [Full fix listing](https://gist.github.com/alexanderzobnin/f2348f318d7a93466a0c). For more details see zabbix issues [ZBXNEXT-1377](https://support.zabbix.com/browse/ZBXNEXT-1377) and [ZBX-8459](https://support.zabbix.com/browse/ZBX-8459). ## Note about Browser Cache + After updating plugin, clear browser cache and reload application page. See details for [Chrome](https://support.google.com/chrome/answer/95582), [Firefox](https://support.mozilla.org/en-US/kb/how-clear-firefox-cache). You need to clear cache diff --git a/docs/sources/reference/direct-db-connection.md b/docs/sources/reference/direct-db-connection.md new file mode 100644 index 0000000..3d9aaea --- /dev/null +++ b/docs/sources/reference/direct-db-connection.md @@ -0,0 +1,51 @@ +# Direct DB Connection + +Since version 4.3 Grafana has MySQL data source, Grafana-Zabbix plugin can use it for querying data directly from +Zabbix database. + +One of the most hard queries for Zabbix API is history queries. For long time intervals `history.get` +returns huge amount of data. In order to display it, plugin should adjust time series resolution +by using [consolidateBy](/reference/functions/#consolidateby) function. Ultimately, Grafana displays this reduced +time series, but that data should be loaded and processed on the client side first. Direct DB Connection solves this +two problems by moving consolidation to the server side. Thus, client get ready-to-use dataset which has much smaller +size. Data loads faster and client doesn't spend time for data processing. + +Also, many users point better performance of direct database queries versus API calls. This caused by several reasons, +such as additional PHP layer and additional SQL queries (user permissions checks). + +## Data Flow + +This chart illustrates how plugin uses both Zabbix API and MySQL data source for querying different types +of data from Zabbix. MySQL data source is used only for pulling history and trend data instead of `history.get` +and `trend.get` API calls. + +[![Direct DB Connection](../img/reference-direct-db-connection.svg)](../img/reference-direct-db-connection.svg) + +## Query structure + +Grafana-Zabbix uses queries like this for getting history: + +```sql +SELECT itemid AS metric, clock AS time_sec, {aggFunc}(value) as value + FROM {historyTable} + WHERE itemid IN ({itemids}) + AND clock > {timeFrom} AND clock < {timeTill} + GROUP BY time_sec DIV {intervalSec}, metric +``` + +where `{aggFunc}` is one of `[AVG, MIN, MAX, SUM, COUNT]` aggregation function, `{historyTable}` is a history table, +`{intervalSec}` - consolidation interval in seconds. + +When getting trends, plugin additionally queries particular value column (`value_avg`, `value_min` or `value_max`) +depends on `consolidateBy` function value: + +```sql +SELECT itemid AS metric, clock AS time_sec, {aggFunc}({valueColumn}) as value + FROM {trendsTable} + WHERE itemid IN ({itemids}) + AND clock > {timeFrom} AND clock < {timeTill} + GROUP BY time_sec DIV {intervalSec}, metric +``` + +As you can see, plugin uses aggregation by given time interval. This interval is provided by Grafana and depends on the +panel with in pixels. Thus, Grafana always gets data in necessary resolution. diff --git a/docs/sources/reference/functions.md b/docs/sources/reference/functions.md index 17e800a..69aba1b 100644 --- a/docs/sources/reference/functions.md +++ b/docs/sources/reference/functions.md @@ -197,3 +197,14 @@ replaceAlias(/.*CPU (.*) time/, $1) -> system backend01: CPU system time replaceAlias(/(.*): CPU (.*) time/, $1 - $2) -> backend01 - system ``` + +## Special + +### consolidateBy +``` +consolidateBy(consolidationFunc) +``` + +When a graph is drawn where width of the graph size in pixels is smaller than the number of datapoints to be graphed, plugin consolidates the values to to prevent line overlap. The consolidateBy() function changes the consolidation function from the default of average to one of `sum`, `min`, `max` or `count`. + +Valid function names are `sum`, `avg`, `min`, `max` and `count`. diff --git a/package.json b/package.json index 4edc740..5341a44 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "grafana-zabbix", "private": false, - "version": "3.2.0", + "version": "3.5.1", "description": "Zabbix plugin for Grafana", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" diff --git a/src/README.md b/src/README.md index c4b79fd..625f818 100644 --- a/src/README.md +++ b/src/README.md @@ -1,28 +1,22 @@ -## Zabbix plugin for Grafana +# Zabbix plugin for Grafana +[![GitHub version](https://badge.fury.io/gh/alexanderzobnin%2Fgrafana-zabbix.svg)](https://github.com/alexanderzobnin/grafana-zabbix/releases) +[![Change Log](https://img.shields.io/badge/change-log-blue.svg?style=flat)](https://github.com/alexanderzobnin/grafana-zabbix/blob/master/CHANGELOG.md) [![Docs](https://img.shields.io/badge/docs-latest-red.svg?style=flat)](http://docs.grafana-zabbix.org) -[![License](https://img.shields.io/badge/license-Apache_2.0-lightgrey.svg?style=flat)](https://github.com/alexanderzobnin/grafana-zabbix/blob/master/LICENSE) -Zabbix plugin allows to show different type of data from [Zabbix](http://www.zabbix.com/) -monitoring system. +Visualize your Zabbix metrics with the leading open source software for time series analytics. ### Live Demo -Check out the [live demo](http://play.grafana-zabbix.org/) with dashboard examples. +See all features overview and dashboards examples at Grafana-Zabbix [Live demo](http://play.grafana-zabbix.org) site. ### Features -#### Flexible metric editor - * Regex-based metric filtering - * Client-side data processing functions - * Template variables support - -#### Templated dashboards support -Group, host, application or item names can be replaced with a template variable. This allows you to create generic dashboards that can quickly be changed to show stats for a specific cluster, server or application. - -#### Annotations support - * Display zabbix events on graphs - * Show acknowledges for problems - -#### Triggers panel -Panel for showing Zabbix triggers (like Last 20 issues) with some customizable features. +- Select multiple metrics [by using Regex](http://docs.grafana-zabbix.org/guides/gettingstarted/#multiple-items-on-one-graph) +- Create interactive and reusable dashboards with [template variables](http://docs.grafana-zabbix.org/guides/templating/) +- Show events on graphs with [Annotations](http://docs.grafana.org/reference/annotations/) +- Display active problems with Triggers panel +- Transform and shape your data with [metric processing functions](http://docs.grafana-zabbix.org/reference/functions/) (Avg, Median, Min, Max, Multiply, Summarize, Time shift, Alias) +- Find problems faster with [Alerting](http://docs.grafana-zabbix.org/reference/alerting/) feature +- Mix metrics from multiple data sources in the same dashboard or even graph +- Discover and share [dashboards](https://grafana.com/dashboards) in the official library diff --git a/src/datasource-zabbix/config.controller.js b/src/datasource-zabbix/config.controller.js new file mode 100644 index 0000000..226572c --- /dev/null +++ b/src/datasource-zabbix/config.controller.js @@ -0,0 +1,28 @@ +import _ from 'lodash'; + +const SUPPORTED_SQL_DS = ['mysql']; + +const defaultConfig = { + dbConnection: { + enable: false, + } +}; + +export class ZabbixDSConfigController { + /** @ngInject */ + constructor($scope, $injector, datasourceSrv) { + this.datasourceSrv = datasourceSrv; + + _.defaults(this.current.jsonData, defaultConfig); + this.sqlDataSources = this.getSupportedSQLDataSources(); + } + + getSupportedSQLDataSources() { + let datasources = this.datasourceSrv.getAll(); + return _.filter(datasources, ds => { + return _.includes(SUPPORTED_SQL_DS, ds.type); + }); + } +} + +ZabbixDSConfigController.templateUrl = 'datasource-zabbix/partials/config.html'; diff --git a/src/datasource-zabbix/constants.js b/src/datasource-zabbix/constants.js index de3625b..4d76ab6 100644 --- a/src/datasource-zabbix/constants.js +++ b/src/datasource-zabbix/constants.js @@ -1,7 +1,8 @@ // Editor modes export const MODE_METRICS = 0; -export const MODE_TEXT = 2; export const MODE_ITSERVICE = 1; +export const MODE_TEXT = 2; +export const MODE_ITEMID = 3; // Triggers severity export const SEV_NOT_CLASSIFIED = 0; diff --git a/src/datasource-zabbix/datasource.js b/src/datasource-zabbix/datasource.js index a07f006..508fcab 100644 --- a/src/datasource-zabbix/datasource.js +++ b/src/datasource-zabbix/datasource.js @@ -19,6 +19,9 @@ class ZabbixAPIDatasource { this.dashboardSrv = dashboardSrv; this.zabbixAlertingSrv = zabbixAlertingSrv; + // Use custom format for template variables + this.replaceTemplateVars = _.partial(replaceTemplateVars, this.templateSrv); + // General data source settings this.name = instanceSettings.name; this.url = instanceSettings.url; @@ -43,10 +46,21 @@ class ZabbixAPIDatasource { this.addThresholds = instanceSettings.jsonData.addThresholds; this.alertingMinSeverity = instanceSettings.jsonData.alertingMinSeverity || c.SEV_WARNING; - this.zabbix = new Zabbix(this.url, this.username, this.password, this.basicAuth, this.withCredentials, this.cacheTTL); + // Direct DB Connection options + this.enableDirectDBConnection = instanceSettings.jsonData.dbConnection.enable; + this.sqlDatasourceId = instanceSettings.jsonData.dbConnection.datasourceId; - // Use custom format for template variables - this.replaceTemplateVars = _.partial(replaceTemplateVars, this.templateSrv); + let zabbixOptions = { + username: this.username, + password: this.password, + basicAuth: this.basicAuth, + withCredentials: this.withCredentials, + cacheTTL: this.cacheTTL, + enableDirectDBConnection: this.enableDirectDBConnection, + sqlDatasourceId: this.sqlDatasourceId + }; + + this.zabbix = new Zabbix(this.url, zabbixOptions); } //////////////////////// @@ -75,6 +89,11 @@ class ZabbixAPIDatasource { // Create request for each target let promises = _.map(options.targets, t => { + // Don't request undefined and hidden targets + if (t.hide) { + return []; + } + let timeFrom = Math.ceil(dateMath.parse(options.range.from) / 1000); let timeTo = Math.ceil(dateMath.parse(options.range.to) / 1000); @@ -94,7 +113,7 @@ class ZabbixAPIDatasource { let useTrends = this.isUseTrends(timeRange); // Metrics or Text query mode - if (target.mode !== c.MODE_ITSERVICE) { + if (target.mode === c.MODE_METRICS || target.mode === c.MODE_TEXT || target.mode === c.MODE_ITEMID) { // Migrate old targets target = migrations.migrate(target); @@ -107,20 +126,12 @@ class ZabbixAPIDatasource { return this.queryNumericData(target, timeRange, useTrends, options); } else if (target.mode === c.MODE_TEXT) { return this.queryTextData(target, timeRange); + } else if (target.mode === c.MODE_ITEMID) { + return this.queryItemIdData(target, timeRange, useTrends, options); } - } - - // IT services mode - else if (target.mode === c.MODE_ITSERVICE) { - // Don't show undefined and hidden targets - if (target.hide || !target.itservice || !target.slaProperty) { - return []; - } - - return this.zabbix.getSLA(target.itservice.serviceid, timeRange) - .then(slaObject => { - return responseHandler.handleSLAResponse(target.itservice, target.slaProperty, slaObject); - }); + } else if (target.mode === c.MODE_ITSERVICE) { + // IT services mode + return this.queryITServiceData(target, timeRange, options); } }); @@ -132,39 +143,55 @@ class ZabbixAPIDatasource { }); } + /** + * Query target data for Metrics mode + */ queryNumericData(target, timeRange, useTrends, options) { - let [timeFrom, timeTo] = timeRange; let getItemOptions = { itemtype: 'num' }; return this.zabbix.getItemsFromTarget(target, getItemOptions) .then(items => { - let getHistoryPromise; + return this.queryNumericDataForItems(items, target, timeRange, useTrends, options); + }); + } - if (useTrends) { + /** + * Query history for numeric items + */ + queryNumericDataForItems(items, target, timeRange, useTrends, options) { + let [timeFrom, timeTo] = timeRange; + let getHistoryPromise; + options.consolidateBy = getConsolidateBy(target); + + if (useTrends) { + if (this.enableDirectDBConnection) { + getHistoryPromise = this.zabbix.getTrendsDB(items, timeFrom, timeTo, options) + .then(history => this.zabbix.dbConnector.handleGrafanaTSResponse(history, items)); + } else { let valueType = this.getTrendValueType(target); getHistoryPromise = this.zabbix.getTrend(items, timeFrom, timeTo) - .then(history => { - return responseHandler.handleTrends(history, items, valueType); - }) + .then(history => responseHandler.handleTrends(history, items, valueType)) .then(timeseries => { // Sort trend data, issue #202 _.forEach(timeseries, series => { series.datapoints = _.sortBy(series.datapoints, point => point[c.DATAPOINT_TS]); }); - return timeseries; }); - } else { - // Use history - getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo) - .then(history => { - return responseHandler.handleHistory(history, items); - }); } + } else { + // Use history + if (this.enableDirectDBConnection) { + getHistoryPromise = this.zabbix.getHistoryDB(items, timeFrom, timeTo, options) + .then(history => this.zabbix.dbConnector.handleGrafanaTSResponse(history, items)); + } else { + getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo) + .then(history => responseHandler.handleHistory(history, items)); + } + } - return getHistoryPromise; - }) + return getHistoryPromise .then(timeseries => this.applyDataProcessingFunctions(timeseries, target)) .then(timeseries => downsampleSeries(timeseries, options)) .catch(error => { @@ -238,6 +265,9 @@ class ZabbixAPIDatasource { } } + /** + * Query target data for Text mode + */ queryTextData(target, timeRange) { let [timeFrom, timeTo] = timeRange; let options = { @@ -256,6 +286,66 @@ class ZabbixAPIDatasource { }); } + /** + * Query target data for Item ID mode + */ + queryItemIdData(target, timeRange, useTrends, options) { + let itemids = target.itemids; + itemids = this.templateSrv.replace(itemids, options.scopedVars, zabbixItemIdsTemplateFormat); + itemids = _.map(itemids.split(','), itemid => itemid.trim()); + + if (!itemids) { + return []; + } + + return this.zabbix.getItemsByIDs(itemids) + .then(items => { + return this.queryNumericDataForItems(items, target, timeRange, useTrends, options); + }); + } + + /** + * Query target data for IT Services mode + */ + queryITServiceData(target, timeRange, options) { + // Don't show undefined and hidden targets + if (target.hide || (!target.itservice && !target.itServiceFilter) || !target.slaProperty) { + return []; + } + + let itServiceIds = []; + let itServices = []; + let itServiceFilter; + let isOldVersion = target.itservice && !target.itServiceFilter; + + if (isOldVersion) { + // Backward compatibility + itServiceFilter = '/.*/'; + } else { + itServiceFilter = this.replaceTemplateVars(target.itServiceFilter, options.scopedVars); + } + + return this.zabbix.getITServices(itServiceFilter) + .then(itservices => { + itServices = itservices; + if (isOldVersion) { + itServices = _.filter(itServices, {'serviceid': target.itservice.serviceid}); + } + + itServiceIds = _.map(itServices, 'serviceid'); + return itServiceIds; + }) + .then(serviceids => { + return this.zabbix.getSLA(serviceids, timeRange); + }) + .then(slaResponse => { + return _.map(itServiceIds, serviceid => { + let itservice = _.find(itServices, {'serviceid': serviceid}); + return responseHandler.handleSLAResponse(itservice, target.slaProperty, slaResponse); + }); + }); + } + /** * Test connection to Zabbix API * @return {object} Connection status and Zabbix API version @@ -267,6 +357,13 @@ class ZabbixAPIDatasource { zabbixVersion = version; return this.zabbix.login(); }) + .then(() => { + if (this.enableDirectDBConnection) { + return this.zabbix.dbConnector.testSQLDataSource(); + } else { + return Promise.resolve(); + } + }) .then(() => { return { status: "success", @@ -281,6 +378,12 @@ class ZabbixAPIDatasource { title: error.message, message: error.data }; + } else if (error.data && error.data.message) { + return { + status: "error", + title: "Connection failed", + message: error.data.message + }; } else { return { status: "error", @@ -367,13 +470,14 @@ class ZabbixAPIDatasource { return getTriggers.then(triggers => { // Filter triggers by description - if (utils.isRegex(annotation.trigger)) { + let triggerName = this.replaceTemplateVars(annotation.trigger, {}); + if (utils.isRegex(triggerName)) { triggers = _.filter(triggers, trigger => { - return utils.buildRegex(annotation.trigger).test(trigger.description); + return utils.buildRegex(triggerName).test(trigger.description); }); - } else if (annotation.trigger) { + } else if (triggerName) { triggers = _.filter(triggers, trigger => { - return trigger.description === annotation.trigger; + return trigger.description === triggerName; }); } @@ -424,7 +528,9 @@ class ZabbixAPIDatasource { */ alertQuery(options) { let enabled_targets = filterEnabledTargets(options.targets); - let getPanelItems = _.map(enabled_targets, target => { + let getPanelItems = _.map(enabled_targets, t => { + let target = _.cloneDeep(t); + this.replaceTargetVariables(target, options); return this.zabbix.getItemsFromTarget(target, {itemtype: 'num'}); }); @@ -508,11 +614,24 @@ function bindFunctionDefs(functionDefs, category) { }); } +function getConsolidateBy(target) { + let consolidateBy = 'avg'; + let funcDef = _.find(target.functions, func => { + return func.def.name === 'consolidateBy'; + }); + if (funcDef && funcDef.params && funcDef.params.length) { + consolidateBy = funcDef.params[0]; + } + return consolidateBy; +} + function downsampleSeries(timeseries_data, options) { + let defaultAgg = dataProcessor.aggregationFunctions['avg']; + let consolidateByFunc = dataProcessor.aggregationFunctions[options.consolidateBy] || defaultAgg; return _.map(timeseries_data, timeseries => { if (timeseries.datapoints.length > options.maxDataPoints) { timeseries.datapoints = dataProcessor - .groupBy(options.interval, dataProcessor.AVERAGE, timeseries.datapoints); + .groupBy(options.interval, consolidateByFunc, timeseries.datapoints); } return timeseries; }); @@ -544,6 +663,13 @@ function zabbixTemplateFormat(value) { return '(' + escapedValues.join('|') + ')'; } +function zabbixItemIdsTemplateFormat(value) { + if (typeof value === 'string') { + return value; + } + return value.join(','); +} + /** * If template variables are used in request, replace it using regex format * and wrap with '/' for proper multi-value work. Example: diff --git a/src/datasource-zabbix/metricFunctions.js b/src/datasource-zabbix/metricFunctions.js index e167f3a..ca04c32 100644 --- a/src/datasource-zabbix/metricFunctions.js +++ b/src/datasource-zabbix/metricFunctions.js @@ -8,7 +8,8 @@ var categories = { Filter: [], Trends: [], Time: [], - Alias: [] + Alias: [], + Special: [] }; function addFuncDef(funcDef) { @@ -222,6 +223,16 @@ addFuncDef({ defaultParams: ['/(.*)/', '$1'] }); +// Special +addFuncDef({ + name: 'consolidateBy', + category: 'Special', + params: [ + { name: 'type', type: 'string', options: ['avg', 'min', 'max', 'sum', 'count'] } + ], + defaultParams: ['avg'], +}); + _.each(categories, function(funcList, catName) { categories[catName] = _.sortBy(funcList, 'name'); }); diff --git a/src/datasource-zabbix/module.js b/src/datasource-zabbix/module.js index 35bb3af..2913139 100644 --- a/src/datasource-zabbix/module.js +++ b/src/datasource-zabbix/module.js @@ -1,8 +1,6 @@ import {ZabbixAPIDatasource} from './datasource'; import {ZabbixQueryController} from './query.controller'; - -class ZabbixConfigController {} -ZabbixConfigController.templateUrl = 'datasource-zabbix/partials/config.html'; +import {ZabbixDSConfigController} from './config.controller'; class ZabbixQueryOptionsController {} ZabbixQueryOptionsController.templateUrl = 'datasource-zabbix/partials/query.options.html'; @@ -12,7 +10,7 @@ ZabbixAnnotationsQueryController.templateUrl = 'datasource-zabbix/partials/annot export { ZabbixAPIDatasource as Datasource, - ZabbixConfigController as ConfigCtrl, + ZabbixDSConfigController as ConfigCtrl, ZabbixQueryController as QueryCtrl, ZabbixQueryOptionsController as QueryOptionsCtrl, ZabbixAnnotationsQueryController as AnnotationsQueryCtrl diff --git a/src/datasource-zabbix/partials/config.html b/src/datasource-zabbix/partials/config.html index 49e18b8..7f626c2 100644 --- a/src/datasource-zabbix/partials/config.html +++ b/src/datasource-zabbix/partials/config.html @@ -76,24 +76,53 @@
      -

      Alerting

      - +

      Direct DB Connection

      + - - -
      - Min severity +
      +
      + + SQL Data Source + + Select SQL Data Source for Zabbix database. + In order to use this feature you should create and + configure it first. Zabbix plugin uses this data source for querying history data directly from database. + This way usually faster than pulling data from Zabbix API, especially on the wide time ranges, and reduces + amount of data transfered. + +
      -
      +
      +
      + +
      +

      Alerting

      + + +
      + + +
      + Min severity +
      + +
      +
      +
      diff --git a/src/datasource-zabbix/partials/query.editor.html b/src/datasource-zabbix/partials/query.editor.html index 5a7df44..f583102 100644 --- a/src/datasource-zabbix/partials/query.editor.html +++ b/src/datasource-zabbix/partials/query.editor.html @@ -7,7 +7,7 @@
      @@ -17,27 +17,29 @@
      -
      +
      -
      - -
      + +
      - +
      @@ -46,7 +48,7 @@
      -
      +
      @@ -83,7 +85,7 @@
      -
      +
      @@ -129,7 +131,7 @@
      - @@ -137,8 +139,30 @@
      + +
      +
      + + + +
      +
      +
      +
      +
      + -
      +
      @@ -151,7 +175,7 @@
      -
      +
      @@ -165,6 +189,8 @@ +
      +
      +
      - diff --git a/src/datasource-zabbix/query.controller.js b/src/datasource-zabbix/query.controller.js index acfbd25..1330f4f 100644 --- a/src/datasource-zabbix/query.controller.js +++ b/src/datasource-zabbix/query.controller.js @@ -1,5 +1,4 @@ import {QueryCtrl} from 'app/plugins/sdk'; -import angular from 'angular'; import _ from 'lodash'; import * as c from './constants'; import * as utils from './utils'; @@ -22,17 +21,35 @@ export class ZabbixQueryController extends QueryCtrl { this.replaceTemplateVars = this.datasource.replaceTemplateVars; this.templateSrv = templateSrv; - this.editorModes = { - 0: {value: 'num', text: 'Metrics', mode: c.MODE_METRICS}, - 1: {value: 'itservice', text: 'IT Services', mode: c.MODE_ITSERVICE}, - 2: {value: 'text', text: 'Text', mode: c.MODE_TEXT} + this.editorModes = [ + {value: 'num', text: 'Metrics', mode: c.MODE_METRICS}, + {value: 'text', text: 'Text', mode: c.MODE_TEXT}, + {value: 'itservice', text: 'IT Services', mode: c.MODE_ITSERVICE}, + {value: 'itemid', text: 'Item ID', mode: c.MODE_ITEMID} + ]; + + this.$scope.editorMode = { + METRICS: c.MODE_METRICS, + TEXT: c.MODE_TEXT, + ITSERVICE: c.MODE_ITSERVICE, + ITEMID: c.MODE_ITEMID }; + this.slaPropertyList = [ + {name: "Status", property: "status"}, + {name: "SLA", property: "sla"}, + {name: "OK time", property: "okTime"}, + {name: "Problem time", property: "problemTime"}, + {name: "Down time", property: "downtimeTime"} + ]; + // Map functions for bs-typeahead this.getGroupNames = _.bind(this.getMetricNames, this, 'groupList'); this.getHostNames = _.bind(this.getMetricNames, this, 'hostList', true); this.getApplicationNames = _.bind(this.getMetricNames, this, 'appList'); this.getItemNames = _.bind(this.getMetricNames, this, 'itemList'); + this.getITServices = _.bind(this.getMetricNames, this, 'itServiceList'); + this.getVariables = _.bind(this.getTemplateVariables, this); // Update metric suggestion when template variable was changed $rootScope.$on('template-variable-value-updated', () => this.onVariableChange()); @@ -57,14 +74,14 @@ export class ZabbixQueryController extends QueryCtrl { // Load default values var targetDefaults = { - mode: c.MODE_METRICS, - group: { filter: "" }, - host: { filter: "" }, - application: { filter: "" }, - item: { filter: "" }, - functions: [], - options: { - showDisabledItems: false + 'mode': c.MODE_METRICS, + 'group': { 'filter': "" }, + 'host': { 'filter': "" }, + 'application': { 'filter': "" }, + 'item': { 'filter': "" }, + 'functions': [], + 'options': { + 'showDisabledItems': false } }; _.defaults(target, targetDefaults); @@ -77,26 +94,11 @@ export class ZabbixQueryController extends QueryCtrl { if (target.mode === c.MODE_METRICS || target.mode === c.MODE_TEXT) { - this.downsampleFunctionList = [ - {name: "avg", value: "avg"}, - {name: "min", value: "min"}, - {name: "max", value: "max"}, - {name: "sum", value: "sum"}, - {name: "count", value: "count"} - ]; - this.initFilters(); } else if (target.mode === c.MODE_ITSERVICE) { - this.slaPropertyList = [ - {name: "Status", property: "status"}, - {name: "SLA", property: "sla"}, - {name: "OK time", property: "okTime"}, - {name: "Problem time", property: "problemTime"}, - {name: "Down time", property: "downtimeTime"} - ]; - this.itserviceList = [{name: "test"}]; - this.updateITServiceList(); + _.defaults(target, {slaProperty: {name: "SLA", property: "sla"}}); + this.suggestITServices(); } }; @@ -104,7 +106,8 @@ export class ZabbixQueryController extends QueryCtrl { } initFilters() { - let itemtype = this.editorModes[this.target.mode].value; + let itemtype = _.find(this.editorModes, {'mode': this.target.mode}); + itemtype = itemtype ? itemtype.value : null; return Promise.all([ this.suggestGroups(), this.suggestHosts(), @@ -129,6 +132,12 @@ export class ZabbixQueryController extends QueryCtrl { return metrics; } + getTemplateVariables() { + return _.map(this.templateSrv.variables, variable => { + return '$' + variable.name; + }); + } + suggestGroups() { return this.zabbix.getAllGroups() .then(groups => { @@ -173,6 +182,14 @@ export class ZabbixQueryController extends QueryCtrl { }); } + suggestITServices() { + return this.zabbix.getITService() + .then(itservices => { + this.metric.itServiceList = itservices; + return itservices; + }); + } + isRegex(str) { return utils.isRegex(str); } @@ -292,30 +309,7 @@ export class ZabbixQueryController extends QueryCtrl { switchEditorMode(mode) { this.target.mode = mode; this.init(); - } - - ///////////////// - // IT Services // - ///////////////// - - /** - * Update list of IT services - */ - updateITServiceList() { - this.zabbix.getITService().then((iteservices) => { - this.itserviceList = []; - this.itserviceList = this.itserviceList.concat(iteservices); - }); - } - - /** - * Call when IT service is selected. - */ - selectITService() { - if (!_.isEqual(this.oldTarget, this.target) && _.isEmpty(this.target.errors)) { - this.oldTarget = angular.copy(this.target); - this.panelCtrl.refresh(); - } + this.targetChanged(); } } diff --git a/src/datasource-zabbix/specs/datasource_specs.js b/src/datasource-zabbix/specs/datasource_specs.js index 295f4fd..dec10a2 100644 --- a/src/datasource-zabbix/specs/datasource_specs.js +++ b/src/datasource-zabbix/specs/datasource_specs.js @@ -15,7 +15,10 @@ describe('ZabbixDatasource', () => { password: 'zabbix', trends: true, trendsFrom: '14d', - trendsRange: '7d' + trendsRange: '7d', + dbConnection: { + enabled: false + } } }; ctx.templateSrv = {}; diff --git a/src/datasource-zabbix/specs/utils_specs.js b/src/datasource-zabbix/specs/utils_specs.js index 41ab76c..c540db2 100644 --- a/src/datasource-zabbix/specs/utils_specs.js +++ b/src/datasource-zabbix/specs/utils_specs.js @@ -88,4 +88,54 @@ describe('Utils', () => { done(); }); }); + + describe('splitTemplateQuery()', () => { + + // Backward compatibility + it('should properly split query in old format', (done) => { + let test_cases = [ + { + query: `/alu/./tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9{2}/`, + expected: ['/alu/', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9{2}/'] + }, + { + query: `a.b.c.d`, + expected: ['a', 'b', 'c', 'd'] + } + ]; + + _.each(test_cases, test_case => { + let splitQuery = utils.splitTemplateQuery(test_case.query); + expect(splitQuery).to.eql(test_case.expected); + }); + done(); + }); + + it('should properly split query', (done) => { + let test_cases = [ + { + query: `{alu}{/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]*/}`, + expected: ['alu', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]*/'] + }, + { + query: `{alu}{/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]{2}/}`, + expected: ['alu', '/tw-(nyc|que|brx|dwt|brk)-sta_(\w|\d)*-alu-[0-9]{2}/'] + }, + { + query: `{a}{b}{c}{d}`, + expected: ['a', 'b', 'c', 'd'] + }, + { + query: `{a}{b.c.d}`, + expected: ['a', 'b.c.d'] + } + ]; + + _.each(test_cases, test_case => { + let splitQuery = utils.splitTemplateQuery(test_case.query); + expect(splitQuery).to.eql(test_case.expected); + }); + done(); + }); + }); }); diff --git a/src/datasource-zabbix/utils.js b/src/datasource-zabbix/utils.js index bed8fbf..4d2d704 100644 --- a/src/datasource-zabbix/utils.js +++ b/src/datasource-zabbix/utils.js @@ -22,6 +22,15 @@ export function expandItemName(name, key) { return name; } +export function expandItems(items) { + _.forEach(items, item => { + item.item = item.name; + item.name = expandItemName(item.item, item.key_); + return item; + }); + return items; +} + function splitKeyParams(paramStr) { let params = []; let quoted = false; @@ -93,7 +102,7 @@ function escapeMacro(macro) { * {group}{host.com} -> [group, host.com] */ export function splitTemplateQuery(query) { - let splitPattern = /{[^{}]*}/g; + let splitPattern = /\{[^\{\}]*\}|\{\/.*\/\}/g; let split; if (isContainsBraces(query)) { @@ -109,7 +118,8 @@ export function splitTemplateQuery(query) { } function isContainsBraces(query) { - return query.includes('{') && query.includes('}'); + let bracesPattern = /^\{.+\}$/; + return bracesPattern.test(query); } // Pattern for testing regex diff --git a/src/datasource-zabbix/zabbix.js b/src/datasource-zabbix/zabbix.js index ea24873..f5dd714 100644 --- a/src/datasource-zabbix/zabbix.js +++ b/src/datasource-zabbix/zabbix.js @@ -3,30 +3,45 @@ import _ from 'lodash'; import * as utils from './utils'; import './zabbixAPI.service.js'; import './zabbixCachingProxy.service.js'; +import './zabbixDBConnector'; // Use factory() instead service() for multiple data sources support. // Each Zabbix data source instance should initialize its own API instance. /** @ngInject */ -function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy) { +function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy, ZabbixDBConnector) { class Zabbix { - constructor(url, username, password, basicAuth, withCredentials, cacheTTL) { + constructor(url, options) { + let { + username, password, basicAuth, withCredentials, cacheTTL, + enableDirectDBConnection, sqlDatasourceId + } = options; // Initialize Zabbix API var ZabbixAPI = zabbixAPIService; this.zabbixAPI = new ZabbixAPI(url, username, password, basicAuth, withCredentials); + if (enableDirectDBConnection) { + this.dbConnector = new ZabbixDBConnector(sqlDatasourceId); + } + // Initialize caching proxy for requests let cacheOptions = { enabled: true, ttl: cacheTTL }; - this.cachingProxy = new ZabbixCachingProxy(this.zabbixAPI, cacheOptions); + this.cachingProxy = new ZabbixCachingProxy(this.zabbixAPI, this.dbConnector, cacheOptions); // Proxy methods this.getHistory = this.cachingProxy.getHistory.bind(this.cachingProxy); this.getMacros = this.cachingProxy.getMacros.bind(this.cachingProxy); + this.getItemsByIDs = this.cachingProxy.getItemsByIDs.bind(this.cachingProxy); + + if (enableDirectDBConnection) { + this.getHistoryDB = this.cachingProxy.getHistoryDB.bind(this.cachingProxy); + this.getTrendsDB = this.cachingProxy.getTrendsDB.bind(this.cachingProxy); + } this.getTrend = this.zabbixAPI.getTrend.bind(this.zabbixAPI); this.getEvents = this.zabbixAPI.getEvents.bind(this.zabbixAPI); @@ -134,6 +149,11 @@ function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy) { .then(items => filterByQuery(items, itemFilter)); } + getITServices(itServiceFilter) { + return this.cachingProxy.getITServices() + .then(itServices => findByFilter(itServices, itServiceFilter)); + } + /** * Build query - convert target filters to array of Zabbix items */ diff --git a/src/datasource-zabbix/zabbixAPI.service.js b/src/datasource-zabbix/zabbixAPI.service.js index 2fba1af..e2510ba 100644 --- a/src/datasource-zabbix/zabbixAPI.service.js +++ b/src/datasource-zabbix/zabbixAPI.service.js @@ -165,10 +165,7 @@ function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) { sortfield: 'name', webitems: true, filter: {}, - selectHosts: [ - 'hostid', - 'name' - ] + selectHosts: ['hostid', 'name'] }; if (hostids) { params.hostids = hostids; @@ -186,16 +183,25 @@ function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) { } return this.request('item.get', params) - .then(expandItems); + .then(utils.expandItems); + } - function expandItems(items) { - _.forEach(items, item => { - item.item = item.name; - item.name = utils.expandItemName(item.item, item.key_); - return item; - }); - return items; - } + getItemsByIDs(itemids) { + var params = { + itemids: itemids, + output: [ + 'name', 'key_', + 'value_type', + 'hostid', + 'status', + 'state' + ], + webitems: true, + selectHosts: ['hostid', 'name'] + }; + + return this.request('item.get', params) + .then(utils.expandItems); } getMacros(hostids) { diff --git a/src/datasource-zabbix/zabbixCachingProxy.service.js b/src/datasource-zabbix/zabbixCachingProxy.service.js index f450674..7ccd816 100644 --- a/src/datasource-zabbix/zabbixCachingProxy.service.js +++ b/src/datasource-zabbix/zabbixCachingProxy.service.js @@ -8,8 +8,9 @@ import _ from 'lodash'; function ZabbixCachingProxyFactory() { class ZabbixCachingProxy { - constructor(zabbixAPI, cacheOptions) { + constructor(zabbixAPI, zabbixDBConnector, cacheOptions) { this.zabbixAPI = zabbixAPI; + this.dbConnector = zabbixDBConnector; this.cacheEnabled = cacheOptions.enabled; this.ttl = cacheOptions.ttl || 600000; // 10 minutes by default @@ -22,7 +23,8 @@ function ZabbixCachingProxyFactory() { history: {}, trends: {}, macros: {}, - globalMacros: {} + globalMacros: {}, + itServices: {} }; this.historyPromises = {}; @@ -31,6 +33,13 @@ function ZabbixCachingProxyFactory() { this.getHistory = callAPIRequestOnce(_.bind(this.zabbixAPI.getHistory, this.zabbixAPI), this.historyPromises, getHistoryRequestHash); + if (this.dbConnector) { + this.getHistoryDB = callAPIRequestOnce(_.bind(this.dbConnector.getHistory, this.dbConnector), + this.historyPromises, getDBQueryHash); + this.getTrendsDB = callAPIRequestOnce(_.bind(this.dbConnector.getTrends, this.dbConnector), + this.historyPromises, getDBQueryHash); + } + // Don't run duplicated requests this.groupPromises = {}; this.getGroupsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getGroups, this.zabbixAPI), @@ -48,6 +57,14 @@ function ZabbixCachingProxyFactory() { this.getItemsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getItems, this.zabbixAPI), this.itemPromises, getRequestHash); + this.itemByIdPromises = {}; + this.getItemsByIdOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getItemsByIDs, this.zabbixAPI), + this.itemPromises, getRequestHash); + + this.itServicesPromises = {}; + this.getITServicesOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getITService, this.zabbixAPI), + this.itServicesPromises, getRequestHash); + this.macroPromises = {}; this.getMacrosOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getMacros, this.zabbixAPI), this.macroPromises, getRequestHash); @@ -103,6 +120,15 @@ function ZabbixCachingProxyFactory() { return this.proxyRequest(this.getItemsOnce, params, this.cache.items); } + getItemsByIDs(itemids) { + let params = [itemids]; + return this.proxyRequest(this.getItemsByIdOnce, params, this.cache.items); + } + + getITServices() { + return this.proxyRequest(this.getITServicesOnce, [], this.cache.itServices); + } + getMacros(hostids) { // Merge global macros and host macros let promises = [ @@ -195,6 +221,14 @@ function getHistoryRequestHash(args) { return stamp.getHash(); } +function getDBQueryHash(args) { + let itemids = _.map(args[0], 'itemid'); + let consolidateBy = args[3].consolidateBy; + let intervalMs = args[3].intervalMs; + let stamp = itemids.join() + args[1] + args[2] + consolidateBy + intervalMs; + return stamp.getHash(); +} + String.prototype.getHash = function() { var hash = 0, i, chr, len; if (this.length !== 0) { diff --git a/src/datasource-zabbix/zabbixDBConnector.js b/src/datasource-zabbix/zabbixDBConnector.js new file mode 100644 index 0000000..4d8882c --- /dev/null +++ b/src/datasource-zabbix/zabbixDBConnector.js @@ -0,0 +1,192 @@ +import angular from 'angular'; +import _ from 'lodash'; + +const DEFAULT_QUERY_LIMIT = 10000; +const HISTORY_TO_TABLE_MAP = { + '0': 'history', + '1': 'history_str', + '2': 'history_log', + '3': 'history_uint', + '4': 'history_text' +}; + +const TREND_TO_TABLE_MAP = { + '0': 'trends', + '3': 'trends_uint' +}; + +const consolidateByFunc = { + 'avg': 'AVG', + 'min': 'MIN', + 'max': 'MAX', + 'sum': 'SUM', + 'count': 'COUNT' +}; + +const consolidateByTrendColumns = { + 'avg': 'value_avg', + 'min': 'value_min', + 'max': 'value_max' +}; + +/** @ngInject */ +function ZabbixDBConnectorFactory(datasourceSrv, backendSrv) { + + class ZabbixDBConnector { + + constructor(sqlDataSourceId, options = {}) { + let {limit} = options; + + this.sqlDataSourceId = sqlDataSourceId; + this.limit = limit || DEFAULT_QUERY_LIMIT; + } + + /** + * Try to load DS with given id to check it's exist. + * @param {*} datasourceId ID of SQL data source + */ + loadSQLDataSource(datasourceId) { + let ds = _.find(datasourceSrv.getAll(), {'id': datasourceId}); + if (ds) { + return datasourceSrv.loadDatasource(ds.name) + .then(ds => { + console.log('SQL data source loaded', ds); + }); + } else { + return Promise.reject(`SQL Data Source with ID ${datasourceId} not found`); + } + } + + /** + * Try to invoke test query for one of Zabbix database tables. + */ + testSQLDataSource() { + let testQuery = `SELECT itemid AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1`; + return this.invokeSQLQuery(testQuery); + } + + getHistory(items, timeFrom, timeTill, options) { + let {intervalMs, consolidateBy} = options; + let intervalSec = Math.ceil(intervalMs / 1000); + + consolidateBy = consolidateBy || 'avg'; + let aggFunction = consolidateByFunc[consolidateBy]; + + // Group items by value type and perform request for each value type + let grouped_items = _.groupBy(items, 'value_type'); + let promises = _.map(grouped_items, (items, value_type) => { + let itemids = _.map(items, 'itemid').join(', '); + let table = HISTORY_TO_TABLE_MAP[value_type]; + + let query = ` + SELECT itemid AS metric, clock AS time_sec, ${aggFunction}(value) AS value + FROM ${table} + WHERE itemid IN (${itemids}) + AND clock > ${timeFrom} AND clock < ${timeTill} + GROUP BY time_sec DIV ${intervalSec}, metric + `; + + query = compactSQLQuery(query); + return this.invokeSQLQuery(query); + }); + + return Promise.all(promises).then(results => { + return _.flatten(results); + }); + } + + getTrends(items, timeFrom, timeTill, options) { + let {intervalMs, consolidateBy} = options; + let intervalSec = Math.ceil(intervalMs / 1000); + + consolidateBy = consolidateBy || 'avg'; + let aggFunction = consolidateByFunc[consolidateBy]; + + // Group items by value type and perform request for each value type + let grouped_items = _.groupBy(items, 'value_type'); + let promises = _.map(grouped_items, (items, value_type) => { + let itemids = _.map(items, 'itemid').join(', '); + let table = TREND_TO_TABLE_MAP[value_type]; + let valueColumn = _.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg'; + valueColumn = consolidateByTrendColumns[valueColumn]; + + let query = ` + SELECT itemid AS metric, clock AS time_sec, ${aggFunction}(${valueColumn}) AS value + FROM ${table} + WHERE itemid IN (${itemids}) + AND clock > ${timeFrom} AND clock < ${timeTill} + GROUP BY time_sec DIV ${intervalSec}, metric + `; + + query = compactSQLQuery(query); + return this.invokeSQLQuery(query); + }); + + return Promise.all(promises).then(results => { + return _.flatten(results); + }); + } + + handleGrafanaTSResponse(history, items, addHostName = true) { + return convertGrafanaTSResponse(history, items, addHostName); + } + + invokeSQLQuery(query) { + let queryDef = { + refId: 'A', + format: 'time_series', + datasourceId: this.sqlDataSourceId, + rawSql: query, + maxDataPoints: this.limit + }; + + return backendSrv.datasourceRequest({ + url: '/api/tsdb/query', + method: 'POST', + data: { + queries: [queryDef], + } + }) + .then(response => { + let results = response.data.results; + if (results['A']) { + return results['A'].series; + } else { + return null; + } + }); + } + } + + return ZabbixDBConnector; +} + +angular + .module('grafana.services') + .factory('ZabbixDBConnector', ZabbixDBConnectorFactory); + +/////////////////////////////////////////////////////////////////////////////// + +function convertGrafanaTSResponse(time_series, items, addHostName) { + var hosts = _.uniqBy(_.flatten(_.map(items, 'hosts')), 'hostid'); //uniqBy is needed to deduplicate + let grafanaSeries = _.map(time_series, series => { + let itemid = series.name; + let datapoints = series.points; + var item = _.find(items, {'itemid': itemid}); + var alias = item.name; + if (_.keys(hosts).length > 1 && addHostName) { //only when actual multi hosts selected + var host = _.find(hosts, {'hostid': item.hostid}); + alias = host.name + ": " + alias; + } + return { + target: alias, + datapoints: datapoints + }; + }); + + return _.sortBy(grafanaSeries, 'target'); +} + +function compactSQLQuery(query) { + return query.replace(/\s+/g, ' '); +} diff --git a/src/panel-triggers/editor.html b/src/panel-triggers/editor.html index aa60aea..af58a83 100644 --- a/src/panel-triggers/editor.html +++ b/src/panel-triggers/editor.html @@ -55,6 +55,10 @@ placeholder="trigger name" class="gf-form-input" ng-style="editor.panel.triggers.trigger.style" + ng-class="{ + 'zbx-variable': editor.isVariable(editor.panel.triggers.trigger.filter), + 'zbx-regex': editor.isRegex(editor.panel.triggers.trigger.filter) + }" empty-to-null>
      diff --git a/src/panel-triggers/module.js b/src/panel-triggers/module.js index 38d7293..3d34704 100644 --- a/src/panel-triggers/module.js +++ b/src/panel-triggers/module.js @@ -130,6 +130,7 @@ class TriggerPanelCtrl extends PanelCtrl { .then(datasource => { var zabbix = datasource.zabbix; this.zabbix = zabbix; + this.datasource = datasource; var showEvents = this.panel.showEvents.value; var triggerFilter = this.panel.triggers; var hideHostsInMaintenance = this.panel.hideHostsInMaintenance; @@ -143,10 +144,11 @@ class TriggerPanelCtrl extends PanelCtrl { showTriggers: showEvents, hideHostsInMaintenance: hideHostsInMaintenance }; - let getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, triggersOptions); - return getTriggers.then(triggers => { - return _.map(triggers, this.formatTrigger.bind(this)); - }); + + return zabbix.getTriggers(groupFilter, hostFilter, appFilter, triggersOptions); + }) + .then(triggers => { + return _.map(triggers, this.formatTrigger.bind(this)); }); } @@ -191,6 +193,7 @@ class TriggerPanelCtrl extends PanelCtrl { filterTriggers(triggerList) { // Filter triggers by description var triggerFilter = this.panel.triggers.trigger.filter; + triggerFilter = this.datasource.replaceTemplateVars(triggerFilter); if (triggerFilter) { triggerList = filterTriggers(triggerList, triggerFilter); } diff --git a/src/plugin.json b/src/plugin.json index 6bbab7e..9f15b89 100644 --- a/src/plugin.json +++ b/src/plugin.json @@ -26,8 +26,8 @@ {"name": "Metric Editor", "path": "img/screenshot-metric_editor.png"}, {"name": "Triggers", "path": "img/screenshot-triggers.png"} ], - "version": "3.4.0", - "updated": "2017-05-17" + "version": "3.5.1", + "updated": "2017-07-10" }, "includes": [