From 622744a754869c149e7778c212734bfa9235dc39 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Wed, 1 Feb 2017 18:52:38 +0300 Subject: [PATCH 01/10] Initial scroll implementation. --- src/panel-triggers/module.js | 93 +++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/src/panel-triggers/module.js b/src/panel-triggers/module.js index 2218490..2062b7e 100644 --- a/src/panel-triggers/module.js +++ b/src/panel-triggers/module.js @@ -12,6 +12,7 @@ */ import _ from 'lodash'; +import $ from 'jquery'; import moment from 'moment'; import * as utils from '../datasource-zabbix/utils'; import {MetricsPanelCtrl} from 'app/plugins/sdk'; @@ -48,7 +49,9 @@ var panelDefaults = { showEvents: { text: 'Problems', value: '1' }, triggerSeverity: defaultSeverity, okEventColor: 'rgba(0, 245, 153, 0.45)', - ackEventColor: 'rgba(0, 0, 0, 0)' + ackEventColor: 'rgba(0, 0, 0, 0)', + scroll: true, + pageSize: null }; var triggerStatusMap = { @@ -69,6 +72,8 @@ class TriggerPanelCtrl extends MetricsPanelCtrl { this.triggerStatusMap = triggerStatusMap; this.defaultTimeFormat = defaultTimeFormat; + this.pageIndex = 0; + // Load panel defaults // _.cloneDeep() need for prevent changing shared defaultSeverity. // Load object "by value" istead "by reference". @@ -222,6 +227,9 @@ class TriggerPanelCtrl extends MetricsPanelCtrl { // Notify panel that request is finished self.setTimeQueryEnd(); self.loading = false; + + this.panel.triggerList = this.triggerList; + this.render(); }); }); }); @@ -244,6 +252,89 @@ class TriggerPanelCtrl extends MetricsPanelCtrl { }); }); } + + render() { + return super.render(this.table); + } + + link(scope, elem, attrs, ctrl) { + var data; + var panel = ctrl.panel; + var pageCount = 0; + // var formaters = []; + data = ctrl.panel.triggerList; + + function getTableHeight() { + var panelHeight = ctrl.height; + + if (pageCount > 1) { + panelHeight -= 26; + } + + return (panelHeight - 31) + 'px'; + } + + // function appendTableRows(tbodyElem) { + // var renderer = new TableRenderer(panel, data, ctrl.dashboard.isTimezoneUtc(), ctrl.$sanitize); + // tbodyElem.empty(); + // tbodyElem.html(renderer.render(ctrl.pageIndex)); + // } + + function switchPage(e) { + var el = $(e.currentTarget); + ctrl.pageIndex = (parseInt(el.text(), 10)-1); + renderPanel(); + } + + function appendPaginationControls(footerElem) { + footerElem.empty(); + + var pageSize = panel.pageSize || 5; + pageCount = Math.ceil(ctrl.panel.triggerList.length / pageSize); + if (pageCount === 1) { + return; + } + + var startPage = Math.max(ctrl.pageIndex - 3, 0); + var endPage = Math.min(pageCount, startPage + 9); + + var paginationList = $(''); + + for (var i = startPage; i < endPage; i++) { + var activeClass = i === ctrl.pageIndex ? 'active' : ''; + var pageLinkElem = $('
  • ' + (i+1) + '
  • '); + paginationList.append(pageLinkElem); + } + + footerElem.append(paginationList); + } + + function renderPanel() { + var panelElem = elem.parents('.panel'); + var rootElem = elem.find('.triggers-panel-scroll'); + // var tbodyElem = elem.find('tbody'); + var footerElem = elem.find('.triggers-panel-footer'); + + elem.css({'font-size': panel.fontSize}); + panelElem.addClass('triggers-panel-wrapper'); + + // appendTableRows(tbodyElem); + appendPaginationControls(footerElem); + + rootElem.css({'max-height': panel.scroll ? getTableHeight() : '' }); + } + + elem.on('click', '.triggers-panel-page-link', switchPage); + + var unbindDestroy = scope.$on('$destroy', function() { + elem.off('click', '.triggers-panel-page-link'); + unbindDestroy(); + }); + + ctrl.events.on('render', () => { + renderPanel(); + }); + } } TriggerPanelCtrl.templateUrl = 'panel-triggers/module.html'; From 17306c5f73ab8c112fb5b9f398d2ca40339e371a Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Thu, 2 Feb 2017 13:35:51 +0300 Subject: [PATCH 02/10] Add 'enable scroll' control and page size input. --- dist/panel-triggers/editor.html | 16 + dist/panel-triggers/module.js | 131 +++- dist/panel-triggers/module.js.map | 2 +- dist/test/components/config.js | 13 - .../add-metric-function.directive.js | 116 ---- dist/test/datasource-zabbix/dataProcessor.js | 330 ---------- dist/test/datasource-zabbix/datasource.js | 582 ------------------ .../metric-function-editor.directive.js | 246 -------- .../test/datasource-zabbix/metricFunctions.js | 292 --------- dist/test/datasource-zabbix/migrations.js | 48 -- dist/test/datasource-zabbix/module.js | 36 -- .../datasource-zabbix/query.controller.js | 378 ------------ .../test/datasource-zabbix/responseHandler.js | 116 ---- .../specs/datasource_specs.js | 317 ---------- .../specs/modules/datemath.js | 135 ---- .../test/datasource-zabbix/specs/test-main.js | 66 -- dist/test/datasource-zabbix/utils.js | 151 ----- dist/test/datasource-zabbix/zabbix.js | 266 -------- .../datasource-zabbix/zabbixAPI.service.js | 436 ------------- .../zabbixAPICore.service.js | 142 ----- .../zabbixCachingProxy.service.js | 215 ------- dist/test/module.js | 10 - .../panel-triggers/ack-tooltip.directive.js | 122 ---- dist/test/panel-triggers/editor.js | 225 ------- dist/test/panel-triggers/module.js | 302 --------- src/panel-triggers/editor.html | 16 + src/panel-triggers/module.js | 2 +- 27 files changed, 160 insertions(+), 4551 deletions(-) delete mode 100644 dist/test/components/config.js delete mode 100644 dist/test/datasource-zabbix/add-metric-function.directive.js delete mode 100644 dist/test/datasource-zabbix/dataProcessor.js delete mode 100644 dist/test/datasource-zabbix/datasource.js delete mode 100644 dist/test/datasource-zabbix/metric-function-editor.directive.js delete mode 100644 dist/test/datasource-zabbix/metricFunctions.js delete mode 100644 dist/test/datasource-zabbix/migrations.js delete mode 100644 dist/test/datasource-zabbix/module.js delete mode 100644 dist/test/datasource-zabbix/query.controller.js delete mode 100644 dist/test/datasource-zabbix/responseHandler.js delete mode 100644 dist/test/datasource-zabbix/specs/datasource_specs.js delete mode 100644 dist/test/datasource-zabbix/specs/modules/datemath.js delete mode 100644 dist/test/datasource-zabbix/specs/test-main.js delete mode 100644 dist/test/datasource-zabbix/utils.js delete mode 100644 dist/test/datasource-zabbix/zabbix.js delete mode 100644 dist/test/datasource-zabbix/zabbixAPI.service.js delete mode 100644 dist/test/datasource-zabbix/zabbixAPICore.service.js delete mode 100644 dist/test/datasource-zabbix/zabbixCachingProxy.service.js delete mode 100644 dist/test/module.js delete mode 100644 dist/test/panel-triggers/ack-tooltip.directive.js delete mode 100644 dist/test/panel-triggers/editor.js delete mode 100644 dist/test/panel-triggers/module.js diff --git a/dist/panel-triggers/editor.html b/dist/panel-triggers/editor.html index ee1b24b..39e96b8 100644 --- a/dist/panel-triggers/editor.html +++ b/dist/panel-triggers/editor.html @@ -121,6 +121,22 @@ +
    + + +
    + + +
    +
    diff --git a/dist/panel-triggers/module.js b/dist/panel-triggers/module.js index 3c764d3..1e04a3c 100644 --- a/dist/panel-triggers/module.js +++ b/dist/panel-triggers/module.js @@ -1,9 +1,9 @@ 'use strict'; -System.register(['lodash', 'moment', '../datasource-zabbix/utils', 'app/plugins/sdk', './editor', './ack-tooltip.directive', './css/panel_triggers.css!'], function (_export, _context) { +System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'app/plugins/sdk', './editor', './ack-tooltip.directive', './css/panel_triggers.css!'], function (_export, _context) { "use strict"; - var _, moment, utils, MetricsPanelCtrl, triggerPanelEditor, _createClass, defaultSeverity, panelDefaults, triggerStatusMap, defaultTimeFormat, TriggerPanelCtrl; + var _, $, moment, utils, MetricsPanelCtrl, triggerPanelEditor, _createClass, _get, defaultSeverity, panelDefaults, triggerStatusMap, defaultTimeFormat, TriggerPanelCtrl; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { @@ -50,6 +50,8 @@ System.register(['lodash', 'moment', '../datasource-zabbix/utils', 'app/plugins/ return { setters: [function (_lodash) { _ = _lodash.default; + }, function (_jquery) { + $ = _jquery.default; }, function (_moment) { moment = _moment.default; }, function (_datasourceZabbixUtils) { @@ -78,6 +80,31 @@ System.register(['lodash', 'moment', '../datasource-zabbix/utils', 'app/plugins/ }; }(); + _get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); + + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + + if (getter === undefined) { + return undefined; + } + + return getter.call(receiver); + } + }; + defaultSeverity = [{ priority: 0, severity: 'Not classified', color: '#B7DBAB', show: true }, { priority: 1, severity: 'Information', color: '#82B5D8', show: true }, { priority: 2, severity: 'Warning', color: '#E5AC0E', show: true }, { priority: 3, severity: 'Average', color: '#C15C17', show: true }, { priority: 4, severity: 'High', color: '#BF1B00', show: true }, { priority: 5, severity: 'Disaster', color: '#890F02', show: true }]; panelDefaults = { datasource: null, @@ -99,7 +126,9 @@ System.register(['lodash', 'moment', '../datasource-zabbix/utils', 'app/plugins/ showEvents: { text: 'Problems', value: '1' }, triggerSeverity: defaultSeverity, okEventColor: 'rgba(0, 245, 153, 0.45)', - ackEventColor: 'rgba(0, 0, 0, 0)' + ackEventColor: 'rgba(0, 0, 0, 0)', + scroll: true, + pageSize: 10 }; triggerStatusMap = { '0': 'OK', @@ -122,6 +151,8 @@ System.register(['lodash', 'moment', '../datasource-zabbix/utils', 'app/plugins/ _this.triggerStatusMap = triggerStatusMap; _this.defaultTimeFormat = defaultTimeFormat; + _this.pageIndex = 0; + // Load panel defaults // _.cloneDeep() need for prevent changing shared defaultSeverity. // Load object "by value" istead "by reference". @@ -161,6 +192,8 @@ System.register(['lodash', 'moment', '../datasource-zabbix/utils', 'app/plugins/ }, { key: 'refreshData', value: function refreshData() { + var _this2 = this; + // clear loading/error state delete this.error; this.loading = true; @@ -282,6 +315,9 @@ System.register(['lodash', 'moment', '../datasource-zabbix/utils', 'app/plugins/ // Notify panel that request is finished self.setTimeQueryEnd(); self.loading = false; + + _this2.panel.triggerList = _this2.triggerList; + _this2.render(); }); }); }); @@ -294,7 +330,7 @@ System.register(['lodash', 'moment', '../datasource-zabbix/utils', 'app/plugins/ }, { key: 'acknowledgeTrigger', value: function acknowledgeTrigger(trigger, message) { - var _this2 = this; + var _this3 = this; var eventid = trigger.lastEvent.eventid; var grafana_user = this.contextSrv.user.name; @@ -302,10 +338,95 @@ System.register(['lodash', 'moment', '../datasource-zabbix/utils', 'app/plugins/ return this.datasourceSrv.get(this.panel.datasource).then(function (datasource) { var zabbixAPI = datasource.zabbix.zabbixAPI; return zabbixAPI.acknowledgeEvent(eventid, ack_message).then(function () { - _this2.refresh(); + _this3.refresh(); }); }); } + }, { + key: 'render', + value: function render() { + return _get(TriggerPanelCtrl.prototype.__proto__ || Object.getPrototypeOf(TriggerPanelCtrl.prototype), 'render', this).call(this, this.table); + } + }, { + key: 'link', + value: function link(scope, elem, attrs, ctrl) { + var data; + var panel = ctrl.panel; + var pageCount = 0; + // var formaters = []; + data = ctrl.panel.triggerList; + + function getTableHeight() { + var panelHeight = ctrl.height; + + if (pageCount > 1) { + panelHeight -= 26; + } + + return panelHeight - 31 + 'px'; + } + + // function appendTableRows(tbodyElem) { + // var renderer = new TableRenderer(panel, data, ctrl.dashboard.isTimezoneUtc(), ctrl.$sanitize); + // tbodyElem.empty(); + // tbodyElem.html(renderer.render(ctrl.pageIndex)); + // } + + function switchPage(e) { + var el = $(e.currentTarget); + ctrl.pageIndex = parseInt(el.text(), 10) - 1; + renderPanel(); + } + + function appendPaginationControls(footerElem) { + footerElem.empty(); + + var pageSize = panel.pageSize || 5; + pageCount = Math.ceil(ctrl.panel.triggerList.length / pageSize); + if (pageCount === 1) { + return; + } + + var startPage = Math.max(ctrl.pageIndex - 3, 0); + var endPage = Math.min(pageCount, startPage + 9); + + var paginationList = $('
      '); + + for (var i = startPage; i < endPage; i++) { + var activeClass = i === ctrl.pageIndex ? 'active' : ''; + var pageLinkElem = $('
    • ' + (i + 1) + '
    • '); + paginationList.append(pageLinkElem); + } + + footerElem.append(paginationList); + } + + function renderPanel() { + var panelElem = elem.parents('.panel'); + var rootElem = elem.find('.triggers-panel-scroll'); + // var tbodyElem = elem.find('tbody'); + var footerElem = elem.find('.triggers-panel-footer'); + + elem.css({ 'font-size': panel.fontSize }); + panelElem.addClass('triggers-panel-wrapper'); + + // appendTableRows(tbodyElem); + appendPaginationControls(footerElem); + + rootElem.css({ 'max-height': panel.scroll ? getTableHeight() : '' }); + } + + elem.on('click', '.triggers-panel-page-link', switchPage); + + var unbindDestroy = scope.$on('$destroy', function () { + elem.off('click', '.triggers-panel-page-link'); + unbindDestroy(); + }); + + ctrl.events.on('render', function () { + renderPanel(); + }); + } }]); return TriggerPanelCtrl; diff --git a/dist/panel-triggers/module.js.map b/dist/panel-triggers/module.js.map index 75455e9..27b7b48 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","MetricsPanelCtrl","triggerPanelEditor","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","defaults","panel","cloneDeep","triggerList","refreshData","addEditorTab","onMetricsPanelRefresh","otherPanelInFullscreenMode","error","loading","setTimeQueryStart","self","get","then","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","getTriggers","map","triggerObj","lastchangeUnix","Number","lastchange","timestamp","unix","customLastChangeFormat","format","lastChangeFormat","age","fromNow","hosts","length","name","hostTechName","eventids","lastEvent","eventid","getAcknowledges","each","event","find","events","acknowledges","ack","clock","time","user","alias","surname","markAckEvents","sortBy","reverse","slice","setTimeQueryEnd","showComment","message","grafana_user","ack_message","zabbixAPI","acknowledgeEvent","refresh","templateUrl"],"mappings":"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","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 moment from 'moment';\nimport * as utils from '../datasource-zabbix/utils';\nimport {MetricsPanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\nimport './css/panel_triggers.css!';\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 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};\n\nvar triggerStatusMap = {\n '0': 'OK',\n '1': 'Problem'\n};\n\nvar defaultTimeFormat = \"DD MMM YYYY HH:mm:ss\";\n\nclass TriggerPanelCtrl extends MetricsPanelCtrl {\n\n /** @ngInject */\n constructor($scope, $injector, $element, datasourceSrv, templateSrv, contextSrv) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\n this.triggerStatusMap = triggerStatusMap;\n this.defaultTimeFormat = defaultTimeFormat;\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.triggerList = [];\n this.refreshData();\n }\n\n /**\n * Override onInitMetricsPanelEditMode() method from MetricsPanelCtrl.\n * We don't need metric editor from Metrics Panel.\n */\n onInitMetricsPanelEditMode() {\n this.addEditorTab('Options', triggerPanelEditor, 2);\n }\n\n refresh() {\n this.onMetricsPanelRefresh();\n }\n\n onMetricsPanelRefresh() {\n // ignore fetching data if another panel is in fullscreen\n if (this.otherPanelInFullscreenMode()) { return; }\n\n this.refreshData();\n }\n\n refreshData() {\n // clear loading/error state\n delete this.error;\n this.loading = true;\n this.setTimeQueryStart();\n\n var self = this;\n\n // Load datasource\n return this.datasourceSrv.get(this.panel.datasource)\n .then(datasource => {\n var zabbix = datasource.zabbix;\n var showEvents = self.panel.showEvents.value;\n var triggerFilter = self.panel.triggers;\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 var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents);\n return getTriggers.then(triggers => {\n return _.map(triggers, 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 (self.panel.customLastChangeFormat) {\n // User defined format\n triggerObj.lastchange = timestamp.format(self.panel.lastChangeFormat);\n } else {\n triggerObj.lastchange = timestamp.format(self.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 = self.panel.triggerSeverity[trigger.priority].color;\n } else {\n // OK state\n triggerObj.color = self.panel.okEventColor;\n }\n\n triggerObj.severity = self.panel.triggerSeverity[trigger.priority].severity;\n return triggerObj;\n });\n })\n .then(triggerList => {\n\n // Request acknowledges for trigger\n var eventids = _.map(triggerList, trigger => {\n return trigger.lastEvent.eventid;\n });\n\n return 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 (self.panel.customLastChangeFormat) {\n ack.time = timestamp.format(self.panel.lastChangeFormat);\n } else {\n ack.time = timestamp.format(self.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 (self.panel.markAckEvents && trigger.acknowledges.length) {\n trigger.color = self.panel.ackEventColor;\n }\n }\n });\n\n // Filter triggers by description\n var triggerFilter = self.panel.triggers.trigger.filter;\n if (triggerFilter) {\n triggerList = filterTriggers(triggerList, triggerFilter);\n }\n\n // Filter acknowledged triggers\n if (self.panel.showTriggers === 'unacknowledged') {\n triggerList = _.filter(triggerList, trigger => {\n return !trigger.acknowledges;\n });\n } else if (self.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 self.panel.triggerSeverity[trigger.priority].show;\n });\n\n // Sort triggers\n if (self.panel.sortTriggersBy.value === 'priority') {\n triggerList = _.sortBy(triggerList, 'priority').reverse();\n } else {\n triggerList = _.sortBy(triggerList, 'lastchangeUnix').reverse();\n }\n\n // Limit triggers number\n self.triggerList = triggerList.slice(0, self.panel.limit);\n\n // Notify panel that request is finished\n self.setTimeQueryEnd();\n self.loading = false;\n });\n });\n });\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 .then(() => {\n this.refresh();\n });\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","MetricsPanelCtrl","triggerPanelEditor","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","scroll","pageSize","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","pageIndex","defaults","panel","cloneDeep","triggerList","refreshData","addEditorTab","onMetricsPanelRefresh","otherPanelInFullscreenMode","error","loading","setTimeQueryStart","self","get","then","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","getTriggers","map","triggerObj","lastchangeUnix","Number","lastchange","timestamp","unix","customLastChangeFormat","format","lastChangeFormat","age","fromNow","hosts","length","name","hostTechName","eventids","lastEvent","eventid","getAcknowledges","each","event","find","events","acknowledges","ack","clock","time","user","alias","surname","markAckEvents","sortBy","reverse","slice","setTimeQueryEnd","render","showComment","message","grafana_user","ack_message","zabbixAPI","acknowledgeEvent","refresh","table","scope","elem","attrs","ctrl","data","pageCount","getTableHeight","panelHeight","height","switchPage","e","el","currentTarget","parseInt","renderPanel","appendPaginationControls","footerElem","empty","Math","ceil","startPage","max","endPage","min","paginationList","i","activeClass","pageLinkElem","append","panelElem","parents","rootElem","css","fontSize","addClass","on","unbindDestroy","$on","off","templateUrl"],"mappings":"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","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 * as utils from '../datasource-zabbix/utils';\nimport {MetricsPanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\nimport './css/panel_triggers.css!';\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 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};\n\nvar triggerStatusMap = {\n '0': 'OK',\n '1': 'Problem'\n};\n\nvar defaultTimeFormat = \"DD MMM YYYY HH:mm:ss\";\n\nclass TriggerPanelCtrl extends MetricsPanelCtrl {\n\n /** @ngInject */\n constructor($scope, $injector, $element, datasourceSrv, templateSrv, contextSrv) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\n this.triggerStatusMap = triggerStatusMap;\n this.defaultTimeFormat = defaultTimeFormat;\n\n this.pageIndex = 0;\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.triggerList = [];\n this.refreshData();\n }\n\n /**\n * Override onInitMetricsPanelEditMode() method from MetricsPanelCtrl.\n * We don't need metric editor from Metrics Panel.\n */\n onInitMetricsPanelEditMode() {\n this.addEditorTab('Options', triggerPanelEditor, 2);\n }\n\n refresh() {\n this.onMetricsPanelRefresh();\n }\n\n onMetricsPanelRefresh() {\n // ignore fetching data if another panel is in fullscreen\n if (this.otherPanelInFullscreenMode()) { return; }\n\n this.refreshData();\n }\n\n refreshData() {\n // clear loading/error state\n delete this.error;\n this.loading = true;\n this.setTimeQueryStart();\n\n var self = this;\n\n // Load datasource\n return this.datasourceSrv.get(this.panel.datasource)\n .then(datasource => {\n var zabbix = datasource.zabbix;\n var showEvents = self.panel.showEvents.value;\n var triggerFilter = self.panel.triggers;\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 var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents);\n return getTriggers.then(triggers => {\n return _.map(triggers, 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 (self.panel.customLastChangeFormat) {\n // User defined format\n triggerObj.lastchange = timestamp.format(self.panel.lastChangeFormat);\n } else {\n triggerObj.lastchange = timestamp.format(self.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 = self.panel.triggerSeverity[trigger.priority].color;\n } else {\n // OK state\n triggerObj.color = self.panel.okEventColor;\n }\n\n triggerObj.severity = self.panel.triggerSeverity[trigger.priority].severity;\n return triggerObj;\n });\n })\n .then(triggerList => {\n\n // Request acknowledges for trigger\n var eventids = _.map(triggerList, trigger => {\n return trigger.lastEvent.eventid;\n });\n\n return 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 (self.panel.customLastChangeFormat) {\n ack.time = timestamp.format(self.panel.lastChangeFormat);\n } else {\n ack.time = timestamp.format(self.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 (self.panel.markAckEvents && trigger.acknowledges.length) {\n trigger.color = self.panel.ackEventColor;\n }\n }\n });\n\n // Filter triggers by description\n var triggerFilter = self.panel.triggers.trigger.filter;\n if (triggerFilter) {\n triggerList = filterTriggers(triggerList, triggerFilter);\n }\n\n // Filter acknowledged triggers\n if (self.panel.showTriggers === 'unacknowledged') {\n triggerList = _.filter(triggerList, trigger => {\n return !trigger.acknowledges;\n });\n } else if (self.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 self.panel.triggerSeverity[trigger.priority].show;\n });\n\n // Sort triggers\n if (self.panel.sortTriggersBy.value === 'priority') {\n triggerList = _.sortBy(triggerList, 'priority').reverse();\n } else {\n triggerList = _.sortBy(triggerList, 'lastchangeUnix').reverse();\n }\n\n // Limit triggers number\n self.triggerList = triggerList.slice(0, self.panel.limit);\n\n // Notify panel that request is finished\n self.setTimeQueryEnd();\n self.loading = false;\n\n this.panel.triggerList = this.triggerList;\n this.render();\n });\n });\n });\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 .then(() => {\n this.refresh();\n });\n });\n }\n\n render() {\n return super.render(this.table);\n }\n\n link(scope, elem, attrs, ctrl) {\n var data;\n var panel = ctrl.panel;\n var pageCount = 0;\n // var formaters = [];\n data = ctrl.panel.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 appendTableRows(tbodyElem) {\n // var renderer = new TableRenderer(panel, data, ctrl.dashboard.isTimezoneUtc(), ctrl.$sanitize);\n // tbodyElem.empty();\n // tbodyElem.html(renderer.render(ctrl.pageIndex));\n // }\n\n function switchPage(e) {\n var el = $(e.currentTarget);\n ctrl.pageIndex = (parseInt(el.text(), 10)-1);\n renderPanel();\n }\n\n function appendPaginationControls(footerElem) {\n footerElem.empty();\n\n var pageSize = panel.pageSize || 5;\n pageCount = Math.ceil(ctrl.panel.triggerList.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 tbodyElem = elem.find('tbody');\n var footerElem = elem.find('.triggers-panel-footer');\n\n elem.css({'font-size': panel.fontSize});\n panelElem.addClass('triggers-panel-wrapper');\n\n // appendTableRows(tbodyElem);\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', () => {\n renderPanel();\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/test/components/config.js b/dist/test/components/config.js deleted file mode 100644 index ad0987c..0000000 --- a/dist/test/components/config.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var ZabbixAppConfigCtrl = exports.ZabbixAppConfigCtrl = function ZabbixAppConfigCtrl() { - _classCallCheck(this, ZabbixAppConfigCtrl); -}; - -ZabbixAppConfigCtrl.templateUrl = 'components/config.html'; diff --git a/dist/test/datasource-zabbix/add-metric-function.directive.js b/dist/test/datasource-zabbix/add-metric-function.directive.js deleted file mode 100644 index 26b55cc..0000000 --- a/dist/test/datasource-zabbix/add-metric-function.directive.js +++ /dev/null @@ -1,116 +0,0 @@ -'use strict'; - -var _angular = require('angular'); - -var _angular2 = _interopRequireDefault(_angular); - -var _lodash = require('lodash'); - -var _lodash2 = _interopRequireDefault(_lodash); - -var _jquery = require('jquery'); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _metricFunctions = require('./metricFunctions'); - -var metricFunctions = _interopRequireWildcard(_metricFunctions); - -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 }; } - -/** @ngInject */ -_angular2.default.module('grafana.directives').directive('addMetricFunction', function ($compile) { - var inputTemplate = ''; - - var buttonTemplate = '' + ''; - - return { - link: function link($scope, elem) { - var categories = metricFunctions.getCategories(); - var allFunctions = getAllFunctionNames(categories); - - $scope.functionMenu = createFunctionDropDownMenu(categories); - - var $input = (0, _jquery2.default)(inputTemplate); - var $button = (0, _jquery2.default)(buttonTemplate); - $input.appendTo(elem); - $button.appendTo(elem); - - $input.attr('data-provide', 'typeahead'); - $input.typeahead({ - source: allFunctions, - minLength: 1, - items: 10, - updater: function updater(value) { - var funcDef = metricFunctions.getFuncDef(value); - if (!funcDef) { - // try find close match - value = value.toLowerCase(); - funcDef = _lodash2.default.find(allFunctions, function (funcName) { - return funcName.toLowerCase().indexOf(value) === 0; - }); - - if (!funcDef) { - return; - } - } - - $scope.$apply(function () { - $scope.addFunction(funcDef); - }); - - $input.trigger('blur'); - return ''; - } - }); - - $button.click(function () { - $button.hide(); - $input.show(); - $input.focus(); - }); - - $input.keyup(function () { - elem.toggleClass('open', $input.val() === ''); - }); - - $input.blur(function () { - // clicking the function dropdown menu wont - // work if you remove class at once - setTimeout(function () { - $input.val(''); - $input.hide(); - $button.show(); - elem.removeClass('open'); - }, 200); - }); - - $compile(elem.contents())($scope); - } - }; -}); - -function getAllFunctionNames(categories) { - return _lodash2.default.reduce(categories, function (list, category) { - _lodash2.default.each(category, function (func) { - list.push(func.name); - }); - return list; - }, []); -} - -function createFunctionDropDownMenu(categories) { - return _lodash2.default.map(categories, function (list, category) { - return { - text: category, - submenu: _lodash2.default.map(list, function (value) { - return { - text: value.name, - click: "ctrl.addFunction('" + value.name + "')" - }; - }) - }; - }); -} diff --git a/dist/test/datasource-zabbix/dataProcessor.js b/dist/test/datasource-zabbix/dataProcessor.js deleted file mode 100644 index 2ce1585..0000000 --- a/dist/test/datasource-zabbix/dataProcessor.js +++ /dev/null @@ -1,330 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _lodash = require('lodash'); - -var _lodash2 = _interopRequireDefault(_lodash); - -var _utils = require('./utils'); - -var utils = _interopRequireWildcard(_utils); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Downsample datapoints series - */ -function downsampleSeries(datapoints, time_to, ms_interval, func) { - var downsampledSeries = []; - var timeWindow = { - from: time_to * 1000 - ms_interval, - to: time_to * 1000 - }; - - var points_sum = 0; - var points_num = 0; - var value_avg = 0; - var frame = []; - - for (var i = datapoints.length - 1; i >= 0; i -= 1) { - if (timeWindow.from < datapoints[i][1] && datapoints[i][1] <= timeWindow.to) { - points_sum += datapoints[i][0]; - points_num++; - frame.push(datapoints[i][0]); - } else { - value_avg = points_num ? points_sum / points_num : 0; - - if (func === "max") { - downsampledSeries.push([_lodash2.default.max(frame), timeWindow.to]); - } else if (func === "min") { - downsampledSeries.push([_lodash2.default.min(frame), timeWindow.to]); - } - - // avg by default - else { - downsampledSeries.push([value_avg, timeWindow.to]); - } - - // Shift time window - timeWindow.to = timeWindow.from; - timeWindow.from -= ms_interval; - - points_sum = 0; - points_num = 0; - frame = []; - - // Process point again - i++; - } - } - return downsampledSeries.reverse(); -} - -/** - * Group points by given time interval - * datapoints: [[, ], ...] - */ -function groupBy(interval, groupByCallback, datapoints) { - var ms_interval = utils.parseInterval(interval); - - // Calculate frame timestamps - var frames = _lodash2.default.groupBy(datapoints, function (point) { - // Calculate time for group of points - return Math.floor(point[1] / ms_interval) * ms_interval; - }); - - // frame: { '': [[, ], ...] } - // return [{ '': }, { '': }, ...] - var grouped = _lodash2.default.mapValues(frames, function (frame) { - var points = _lodash2.default.map(frame, function (point) { - return point[0]; - }); - return groupByCallback(points); - }); - - // Convert points to Grafana format - return sortByTime(_lodash2.default.map(grouped, function (value, timestamp) { - return [Number(value), Number(timestamp)]; - })); -} - -function sumSeries(timeseries) { - - // Calculate new points for interpolation - var new_timestamps = _lodash2.default.uniq(_lodash2.default.map(_lodash2.default.flatten(timeseries, true), function (point) { - return point[1]; - })); - new_timestamps = _lodash2.default.sortBy(new_timestamps); - - var interpolated_timeseries = _lodash2.default.map(timeseries, function (series) { - var timestamps = _lodash2.default.map(series, function (point) { - return point[1]; - }); - var new_points = _lodash2.default.map(_lodash2.default.difference(new_timestamps, timestamps), function (timestamp) { - return [null, timestamp]; - }); - var new_series = series.concat(new_points); - return sortByTime(new_series); - }); - - _lodash2.default.each(interpolated_timeseries, interpolateSeries); - - var new_timeseries = []; - var sum; - for (var i = new_timestamps.length - 1; i >= 0; i--) { - sum = 0; - for (var j = interpolated_timeseries.length - 1; j >= 0; j--) { - sum += interpolated_timeseries[j][i][0]; - } - new_timeseries.push([sum, new_timestamps[i]]); - } - - return sortByTime(new_timeseries); -} - -function limit(order, n, orderByFunc, timeseries) { - var orderByCallback = aggregationFunctions[orderByFunc]; - var sortByIteratee = function sortByIteratee(ts) { - var values = _lodash2.default.map(ts.datapoints, function (point) { - return point[0]; - }); - return orderByCallback(values); - }; - var sortedTimeseries = _lodash2.default.sortBy(timeseries, sortByIteratee); - if (order === 'bottom') { - return sortedTimeseries.slice(0, n); - } else { - return sortedTimeseries.slice(-n); - } -} - -function AVERAGE(values) { - var sum = 0; - _lodash2.default.each(values, function (value) { - sum += value; - }); - return sum / values.length; -} - -function MIN(values) { - return _lodash2.default.min(values); -} - -function MAX(values) { - return _lodash2.default.max(values); -} - -function MEDIAN(values) { - var sorted = _lodash2.default.sortBy(values); - return sorted[Math.floor(sorted.length / 2)]; -} - -function setAlias(alias, timeseries) { - timeseries.target = alias; - return timeseries; -} - -function setAliasByRegex(alias, timeseries) { - timeseries.target = extractText(timeseries.target, alias); - return timeseries; -} - -function extractText(str, pattern) { - var extractPattern = new RegExp(pattern); - var extractedValue = extractPattern.exec(str); - extractedValue = extractedValue[0]; - return extractedValue; -} - -function scale(factor, datapoints) { - return _lodash2.default.map(datapoints, function (point) { - return [point[0] * factor, point[1]]; - }); -} - -function delta(datapoints) { - var newSeries = []; - var deltaValue = void 0; - for (var i = 1; i < datapoints.length; i++) { - deltaValue = datapoints[i][0] - datapoints[i - 1][0]; - newSeries.push([deltaValue, datapoints[i][1]]); - } - return newSeries; -} - -function groupByWrapper(interval, groupFunc, datapoints) { - var groupByCallback = aggregationFunctions[groupFunc]; - return groupBy(interval, groupByCallback, datapoints); -} - -function aggregateByWrapper(interval, aggregateFunc, datapoints) { - // Flatten all points in frame and then just use groupBy() - var flattenedPoints = _lodash2.default.flatten(datapoints, true); - var groupByCallback = aggregationFunctions[aggregateFunc]; - return groupBy(interval, groupByCallback, flattenedPoints); -} - -function aggregateWrapper(groupByCallback, interval, datapoints) { - var flattenedPoints = _lodash2.default.flatten(datapoints, true); - return groupBy(interval, groupByCallback, flattenedPoints); -} - -function sortByTime(series) { - return _lodash2.default.sortBy(series, function (point) { - return point[1]; - }); -} - -/** - * Interpolate series with gaps - */ -function interpolateSeries(series) { - var left, right; - - // Interpolate series - for (var i = series.length - 1; i >= 0; i--) { - if (!series[i][0]) { - left = findNearestLeft(series, series[i]); - right = findNearestRight(series, series[i]); - if (!left) { - left = right; - } - if (!right) { - right = left; - } - series[i][0] = linearInterpolation(series[i][1], left, right); - } - } - return series; -} - -function linearInterpolation(timestamp, left, right) { - if (left[1] === right[1]) { - return (left[0] + right[0]) / 2; - } else { - return left[0] + (right[0] - left[0]) / (right[1] - left[1]) * (timestamp - left[1]); - } -} - -function findNearestRight(series, point) { - var point_index = _lodash2.default.indexOf(series, point); - var nearestRight; - for (var i = point_index; i < series.length; i++) { - if (series[i][0] !== null) { - return series[i]; - } - } - return nearestRight; -} - -function findNearestLeft(series, point) { - var point_index = _lodash2.default.indexOf(series, point); - var nearestLeft; - for (var i = point_index; i > 0; i--) { - if (series[i][0] !== null) { - return series[i]; - } - } - return nearestLeft; -} - -function timeShift(interval, range) { - var shift = utils.parseTimeShiftInterval(interval) / 1000; - return range.map(function (time) { - return time - shift; - }); -} - -function unShiftTimeSeries(interval, datapoints) { - var unshift = utils.parseTimeShiftInterval(interval); - return datapoints.map(function (dp) { - return [dp[0], dp[1] + unshift]; - }); -} - -var metricFunctions = { - groupBy: groupByWrapper, - scale: scale, - delta: delta, - aggregateBy: aggregateByWrapper, - average: _lodash2.default.partial(aggregateWrapper, AVERAGE), - min: _lodash2.default.partial(aggregateWrapper, MIN), - max: _lodash2.default.partial(aggregateWrapper, MAX), - median: _lodash2.default.partial(aggregateWrapper, MEDIAN), - sumSeries: sumSeries, - top: _lodash2.default.partial(limit, 'top'), - bottom: _lodash2.default.partial(limit, 'bottom'), - timeShift: timeShift, - setAlias: setAlias, - setAliasByRegex: setAliasByRegex -}; - -var aggregationFunctions = { - avg: AVERAGE, - min: MIN, - max: MAX, - median: MEDIAN -}; - -exports.default = { - downsampleSeries: downsampleSeries, - groupBy: groupBy, - AVERAGE: AVERAGE, - MIN: MIN, - MAX: MAX, - MEDIAN: MEDIAN, - unShiftTimeSeries: unShiftTimeSeries, - - get aggregationFunctions() { - return aggregationFunctions; - }, - - get metricFunctions() { - return metricFunctions; - } -}; diff --git a/dist/test/datasource-zabbix/datasource.js b/dist/test/datasource-zabbix/datasource.js deleted file mode 100644 index 2ecc64a..0000000 --- a/dist/test/datasource-zabbix/datasource.js +++ /dev/null @@ -1,582 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.zabbixTemplateFormat = exports.ZabbixAPIDatasource = undefined; - -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); - -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; }; }(); //import angular from 'angular'; - - -var _lodash = require('lodash'); - -var _lodash2 = _interopRequireDefault(_lodash); - -var _datemath = require('app/core/utils/datemath'); - -var dateMath = _interopRequireWildcard(_datemath); - -var _utils = require('./utils'); - -var utils = _interopRequireWildcard(_utils); - -var _migrations = require('./migrations'); - -var migrations = _interopRequireWildcard(_migrations); - -var _metricFunctions = require('./metricFunctions'); - -var metricFunctions = _interopRequireWildcard(_metricFunctions); - -var _dataProcessor = require('./dataProcessor'); - -var _dataProcessor2 = _interopRequireDefault(_dataProcessor); - -var _responseHandler = require('./responseHandler'); - -var _responseHandler2 = _interopRequireDefault(_responseHandler); - -require('./zabbix.js'); - -var _zabbixAPICoreService = require('./zabbixAPICore.service.js'); - -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 }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var ZabbixAPIDatasource = function () { - - /** @ngInject */ - function ZabbixAPIDatasource(instanceSettings, templateSrv, alertSrv, Zabbix) { - _classCallCheck(this, ZabbixAPIDatasource); - - this.templateSrv = templateSrv; - this.alertSrv = alertSrv; - - // General data source settings - this.name = instanceSettings.name; - this.url = instanceSettings.url; - this.basicAuth = instanceSettings.basicAuth; - this.withCredentials = instanceSettings.withCredentials; - - // Zabbix API credentials - this.username = instanceSettings.jsonData.username; - this.password = instanceSettings.jsonData.password; - - // Use trends instead history since specified time - this.trends = instanceSettings.jsonData.trends; - this.trendsFrom = instanceSettings.jsonData.trendsFrom || '7d'; - - // Set cache update interval - var ttl = instanceSettings.jsonData.cacheTTL || '1h'; - this.cacheTTL = utils.parseInterval(ttl); - - this.zabbix = new Zabbix(this.url, this.username, this.password, this.basicAuth, this.withCredentials, this.cacheTTL); - - // Use custom format for template variables - this.replaceTemplateVars = _lodash2.default.partial(replaceTemplateVars, this.templateSrv); - } - - //////////////////////// - // Datasource methods // - //////////////////////// - - /** - * Query panel data. Calls for each panel in dashboard. - * @param {Object} options Contains time range, targets and other info. - * @return {Object} Grafana metrics object with timeseries data for each target. - */ - - - _createClass(ZabbixAPIDatasource, [{ - key: 'query', - value: function query(options) { - var _this = this; - - var timeFrom = Math.ceil(dateMath.parse(options.range.from) / 1000); - var timeTo = Math.ceil(dateMath.parse(options.range.to) / 1000); - - var useTrendsFrom = Math.ceil(dateMath.parse('now-' + this.trendsFrom) / 1000); - var useTrends = timeFrom <= useTrendsFrom && this.trends; - - // Create request for each target - var promises = _lodash2.default.map(options.targets, function (target) { - // Prevent changes of original object - target = _lodash2.default.cloneDeep(target); - _this.replaceTargetVariables(target, options); - - // Apply Time-related functions (timeShift(), etc) - var timeFunctions = bindFunctionDefs(target.functions, 'Time'); - if (timeFunctions.length) { - var _sequence = sequence(timeFunctions)([timeFrom, timeTo]), - _sequence2 = _slicedToArray(_sequence, 2), - time_from = _sequence2[0], - time_to = _sequence2[1]; - - timeFrom = time_from; - timeTo = time_to; - } - - // Metrics or Text query mode - if (target.mode !== 1) { - // Migrate old targets - target = migrations.migrate(target); - - // Don't request undefined and hidden targets - if (target.hide || !target.group || !target.host || !target.item) { - return []; - } - - if (!target.mode || target.mode === 0) { - return _this.queryNumericData(target, timeFrom, timeTo, useTrends); - } else if (target.mode === 2) { - return _this.queryTextData(target, timeFrom, timeTo); - } - } - - // IT services mode - else if (target.mode === 1) { - // Don't show undefined and hidden targets - if (target.hide || !target.itservice || !target.slaProperty) { - return []; - } - - return _this.zabbix.getSLA(target.itservice.serviceid, timeFrom, timeTo).then(function (slaObject) { - return _responseHandler2.default.handleSLAResponse(target.itservice, target.slaProperty, slaObject); - }); - } - }); - - // Data for panel (all targets) - return Promise.all(_lodash2.default.flatten(promises)).then(_lodash2.default.flatten).then(function (timeseries_data) { - return downsampleSeries(timeseries_data, options); - }).then(function (data) { - return { data: data }; - }); - } - }, { - key: 'queryNumericData', - value: function queryNumericData(target, timeFrom, timeTo, useTrends) { - var _this2 = this; - - var options = { - itemtype: 'num' - }; - return this.zabbix.getItemsFromTarget(target, options).then(function (items) { - var getHistoryPromise = void 0; - - if (useTrends) { - (function () { - var valueType = _this2.getTrendValueType(target); - getHistoryPromise = _this2.zabbix.getTrend(items, timeFrom, timeTo).then(function (history) { - return _responseHandler2.default.handleTrends(history, items, valueType); - }); - })(); - } else { - // Use history - getHistoryPromise = _this2.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) { - return _responseHandler2.default.handleHistory(history, items); - }); - } - - return getHistoryPromise.then(function (timeseries_data) { - return _this2.applyDataProcessingFunctions(timeseries_data, target); - }); - }); - } - }, { - key: 'getTrendValueType', - value: function getTrendValueType(target) { - // Find trendValue() function and get specified trend value - var trendFunctions = _lodash2.default.map(metricFunctions.getCategories()['Trends'], 'name'); - var trendValueFunc = _lodash2.default.find(target.functions, function (func) { - return _lodash2.default.includes(trendFunctions, func.def.name); - }); - return trendValueFunc ? trendValueFunc.params[0] : "avg"; - } - }, { - key: 'applyDataProcessingFunctions', - value: function applyDataProcessingFunctions(timeseries_data, target) { - var transformFunctions = bindFunctionDefs(target.functions, 'Transform'); - var aggregationFunctions = bindFunctionDefs(target.functions, 'Aggregate'); - var filterFunctions = bindFunctionDefs(target.functions, 'Filter'); - var aliasFunctions = bindFunctionDefs(target.functions, 'Alias'); - - // Apply transformation functions - timeseries_data = _lodash2.default.map(timeseries_data, function (timeseries) { - timeseries.datapoints = sequence(transformFunctions)(timeseries.datapoints); - return timeseries; - }); - - // Apply filter functions - if (filterFunctions.length) { - timeseries_data = sequence(filterFunctions)(timeseries_data); - } - - // Apply aggregations - if (aggregationFunctions.length) { - (function () { - var dp = _lodash2.default.map(timeseries_data, 'datapoints'); - dp = sequence(aggregationFunctions)(dp); - - var aggFuncNames = _lodash2.default.map(metricFunctions.getCategories()['Aggregate'], 'name'); - var lastAgg = _lodash2.default.findLast(target.functions, function (func) { - return _lodash2.default.includes(aggFuncNames, func.def.name); - }); - - timeseries_data = [{ - target: lastAgg.text, - datapoints: dp - }]; - })(); - } - - // Apply alias functions - _lodash2.default.forEach(timeseries_data, sequence(aliasFunctions)); - - // Apply Time-related functions (timeShift(), etc) - // Find timeShift() function and get specified trend value - this.applyTimeShiftFunction(timeseries_data, target); - - return timeseries_data; - } - }, { - key: 'applyTimeShiftFunction', - value: function applyTimeShiftFunction(timeseries_data, target) { - // Find timeShift() function and get specified interval - var timeShiftFunc = _lodash2.default.find(target.functions, function (func) { - return func.def.name === 'timeShift'; - }); - if (timeShiftFunc) { - (function () { - var shift = timeShiftFunc.params[0]; - _lodash2.default.forEach(timeseries_data, function (series) { - series.datapoints = _dataProcessor2.default.unShiftTimeSeries(shift, series.datapoints); - }); - })(); - } - } - }, { - key: 'queryTextData', - value: function queryTextData(target, timeFrom, timeTo) { - var _this3 = this; - - var options = { - itemtype: 'text' - }; - return this.zabbix.getItemsFromTarget(target, options).then(function (items) { - if (items.length) { - return _this3.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) { - return _responseHandler2.default.convertHistory(history, items, false, function (point) { - var value = point.value; - - // Regex-based extractor - if (target.textFilter) { - value = extractText(point.value, target.textFilter, target.useCaptureGroups); - } - - return [value, point.clock * 1000]; - }); - }); - } else { - return Promise.resolve([]); - } - }); - } - - /** - * Test connection to Zabbix API - * @return {object} Connection status and Zabbix API version - */ - - }, { - key: 'testDatasource', - value: function testDatasource() { - var _this4 = this; - - var zabbixVersion = void 0; - return this.zabbix.getVersion().then(function (version) { - zabbixVersion = version; - return _this4.zabbix.login(); - }).then(function () { - return { - status: "success", - title: "Success", - message: "Zabbix API version: " + zabbixVersion - }; - }).catch(function (error) { - if (error instanceof _zabbixAPICoreService.ZabbixAPIError) { - return { - status: "error", - title: error.message, - message: error.data - }; - } else { - return { - status: "error", - title: "Connection failed", - message: "Could not connect to given url" - }; - } - }); - } - - //////////////// - // Templating // - //////////////// - - /** - * Find metrics from templated request. - * - * @param {string} query Query from Templating - * @return {string} Metric name - group, host, app or item or list - * of metrics in "{metric1,metcic2,...,metricN}" format. - */ - - }, { - key: 'metricFindQuery', - value: function metricFindQuery(query) { - var _this5 = this; - - var result = void 0; - var parts = []; - - // Split query. Query structure: group.host.app.item - _lodash2.default.each(query.split('.'), function (part) { - part = _this5.replaceTemplateVars(part, {}); - - // Replace wildcard to regex - if (part === '*') { - part = '/.*/'; - } - parts.push(part); - }); - var template = _lodash2.default.zipObject(['group', 'host', 'app', 'item'], parts); - - // Get items - if (parts.length === 4) { - // Search for all items, even it's not belong to any application - if (template.app === '/.*/') { - template.app = ''; - } - result = this.zabbix.getItems(template.group, template.host, template.app, template.item); - } else if (parts.length === 3) { - // Get applications - result = this.zabbix.getApps(template.group, template.host, template.app); - } else if (parts.length === 2) { - // Get hosts - result = this.zabbix.getHosts(template.group, template.host); - } else if (parts.length === 1) { - // Get groups - result = this.zabbix.getGroups(template.group); - } else { - result = Promise.resolve([]); - } - - return result.then(function (metrics) { - return metrics.map(formatMetric); - }); - } - - ///////////////// - // Annotations // - ///////////////// - - }, { - key: 'annotationQuery', - value: function annotationQuery(options) { - var _this6 = this; - - var timeFrom = Math.ceil(dateMath.parse(options.rangeRaw.from) / 1000); - var timeTo = Math.ceil(dateMath.parse(options.rangeRaw.to) / 1000); - var annotation = options.annotation; - var showOkEvents = annotation.showOkEvents ? [0, 1] : 1; - - // Show all triggers - var showTriggers = [0, 1]; - - var getTriggers = this.zabbix.getTriggers(this.replaceTemplateVars(annotation.group, {}), this.replaceTemplateVars(annotation.host, {}), this.replaceTemplateVars(annotation.application, {}), showTriggers); - - return getTriggers.then(function (triggers) { - - // Filter triggers by description - if (utils.isRegex(annotation.trigger)) { - triggers = _lodash2.default.filter(triggers, function (trigger) { - return utils.buildRegex(annotation.trigger).test(trigger.description); - }); - } else if (annotation.trigger) { - triggers = _lodash2.default.filter(triggers, function (trigger) { - return trigger.description === annotation.trigger; - }); - } - - // Remove events below the chose severity - triggers = _lodash2.default.filter(triggers, function (trigger) { - return Number(trigger.priority) >= Number(annotation.minseverity); - }); - - var objectids = _lodash2.default.map(triggers, 'triggerid'); - return _this6.zabbix.getEvents(objectids, timeFrom, timeTo, showOkEvents).then(function (events) { - var indexedTriggers = _lodash2.default.keyBy(triggers, 'triggerid'); - - // Hide acknowledged events if option enabled - if (annotation.hideAcknowledged) { - events = _lodash2.default.filter(events, function (event) { - return !event.acknowledges.length; - }); - } - - return _lodash2.default.map(events, function (event) { - var tags = void 0; - if (annotation.showHostname) { - tags = _lodash2.default.map(event.hosts, 'name'); - } - - // Show event type (OK or Problem) - var title = Number(event.value) ? 'Problem' : 'OK'; - - var formatted_acknowledges = utils.formatAcknowledges(event.acknowledges); - return { - annotation: annotation, - time: event.clock * 1000, - title: title, - tags: tags, - text: indexedTriggers[event.objectid].description + formatted_acknowledges - }; - }); - }); - }); - } - - // Replace template variables - - }, { - key: 'replaceTargetVariables', - value: function replaceTargetVariables(target, options) { - var _this7 = this; - - var parts = ['group', 'host', 'application', 'item']; - parts.forEach(function (p) { - if (target[p] && target[p].filter) { - target[p].filter = _this7.replaceTemplateVars(target[p].filter, options.scopedVars); - } - }); - target.textFilter = this.replaceTemplateVars(target.textFilter, options.scopedVars); - - _lodash2.default.forEach(target.functions, function (func) { - func.params = func.params.map(function (param) { - if (typeof param === 'number') { - return +_this7.templateSrv.replace(param.toString(), options.scopedVars); - } else { - return _this7.templateSrv.replace(param, options.scopedVars); - } - }); - }); - } - }]); - - return ZabbixAPIDatasource; -}(); - -function bindFunctionDefs(functionDefs, category) { - var aggregationFunctions = _lodash2.default.map(metricFunctions.getCategories()[category], 'name'); - var aggFuncDefs = _lodash2.default.filter(functionDefs, function (func) { - return _lodash2.default.includes(aggregationFunctions, func.def.name); - }); - - return _lodash2.default.map(aggFuncDefs, function (func) { - var funcInstance = metricFunctions.createFuncInstance(func.def, func.params); - return funcInstance.bindFunction(_dataProcessor2.default.metricFunctions); - }); -} - -function downsampleSeries(timeseries_data, options) { - 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); - } - return timeseries; - }); -} - -function formatMetric(metricObj) { - return { - text: metricObj.name, - expandable: false - }; -} - -/** - * Custom formatter for template variables. - * Default Grafana "regex" formatter returns - * value1|value2 - * This formatter returns - * (value1|value2) - * This format needed for using in complex regex with - * template variables, for example - * /CPU $cpu_item.*time/ where $cpu_item is system,user,iowait - */ -function zabbixTemplateFormat(value) { - if (typeof value === 'string') { - return utils.escapeRegex(value); - } - - var escapedValues = _lodash2.default.map(value, utils.escapeRegex); - return '(' + escapedValues.join('|') + ')'; -} - -/** - * If template variables are used in request, replace it using regex format - * and wrap with '/' for proper multi-value work. Example: - * $variable selected as a, b, c - * We use filter $variable - * $variable -> a|b|c -> /a|b|c/ - * /$variable/ -> /a|b|c/ -> /a|b|c/ - */ -function replaceTemplateVars(templateSrv, target, scopedVars) { - var replacedTarget = templateSrv.replace(target, scopedVars, zabbixTemplateFormat); - if (target !== replacedTarget && !utils.isRegex(replacedTarget)) { - replacedTarget = '/^' + replacedTarget + '$/'; - } - return replacedTarget; -} - -function extractText(str, pattern, useCaptureGroups) { - var extractPattern = new RegExp(pattern); - var extractedValue = extractPattern.exec(str); - if (extractedValue) { - if (useCaptureGroups) { - extractedValue = extractedValue[1]; - } else { - extractedValue = extractedValue[0]; - } - } - return extractedValue; -} - -// Apply function one by one: -// sequence([a(), b(), c()]) = c(b(a())); -function sequence(funcsArray) { - return function (result) { - for (var i = 0; i < funcsArray.length; i++) { - result = funcsArray[i].call(this, result); - } - return result; - }; -} - -exports.ZabbixAPIDatasource = ZabbixAPIDatasource; -exports.zabbixTemplateFormat = zabbixTemplateFormat; - -// Fix for backward compatibility with lodash 2.4 - -if (!_lodash2.default.includes) { - _lodash2.default.includes = _lodash2.default.contains; -} -if (!_lodash2.default.keyBy) { - _lodash2.default.keyBy = _lodash2.default.indexBy; -} diff --git a/dist/test/datasource-zabbix/metric-function-editor.directive.js b/dist/test/datasource-zabbix/metric-function-editor.directive.js deleted file mode 100644 index 02135e9..0000000 --- a/dist/test/datasource-zabbix/metric-function-editor.directive.js +++ /dev/null @@ -1,246 +0,0 @@ -'use strict'; - -var _angular = require('angular'); - -var _angular2 = _interopRequireDefault(_angular); - -var _lodash = require('lodash'); - -var _lodash2 = _interopRequireDefault(_lodash); - -var _jquery = require('jquery'); - -var _jquery2 = _interopRequireDefault(_jquery); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** @ngInject */ -_angular2.default.module('grafana.directives').directive('metricFunctionEditor', function ($compile, templateSrv) { - - var funcSpanTemplate = '{{func.def.name}}('; - var paramTemplate = ''; - - var funcControlsTemplate = '
        ' + '' + '' + '' + '' + '
        '; - - return { - restrict: 'A', - link: function postLink($scope, elem) { - var $funcLink = (0, _jquery2.default)(funcSpanTemplate); - var $funcControls = (0, _jquery2.default)(funcControlsTemplate); - var ctrl = $scope.ctrl; - var func = $scope.func; - var funcDef = func.def; - var scheduledRelink = false; - var paramCountAtLink = 0; - - function clickFuncParam(paramIndex) { - /*jshint validthis:true */ - - var $link = (0, _jquery2.default)(this); - var $input = $link.next(); - - $input.val(func.params[paramIndex]); - $input.css('width', $link.width() + 16 + 'px'); - - $link.hide(); - $input.show(); - $input.focus(); - $input.select(); - - var typeahead = $input.data('typeahead'); - if (typeahead) { - $input.val(''); - typeahead.lookup(); - } - } - - function scheduledRelinkIfNeeded() { - if (paramCountAtLink === func.params.length) { - return; - } - - if (!scheduledRelink) { - scheduledRelink = true; - setTimeout(function () { - relink(); - scheduledRelink = false; - }, 200); - } - } - - function inputBlur(paramIndex) { - /*jshint validthis:true */ - var $input = (0, _jquery2.default)(this); - var $link = $input.prev(); - var newValue = $input.val(); - - if (newValue !== '' || func.def.params[paramIndex].optional) { - $link.html(templateSrv.highlightVariablesAsHtml(newValue)); - - func.updateParam($input.val(), paramIndex); - scheduledRelinkIfNeeded(); - - $scope.$apply(function () { - ctrl.targetChanged(); - }); - - $input.hide(); - $link.show(); - } - } - - function inputKeyPress(paramIndex, e) { - /*jshint validthis:true */ - if (e.which === 13) { - inputBlur.call(this, paramIndex); - } - } - - function inputKeyDown() { - /*jshint validthis:true */ - this.style.width = (3 + this.value.length) * 8 + 'px'; - } - - function addTypeahead($input, paramIndex) { - $input.attr('data-provide', 'typeahead'); - - var options = funcDef.params[paramIndex].options; - if (funcDef.params[paramIndex].type === 'int' || funcDef.params[paramIndex].type === 'float') { - options = _lodash2.default.map(options, function (val) { - return val.toString(); - }); - } - - $input.typeahead({ - source: options, - minLength: 0, - items: 20, - updater: function updater(value) { - setTimeout(function () { - inputBlur.call($input[0], paramIndex); - }, 0); - return value; - } - }); - - var typeahead = $input.data('typeahead'); - typeahead.lookup = function () { - this.query = this.$element.val() || ''; - return this.process(this.source); - }; - } - - function toggleFuncControls() { - var targetDiv = elem.closest('.tight-form'); - - if (elem.hasClass('show-function-controls')) { - elem.removeClass('show-function-controls'); - targetDiv.removeClass('has-open-function'); - $funcControls.hide(); - return; - } - - elem.addClass('show-function-controls'); - targetDiv.addClass('has-open-function'); - - $funcControls.show(); - } - - function addElementsAndCompile() { - $funcControls.appendTo(elem); - $funcLink.appendTo(elem); - - _lodash2.default.each(funcDef.params, function (param, index) { - if (param.optional && func.params.length <= index) { - return; - } - - if (index > 0) { - (0, _jquery2.default)(', ').appendTo(elem); - } - - var paramValue = templateSrv.highlightVariablesAsHtml(func.params[index]); - var $paramLink = (0, _jquery2.default)('' + paramValue + ''); - var $input = (0, _jquery2.default)(paramTemplate); - - paramCountAtLink++; - - $paramLink.appendTo(elem); - $input.appendTo(elem); - - $input.blur(_lodash2.default.partial(inputBlur, index)); - $input.keyup(inputKeyDown); - $input.keypress(_lodash2.default.partial(inputKeyPress, index)); - $paramLink.click(_lodash2.default.partial(clickFuncParam, index)); - - if (funcDef.params[index].options) { - addTypeahead($input, index); - } - }); - - (0, _jquery2.default)(')').appendTo(elem); - - $compile(elem.contents())($scope); - } - - function ifJustAddedFocusFistParam() { - if ($scope.func.added) { - $scope.func.added = false; - setTimeout(function () { - elem.find('.graphite-func-param-link').first().click(); - }, 10); - } - } - - function registerFuncControlsToggle() { - $funcLink.click(toggleFuncControls); - } - - function registerFuncControlsActions() { - $funcControls.click(function (e) { - var $target = (0, _jquery2.default)(e.target); - if ($target.hasClass('fa-remove')) { - toggleFuncControls(); - $scope.$apply(function () { - ctrl.removeFunction($scope.func); - }); - return; - } - - if ($target.hasClass('fa-arrow-left')) { - $scope.$apply(function () { - _lodash2.default.move($scope.target.functions, $scope.$index, $scope.$index - 1); - ctrl.targetChanged(); - }); - return; - } - - if ($target.hasClass('fa-arrow-right')) { - $scope.$apply(function () { - _lodash2.default.move($scope.target.functions, $scope.$index, $scope.$index + 1); - ctrl.targetChanged(); - }); - return; - } - - if ($target.hasClass('fa-question-circle')) { - var docSite = "http://docs.grafana-zabbix.org/reference/functions/"; - window.open(docSite + '#' + funcDef.name.toLowerCase(), '_blank'); - return; - } - }); - } - - function relink() { - elem.children().remove(); - - addElementsAndCompile(); - ifJustAddedFocusFistParam(); - registerFuncControlsToggle(); - registerFuncControlsActions(); - } - - relink(); - } - }; -}); diff --git a/dist/test/datasource-zabbix/metricFunctions.js b/dist/test/datasource-zabbix/metricFunctions.js deleted file mode 100644 index 1a54a57..0000000 --- a/dist/test/datasource-zabbix/metricFunctions.js +++ /dev/null @@ -1,292 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -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; }; }(); - -exports.createFuncInstance = createFuncInstance; -exports.getFuncDef = getFuncDef; -exports.getCategories = getCategories; - -var _lodash = require('lodash'); - -var _lodash2 = _interopRequireDefault(_lodash); - -var _jquery = require('jquery'); - -var _jquery2 = _interopRequireDefault(_jquery); - -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 index = []; -var categories = { - Transform: [], - Aggregate: [], - Filter: [], - Trends: [], - Time: [], - Alias: [] -}; - -function addFuncDef(funcDef) { - funcDef.params = funcDef.params || []; - funcDef.defaultParams = funcDef.defaultParams || []; - - if (funcDef.category) { - categories[funcDef.category].push(funcDef); - } - index[funcDef.name] = funcDef; - index[funcDef.shortName || funcDef.name] = funcDef; -} - -// Transform - -addFuncDef({ - name: 'groupBy', - category: 'Transform', - params: [{ name: 'interval', type: 'string' }, { name: 'function', type: 'string', options: ['avg', 'min', 'max', 'median'] }], - defaultParams: ['1m', 'avg'] -}); - -addFuncDef({ - name: 'scale', - category: 'Transform', - params: [{ name: 'factor', type: 'float', options: [100, 0.01, 10, -1] }], - defaultParams: [100] -}); - -addFuncDef({ - name: 'delta', - category: 'Transform', - params: [], - defaultParams: [] -}); - -// Aggregate - -addFuncDef({ - name: 'sumSeries', - category: 'Aggregate', - params: [], - defaultParams: [] -}); - -addFuncDef({ - name: 'median', - category: 'Aggregate', - params: [{ name: 'interval', type: 'string' }], - defaultParams: ['1m'] -}); - -addFuncDef({ - name: 'average', - category: 'Aggregate', - params: [{ name: 'interval', type: 'string' }], - defaultParams: ['1m'] -}); - -addFuncDef({ - name: 'min', - category: 'Aggregate', - params: [{ name: 'interval', type: 'string' }], - defaultParams: ['1m'] -}); - -addFuncDef({ - name: 'max', - category: 'Aggregate', - params: [{ name: 'interval', type: 'string' }], - defaultParams: ['1m'] -}); - -addFuncDef({ - name: 'aggregateBy', - category: 'Aggregate', - params: [{ name: 'interval', type: 'string' }, { name: 'function', type: 'string', options: ['avg', 'min', 'max', 'median'] }], - defaultParams: ['1m', 'avg'] -}); - -// Filter - -addFuncDef({ - name: 'top', - category: 'Filter', - params: [{ name: 'number', type: 'int' }, { name: 'value', type: 'string', options: ['avg', 'min', 'max', 'median'] }], - defaultParams: [5, 'avg'] -}); - -addFuncDef({ - name: 'bottom', - category: 'Filter', - params: [{ name: 'number', type: 'int' }, { name: 'value', type: 'string', options: ['avg', 'min', 'max', 'median'] }], - defaultParams: [5, 'avg'] -}); - -// Trends - -addFuncDef({ - name: 'trendValue', - category: 'Trends', - params: [{ name: 'type', type: 'string', options: ['avg', 'min', 'max'] }], - defaultParams: ['avg'] -}); - -// Time - -addFuncDef({ - name: 'timeShift', - category: 'Time', - params: [{ name: 'interval', type: 'string', options: ['24h', '7d', '1M', '+24h', '-24h'] }], - defaultParams: ['24h'] -}); - -//Alias - -addFuncDef({ - name: 'setAlias', - category: 'Alias', - params: [{ name: 'alias', type: 'string' }], - defaultParams: [] -}); - -addFuncDef({ - name: 'setAliasByRegex', - category: 'Alias', - params: [{ name: 'aliasByRegex', type: 'string' }], - defaultParams: [] -}); - -_lodash2.default.each(categories, function (funcList, catName) { - categories[catName] = _lodash2.default.sortBy(funcList, 'name'); -}); - -var FuncInstance = function () { - function FuncInstance(funcDef, params) { - _classCallCheck(this, FuncInstance); - - this.def = funcDef; - - if (params) { - this.params = params; - } else { - // Create with default params - this.params = []; - this.params = funcDef.defaultParams.slice(0); - } - - this.updateText(); - } - - _createClass(FuncInstance, [{ - key: 'bindFunction', - value: function bindFunction(metricFunctions) { - var func = metricFunctions[this.def.name]; - if (func) { - - // Bind function arguments - var bindedFunc = func; - var param; - for (var i = 0; i < this.params.length; i++) { - param = this.params[i]; - - // Convert numeric params - if (this.def.params[i].type === 'int' || this.def.params[i].type === 'float') { - param = Number(param); - } - bindedFunc = _lodash2.default.partial(bindedFunc, param); - } - return bindedFunc; - } else { - throw { message: 'Method not found ' + this.def.name }; - } - } - }, { - key: 'render', - value: function render(metricExp) { - var str = this.def.name + '('; - var parameters = _lodash2.default.map(this.params, function (value, index) { - - var paramType = this.def.params[index].type; - if (paramType === 'int' || paramType === 'float' || paramType === 'value_or_series' || paramType === 'boolean') { - return value; - } else if (paramType === 'int_or_interval' && _jquery2.default.isNumeric(value)) { - return value; - } - - return "'" + value + "'"; - }, this); - - if (metricExp) { - parameters.unshift(metricExp); - } - - return str + parameters.join(', ') + ')'; - } - }, { - key: '_hasMultipleParamsInString', - value: function _hasMultipleParamsInString(strValue, index) { - if (strValue.indexOf(',') === -1) { - return false; - } - - return this.def.params[index + 1] && this.def.params[index + 1].optional; - } - }, { - key: 'updateParam', - value: function updateParam(strValue, index) { - // handle optional parameters - // if string contains ',' and next param is optional, split and update both - if (this._hasMultipleParamsInString(strValue, index)) { - _lodash2.default.each(strValue.split(','), function (partVal, idx) { - this.updateParam(partVal.trim(), idx); - }, this); - return; - } - - if (strValue === '' && this.def.params[index].optional) { - this.params.splice(index, 1); - } else { - this.params[index] = strValue; - } - - this.updateText(); - } - }, { - key: 'updateText', - value: function updateText() { - if (this.params.length === 0) { - this.text = this.def.name + '()'; - return; - } - - var text = this.def.name + '('; - text += this.params.join(', '); - text += ')'; - this.text = text; - } - }]); - - return FuncInstance; -}(); - -function createFuncInstance(funcDef, params) { - if (_lodash2.default.isString(funcDef)) { - if (!index[funcDef]) { - throw { message: 'Method not found ' + name }; - } - funcDef = index[funcDef]; - } - return new FuncInstance(funcDef, params); -} - -function getFuncDef(name) { - return index[name]; -} - -function getCategories() { - return categories; -} diff --git a/dist/test/datasource-zabbix/migrations.js b/dist/test/datasource-zabbix/migrations.js deleted file mode 100644 index dc422c0..0000000 --- a/dist/test/datasource-zabbix/migrations.js +++ /dev/null @@ -1,48 +0,0 @@ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.isGrafana2target = isGrafana2target; -exports.migrateFrom2To3version = migrateFrom2To3version; -exports.migrate = migrate; -/** - * Query format migration. - * This module can detect query format version and make migration. - */ - -function isGrafana2target(target) { - if (!target.mode || target.mode === 0 || target.mode === 2) { - if ((target.hostFilter || target.itemFilter || target.downsampleFunction || target.host && target.host.host) && target.item.filter === undefined && target.host.filter === undefined) { - return true; - } else { - return false; - } - } else { - return false; - } -} - -function migrateFrom2To3version(target) { - target.group.filter = target.group.name === "*" ? "/.*/" : target.group.name; - target.host.filter = target.host.name === "*" ? convertToRegex(target.hostFilter) : target.host.name; - target.application.filter = target.application.name === "*" ? "" : target.application.name; - target.item.filter = target.item.name === "All" ? convertToRegex(target.itemFilter) : target.item.name; - return target; -} - -function migrate(target) { - if (isGrafana2target(target)) { - return migrateFrom2To3version(target); - } else { - return target; - } -} - -function convertToRegex(str) { - if (str) { - return '/' + str + '/'; - } else { - return '/.*/'; - } -} diff --git a/dist/test/datasource-zabbix/module.js b/dist/test/datasource-zabbix/module.js deleted file mode 100644 index 10f88d0..0000000 --- a/dist/test/datasource-zabbix/module.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.AnnotationsQueryCtrl = exports.QueryOptionsCtrl = exports.QueryCtrl = exports.ConfigCtrl = exports.Datasource = undefined; - -var _datasource = require('./datasource'); - -var _query = require('./query.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); -}; - -ZabbixQueryOptionsController.templateUrl = 'datasource-zabbix/partials/query.options.html'; - -var ZabbixAnnotationsQueryController = function ZabbixAnnotationsQueryController() { - _classCallCheck(this, ZabbixAnnotationsQueryController); -}; - -ZabbixAnnotationsQueryController.templateUrl = 'datasource-zabbix/partials/annotations.editor.html'; - -exports.Datasource = _datasource.ZabbixAPIDatasource; -exports.ConfigCtrl = ZabbixConfigController; -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 deleted file mode 100644 index 24542f5..0000000 --- a/dist/test/datasource-zabbix/query.controller.js +++ /dev/null @@ -1,378 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.ZabbixQueryController = 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 _sdk = require('app/plugins/sdk'); - -var _angular = require('angular'); - -var _angular2 = _interopRequireDefault(_angular); - -var _lodash = require('lodash'); - -var _lodash2 = _interopRequireDefault(_lodash); - -var _utils = require('./utils'); - -var utils = _interopRequireWildcard(_utils); - -var _metricFunctions = require('./metricFunctions'); - -var metricFunctions = _interopRequireWildcard(_metricFunctions); - -var _migrations = require('./migrations'); - -var migrations = _interopRequireWildcard(_migrations); - -require('./add-metric-function.directive'); - -require('./metric-function-editor.directive'); - -require('./css/query-editor.css!'); - -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 }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -var ZabbixQueryController = exports.ZabbixQueryController = function (_QueryCtrl) { - _inherits(ZabbixQueryController, _QueryCtrl); - - // ZabbixQueryCtrl constructor - function ZabbixQueryController($scope, $injector, $rootScope, $sce, templateSrv) { - _classCallCheck(this, ZabbixQueryController); - - var _this = _possibleConstructorReturn(this, (ZabbixQueryController.__proto__ || Object.getPrototypeOf(ZabbixQueryController)).call(this, $scope, $injector)); - - _this.zabbix = _this.datasource.zabbix; - - // Use custom format for template variables - _this.replaceTemplateVars = _this.datasource.replaceTemplateVars; - _this.templateSrv = templateSrv; - - _this.editorModes = { - 0: { value: 'num', text: 'Metrics', mode: 0 }, - 1: { value: 'itservice', text: 'IT Services', mode: 1 }, - 2: { value: 'text', text: 'Text', mode: 2 } - }; - - // Map functions for bs-typeahead - _this.getGroupNames = _lodash2.default.partial(getMetricNames, _this, 'groupList'); - _this.getHostNames = _lodash2.default.partial(getMetricNames, _this, 'hostList'); - _this.getApplicationNames = _lodash2.default.partial(getMetricNames, _this, 'appList'); - _this.getItemNames = _lodash2.default.partial(getMetricNames, _this, 'itemList'); - - // Update metric suggestion when template variable was changed - $rootScope.$on('template-variable-value-updated', function () { - return _this.onVariableChange(); - }); - - // Update metrics when item selected from dropdown - $scope.$on('typeahead-updated', function () { - _this.onTargetBlur(); - }); - - _this.init = function () { - var target = this.target; - - // Migrate old targets - target = migrations.migrate(target); - - var scopeDefaults = { - metric: {}, - oldTarget: _lodash2.default.cloneDeep(this.target), - queryOptionsText: this.renderQueryOptionsText() - }; - _lodash2.default.defaults(this, scopeDefaults); - - // Load default values - var targetDefaults = { - mode: 0, - group: { filter: "" }, - host: { filter: "" }, - application: { filter: "" }, - item: { filter: "" }, - functions: [], - options: { - showDisabledItems: false - } - }; - _lodash2.default.defaults(target, targetDefaults); - - // Create function instances from saved JSON - target.functions = _lodash2.default.map(target.functions, function (func) { - return metricFunctions.createFuncInstance(func.def, func.params); - }); - - if (target.mode === 0 || target.mode === 2) { - - this.downsampleFunctionList = [{ name: "avg", value: "avg" }, { name: "min", value: "min" }, { name: "max", value: "max" }]; - - this.initFilters(); - } else if (target.mode === 1) { - 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(); - } - }; - - _this.init(); - return _this; - } - - _createClass(ZabbixQueryController, [{ - key: 'initFilters', - value: function initFilters() { - var itemtype = this.editorModes[this.target.mode].value; - return Promise.all([this.suggestGroups(), this.suggestHosts(), this.suggestApps(), this.suggestItems(itemtype)]); - } - }, { - key: 'suggestGroups', - value: function suggestGroups() { - var _this2 = this; - - return this.zabbix.getAllGroups().then(function (groups) { - _this2.metric.groupList = groups; - return groups; - }); - } - }, { - key: 'suggestHosts', - value: function suggestHosts() { - var _this3 = this; - - var groupFilter = this.replaceTemplateVars(this.target.group.filter); - return this.zabbix.getAllHosts(groupFilter).then(function (hosts) { - _this3.metric.hostList = hosts; - return hosts; - }); - } - }, { - key: 'suggestApps', - value: function suggestApps() { - var _this4 = this; - - var groupFilter = this.replaceTemplateVars(this.target.group.filter); - var hostFilter = this.replaceTemplateVars(this.target.host.filter); - return this.zabbix.getAllApps(groupFilter, hostFilter).then(function (apps) { - _this4.metric.appList = apps; - return apps; - }); - } - }, { - key: 'suggestItems', - value: function suggestItems() { - var _this5 = this; - - var itemtype = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'num'; - - var groupFilter = this.replaceTemplateVars(this.target.group.filter); - var hostFilter = this.replaceTemplateVars(this.target.host.filter); - var appFilter = this.replaceTemplateVars(this.target.application.filter); - var options = { - itemtype: itemtype, - showDisabledItems: this.target.options.showDisabledItems - }; - - return this.zabbix.getAllItems(groupFilter, hostFilter, appFilter, options).then(function (items) { - _this5.metric.itemList = items; - return items; - }); - } - }, { - key: 'isRegex', - value: function isRegex(str) { - return utils.isRegex(str); - } - }, { - key: 'isVariable', - value: function isVariable(str) { - return utils.isTemplateVariable(str, this.templateSrv.variables); - } - }, { - key: 'onTargetBlur', - value: function onTargetBlur() { - var newTarget = _lodash2.default.cloneDeep(this.target); - if (!_lodash2.default.isEqual(this.oldTarget, this.target)) { - this.oldTarget = newTarget; - this.targetChanged(); - } - } - }, { - key: 'onVariableChange', - value: function onVariableChange() { - if (this.isContainsVariables()) { - this.targetChanged(); - } - } - - /** - * Check query for template variables - */ - - }, { - key: 'isContainsVariables', - value: function isContainsVariables() { - var _this6 = 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); - } else { - return false; - } - }); - } - }, { - key: 'parseTarget', - value: function parseTarget() {} - // Parse target - - - // Validate target and set validation info - - }, { - key: 'validateTarget', - value: function validateTarget() { - // validate - } - }, { - key: 'targetChanged', - value: function targetChanged() { - this.initFilters(); - this.parseTarget(); - this.panelCtrl.refresh(); - } - }, { - key: 'addFunction', - value: function addFunction(funcDef) { - var newFunc = metricFunctions.createFuncInstance(funcDef); - newFunc.added = true; - this.target.functions.push(newFunc); - - this.moveAliasFuncLast(); - - if (newFunc.params.length && newFunc.added || newFunc.def.params.length === 0) { - this.targetChanged(); - } - } - }, { - key: 'removeFunction', - value: function removeFunction(func) { - this.target.functions = _lodash2.default.without(this.target.functions, func); - this.targetChanged(); - } - }, { - key: 'moveAliasFuncLast', - value: function moveAliasFuncLast() { - var aliasFunc = _lodash2.default.find(this.target.functions, function (func) { - return func.def.name === 'alias' || func.def.name === 'aliasByNode' || func.def.name === 'aliasByMetric'; - }); - - if (aliasFunc) { - this.target.functions = _lodash2.default.without(this.target.functions, aliasFunc); - this.target.functions.push(aliasFunc); - } - } - }, { - key: 'toggleQueryOptions', - value: function toggleQueryOptions() { - this.showQueryOptions = !this.showQueryOptions; - } - }, { - key: 'onQueryOptionChange', - value: function onQueryOptionChange() { - this.queryOptionsText = this.renderQueryOptionsText(); - this.onTargetBlur(); - } - }, { - key: 'renderQueryOptionsText', - value: function renderQueryOptionsText() { - var optionsMap = { - showDisabledItems: "Show disabled items" - }; - var options = []; - _lodash2.default.forOwn(this.target.options, function (value, key) { - if (value) { - if (value === true) { - // Show only option name (if enabled) for boolean options - options.push(optionsMap[key]); - } else { - // Show "option = value" for another options - options.push(optionsMap[key] + " = " + value); - } - } - }); - return "Options: " + options.join(', '); - } - - /** - * Switch query editor to specified mode. - * Modes: - * 0 - items - * 1 - IT services - * 2 - Text metrics - */ - - }, { - key: 'switchEditorMode', - 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(); - } - } - }]); - - return ZabbixQueryController; -}(_sdk.QueryCtrl); - -// Set templateUrl as static property - - -ZabbixQueryController.templateUrl = 'datasource-zabbix/partials/query.editor.html'; - -// Get list of metric names for bs-typeahead directive -function getMetricNames(scope, metricList) { - return _lodash2.default.uniq(_lodash2.default.map(scope.metric[metricList], 'name')); -} diff --git a/dist/test/datasource-zabbix/responseHandler.js b/dist/test/datasource-zabbix/responseHandler.js deleted file mode 100644 index 8bad6f4..0000000 --- a/dist/test/datasource-zabbix/responseHandler.js +++ /dev/null @@ -1,116 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _lodash = require('lodash'); - -var _lodash2 = _interopRequireDefault(_lodash); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Convert Zabbix API history.get response to Grafana format - * - * @return {Array} Array of timeseries in Grafana format - * { - * target: "Metric name", - * datapoints: [[, ], ...] - * } - */ -function convertHistory(history, items, addHostName, convertPointCallback) { - /** - * Response should be in the format: - * data: [ - * { - * target: "Metric name", - * datapoints: [[, ], ...] - * }, ... - * ] - */ - - // Group history by itemid - var grouped_history = _lodash2.default.groupBy(history, 'itemid'); - var hosts = _lodash2.default.uniqBy(_lodash2.default.flatten(_lodash2.default.map(items, 'hosts')), 'hostid'); //uniqBy is needed to deduplicate - - return _lodash2.default.map(grouped_history, function (hist, itemid) { - 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: _lodash2.default.map(hist, convertPointCallback) - }; - }); -} - -function handleHistory(history, items) { - var addHostName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; - - return convertHistory(history, items, addHostName, convertHistoryPoint); -} - -function handleTrends(history, items, valueType) { - var addHostName = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; - - var convertPointCallback = _lodash2.default.partial(convertTrendPoint, valueType); - return convertHistory(history, items, addHostName, convertPointCallback); -} - -function handleSLAResponse(itservice, slaProperty, slaObject) { - var targetSLA = slaObject[itservice.serviceid].sla[0]; - if (slaProperty.property === 'status') { - var targetStatus = parseInt(slaObject[itservice.serviceid].status); - return { - target: itservice.name + ' ' + slaProperty.name, - datapoints: [[targetStatus, targetSLA.to * 1000]] - }; - } else { - return { - target: itservice.name + ' ' + slaProperty.name, - datapoints: [[targetSLA[slaProperty.property], targetSLA.from * 1000], [targetSLA[slaProperty.property], targetSLA.to * 1000]] - }; - } -} - -function convertHistoryPoint(point) { - // Value must be a number for properly work - return [Number(point.value), point.clock * 1000]; -} - -function convertTrendPoint(valueType, point) { - var value; - switch (valueType) { - case "min": - value = point.value_min; - break; - case "max": - value = point.value_max; - break; - case "avg": - value = point.value_avg; - break; - default: - value = point.value_avg; - } - - return [Number(value), point.clock * 1000]; -} - -exports.default = { - handleHistory: handleHistory, - convertHistory: convertHistory, - handleTrends: handleTrends, - handleSLAResponse: handleSLAResponse -}; - -// Fix for backward compatibility with lodash 2.4 - -if (!_lodash2.default.uniqBy) { - _lodash2.default.uniqBy = _lodash2.default.uniq; -} diff --git a/dist/test/datasource-zabbix/specs/datasource_specs.js b/dist/test/datasource-zabbix/specs/datasource_specs.js deleted file mode 100644 index f34a105..0000000 --- a/dist/test/datasource-zabbix/specs/datasource_specs.js +++ /dev/null @@ -1,317 +0,0 @@ -"use strict"; - -var _module = require("../module"); - -var _datasource = require("../datasource"); - -var _q = require("q"); - -var _q2 = _interopRequireDefault(_q); - -var _sinon = require("sinon"); - -var _sinon2 = _interopRequireDefault(_sinon); - -var _lodash = require("lodash"); - -var _lodash2 = _interopRequireDefault(_lodash); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -describe('ZabbixDatasource', function () { - var ctx = {}; - var defined = _sinon2.default.match.defined; - - beforeEach(function () { - ctx.instanceSettings = { - jsonData: { - username: 'zabbix', - password: 'zabbix', - trends: true, - trendsFrom: '7d' - } - }; - ctx.templateSrv = {}; - ctx.alertSrv = {}; - ctx.zabbix = function () {}; - - ctx.ds = new _module.Datasource(ctx.instanceSettings, ctx.templateSrv, ctx.alertSrv, ctx.zabbix); - }); - - describe('When querying data', function () { - beforeEach(function () { - ctx.ds.replaceTemplateVars = function (str) { - return str; - }; - }); - - ctx.options = { - targets: [{ - group: { filter: "" }, - host: { filter: "" }, - application: { filter: "" }, - item: { filter: "" } - }], - range: { from: 'now-7d', to: 'now' } - }; - - it('should return an empty array when no targets are set', function (done) { - var options = { - targets: [], - range: { from: 'now-6h', to: 'now' } - }; - ctx.ds.query(options).then(function (result) { - expect(result.data).to.have.length(0); - done(); - }); - }); - - it('should use trends if it enabled and time more than trendsFrom', function (done) { - var ranges = ['now-7d', 'now-168h', 'now-1M', 'now-1y']; - - _lodash2.default.forEach(ranges, function (range) { - ctx.options.range.from = range; - ctx.ds.queryNumericData = _sinon2.default.spy(); - ctx.ds.query(ctx.options); - - // Check that useTrends options is true - expect(ctx.ds.queryNumericData).to.have.been.calledWith(defined, defined, defined, true); - }); - - done(); - }); - - it('shouldnt use trends if it enabled and time less than trendsFrom', function (done) { - var ranges = ['now-6d', 'now-167h', 'now-1h', 'now-30m', 'now-30s']; - - _lodash2.default.forEach(ranges, function (range) { - ctx.options.range.from = range; - ctx.ds.queryNumericData = _sinon2.default.spy(); - ctx.ds.query(ctx.options); - - // Check that useTrends options is false - expect(ctx.ds.queryNumericData).to.have.been.calledWith(defined, defined, defined, false); - }); - done(); - }); - }); - - describe('When replacing template variables', function () { - - function testReplacingVariable(target, varValue, expectedResult, done) { - ctx.ds.templateSrv.replace = function () { - return (0, _datasource.zabbixTemplateFormat)(varValue); - }; - - var result = ctx.ds.replaceTemplateVars(target); - expect(result).to.equal(expectedResult); - done(); - } - - /* - * Alphanumerics, spaces, dots, dashes and underscores - * are allowed in Zabbix host name. - * 'AaBbCc0123 .-_' - */ - it('should return properly escaped regex', function (done) { - var target = '$host'; - var template_var_value = 'AaBbCc0123 .-_'; - var expected_result = '/^AaBbCc0123 \\.-_$/'; - - testReplacingVariable(target, template_var_value, expected_result, done); - }); - - /* - * Single-value variable - * $host = backend01 - * $host => /^backend01|backend01$/ - */ - it('should return proper regex for single value', function (done) { - var target = '$host'; - var template_var_value = 'backend01'; - var expected_result = '/^backend01$/'; - - testReplacingVariable(target, template_var_value, expected_result, done); - }); - - /* - * Multi-value variable - * $host = [backend01, backend02] - * $host => /^(backend01|backend01)$/ - */ - it('should return proper regex for multi-value', function (done) { - var target = '$host'; - var template_var_value = ['backend01', 'backend02']; - var expected_result = '/^(backend01|backend02)$/'; - - testReplacingVariable(target, template_var_value, expected_result, done); - }); - }); - - describe('When invoking metricFindQuery()', function () { - beforeEach(function () { - ctx.ds.replaceTemplateVars = function (str) { - return str; - }; - ctx.ds.zabbix = { - getGroups: function getGroups() { - return _q2.default.when([]); - }, - getHosts: function getHosts() { - return _q2.default.when([]); - }, - getApps: function getApps() { - return _q2.default.when([]); - }, - getItems: function getItems() { - return _q2.default.when([]); - } - }; - }); - - it('should return groups', function (done) { - var tests = [{ query: '*', expect: '/.*/' }, { query: '', expect: '' }, { query: 'Backend', expect: 'Backend' }, { query: 'Back*', expect: 'Back*' }]; - - var getGroups = _sinon2.default.spy(ctx.ds.zabbix, 'getGroups'); - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = tests[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var test = _step.value; - - ctx.ds.metricFindQuery(test.query); - expect(getGroups).to.have.been.calledWith(test.expect); - getGroups.reset(); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - done(); - }); - - it('should return hosts', function (done) { - var tests = [{ query: '*.*', expect: '/.*/' }, { query: '.', expect: '' }, { query: 'Backend.*', expect: 'Backend' }, { query: 'Back*.', expect: 'Back*' }]; - - var getHosts = _sinon2.default.spy(ctx.ds.zabbix, 'getHosts'); - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - for (var _iterator2 = tests[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - var test = _step2.value; - - ctx.ds.metricFindQuery(test.query); - expect(getHosts).to.have.been.calledWith(test.expect); - getHosts.reset(); - } - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - - done(); - }); - - it('should return applications', function (done) { - var tests = [{ query: '*.*.*', expect: ['/.*/', '/.*/'] }, { query: '.*.', expect: ['', '/.*/'] }, { query: 'Backend.backend01.*', expect: ['Backend', 'backend01'] }, { query: 'Back*.*.', expect: ['Back*', '/.*/'] }]; - - var getApps = _sinon2.default.spy(ctx.ds.zabbix, 'getApps'); - var _iteratorNormalCompletion3 = true; - var _didIteratorError3 = false; - var _iteratorError3 = undefined; - - try { - for (var _iterator3 = tests[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { - var test = _step3.value; - - ctx.ds.metricFindQuery(test.query); - expect(getApps).to.have.been.calledWith(test.expect[0], test.expect[1]); - getApps.reset(); - } - } catch (err) { - _didIteratorError3 = true; - _iteratorError3 = err; - } finally { - try { - if (!_iteratorNormalCompletion3 && _iterator3.return) { - _iterator3.return(); - } - } finally { - if (_didIteratorError3) { - throw _iteratorError3; - } - } - } - - done(); - }); - - it('should return items', function (done) { - var tests = [{ query: '*.*.*.*', expect: ['/.*/', '/.*/', ''] }, { query: '.*.*.*', expect: ['', '/.*/', ''] }, { query: 'Backend.backend01.*.*', expect: ['Backend', 'backend01', ''] }, { query: 'Back*.*.cpu.*', expect: ['Back*', '/.*/', 'cpu'] }]; - - var getItems = _sinon2.default.spy(ctx.ds.zabbix, 'getItems'); - var _iteratorNormalCompletion4 = true; - var _didIteratorError4 = false; - var _iteratorError4 = undefined; - - try { - for (var _iterator4 = tests[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { - var test = _step4.value; - - ctx.ds.metricFindQuery(test.query); - expect(getItems).to.have.been.calledWith(test.expect[0], test.expect[1], test.expect[2]); - getItems.reset(); - } - } catch (err) { - _didIteratorError4 = true; - _iteratorError4 = err; - } finally { - try { - if (!_iteratorNormalCompletion4 && _iterator4.return) { - _iterator4.return(); - } - } finally { - if (_didIteratorError4) { - throw _iteratorError4; - } - } - } - - done(); - }); - - it('should invoke method with proper arguments', function (done) { - var query = '*.*'; - - var getHosts = _sinon2.default.spy(ctx.ds.zabbix, 'getHosts'); - ctx.ds.metricFindQuery(query); - expect(getHosts).to.have.been.calledWith('/.*/'); - done(); - }); - }); -}); diff --git a/dist/test/datasource-zabbix/specs/modules/datemath.js b/dist/test/datasource-zabbix/specs/modules/datemath.js deleted file mode 100644 index 063ad04..0000000 --- a/dist/test/datasource-zabbix/specs/modules/datemath.js +++ /dev/null @@ -1,135 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.parse = parse; -exports.isValid = isValid; -exports.parseDateMath = parseDateMath; - -var _lodash = require('lodash'); - -var _lodash2 = _interopRequireDefault(_lodash); - -var _moment = require('moment'); - -var _moment2 = _interopRequireDefault(_moment); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var units = ['y', 'M', 'w', 'd', 'h', 'm', 's']; - -function parse(text, roundUp) { - if (!text) { - return undefined; - } - if (_moment2.default.isMoment(text)) { - return text; - } - if (_lodash2.default.isDate(text)) { - return (0, _moment2.default)(text); - } - - var time; - var mathString = ''; - var index; - var parseString; - - if (text.substring(0, 3) === 'now') { - time = (0, _moment2.default)(); - mathString = text.substring('now'.length); - } else { - index = text.indexOf('||'); - if (index === -1) { - parseString = text; - mathString = ''; // nothing else - } else { - parseString = text.substring(0, index); - mathString = text.substring(index + 2); - } - // We're going to just require ISO8601 timestamps, k? - time = (0, _moment2.default)(parseString, _moment2.default.ISO_8601); - } - - if (!mathString.length) { - return time; - } - - return parseDateMath(mathString, time, roundUp); -} - -function isValid(text) { - var date = parse(text); - if (!date) { - return false; - } - - if (_moment2.default.isMoment(date)) { - return date.isValid(); - } - - return false; -} - -function parseDateMath(mathString, time, roundUp) { - var dateTime = time; - var i = 0; - var len = mathString.length; - - while (i < len) { - var c = mathString.charAt(i++); - var type; - var num; - var unit; - - if (c === '/') { - type = 0; - } else if (c === '+') { - type = 1; - } else if (c === '-') { - type = 2; - } else { - return undefined; - } - - if (isNaN(mathString.charAt(i))) { - num = 1; - } else if (mathString.length === 2) { - num = mathString.charAt(i); - } else { - var numFrom = i; - while (!isNaN(mathString.charAt(i))) { - i++; - if (i > 10) { - return undefined; - } - } - num = parseInt(mathString.substring(numFrom, i), 10); - } - - if (type === 0) { - // rounding is only allowed on whole, single, units (eg M or 1M, not 0.5M or 2M) - if (num !== 1) { - return undefined; - } - } - unit = mathString.charAt(i++); - - if (!_lodash2.default.includes(units, unit)) { - return undefined; - } else { - if (type === 0) { - if (roundUp) { - dateTime.endOf(unit); - } else { - dateTime.startOf(unit); - } - } else if (type === 1) { - dateTime.add(num, unit); - } else if (type === 2) { - dateTime.subtract(num, unit); - } - } - } - return dateTime; -} diff --git a/dist/test/datasource-zabbix/specs/test-main.js b/dist/test/datasource-zabbix/specs/test-main.js deleted file mode 100644 index a80d33a..0000000 --- a/dist/test/datasource-zabbix/specs/test-main.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -var _prunk = require('prunk'); - -var _prunk2 = _interopRequireDefault(_prunk); - -var _jsdom = require('jsdom'); - -var _chai = require('chai'); - -var _chai2 = _interopRequireDefault(_chai); - -var _sinonChai = require('sinon-chai'); - -var _sinonChai2 = _interopRequireDefault(_sinonChai); - -var _datemath = require('./modules/datemath'); - -var dateMath = _interopRequireWildcard(_datemath); - -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 }; } - -// Mock angular module - -// import sinon from 'sinon'; -var angularMocks = { - module: function module() { - return { - directive: function directive() {}, - service: function service() {}, - factory: function factory() {} - }; - } -}; // JSHint options -/* globals global: false */ - -var datemathMock = { - parse: dateMath.parse, - parseDateMath: dateMath.parseDateMath, - isValid: dateMath.isValid -}; - -// Mock Grafana modules that are not available outside of the core project -// Required for loading module.js -_prunk2.default.mock('./css/query-editor.css!', 'no css, dude.'); -_prunk2.default.mock('app/plugins/sdk', { - QueryCtrl: null -}); -_prunk2.default.mock('app/core/utils/datemath', datemathMock); -_prunk2.default.mock('angular', angularMocks); -_prunk2.default.mock('jquery', 'module not found'); - -// Setup jsdom -// Required for loading angularjs -global.document = (0, _jsdom.jsdom)(''); -global.window = global.document.parentWindow; -global.navigator = window.navigator = {}; -global.Node = window.Node; - -// Setup Chai -_chai2.default.should(); -_chai2.default.use(_sinonChai2.default); -global.assert = _chai2.default.assert; -global.expect = _chai2.default.expect; diff --git a/dist/test/datasource-zabbix/utils.js b/dist/test/datasource-zabbix/utils.js deleted file mode 100644 index 36eceb9..0000000 --- a/dist/test/datasource-zabbix/utils.js +++ /dev/null @@ -1,151 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.regexPattern = undefined; -exports.expandItemName = expandItemName; -exports.isRegex = isRegex; -exports.isTemplateVariable = isTemplateVariable; -exports.buildRegex = buildRegex; -exports.escapeRegex = escapeRegex; -exports.parseInterval = parseInterval; -exports.parseTimeShiftInterval = parseTimeShiftInterval; -exports.formatAcknowledges = formatAcknowledges; -exports.convertToZabbixAPIUrl = convertToZabbixAPIUrl; -exports.callOnce = callOnce; - -var _lodash = require('lodash'); - -var _lodash2 = _interopRequireDefault(_lodash); - -var _moment = require('moment'); - -var _moment2 = _interopRequireDefault(_moment); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Expand Zabbix item name - * - * @param {string} name item name, ie "CPU $2 time" - * @param {string} key item key, ie system.cpu.util[,system,avg1] - * @return {string} expanded name, ie "CPU system time" - */ -function expandItemName(name, key) { - - // extract params from key: - // "system.cpu.util[,system,avg1]" --> ["", "system", "avg1"] - var key_params = key.substring(key.indexOf('[') + 1, key.lastIndexOf(']')).split(','); - - // replace item parameters - for (var i = key_params.length; i >= 1; i--) { - name = name.replace('$' + i, key_params[i - 1]); - } - return name; -} - -// Pattern for testing regex -var regexPattern = exports.regexPattern = /^\/(.*)\/([gmi]*)$/m; - -function isRegex(str) { - return regexPattern.test(str); -} - -function isTemplateVariable(str, templateVariables) { - var variablePattern = /^\$\w+/; - if (variablePattern.test(str)) { - var variables = _lodash2.default.map(templateVariables, function (variable) { - return '$' + variable.name; - }); - return _lodash2.default.includes(variables, str); - } else { - return false; - } -} - -function buildRegex(str) { - var matches = str.match(regexPattern); - var pattern = matches[1]; - var flags = matches[2] !== "" ? matches[2] : undefined; - return new RegExp(pattern, flags); -} - -// Need for template variables replace -// From Grafana's templateSrv.js -function escapeRegex(value) { - return value.replace(/[\\^$*+?.()|[\]{}\/]/g, '\\$&'); -} - -function parseInterval(interval) { - var intervalPattern = /(^[\d]+)(y|M|w|d|h|m|s)/g; - var momentInterval = intervalPattern.exec(interval); - return _moment2.default.duration(Number(momentInterval[1]), momentInterval[2]).valueOf(); -} - -function parseTimeShiftInterval(interval) { - var intervalPattern = /^([\+\-]*)([\d]+)(y|M|w|d|h|m|s)/g; - var momentInterval = intervalPattern.exec(interval); - var duration = 0; - - if (momentInterval[1] === '+') { - duration = 0 - _moment2.default.duration(Number(momentInterval[2]), momentInterval[3]).valueOf(); - } else { - duration = _moment2.default.duration(Number(momentInterval[2]), momentInterval[3]).valueOf(); - } - - return duration; -} - -/** - * Format acknowledges. - * - * @param {array} acknowledges array of Zabbix acknowledge objects - * @return {string} HTML-formatted table - */ -function formatAcknowledges(acknowledges) { - if (acknowledges.length) { - var formatted_acknowledges = '

        Acknowledges:
        ' + ''; - _lodash2.default.each(_lodash2.default.map(acknowledges, function (ack) { - var timestamp = _moment2.default.unix(ack.clock); - return ''; - }), function (ack) { - formatted_acknowledges = formatted_acknowledges.concat(ack); - }); - formatted_acknowledges = formatted_acknowledges.concat('
        TimeUserComments
        ' + timestamp.format("DD MMM YYYY HH:mm:ss") + '' + ack.alias + ' (' + ack.name + ' ' + ack.surname + ')' + '' + ack.message + '
        '); - return formatted_acknowledges; - } else { - return ''; - } -} - -function convertToZabbixAPIUrl(url) { - var zabbixAPIUrlPattern = /.*api_jsonrpc.php$/; - var trimSlashPattern = /(.*?)[\/]*$/; - if (url.match(zabbixAPIUrlPattern)) { - return url; - } else { - return url.replace(trimSlashPattern, "$1"); - } -} - -/** - * Wrap function to prevent multiple calls - * when waiting for result. - */ -function callOnce(func, promiseKeeper) { - return function () { - if (!promiseKeeper) { - promiseKeeper = Promise.resolve(func.apply(this, arguments).then(function (result) { - promiseKeeper = null; - return result; - })); - } - return promiseKeeper; - }; -} - -// Fix for backward compatibility with lodash 2.4 -if (!_lodash2.default.includes) { - _lodash2.default.includes = _lodash2.default.contains; -} diff --git a/dist/test/datasource-zabbix/zabbix.js b/dist/test/datasource-zabbix/zabbix.js deleted file mode 100644 index 627d107..0000000 --- a/dist/test/datasource-zabbix/zabbix.js +++ /dev/null @@ -1,266 +0,0 @@ -'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); - -var _utils = require('./utils'); - -var utils = _interopRequireWildcard(_utils); - -require('./zabbixAPI.service.js'); - -require('./zabbixCachingProxy.service.js'); - -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 }; } - -function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -// 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) { - var Zabbix = function () { - function Zabbix(url, username, password, basicAuth, withCredentials, cacheTTL) { - _classCallCheck(this, Zabbix); - - // Initialize Zabbix API - var ZabbixAPI = zabbixAPIService; - this.zabbixAPI = new ZabbixAPI(url, username, password, basicAuth, withCredentials); - - // Initialize caching proxy for requests - var cacheOptions = { - enabled: true, - ttl: cacheTTL - }; - this.cachingProxy = new ZabbixCachingProxy(this.zabbixAPI, cacheOptions); - - // Proxy methods - this.getHistory = this.cachingProxy.getHistory.bind(this.cachingProxy); - - this.getTrend = this.zabbixAPI.getTrend.bind(this.zabbixAPI); - this.getEvents = this.zabbixAPI.getEvents.bind(this.zabbixAPI); - this.getAcknowledges = this.zabbixAPI.getAcknowledges.bind(this.zabbixAPI); - this.getITService = this.zabbixAPI.getITService.bind(this.zabbixAPI); - this.getSLA = this.zabbixAPI.getSLA.bind(this.zabbixAPI); - this.getVersion = this.zabbixAPI.getVersion.bind(this.zabbixAPI); - this.login = this.zabbixAPI.login.bind(this.zabbixAPI); - } - - _createClass(Zabbix, [{ - key: 'getItemsFromTarget', - value: function getItemsFromTarget(target, options) { - var parts = ['group', 'host', 'application', 'item']; - var filters = _lodash2.default.map(parts, function (p) { - return target[p].filter; - }); - return this.getItems.apply(this, _toConsumableArray(filters).concat([options])); - } - }, { - key: 'getAllGroups', - value: function getAllGroups() { - return this.cachingProxy.getGroups(); - } - }, { - key: 'getGroups', - value: function getGroups(groupFilter) { - return this.getAllGroups().then(function (groups) { - return findByFilter(groups, groupFilter); - }); - } - - /** - * Get list of host belonging to given groups. - */ - - }, { - key: 'getAllHosts', - value: function getAllHosts(groupFilter) { - var _this = this; - - return this.getGroups(groupFilter).then(function (groups) { - var groupids = _lodash2.default.map(groups, 'groupid'); - return _this.cachingProxy.getHosts(groupids); - }); - } - }, { - key: 'getHosts', - value: function getHosts(groupFilter, hostFilter) { - return this.getAllHosts(groupFilter).then(function (hosts) { - return findByFilter(hosts, hostFilter); - }); - } - - /** - * Get list of applications belonging to given groups and hosts. - */ - - }, { - key: 'getAllApps', - value: function getAllApps(groupFilter, hostFilter) { - var _this2 = this; - - return this.getHosts(groupFilter, hostFilter).then(function (hosts) { - var hostids = _lodash2.default.map(hosts, 'hostid'); - return _this2.cachingProxy.getApps(hostids); - }); - } - }, { - key: 'getApps', - value: function getApps(groupFilter, hostFilter, appFilter) { - var _this3 = this; - - return this.getHosts(groupFilter, hostFilter).then(function (hosts) { - var hostids = _lodash2.default.map(hosts, 'hostid'); - if (appFilter) { - return _this3.cachingProxy.getApps(hostids).then(function (apps) { - return filterByQuery(apps, appFilter); - }); - } else { - return { - appFilterEmpty: true, - hostids: hostids - }; - } - }); - } - }, { - key: 'getAllItems', - value: function getAllItems(groupFilter, hostFilter, appFilter) { - var _this4 = this; - - var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; - - return this.getApps(groupFilter, hostFilter, appFilter).then(function (apps) { - if (apps.appFilterEmpty) { - return _this4.cachingProxy.getItems(apps.hostids, undefined, options.itemtype); - } else { - var appids = _lodash2.default.map(apps, 'applicationid'); - return _this4.cachingProxy.getItems(undefined, appids, options.itemtype); - } - }).then(function (items) { - if (!options.showDisabledItems) { - items = _lodash2.default.filter(items, { 'status': '0' }); - } - return items; - }); - } - }, { - key: 'getItems', - value: function getItems(groupFilter, hostFilter, appFilter, itemFilter) { - var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; - - return this.getAllItems(groupFilter, hostFilter, appFilter, options).then(function (items) { - return filterByQuery(items, itemFilter); - }); - } - - /** - * Build query - convert target filters to array of Zabbix items - */ - - }, { - key: 'getTriggers', - value: function getTriggers(groupFilter, hostFilter, appFilter, showTriggers) { - var _this5 = this; - - var promises = [this.getGroups(groupFilter), this.getHosts(groupFilter, hostFilter), this.getApps(groupFilter, hostFilter, appFilter)]; - - return Promise.all(promises).then(function (results) { - var filteredGroups = results[0]; - var filteredHosts = results[1]; - var filteredApps = results[2]; - var query = {}; - - if (appFilter) { - query.applicationids = _lodash2.default.flatten(_lodash2.default.map(filteredApps, 'applicationid')); - } - if (hostFilter) { - query.hostids = _lodash2.default.map(filteredHosts, 'hostid'); - } - if (groupFilter) { - query.groupids = _lodash2.default.map(filteredGroups, 'groupid'); - } - - return query; - }).then(function (query) { - return _this5.zabbixAPI.getTriggers(query.groupids, query.hostids, query.applicationids, showTriggers); - }); - } - }]); - - return Zabbix; - }(); - - return Zabbix; -} - -_angular2.default.module('grafana.services').factory('Zabbix', ZabbixFactory); - -/////////////////////////////////////////////////////////////////////////////// - -/** - * Find group, host, app or item by given name. - * @param list list of groups, apps or other - * @param name visible name - * @return array with finded element or undefined - */ -function findByName(list, name) { - var finded = _lodash2.default.find(list, { 'name': name }); - if (finded) { - return [finded]; - } else { - return undefined; - } -} - -/** - * Different hosts can contains applications and items with same name. - * For this reason use _.filter, which return all elements instead _.find, - * which return only first finded. - * @param {[type]} list list of elements - * @param {[type]} name app name - * @return {[type]} array with finded element or undefined - */ -function filterByName(list, name) { - var finded = _lodash2.default.filter(list, { 'name': name }); - if (finded) { - return finded; - } else { - return undefined; - } -} - -function filterByRegex(list, regex) { - var filterPattern = utils.buildRegex(regex); - return _lodash2.default.filter(list, function (zbx_obj) { - return filterPattern.test(zbx_obj.name); - }); -} - -function findByFilter(list, filter) { - if (utils.isRegex(filter)) { - return filterByRegex(list, filter); - } else { - return findByName(list, filter); - } -} - -function filterByQuery(list, filter) { - if (utils.isRegex(filter)) { - return filterByRegex(list, filter); - } else { - return filterByName(list, filter); - } -} diff --git a/dist/test/datasource-zabbix/zabbixAPI.service.js b/dist/test/datasource-zabbix/zabbixAPI.service.js deleted file mode 100644 index cd82a13..0000000 --- a/dist/test/datasource-zabbix/zabbixAPI.service.js +++ /dev/null @@ -1,436 +0,0 @@ -'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); - -var _utils = require('./utils'); - -var utils = _interopRequireWildcard(_utils); - -require('./zabbixAPICore.service'); - -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 }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** @ngInject */ -function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) { - - /** - * Zabbix API Wrapper. - * Creates Zabbix API instance with given parameters (url, credentials and other). - * Wraps API calls and provides high-level methods. - */ - var ZabbixAPI = function () { - function ZabbixAPI(api_url, username, password, basicAuth, withCredentials) { - _classCallCheck(this, ZabbixAPI); - - this.url = api_url; - this.username = username; - this.password = password; - this.auth = ""; - - this.requestOptions = { - basicAuth: basicAuth, - withCredentials: withCredentials - }; - - this.loginPromise = null; - this.loginErrorCount = 0; - this.maxLoginAttempts = 3; - - this.alertSrv = alertSrv; - this.zabbixAPICore = zabbixAPICoreService; - - this.getTrend = this.getTrend_ZBXNEXT1193; - //getTrend = getTrend_30; - } - - ////////////////////////// - // Core method wrappers // - ////////////////////////// - - _createClass(ZabbixAPI, [{ - key: 'request', - value: function request(method, params) { - var _this = this; - - return this.zabbixAPICore.request(this.url, method, params, this.requestOptions, this.auth).catch(function (error) { - if (isNotAuthorized(error.data)) { - // Handle auth errors - _this.loginErrorCount++; - if (_this.loginErrorCount > _this.maxLoginAttempts) { - _this.loginErrorCount = 0; - return null; - } else { - return _this.loginOnce().then(function () { - return _this.request(method, params); - }); - } - } else { - // Handle API errors - var message = error.data ? error.data : error.statusText; - _this.alertAPIError(message); - } - }); - } - }, { - key: 'alertAPIError', - value: function alertAPIError(message) { - var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5000; - - this.alertSrv.set("Zabbix API Error", message, 'error', timeout); - } - - /** - * When API unauthenticated or auth token expired each request produce login() - * call. But auth token is common to all requests. This function wraps login() method - * and call it once. If login() already called just wait for it (return its promise). - * @return login promise - */ - - }, { - key: 'loginOnce', - value: function loginOnce() { - var _this2 = this; - - if (!this.loginPromise) { - this.loginPromise = Promise.resolve(this.login().then(function (auth) { - _this2.auth = auth; - _this2.loginPromise = null; - return auth; - })); - } - return this.loginPromise; - } - - /** - * Get authentication token. - */ - - }, { - key: 'login', - value: function login() { - return this.zabbixAPICore.login(this.url, this.username, this.password, this.requestOptions); - } - - /** - * Get Zabbix API version - */ - - }, { - key: 'getVersion', - value: function getVersion() { - return this.zabbixAPICore.getVersion(this.url, this.requestOptions); - } - - //////////////////////////////// - // Zabbix API method wrappers // - //////////////////////////////// - - }, { - key: 'acknowledgeEvent', - value: function acknowledgeEvent(eventid, message) { - var params = { - eventids: eventid, - message: message - }; - - return this.request('event.acknowledge', params); - } - }, { - key: 'getGroups', - value: function getGroups() { - var params = { - output: ['name'], - sortfield: 'name', - real_hosts: true - }; - - return this.request('hostgroup.get', params); - } - }, { - key: 'getHosts', - value: function getHosts(groupids) { - var params = { - output: ['name', 'host'], - sortfield: 'name' - }; - if (groupids) { - params.groupids = groupids; - } - - return this.request('host.get', params); - } - }, { - key: 'getApps', - value: function getApps(hostids) { - var params = { - output: ['applicationid', 'name'], - hostids: hostids - }; - - return this.request('application.get', params); - } - - /** - * Get Zabbix items - * @param {[type]} hostids host ids - * @param {[type]} appids application ids - * @param {String} itemtype 'num' or 'text' - * @return {[type]} array of items - */ - - }, { - key: 'getItems', - value: function getItems(hostids, appids, itemtype) { - var params = { - output: ['name', 'key_', 'value_type', 'hostid', 'status', 'state'], - sortfield: 'name', - webitems: true, - filter: {}, - selectHosts: ['hostid', 'name'] - }; - if (hostids) { - params.hostids = hostids; - } - if (appids) { - params.applicationids = appids; - } - if (itemtype === 'num') { - // Return only numeric metrics - params.filter.value_type = [0, 3]; - } - if (itemtype === 'text') { - // Return only text metrics - params.filter.value_type = [1, 2, 4]; - } - - return this.request('item.get', params).then(expandItems); - - function expandItems(items) { - items.forEach(function (item) { - item.item = item.name; - item.name = utils.expandItemName(item.item, item.key_); - return item; - }); - return items; - } - } - }, { - key: 'getLastValue', - value: function getLastValue(itemid) { - var params = { - output: ['lastvalue'], - itemids: itemid - }; - return this.request('item.get', params).then(function (items) { - return items.length ? items[0].lastvalue : null; - }); - } - - /** - * Perform history query from Zabbix API - * - * @param {Array} items Array of Zabbix item objects - * @param {Number} timeFrom Time in seconds - * @param {Number} timeTill Time in seconds - * @return {Array} Array of Zabbix history objects - */ - - }, { - key: 'getHistory', - value: function getHistory(items, timeFrom, timeTill) { - var _this3 = this; - - // 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'); - var params = { - output: 'extend', - history: value_type, - itemids: itemids, - sortfield: 'clock', - sortorder: 'ASC', - time_from: timeFrom - }; - - // Relative queries (e.g. last hour) don't include an end time - if (timeTill) { - params.time_till = timeTill; - } - - return _this3.request('history.get', params); - }); - - return Promise.all(promises).then(_lodash2.default.flatten); - } - - /** - * Perform trends query from Zabbix API - * Use trends api extension from ZBXNEXT-1193 patch. - * - * @param {Array} items Array of Zabbix item objects - * @param {Number} time_from Time in seconds - * @param {Number} time_till Time in seconds - * @return {Array} Array of Zabbix trend objects - */ - - }, { - key: 'getTrend_ZBXNEXT1193', - value: function getTrend_ZBXNEXT1193(items, timeFrom, timeTill) { - var _this4 = this; - - // 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'); - var params = { - output: 'extend', - trend: value_type, - itemids: itemids, - sortfield: 'clock', - sortorder: 'ASC', - time_from: timeFrom - }; - - // Relative queries (e.g. last hour) don't include an end time - if (timeTill) { - params.time_till = timeTill; - } - - return _this4.request('trend.get', params); - }); - - return Promise.all(promises).then(_lodash2.default.flatten); - } - }, { - key: 'getTrend_30', - value: function getTrend_30(items, time_from, time_till, value_type) { - var self = this; - var itemids = _lodash2.default.map(items, 'itemid'); - - var params = { - output: ["itemid", "clock", value_type], - itemids: itemids, - time_from: time_from - }; - - // Relative queries (e.g. last hour) don't include an end time - if (time_till) { - params.time_till = time_till; - } - - return self.request('trend.get', params); - } - }, { - key: 'getITService', - value: function getITService(serviceids) { - var params = { - output: 'extend', - serviceids: serviceids - }; - return this.request('service.get', params); - } - }, { - key: 'getSLA', - value: function getSLA(serviceids, timeFrom, timeTo) { - var params = { - serviceids: serviceids, - intervals: [{ - from: timeFrom, - to: timeTo - }] - }; - return this.request('service.getsla', params); - } - }, { - key: 'getTriggers', - value: function getTriggers(groupids, hostids, applicationids, showTriggers, timeFrom, timeTo) { - var params = { - output: 'extend', - groupids: groupids, - hostids: hostids, - applicationids: applicationids, - expandDescription: true, - expandData: true, - expandComment: true, - monitored: true, - skipDependent: true, - //only_true: true, - filter: { - value: 1 - }, - selectGroups: ['name'], - selectHosts: ['name', 'host'], - selectItems: ['name', 'key_', 'lastvalue'], - selectLastEvent: 'extend' - }; - - if (showTriggers) { - params.filter.value = showTriggers; - } - - if (timeFrom || timeTo) { - params.lastChangeSince = timeFrom; - params.lastChangeTill = timeTo; - } - - return this.request('trigger.get', params); - } - }, { - key: 'getEvents', - value: function getEvents(objectids, timeFrom, timeTo, showEvents) { - var params = { - output: 'extend', - time_from: timeFrom, - time_till: timeTo, - objectids: objectids, - select_acknowledges: 'extend', - selectHosts: 'extend', - value: showEvents - }; - - return this.request('event.get', params); - } - }, { - key: 'getAcknowledges', - value: function getAcknowledges(eventids) { - var params = { - output: 'extend', - eventids: eventids, - preservekeys: true, - select_acknowledges: 'extend', - sortfield: 'clock', - sortorder: 'DESC' - }; - - return this.request('event.get', params).then(function (events) { - return _lodash2.default.filter(events, function (event) { - return event.acknowledges.length; - }); - }); - } - }]); - - return ZabbixAPI; - }(); - - return ZabbixAPI; -} - -function isNotAuthorized(message) { - return message === "Session terminated, re-login, please." || message === "Not authorised." || message === "Not authorized."; -} - -_angular2.default.module('grafana.services').factory('zabbixAPIService', ZabbixAPIServiceFactory); diff --git a/dist/test/datasource-zabbix/zabbixAPICore.service.js b/dist/test/datasource-zabbix/zabbixAPICore.service.js deleted file mode 100644 index 075f149..0000000 --- a/dist/test/datasource-zabbix/zabbixAPICore.service.js +++ /dev/null @@ -1,142 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.ZabbixAPIError = 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; }; }(); /** - * General Zabbix API methods - */ - -var _angular = require('angular'); - -var _angular2 = _interopRequireDefault(_angular); - -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 ZabbixAPICoreService = function () { - - /** @ngInject */ - function ZabbixAPICoreService(backendSrv) { - _classCallCheck(this, ZabbixAPICoreService); - - this.backendSrv = backendSrv; - } - - /** - * Request data from Zabbix API - * @return {object} response.result - */ - - - _createClass(ZabbixAPICoreService, [{ - key: 'request', - value: function request(api_url, method, params, options, auth) { - var requestData = { - jsonrpc: '2.0', - method: method, - params: params, - id: 1 - }; - - if (auth === "") { - // Reject immediately if not authenticated - return Promise.reject(new ZabbixAPIError({ data: "Not authorised." })); - } else if (auth) { - // Set auth parameter only if it needed - requestData.auth = auth; - } - - var requestOptions = { - method: 'POST', - url: api_url, - data: requestData, - headers: { - 'Content-Type': 'application/json' - } - }; - - // Set request options for basic auth - if (options.basicAuth || options.withCredentials) { - requestOptions.withCredentials = true; - } - if (options.basicAuth) { - requestOptions.headers.Authorization = options.basicAuth; - } - - return this.datasourceRequest(requestOptions); - } - }, { - key: 'datasourceRequest', - value: function datasourceRequest(requestOptions) { - return this.backendSrv.datasourceRequest(requestOptions).then(function (response) { - if (!response.data) { - return Promise.reject(new ZabbixAPIError({ data: "General Error, no data" })); - } else if (response.data.error) { - - // Handle Zabbix API errors - return Promise.reject(new ZabbixAPIError(response.data.error)); - } - - // Success - return response.data.result; - }); - } - - /** - * Get authentication token. - * @return {string} auth token - */ - - }, { - key: 'login', - value: function login(api_url, username, password, options) { - var params = { - user: username, - password: password - }; - return this.request(api_url, 'user.login', params, options, null); - } - - /** - * Get Zabbix API version - * Matches the version of Zabbix starting from Zabbix 2.0.4 - */ - - }, { - key: 'getVersion', - value: function getVersion(api_url, options) { - return this.request(api_url, 'apiinfo.version', [], options); - } - }]); - - return ZabbixAPICoreService; -}(); - -// Define zabbix API exception type - - -var ZabbixAPIError = exports.ZabbixAPIError = function () { - function ZabbixAPIError(error) { - _classCallCheck(this, ZabbixAPIError); - - this.code = error.code; - this.name = error.data; - this.message = error.data; - this.data = error.data; - } - - _createClass(ZabbixAPIError, [{ - key: 'toString', - value: function toString() { - return this.name + ": " + this.message; - } - }]); - - return ZabbixAPIError; -}(); - -_angular2.default.module('grafana.services').service('zabbixAPICoreService', ZabbixAPICoreService); diff --git a/dist/test/datasource-zabbix/zabbixCachingProxy.service.js b/dist/test/datasource-zabbix/zabbixCachingProxy.service.js deleted file mode 100644 index a378045..0000000 --- a/dist/test/datasource-zabbix/zabbixCachingProxy.service.js +++ /dev/null @@ -1,215 +0,0 @@ -'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 _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -// Use factory() instead service() for multiple datasources support. -// Each datasource instance must initialize its own cache. - -/** @ngInject */ -function ZabbixCachingProxyFactory() { - var ZabbixCachingProxy = function () { - function ZabbixCachingProxy(zabbixAPI, cacheOptions) { - _classCallCheck(this, ZabbixCachingProxy); - - this.zabbixAPI = zabbixAPI; - this.cacheEnabled = cacheOptions.enabled; - this.ttl = cacheOptions.ttl || 600000; // 10 minutes by default - - // Internal objects for data storing - this.cache = { - groups: {}, - hosts: {}, - applications: {}, - items: {}, - history: {}, - trends: {} - }; - - this.historyPromises = {}; - - // Don't run duplicated history requests - this.getHistory = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getHistory, this.zabbixAPI), this.historyPromises, getHistoryRequestHash); - - // Don't run duplicated requests - this.groupPromises = {}; - this.getGroupsOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getGroups, this.zabbixAPI), this.groupPromises, getRequestHash); - - this.hostPromises = {}; - this.getHostsOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getHosts, this.zabbixAPI), this.hostPromises, getRequestHash); - - this.appPromises = {}; - this.getAppsOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getApps, this.zabbixAPI), this.appPromises, getRequestHash); - - this.itemPromises = {}; - this.getItemsOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getItems, this.zabbixAPI), this.itemPromises, getRequestHash); - } - - _createClass(ZabbixCachingProxy, [{ - key: 'isExpired', - value: function isExpired(cacheObject) { - if (cacheObject) { - var object_age = Date.now() - cacheObject.timestamp; - return !(cacheObject.timestamp && object_age < this.ttl); - } else { - return true; - } - } - - /** - * Check that result is present in cache and up to date - * or send request to API. - */ - - }, { - key: 'proxyRequest', - value: function proxyRequest(request, params, cacheObject) { - var hash = getRequestHash(params); - if (this.cacheEnabled && !this.isExpired(cacheObject[hash])) { - return Promise.resolve(cacheObject[hash].value); - } else { - return request.apply(undefined, _toConsumableArray(params)).then(function (result) { - cacheObject[hash] = { - value: result, - timestamp: Date.now() - }; - return result; - }); - } - } - }, { - key: 'getGroups', - value: function getGroups() { - return this.proxyRequest(this.getGroupsOnce, [], this.cache.groups); - } - }, { - key: 'getHosts', - value: function getHosts(groupids) { - return this.proxyRequest(this.getHostsOnce, [groupids], this.cache.hosts); - } - }, { - key: 'getApps', - value: function getApps(hostids) { - return this.proxyRequest(this.getAppsOnce, [hostids], this.cache.applications); - } - }, { - key: 'getItems', - value: function getItems(hostids, appids, itemtype) { - var params = [hostids, appids, itemtype]; - return this.proxyRequest(this.getItemsOnce, params, this.cache.items); - } - }, { - key: 'getHistoryFromCache', - value: function getHistoryFromCache(items, time_from, time_till) { - var historyStorage = this.cache.history; - var full_history; - var expired = _lodash2.default.filter(_lodash2.default.keyBy(items, 'itemid'), function (item, itemid) { - return !historyStorage[itemid]; - }); - if (expired.length) { - return this.zabbixAPI.getHistory(expired, time_from, time_till).then(function (history) { - var grouped_history = _lodash2.default.groupBy(history, 'itemid'); - _lodash2.default.forEach(expired, function (item) { - var itemid = item.itemid; - historyStorage[itemid] = item; - historyStorage[itemid].time_from = time_from; - historyStorage[itemid].time_till = time_till; - historyStorage[itemid].history = grouped_history[itemid]; - }); - full_history = _lodash2.default.map(items, function (item) { - return historyStorage[item.itemid].history; - }); - return _lodash2.default.flatten(full_history, true); - }); - } else { - full_history = _lodash2.default.map(items, function (item) { - return historyStorage[item.itemid].history; - }); - return Promise.resolve(_lodash2.default.flatten(full_history, true)); - } - } - }, { - key: 'getHistoryFromAPI', - value: function getHistoryFromAPI(items, time_from, time_till) { - return this.zabbixAPI.getHistory(items, time_from, time_till); - } - }]); - - return ZabbixCachingProxy; - }(); - - return ZabbixCachingProxy; -} - -_angular2.default.module('grafana.services').factory('ZabbixCachingProxy', ZabbixCachingProxyFactory); - -/** - * Wrap zabbix API request to prevent multiple calls - * with same params when waiting for result. - */ -function callAPIRequestOnce(func, promiseKeeper, argsHashFunc) { - return function () { - var hash = argsHashFunc(arguments); - if (!promiseKeeper[hash]) { - promiseKeeper[hash] = Promise.resolve(func.apply(this, arguments).then(function (result) { - promiseKeeper[hash] = null; - return result; - })); - } - return promiseKeeper[hash]; - }; -} - -function getRequestHash(args) { - var requestStamp = _lodash2.default.map(args, function (arg) { - if (arg === undefined) { - return 'undefined'; - } else { - if (_lodash2.default.isArray(arg)) { - return arg.sort().toString(); - } else { - return arg.toString(); - } - } - }).join(); - return requestStamp.getHash(); -} - -function getHistoryRequestHash(args) { - var itemids = _lodash2.default.map(args[0], 'itemid'); - var stamp = itemids.join() + args[1] + args[2]; - return stamp.getHash(); -} - -String.prototype.getHash = function () { - var hash = 0, - i, - chr, - len; - if (this.length !== 0) { - for (i = 0, len = this.length; i < len; i++) { - chr = this.charCodeAt(i); - hash = (hash << 5) - hash + chr; - hash |= 0; // Convert to 32bit integer - } - } - return hash; -}; - -// Fix for backward compatibility with lodash 2.4 -if (!_lodash2.default.keyBy) { - _lodash2.default.keyBy = _lodash2.default.indexBy; -} diff --git a/dist/test/module.js b/dist/test/module.js deleted file mode 100644 index ac26ed7..0000000 --- a/dist/test/module.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.ConfigCtrl = undefined; - -var _config = require('./components/config'); - -exports.ConfigCtrl = _config.ZabbixAppConfigCtrl; diff --git a/dist/test/panel-triggers/ack-tooltip.directive.js b/dist/test/panel-triggers/ack-tooltip.directive.js deleted file mode 100644 index e74683e..0000000 --- a/dist/test/panel-triggers/ack-tooltip.directive.js +++ /dev/null @@ -1,122 +0,0 @@ -'use strict'; - -var _angular = require('angular'); - -var _angular2 = _interopRequireDefault(_angular); - -var _jquery = require('jquery'); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tetherDrop = require('tether-drop'); - -var _tetherDrop2 = _interopRequireDefault(_tetherDrop); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** @ngInject */ -_angular2.default.module('grafana.directives').directive('ackTooltip', function ($sanitize, $compile) { - var buttonTemplate = ''; - - return { - scope: { - ack: "=", - trigger: "=", - onAck: "=", - context: "=" - }, - link: function link(scope, element) { - var acknowledges = scope.ack; - var $button = (0, _jquery2.default)(buttonTemplate); - $button.appendTo(element); - - $button.click(function () { - var tooltip = '
        '; - - if (acknowledges && acknowledges.length) { - tooltip += '' + '' + '' + '' + ''; - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = acknowledges[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var ack = _step.value; - - tooltip += '' + '' + ''; - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - tooltip += '
        TimeUserComments
        ' + ack.time + '' + ack.user + '' + ack.message + '
        '; - } else { - tooltip += 'Add acknowledge'; - } - - var addAckButtonTemplate = '
        ' + '
        '; - tooltip += addAckButtonTemplate; - tooltip += '
        '; - - var drop = new _tetherDrop2.default({ - target: element[0], - content: tooltip, - position: "bottom left", - classes: 'drop-popover ack-tooltip', - openOn: 'hover', - hoverCloseDelay: 500, - tetherOptions: { - constraints: [{ to: 'window', pin: true, attachment: "both" }] - } - }); - - drop.open(); - drop.on('close', closeDrop); - - (0, _jquery2.default)('#add-acknowledge-btn').on('click', onAddAckButtonClick); - - function onAddAckButtonClick() { - var inputTemplate = '
        ' + '' + '' + '
        '; - - var $input = (0, _jquery2.default)(inputTemplate); - var $addAckButton = (0, _jquery2.default)('.ack-tooltip .ack-add-button'); - $addAckButton.replaceWith($input); - (0, _jquery2.default)('.ack-tooltip #cancel-ack-button').on('click', onAckCancelButtonClick); - (0, _jquery2.default)('.ack-tooltip #send-ack-button').on('click', onAckSendlButtonClick); - } - - function onAckCancelButtonClick() { - (0, _jquery2.default)('.ack-tooltip .ack-input-group').replaceWith(addAckButtonTemplate); - (0, _jquery2.default)('#add-acknowledge-btn').on('click', onAddAckButtonClick); - } - - function onAckSendlButtonClick() { - var message = (0, _jquery2.default)('.ack-tooltip #ack-message')[0].value; - var onAck = scope.onAck.bind(scope.context); - onAck(scope.trigger, message).then(function () { - closeDrop(); - }); - } - - function closeDrop() { - setTimeout(function () { - drop.destroy(); - }); - } - }); - - $compile(element.contents())(scope); - } - }; -}); diff --git a/dist/test/panel-triggers/editor.js b/dist/test/panel-triggers/editor.js deleted file mode 100644 index ceb50a8..0000000 --- a/dist/test/panel-triggers/editor.js +++ /dev/null @@ -1,225 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -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; }; }(); /** - * Grafana-Zabbix - * Zabbix plugin for Grafana. - * http://github.com/alexanderzobnin/grafana-zabbix - * - * Trigger panel. - * This feature sponsored by CORE IT - * http://www.coreit.fr - * - * Copyright 2015 Alexander Zobnin alexanderzobnin@gmail.com - * Licensed under the Apache License, Version 2.0 - */ - -exports.triggerPanelEditor = triggerPanelEditor; - -var _lodash = require('lodash'); - -var _lodash2 = _interopRequireDefault(_lodash); - -var _utils = require('../datasource-zabbix/utils'); - -var utils = _interopRequireWildcard(_utils); - -require('../datasource-zabbix/css/query-editor.css!'); - -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 }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var TriggerPanelEditorCtrl = function () { - - /** @ngInject */ - function TriggerPanelEditorCtrl($scope, $rootScope, uiSegmentSrv, datasourceSrv, templateSrv, popoverSrv) { - var _this = this; - - _classCallCheck(this, TriggerPanelEditorCtrl); - - $scope.editor = this; - this.panelCtrl = $scope.ctrl; - this.panel = this.panelCtrl.panel; - - this.datasourceSrv = datasourceSrv; - this.templateSrv = templateSrv; - this.popoverSrv = popoverSrv; - - // Map functions for bs-typeahead - this.getGroupNames = _lodash2.default.partial(getMetricNames, this, 'groupList'); - this.getHostNames = _lodash2.default.partial(getMetricNames, this, 'hostList'); - this.getApplicationNames = _lodash2.default.partial(getMetricNames, this, 'appList'); - - // Update metric suggestion when template variable was changed - $rootScope.$on('template-variable-value-updated', function () { - return _this.onVariableChange(); - }); - - this.ackFilters = ['all triggers', 'unacknowledged', 'acknowledged']; - - this.sortByFields = [{ text: 'last change', value: 'lastchange' }, { text: 'severity', value: 'priority' }]; - - this.showEventsFields = [{ text: 'All', value: [0, 1] }, { text: 'OK', value: [0] }, { text: 'Problems', value: 1 }]; - - // Load scope defaults - var scopeDefaults = { - metric: {}, - inputStyles: {}, - oldTarget: _lodash2.default.cloneDeep(this.panel.triggers) - }; - _lodash2.default.defaults(this, scopeDefaults); - - // Set default datasource - this.datasources = _lodash2.default.map(this.getZabbixDataSources(), 'name'); - if (!this.panel.datasource) { - this.panel.datasource = this.datasources[0]; - } - // Load datasource - this.datasourceSrv.get(this.panel.datasource).then(function (datasource) { - _this.datasource = datasource; - _this.zabbix = datasource.zabbix; - _this.queryBuilder = datasource.queryBuilder; - _this.initFilters(); - _this.panelCtrl.refresh(); - }); - } - - _createClass(TriggerPanelEditorCtrl, [{ - key: 'initFilters', - value: function initFilters() { - return Promise.all([this.suggestGroups(), this.suggestHosts(), this.suggestApps()]); - } - }, { - key: 'suggestGroups', - value: function suggestGroups() { - var _this2 = this; - - return this.zabbix.getAllGroups().then(function (groups) { - _this2.metric.groupList = groups; - return groups; - }); - } - }, { - key: 'suggestHosts', - value: function suggestHosts() { - var _this3 = this; - - var groupFilter = this.datasource.replaceTemplateVars(this.panel.triggers.group.filter); - return this.zabbix.getAllHosts(groupFilter).then(function (hosts) { - _this3.metric.hostList = hosts; - return hosts; - }); - } - }, { - key: 'suggestApps', - value: function suggestApps() { - var _this4 = this; - - var groupFilter = this.datasource.replaceTemplateVars(this.panel.triggers.group.filter); - var hostFilter = this.datasource.replaceTemplateVars(this.panel.triggers.host.filter); - return this.zabbix.getAllApps(groupFilter, hostFilter).then(function (apps) { - _this4.metric.appList = apps; - return apps; - }); - } - }, { - key: 'onVariableChange', - value: function onVariableChange() { - if (this.isContainsVariables()) { - this.targetChanged(); - } - } - - /** - * Check query for template variables - */ - - }, { - key: 'isContainsVariables', - value: function isContainsVariables() { - var _this5 = this; - - return _lodash2.default.some(['group', 'host', 'application'], function (field) { - return utils.isTemplateVariable(_this5.panel.triggers[field].filter, _this5.templateSrv.variables); - }); - } - }, { - key: 'targetChanged', - value: function targetChanged() { - this.initFilters(); - this.panelCtrl.refresh(); - } - }, { - key: 'parseTarget', - value: function parseTarget() { - this.initFilters(); - var newTarget = _lodash2.default.cloneDeep(this.panel.triggers); - if (!_lodash2.default.isEqual(this.oldTarget, this.panel.triggers)) { - this.oldTarget = newTarget; - this.panelCtrl.refresh(); - } - } - }, { - key: 'refreshTriggerSeverity', - value: function refreshTriggerSeverity() { - _lodash2.default.each(this.triggerList, function (trigger) { - trigger.color = this.panel.triggerSeverity[trigger.priority].color; - trigger.severity = this.panel.triggerSeverity[trigger.priority].severity; - }); - this.panelCtrl.refresh(); - } - }, { - key: 'datasourceChanged', - value: function datasourceChanged() { - this.panelCtrl.refresh(); - } - }, { - key: 'changeTriggerSeverityColor', - value: function changeTriggerSeverityColor(trigger, color) { - this.panel.triggerSeverity[trigger.priority].color = color; - this.refreshTriggerSeverity(); - } - }, { - key: 'isRegex', - value: function isRegex(str) { - return utils.isRegex(str); - } - }, { - key: 'isVariable', - value: function isVariable(str) { - return utils.isTemplateVariable(str, this.templateSrv.variables); - } - }, { - key: 'getZabbixDataSources', - value: function getZabbixDataSources() { - var ZABBIX_DS_ID = 'alexanderzobnin-zabbix-datasource'; - return _lodash2.default.filter(this.datasourceSrv.getMetricSources(), function (datasource) { - return datasource.meta.id === ZABBIX_DS_ID && datasource.value; - }); - } - }]); - - return TriggerPanelEditorCtrl; -}(); - -// Get list of metric names for bs-typeahead directive - - -function getMetricNames(scope, metricList) { - return _lodash2.default.uniq(_lodash2.default.map(scope.metric[metricList], 'name')); -} - -function triggerPanelEditor() { - return { - restrict: 'E', - scope: true, - templateUrl: 'public/plugins/alexanderzobnin-zabbix-app/panel-triggers/editor.html', - controller: TriggerPanelEditorCtrl - }; -} diff --git a/dist/test/panel-triggers/module.js b/dist/test/panel-triggers/module.js deleted file mode 100644 index c1542a4..0000000 --- a/dist/test/panel-triggers/module.js +++ /dev/null @@ -1,302 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.PanelCtrl = exports.TriggerPanelCtrl = 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); - -var _moment = require('moment'); - -var _moment2 = _interopRequireDefault(_moment); - -var _utils = require('../datasource-zabbix/utils'); - -var utils = _interopRequireWildcard(_utils); - -var _sdk = require('app/plugins/sdk'); - -var _editor = require('./editor'); - -require('./ack-tooltip.directive'); - -require('./css/panel_triggers.css!'); - -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 }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * Grafana-Zabbix - * Zabbix plugin for Grafana. - * http://github.com/alexanderzobnin/grafana-zabbix - * - * Trigger panel. - * This feature sponsored by CORE IT - * http://www.coreit.fr - * - * Copyright 2015 Alexander Zobnin alexanderzobnin@gmail.com - * Licensed under the Apache License, Version 2.0 - */ - -var defaultSeverity = [{ priority: 0, severity: 'Not classified', color: '#B7DBAB', show: true }, { priority: 1, severity: 'Information', color: '#82B5D8', show: true }, { priority: 2, severity: 'Warning', color: '#E5AC0E', show: true }, { priority: 3, severity: 'Average', color: '#C15C17', show: true }, { priority: 4, severity: 'High', color: '#BF1B00', show: true }, { priority: 5, severity: 'Disaster', color: '#890F02', show: true }]; - -var panelDefaults = { - datasource: null, - triggers: { - group: { filter: "" }, - host: { filter: "" }, - application: { filter: "" }, - trigger: { filter: "" } - }, - hostField: true, - statusField: false, - severityField: false, - lastChangeField: true, - ageField: true, - infoField: true, - limit: 10, - showTriggers: 'all triggers', - sortTriggersBy: { text: 'last change', value: 'lastchange' }, - showEvents: { text: 'Problems', value: '1' }, - triggerSeverity: defaultSeverity, - okEventColor: 'rgba(0, 245, 153, 0.45)', - ackEventColor: 'rgba(0, 0, 0, 0)' -}; - -var triggerStatusMap = { - '0': 'OK', - '1': 'Problem' -}; - -var defaultTimeFormat = "DD MMM YYYY HH:mm:ss"; - -var TriggerPanelCtrl = function (_MetricsPanelCtrl) { - _inherits(TriggerPanelCtrl, _MetricsPanelCtrl); - - /** @ngInject */ - function TriggerPanelCtrl($scope, $injector, $element, datasourceSrv, templateSrv, contextSrv) { - _classCallCheck(this, TriggerPanelCtrl); - - var _this = _possibleConstructorReturn(this, (TriggerPanelCtrl.__proto__ || Object.getPrototypeOf(TriggerPanelCtrl)).call(this, $scope, $injector)); - - _this.datasourceSrv = datasourceSrv; - _this.templateSrv = templateSrv; - _this.contextSrv = contextSrv; - _this.triggerStatusMap = triggerStatusMap; - _this.defaultTimeFormat = defaultTimeFormat; - - // Load panel defaults - // _.cloneDeep() need for prevent changing shared defaultSeverity. - // Load object "by value" istead "by reference". - _lodash2.default.defaults(_this.panel, _lodash2.default.cloneDeep(panelDefaults)); - - _this.triggerList = []; - _this.refreshData(); - return _this; - } - - /** - * Override onInitMetricsPanelEditMode() method from MetricsPanelCtrl. - * We don't need metric editor from Metrics Panel. - */ - - - _createClass(TriggerPanelCtrl, [{ - key: 'onInitMetricsPanelEditMode', - value: function onInitMetricsPanelEditMode() { - this.addEditorTab('Options', _editor.triggerPanelEditor, 2); - } - }, { - key: 'refresh', - value: function refresh() { - this.onMetricsPanelRefresh(); - } - }, { - key: 'onMetricsPanelRefresh', - value: function onMetricsPanelRefresh() { - // ignore fetching data if another panel is in fullscreen - if (this.otherPanelInFullscreenMode()) { - return; - } - - this.refreshData(); - } - }, { - key: 'refreshData', - value: function refreshData() { - // clear loading/error state - delete this.error; - this.loading = true; - this.setTimeQueryStart(); - - var self = this; - - // Load datasource - return this.datasourceSrv.get(this.panel.datasource).then(function (datasource) { - var zabbix = datasource.zabbix; - var showEvents = self.panel.showEvents.value; - var triggerFilter = self.panel.triggers; - - // Replace template variables - var groupFilter = datasource.replaceTemplateVars(triggerFilter.group.filter); - var hostFilter = datasource.replaceTemplateVars(triggerFilter.host.filter); - var appFilter = datasource.replaceTemplateVars(triggerFilter.application.filter); - - var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents); - return getTriggers.then(function (triggers) { - return _lodash2.default.map(triggers, function (trigger) { - var triggerObj = trigger; - - // Format last change and age - trigger.lastchangeUnix = Number(trigger.lastchange); - var timestamp = _moment2.default.unix(trigger.lastchangeUnix); - if (self.panel.customLastChangeFormat) { - // User defined format - triggerObj.lastchange = timestamp.format(self.panel.lastChangeFormat); - } else { - triggerObj.lastchange = timestamp.format(self.defaultTimeFormat); - } - triggerObj.age = timestamp.fromNow(true); - - // Set host that the trigger belongs - if (trigger.hosts.length) { - triggerObj.host = trigger.hosts[0].name; - triggerObj.hostTechName = trigger.hosts[0].host; - } - - // Set color - if (trigger.value === '1') { - // Problem state - triggerObj.color = self.panel.triggerSeverity[trigger.priority].color; - } else { - // OK state - triggerObj.color = self.panel.okEventColor; - } - - triggerObj.severity = self.panel.triggerSeverity[trigger.priority].severity; - return triggerObj; - }); - }).then(function (triggerList) { - - // Request acknowledges for trigger - var eventids = _lodash2.default.map(triggerList, function (trigger) { - return trigger.lastEvent.eventid; - }); - - return zabbix.getAcknowledges(eventids).then(function (events) { - - // Map events to triggers - _lodash2.default.each(triggerList, function (trigger) { - var event = _lodash2.default.find(events, function (event) { - return event.eventid === trigger.lastEvent.eventid; - }); - - if (event) { - trigger.acknowledges = _lodash2.default.map(event.acknowledges, function (ack) { - var timestamp = _moment2.default.unix(ack.clock); - if (self.panel.customLastChangeFormat) { - ack.time = timestamp.format(self.panel.lastChangeFormat); - } else { - ack.time = timestamp.format(self.defaultTimeFormat); - } - ack.user = ack.alias + ' (' + ack.name + ' ' + ack.surname + ')'; - return ack; - }); - - // Mark acknowledged triggers with different color - if (self.panel.markAckEvents && trigger.acknowledges.length) { - trigger.color = self.panel.ackEventColor; - } - } - }); - - // Filter triggers by description - var triggerFilter = self.panel.triggers.trigger.filter; - if (triggerFilter) { - triggerList = filterTriggers(triggerList, triggerFilter); - } - - // Filter acknowledged triggers - if (self.panel.showTriggers === 'unacknowledged') { - triggerList = _lodash2.default.filter(triggerList, function (trigger) { - return !trigger.acknowledges; - }); - } else if (self.panel.showTriggers === 'acknowledged') { - triggerList = _lodash2.default.filter(triggerList, 'acknowledges'); - } else { - triggerList = triggerList; - } - - // Filter triggers by severity - triggerList = _lodash2.default.filter(triggerList, function (trigger) { - return self.panel.triggerSeverity[trigger.priority].show; - }); - - // Sort triggers - if (self.panel.sortTriggersBy.value === 'priority') { - triggerList = _lodash2.default.sortBy(triggerList, 'priority').reverse(); - } else { - triggerList = _lodash2.default.sortBy(triggerList, 'lastchangeUnix').reverse(); - } - - // Limit triggers number - self.triggerList = triggerList.slice(0, self.panel.limit); - - // Notify panel that request is finished - self.setTimeQueryEnd(); - self.loading = false; - }); - }); - }); - } - }, { - key: 'switchComment', - value: function switchComment(trigger) { - trigger.showComment = !trigger.showComment; - } - }, { - key: 'acknowledgeTrigger', - value: function acknowledgeTrigger(trigger, message) { - var _this2 = this; - - var eventid = trigger.lastEvent.eventid; - var grafana_user = this.contextSrv.user.name; - var ack_message = grafana_user + ' (Grafana): ' + message; - return this.datasourceSrv.get(this.panel.datasource).then(function (datasource) { - var zabbixAPI = datasource.zabbix.zabbixAPI; - return zabbixAPI.acknowledgeEvent(eventid, ack_message).then(function () { - _this2.refresh(); - }); - }); - } - }]); - - return TriggerPanelCtrl; -}(_sdk.MetricsPanelCtrl); - -TriggerPanelCtrl.templateUrl = 'panel-triggers/module.html'; - -function filterTriggers(triggers, triggerFilter) { - if (utils.isRegex(triggerFilter)) { - return _lodash2.default.filter(triggers, function (trigger) { - return utils.buildRegex(triggerFilter).test(trigger.description); - }); - } else { - return _lodash2.default.filter(triggers, function (trigger) { - return trigger.description === triggerFilter; - }); - } -} - -exports.TriggerPanelCtrl = TriggerPanelCtrl; -exports.PanelCtrl = TriggerPanelCtrl; diff --git a/src/panel-triggers/editor.html b/src/panel-triggers/editor.html index ee1b24b..39e96b8 100644 --- a/src/panel-triggers/editor.html +++ b/src/panel-triggers/editor.html @@ -121,6 +121,22 @@
        +
        + + +
        + + +
        +
        diff --git a/src/panel-triggers/module.js b/src/panel-triggers/module.js index 2062b7e..cea971b 100644 --- a/src/panel-triggers/module.js +++ b/src/panel-triggers/module.js @@ -51,7 +51,7 @@ var panelDefaults = { okEventColor: 'rgba(0, 245, 153, 0.45)', ackEventColor: 'rgba(0, 0, 0, 0)', scroll: true, - pageSize: null + pageSize: 10 }; var triggerStatusMap = { From ce5e4abc15ef84a3e5caa7055a2605c9eb368e41 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 10 Feb 2017 12:41:12 +0300 Subject: [PATCH 03/10] Add initial pagination control. --- dist/panel-triggers/module.html | 2 +- dist/panel-triggers/module.js | 26 ++++++++++++++++---------- dist/panel-triggers/module.js.map | 2 +- src/panel-triggers/module.html | 2 +- src/panel-triggers/module.js | 28 +++++++++++++++++----------- 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/dist/panel-triggers/module.html b/dist/panel-triggers/module.html index 23c3ce0..244eca4 100644 --- a/dist/panel-triggers/module.html +++ b/dist/panel-triggers/module.html @@ -35,7 +35,7 @@ - +
        diff --git a/dist/panel-triggers/module.js b/dist/panel-triggers/module.js index 1e04a3c..3961917 100644 --- a/dist/panel-triggers/module.js +++ b/dist/panel-triggers/module.js @@ -159,6 +159,7 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap _.defaults(_this.panel, _.cloneDeep(panelDefaults)); _this.triggerList = []; + _this.currentPage = []; _this.refreshData(); return _this; } @@ -345,7 +346,7 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap }, { key: 'render', value: function render() { - return _get(TriggerPanelCtrl.prototype.__proto__ || Object.getPrototypeOf(TriggerPanelCtrl.prototype), 'render', this).call(this, this.table); + return _get(TriggerPanelCtrl.prototype.__proto__ || Object.getPrototypeOf(TriggerPanelCtrl.prototype), 'render', this).call(this, this.triggerList); } }, { key: 'link', @@ -366,16 +367,16 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap return panelHeight - 31 + 'px'; } - // function appendTableRows(tbodyElem) { - // var renderer = new TableRenderer(panel, data, ctrl.dashboard.isTimezoneUtc(), ctrl.$sanitize); - // tbodyElem.empty(); - // tbodyElem.html(renderer.render(ctrl.pageIndex)); - // } - function switchPage(e) { var el = $(e.currentTarget); ctrl.pageIndex = parseInt(el.text(), 10) - 1; - renderPanel(); + + var pageSize = ctrl.panel.pageSize || 10; + var startPos = ctrl.pageIndex * pageSize; + var endPos = Math.min(startPos + pageSize, ctrl.triggerList.length); + ctrl.currentPage = ctrl.triggerList.slice(startPos, endPos); + ctrl.render(); + // renderPanel(); } function appendPaginationControls(footerElem) { @@ -414,6 +415,7 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap appendPaginationControls(footerElem); rootElem.css({ 'max-height': panel.scroll ? getTableHeight() : '' }); + // ctrl.render(); } elem.on('click', '.triggers-panel-page-link', switchPage); @@ -423,8 +425,12 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap unbindDestroy(); }); - ctrl.events.on('render', function () { - renderPanel(); + ctrl.events.on('render', function (renderData) { + data = renderData || data; + if (data) { + renderPanel(); + } + ctrl.renderingCompleted(); }); } }]); diff --git a/dist/panel-triggers/module.js.map b/dist/panel-triggers/module.js.map index 27b7b48..cef7dd9 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","MetricsPanelCtrl","triggerPanelEditor","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","scroll","pageSize","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","pageIndex","defaults","panel","cloneDeep","triggerList","refreshData","addEditorTab","onMetricsPanelRefresh","otherPanelInFullscreenMode","error","loading","setTimeQueryStart","self","get","then","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","getTriggers","map","triggerObj","lastchangeUnix","Number","lastchange","timestamp","unix","customLastChangeFormat","format","lastChangeFormat","age","fromNow","hosts","length","name","hostTechName","eventids","lastEvent","eventid","getAcknowledges","each","event","find","events","acknowledges","ack","clock","time","user","alias","surname","markAckEvents","sortBy","reverse","slice","setTimeQueryEnd","render","showComment","message","grafana_user","ack_message","zabbixAPI","acknowledgeEvent","refresh","table","scope","elem","attrs","ctrl","data","pageCount","getTableHeight","panelHeight","height","switchPage","e","el","currentTarget","parseInt","renderPanel","appendPaginationControls","footerElem","empty","Math","ceil","startPage","max","endPage","min","paginationList","i","activeClass","pageLinkElem","append","panelElem","parents","rootElem","css","fontSize","addClass","on","unbindDestroy","$on","off","templateUrl"],"mappings":"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","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 * as utils from '../datasource-zabbix/utils';\nimport {MetricsPanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\nimport './css/panel_triggers.css!';\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 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};\n\nvar triggerStatusMap = {\n '0': 'OK',\n '1': 'Problem'\n};\n\nvar defaultTimeFormat = \"DD MMM YYYY HH:mm:ss\";\n\nclass TriggerPanelCtrl extends MetricsPanelCtrl {\n\n /** @ngInject */\n constructor($scope, $injector, $element, datasourceSrv, templateSrv, contextSrv) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\n this.triggerStatusMap = triggerStatusMap;\n this.defaultTimeFormat = defaultTimeFormat;\n\n this.pageIndex = 0;\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.triggerList = [];\n this.refreshData();\n }\n\n /**\n * Override onInitMetricsPanelEditMode() method from MetricsPanelCtrl.\n * We don't need metric editor from Metrics Panel.\n */\n onInitMetricsPanelEditMode() {\n this.addEditorTab('Options', triggerPanelEditor, 2);\n }\n\n refresh() {\n this.onMetricsPanelRefresh();\n }\n\n onMetricsPanelRefresh() {\n // ignore fetching data if another panel is in fullscreen\n if (this.otherPanelInFullscreenMode()) { return; }\n\n this.refreshData();\n }\n\n refreshData() {\n // clear loading/error state\n delete this.error;\n this.loading = true;\n this.setTimeQueryStart();\n\n var self = this;\n\n // Load datasource\n return this.datasourceSrv.get(this.panel.datasource)\n .then(datasource => {\n var zabbix = datasource.zabbix;\n var showEvents = self.panel.showEvents.value;\n var triggerFilter = self.panel.triggers;\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 var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents);\n return getTriggers.then(triggers => {\n return _.map(triggers, 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 (self.panel.customLastChangeFormat) {\n // User defined format\n triggerObj.lastchange = timestamp.format(self.panel.lastChangeFormat);\n } else {\n triggerObj.lastchange = timestamp.format(self.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 = self.panel.triggerSeverity[trigger.priority].color;\n } else {\n // OK state\n triggerObj.color = self.panel.okEventColor;\n }\n\n triggerObj.severity = self.panel.triggerSeverity[trigger.priority].severity;\n return triggerObj;\n });\n })\n .then(triggerList => {\n\n // Request acknowledges for trigger\n var eventids = _.map(triggerList, trigger => {\n return trigger.lastEvent.eventid;\n });\n\n return 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 (self.panel.customLastChangeFormat) {\n ack.time = timestamp.format(self.panel.lastChangeFormat);\n } else {\n ack.time = timestamp.format(self.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 (self.panel.markAckEvents && trigger.acknowledges.length) {\n trigger.color = self.panel.ackEventColor;\n }\n }\n });\n\n // Filter triggers by description\n var triggerFilter = self.panel.triggers.trigger.filter;\n if (triggerFilter) {\n triggerList = filterTriggers(triggerList, triggerFilter);\n }\n\n // Filter acknowledged triggers\n if (self.panel.showTriggers === 'unacknowledged') {\n triggerList = _.filter(triggerList, trigger => {\n return !trigger.acknowledges;\n });\n } else if (self.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 self.panel.triggerSeverity[trigger.priority].show;\n });\n\n // Sort triggers\n if (self.panel.sortTriggersBy.value === 'priority') {\n triggerList = _.sortBy(triggerList, 'priority').reverse();\n } else {\n triggerList = _.sortBy(triggerList, 'lastchangeUnix').reverse();\n }\n\n // Limit triggers number\n self.triggerList = triggerList.slice(0, self.panel.limit);\n\n // Notify panel that request is finished\n self.setTimeQueryEnd();\n self.loading = false;\n\n this.panel.triggerList = this.triggerList;\n this.render();\n });\n });\n });\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 .then(() => {\n this.refresh();\n });\n });\n }\n\n render() {\n return super.render(this.table);\n }\n\n link(scope, elem, attrs, ctrl) {\n var data;\n var panel = ctrl.panel;\n var pageCount = 0;\n // var formaters = [];\n data = ctrl.panel.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 appendTableRows(tbodyElem) {\n // var renderer = new TableRenderer(panel, data, ctrl.dashboard.isTimezoneUtc(), ctrl.$sanitize);\n // tbodyElem.empty();\n // tbodyElem.html(renderer.render(ctrl.pageIndex));\n // }\n\n function switchPage(e) {\n var el = $(e.currentTarget);\n ctrl.pageIndex = (parseInt(el.text(), 10)-1);\n renderPanel();\n }\n\n function appendPaginationControls(footerElem) {\n footerElem.empty();\n\n var pageSize = panel.pageSize || 5;\n pageCount = Math.ceil(ctrl.panel.triggerList.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 tbodyElem = elem.find('tbody');\n var footerElem = elem.find('.triggers-panel-footer');\n\n elem.css({'font-size': panel.fontSize});\n panelElem.addClass('triggers-panel-wrapper');\n\n // appendTableRows(tbodyElem);\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', () => {\n renderPanel();\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","MetricsPanelCtrl","triggerPanelEditor","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","scroll","pageSize","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","pageIndex","defaults","panel","cloneDeep","triggerList","currentPage","refreshData","addEditorTab","onMetricsPanelRefresh","otherPanelInFullscreenMode","error","loading","setTimeQueryStart","self","get","then","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","getTriggers","map","triggerObj","lastchangeUnix","Number","lastchange","timestamp","unix","customLastChangeFormat","format","lastChangeFormat","age","fromNow","hosts","length","name","hostTechName","eventids","lastEvent","eventid","getAcknowledges","each","event","find","events","acknowledges","ack","clock","time","user","alias","surname","markAckEvents","sortBy","reverse","slice","setTimeQueryEnd","render","showComment","message","grafana_user","ack_message","zabbixAPI","acknowledgeEvent","refresh","scope","elem","attrs","ctrl","data","pageCount","getTableHeight","panelHeight","height","switchPage","e","el","currentTarget","parseInt","startPos","endPos","Math","min","appendPaginationControls","footerElem","empty","ceil","startPage","max","endPage","paginationList","i","activeClass","pageLinkElem","append","renderPanel","panelElem","parents","rootElem","css","fontSize","addClass","on","unbindDestroy","$on","off","renderData","renderingCompleted","templateUrl"],"mappings":"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","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 * as utils from '../datasource-zabbix/utils';\nimport {MetricsPanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\nimport './css/panel_triggers.css!';\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 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};\n\nvar triggerStatusMap = {\n '0': 'OK',\n '1': 'Problem'\n};\n\nvar defaultTimeFormat = \"DD MMM YYYY HH:mm:ss\";\n\nclass TriggerPanelCtrl extends MetricsPanelCtrl {\n\n /** @ngInject */\n constructor($scope, $injector, $element, datasourceSrv, templateSrv, contextSrv) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\n this.triggerStatusMap = triggerStatusMap;\n this.defaultTimeFormat = defaultTimeFormat;\n\n this.pageIndex = 0;\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.triggerList = [];\n this.currentPage = [];\n this.refreshData();\n }\n\n /**\n * Override onInitMetricsPanelEditMode() method from MetricsPanelCtrl.\n * We don't need metric editor from Metrics Panel.\n */\n onInitMetricsPanelEditMode() {\n this.addEditorTab('Options', triggerPanelEditor, 2);\n }\n\n refresh() {\n this.onMetricsPanelRefresh();\n }\n\n onMetricsPanelRefresh() {\n // ignore fetching data if another panel is in fullscreen\n if (this.otherPanelInFullscreenMode()) { return; }\n\n this.refreshData();\n }\n\n refreshData() {\n // clear loading/error state\n delete this.error;\n this.loading = true;\n this.setTimeQueryStart();\n\n var self = this;\n\n // Load datasource\n return this.datasourceSrv.get(this.panel.datasource)\n .then(datasource => {\n var zabbix = datasource.zabbix;\n var showEvents = self.panel.showEvents.value;\n var triggerFilter = self.panel.triggers;\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 var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents);\n return getTriggers.then(triggers => {\n return _.map(triggers, 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 (self.panel.customLastChangeFormat) {\n // User defined format\n triggerObj.lastchange = timestamp.format(self.panel.lastChangeFormat);\n } else {\n triggerObj.lastchange = timestamp.format(self.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 = self.panel.triggerSeverity[trigger.priority].color;\n } else {\n // OK state\n triggerObj.color = self.panel.okEventColor;\n }\n\n triggerObj.severity = self.panel.triggerSeverity[trigger.priority].severity;\n return triggerObj;\n });\n })\n .then(triggerList => {\n\n // Request acknowledges for trigger\n var eventids = _.map(triggerList, trigger => {\n return trigger.lastEvent.eventid;\n });\n\n return 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 (self.panel.customLastChangeFormat) {\n ack.time = timestamp.format(self.panel.lastChangeFormat);\n } else {\n ack.time = timestamp.format(self.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 (self.panel.markAckEvents && trigger.acknowledges.length) {\n trigger.color = self.panel.ackEventColor;\n }\n }\n });\n\n // Filter triggers by description\n var triggerFilter = self.panel.triggers.trigger.filter;\n if (triggerFilter) {\n triggerList = filterTriggers(triggerList, triggerFilter);\n }\n\n // Filter acknowledged triggers\n if (self.panel.showTriggers === 'unacknowledged') {\n triggerList = _.filter(triggerList, trigger => {\n return !trigger.acknowledges;\n });\n } else if (self.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 self.panel.triggerSeverity[trigger.priority].show;\n });\n\n // Sort triggers\n if (self.panel.sortTriggersBy.value === 'priority') {\n triggerList = _.sortBy(triggerList, 'priority').reverse();\n } else {\n triggerList = _.sortBy(triggerList, 'lastchangeUnix').reverse();\n }\n\n // Limit triggers number\n self.triggerList = triggerList.slice(0, self.panel.limit);\n\n // Notify panel that request is finished\n self.setTimeQueryEnd();\n self.loading = false;\n\n this.panel.triggerList = this.triggerList;\n this.render();\n });\n });\n });\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 .then(() => {\n this.refresh();\n });\n });\n }\n\n render() {\n return super.render(this.triggerList);\n }\n\n link(scope, elem, attrs, ctrl) {\n var data;\n var panel = ctrl.panel;\n var pageCount = 0;\n // var formaters = [];\n data = ctrl.panel.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.currentPage = ctrl.triggerList.slice(startPos, endPos);\n ctrl.render();\n // renderPanel();\n }\n\n function appendPaginationControls(footerElem) {\n footerElem.empty();\n\n var pageSize = panel.pageSize || 5;\n pageCount = Math.ceil(ctrl.panel.triggerList.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 tbodyElem = elem.find('tbody');\n var footerElem = elem.find('.triggers-panel-footer');\n\n elem.css({'font-size': panel.fontSize});\n panelElem.addClass('triggers-panel-wrapper');\n\n // appendTableRows(tbodyElem);\n appendPaginationControls(footerElem);\n\n rootElem.css({'max-height': panel.scroll ? getTableHeight() : '' });\n // ctrl.render();\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/src/panel-triggers/module.html b/src/panel-triggers/module.html index 23c3ce0..244eca4 100644 --- a/src/panel-triggers/module.html +++ b/src/panel-triggers/module.html @@ -35,7 +35,7 @@ - +
            diff --git a/src/panel-triggers/module.js b/src/panel-triggers/module.js index cea971b..4d6a226 100644 --- a/src/panel-triggers/module.js +++ b/src/panel-triggers/module.js @@ -80,6 +80,7 @@ class TriggerPanelCtrl extends MetricsPanelCtrl { _.defaults(this.panel, _.cloneDeep(panelDefaults)); this.triggerList = []; + this.currentPage = []; this.refreshData(); } @@ -254,7 +255,7 @@ class TriggerPanelCtrl extends MetricsPanelCtrl { } render() { - return super.render(this.table); + return super.render(this.triggerList); } link(scope, elem, attrs, ctrl) { @@ -274,16 +275,16 @@ class TriggerPanelCtrl extends MetricsPanelCtrl { return (panelHeight - 31) + 'px'; } - // function appendTableRows(tbodyElem) { - // var renderer = new TableRenderer(panel, data, ctrl.dashboard.isTimezoneUtc(), ctrl.$sanitize); - // tbodyElem.empty(); - // tbodyElem.html(renderer.render(ctrl.pageIndex)); - // } - function switchPage(e) { - var el = $(e.currentTarget); + let el = $(e.currentTarget); ctrl.pageIndex = (parseInt(el.text(), 10)-1); - renderPanel(); + + let pageSize = ctrl.panel.pageSize || 10; + let startPos = ctrl.pageIndex * pageSize; + let endPos = Math.min(startPos + pageSize, ctrl.triggerList.length); + ctrl.currentPage = ctrl.triggerList.slice(startPos, endPos); + ctrl.render(); + // renderPanel(); } function appendPaginationControls(footerElem) { @@ -322,6 +323,7 @@ class TriggerPanelCtrl extends MetricsPanelCtrl { appendPaginationControls(footerElem); rootElem.css({'max-height': panel.scroll ? getTableHeight() : '' }); + // ctrl.render(); } elem.on('click', '.triggers-panel-page-link', switchPage); @@ -331,8 +333,12 @@ class TriggerPanelCtrl extends MetricsPanelCtrl { unbindDestroy(); }); - ctrl.events.on('render', () => { - renderPanel(); + ctrl.events.on('render', (renderData) => { + data = renderData || data; + if (data) { + renderPanel(); + } + ctrl.renderingCompleted(); }); } } From 4d9b2f36d1e4adc95ad472c328bc80f1017d1783 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 10 Feb 2017 13:18:12 +0300 Subject: [PATCH 04/10] Triggers Panel: refactor. --- dist/panel-triggers/module.html | 2 +- dist/panel-triggers/module.js | 305 +++++++++++++++--------------- dist/panel-triggers/module.js.map | 2 +- src/panel-triggers/module.html | 2 +- src/panel-triggers/module.js | 257 +++++++++++++------------ 5 files changed, 284 insertions(+), 284 deletions(-) diff --git a/dist/panel-triggers/module.html b/dist/panel-triggers/module.html index 244eca4..23c3ce0 100644 --- a/dist/panel-triggers/module.html +++ b/dist/panel-triggers/module.html @@ -35,7 +35,7 @@ - +
            diff --git a/dist/panel-triggers/module.js b/dist/panel-triggers/module.js index 3961917..fd636c6 100644 --- a/dist/panel-triggers/module.js +++ b/dist/panel-triggers/module.js @@ -3,7 +3,7 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'app/plugins/sdk', './editor', './ack-tooltip.directive', './css/panel_triggers.css!'], function (_export, _context) { "use strict"; - var _, $, moment, utils, MetricsPanelCtrl, triggerPanelEditor, _createClass, _get, defaultSeverity, panelDefaults, triggerStatusMap, defaultTimeFormat, TriggerPanelCtrl; + var _, $, moment, utils, PanelCtrl, triggerPanelEditor, _createClass, defaultSeverity, panelDefaults, triggerStatusMap, defaultTimeFormat, TriggerPanelCtrl; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { @@ -35,7 +35,7 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - function filterTriggers(triggers, triggerFilter) { + function _filterTriggers(triggers, triggerFilter) { if (utils.isRegex(triggerFilter)) { return _.filter(triggers, function (trigger) { return utils.buildRegex(triggerFilter).test(trigger.description); @@ -57,7 +57,7 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap }, function (_datasourceZabbixUtils) { utils = _datasourceZabbixUtils; }, function (_appPluginsSdk) { - MetricsPanelCtrl = _appPluginsSdk.MetricsPanelCtrl; + PanelCtrl = _appPluginsSdk.PanelCtrl; }, function (_editor) { triggerPanelEditor = _editor.triggerPanelEditor; }, function (_ackTooltipDirective) {}, function (_cssPanel_triggersCss) {}], @@ -80,31 +80,6 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap }; }(); - _get = function get(object, property, receiver) { - if (object === null) object = Function.prototype; - var desc = Object.getOwnPropertyDescriptor(object, property); - - if (desc === undefined) { - var parent = Object.getPrototypeOf(object); - - if (parent === null) { - return undefined; - } else { - return get(parent, property, receiver); - } - } else if ("value" in desc) { - return desc.value; - } else { - var getter = desc.get; - - if (getter === undefined) { - return undefined; - } - - return getter.call(receiver); - } - }; - defaultSeverity = [{ priority: 0, severity: 'Not classified', color: '#B7DBAB', show: true }, { priority: 1, severity: 'Information', color: '#82B5D8', show: true }, { priority: 2, severity: 'Warning', color: '#E5AC0E', show: true }, { priority: 3, severity: 'Average', color: '#C15C17', show: true }, { priority: 4, severity: 'High', color: '#BF1B00', show: true }, { priority: 5, severity: 'Disaster', color: '#890F02', show: true }]; panelDefaults = { datasource: null, @@ -136,8 +111,8 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap }; defaultTimeFormat = "DD MMM YYYY HH:mm:ss"; - _export('PanelCtrl', _export('TriggerPanelCtrl', TriggerPanelCtrl = function (_MetricsPanelCtrl) { - _inherits(TriggerPanelCtrl, _MetricsPanelCtrl); + _export('PanelCtrl', _export('TriggerPanelCtrl', TriggerPanelCtrl = function (_PanelCtrl) { + _inherits(TriggerPanelCtrl, _PanelCtrl); /** @ngInject */ function TriggerPanelCtrl($scope, $injector, $element, datasourceSrv, templateSrv, contextSrv) { @@ -160,6 +135,11 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap _this.triggerList = []; _this.currentPage = []; + + _this.events.on('init-edit-mode', _this.onInitEditMode.bind(_this)); + _this.events.on('render', _this.onRender.bind(_this)); + _this.events.on('refresh', _this.onRender.bind(_this)); + _this.refreshData(); return _this; } @@ -171,15 +151,10 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap _createClass(TriggerPanelCtrl, [{ - key: 'onInitMetricsPanelEditMode', - value: function onInitMetricsPanelEditMode() { + key: 'onInitEditMode', + value: function onInitEditMode() { this.addEditorTab('Options', triggerPanelEditor, 2); } - }, { - key: 'refresh', - value: function refresh() { - this.onMetricsPanelRefresh(); - } }, { key: 'onMetricsPanelRefresh', value: function onMetricsPanelRefresh() { @@ -191,22 +166,37 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap this.refreshData(); } }, { - key: 'refreshData', - value: function refreshData() { + key: 'onRender', + value: function onRender() { var _this2 = this; // clear loading/error state delete this.error; this.loading = true; - this.setTimeQueryStart(); - var self = this; + return this.refreshData().then(function (triggerList) { + // Limit triggers number + _this2.triggerList = triggerList.slice(0, _this2.panel.limit); + + // Notify panel that request is finished + _this2.loading = false; + }); + } + }, { + key: 'refreshData', + value: function refreshData() { + return this.getTriggers().then(this.getAcknowledges.bind(this)).then(this.filterTriggers.bind(this)); + } + }, { + key: 'getTriggers', + value: function getTriggers() { + var _this3 = this; - // Load datasource return this.datasourceSrv.get(this.panel.datasource).then(function (datasource) { var zabbix = datasource.zabbix; - var showEvents = self.panel.showEvents.value; - var triggerFilter = self.panel.triggers; + _this3.zabbix = zabbix; + var showEvents = _this3.panel.showEvents.value; + var triggerFilter = _this3.panel.triggers; // Replace template variables var groupFilter = datasource.replaceTemplateVars(triggerFilter.group.filter); @@ -215,114 +205,120 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents); return getTriggers.then(function (triggers) { - return _.map(triggers, function (trigger) { - var triggerObj = trigger; - - // Format last change and age - trigger.lastchangeUnix = Number(trigger.lastchange); - var timestamp = moment.unix(trigger.lastchangeUnix); - if (self.panel.customLastChangeFormat) { - // User defined format - triggerObj.lastchange = timestamp.format(self.panel.lastChangeFormat); - } else { - triggerObj.lastchange = timestamp.format(self.defaultTimeFormat); - } - triggerObj.age = timestamp.fromNow(true); - - // Set host that the trigger belongs - if (trigger.hosts.length) { - triggerObj.host = trigger.hosts[0].name; - triggerObj.hostTechName = trigger.hosts[0].host; - } - - // Set color - if (trigger.value === '1') { - // Problem state - triggerObj.color = self.panel.triggerSeverity[trigger.priority].color; - } else { - // OK state - triggerObj.color = self.panel.okEventColor; - } - - triggerObj.severity = self.panel.triggerSeverity[trigger.priority].severity; - return triggerObj; - }); - }).then(function (triggerList) { - - // Request acknowledges for trigger - var eventids = _.map(triggerList, function (trigger) { - return trigger.lastEvent.eventid; - }); - - return zabbix.getAcknowledges(eventids).then(function (events) { - - // Map events to triggers - _.each(triggerList, function (trigger) { - var event = _.find(events, function (event) { - return event.eventid === trigger.lastEvent.eventid; - }); - - if (event) { - trigger.acknowledges = _.map(event.acknowledges, function (ack) { - var timestamp = moment.unix(ack.clock); - if (self.panel.customLastChangeFormat) { - ack.time = timestamp.format(self.panel.lastChangeFormat); - } else { - ack.time = timestamp.format(self.defaultTimeFormat); - } - ack.user = ack.alias + ' (' + ack.name + ' ' + ack.surname + ')'; - return ack; - }); - - // Mark acknowledged triggers with different color - if (self.panel.markAckEvents && trigger.acknowledges.length) { - trigger.color = self.panel.ackEventColor; - } - } - }); - - // Filter triggers by description - var triggerFilter = self.panel.triggers.trigger.filter; - if (triggerFilter) { - triggerList = filterTriggers(triggerList, triggerFilter); - } - - // Filter acknowledged triggers - if (self.panel.showTriggers === 'unacknowledged') { - triggerList = _.filter(triggerList, function (trigger) { - return !trigger.acknowledges; - }); - } else if (self.panel.showTriggers === 'acknowledged') { - triggerList = _.filter(triggerList, 'acknowledges'); - } else { - triggerList = triggerList; - } - - // Filter triggers by severity - triggerList = _.filter(triggerList, function (trigger) { - return self.panel.triggerSeverity[trigger.priority].show; - }); - - // Sort triggers - if (self.panel.sortTriggersBy.value === 'priority') { - triggerList = _.sortBy(triggerList, 'priority').reverse(); - } else { - triggerList = _.sortBy(triggerList, 'lastchangeUnix').reverse(); - } - - // Limit triggers number - self.triggerList = triggerList.slice(0, self.panel.limit); - - // Notify panel that request is finished - self.setTimeQueryEnd(); - self.loading = false; - - _this2.panel.triggerList = _this2.triggerList; - _this2.render(); - }); + return _.map(triggers, _this3.formatTrigger.bind(_this3)); }); }); } + }, { + key: 'getAcknowledges', + value: function getAcknowledges(triggerList) { + var _this4 = this; + + // Request acknowledges for trigger + var eventids = _.map(triggerList, function (trigger) { + return trigger.lastEvent.eventid; + }); + + return this.zabbix.getAcknowledges(eventids).then(function (events) { + + // Map events to triggers + _.each(triggerList, function (trigger) { + var event = _.find(events, function (event) { + return event.eventid === trigger.lastEvent.eventid; + }); + + if (event) { + trigger.acknowledges = _.map(event.acknowledges, function (ack) { + var timestamp = moment.unix(ack.clock); + if (_this4.panel.customLastChangeFormat) { + ack.time = timestamp.format(_this4.panel.lastChangeFormat); + } else { + ack.time = timestamp.format(_this4.defaultTimeFormat); + } + ack.user = ack.alias + ' (' + ack.name + ' ' + ack.surname + ')'; + return ack; + }); + + // Mark acknowledged triggers with different color + if (_this4.panel.markAckEvents && trigger.acknowledges.length) { + trigger.color = _this4.panel.ackEventColor; + } + } + }); + + return triggerList; + }); + } + }, { + key: 'filterTriggers', + value: function filterTriggers(triggerList) { + var _this5 = this; + + // Filter triggers by description + var triggerFilter = this.panel.triggers.trigger.filter; + if (triggerFilter) { + triggerList = _filterTriggers(triggerList, triggerFilter); + } + + // Filter acknowledged triggers + if (this.panel.showTriggers === 'unacknowledged') { + triggerList = _.filter(triggerList, function (trigger) { + return !trigger.acknowledges; + }); + } else if (this.panel.showTriggers === 'acknowledged') { + triggerList = _.filter(triggerList, 'acknowledges'); + } else { + triggerList = triggerList; + } + + // Filter triggers by severity + triggerList = _.filter(triggerList, function (trigger) { + return _this5.panel.triggerSeverity[trigger.priority].show; + }); + + // Sort triggers + if (this.panel.sortTriggersBy.value === 'priority') { + triggerList = _.sortBy(triggerList, 'priority').reverse(); + } else { + triggerList = _.sortBy(triggerList, 'lastchangeUnix').reverse(); + } + + return triggerList; + } + }, { + key: 'formatTrigger', + value: function formatTrigger(trigger) { + var triggerObj = trigger; + + // Format last change and age + trigger.lastchangeUnix = Number(trigger.lastchange); + var timestamp = moment.unix(trigger.lastchangeUnix); + if (this.panel.customLastChangeFormat) { + // User defined format + triggerObj.lastchange = timestamp.format(this.panel.lastChangeFormat); + } else { + triggerObj.lastchange = timestamp.format(this.defaultTimeFormat); + } + triggerObj.age = timestamp.fromNow(true); + + // Set host that the trigger belongs + if (trigger.hosts.length) { + triggerObj.host = trigger.hosts[0].name; + triggerObj.hostTechName = trigger.hosts[0].host; + } + + // Set color + if (trigger.value === '1') { + // Problem state + triggerObj.color = this.panel.triggerSeverity[trigger.priority].color; + } else { + // OK state + triggerObj.color = this.panel.okEventColor; + } + + triggerObj.severity = this.panel.triggerSeverity[trigger.priority].severity; + return triggerObj; + } }, { key: 'switchComment', value: function switchComment(trigger) { @@ -331,7 +327,7 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap }, { key: 'acknowledgeTrigger', value: function acknowledgeTrigger(trigger, message) { - var _this3 = this; + var _this6 = this; var eventid = trigger.lastEvent.eventid; var grafana_user = this.contextSrv.user.name; @@ -339,15 +335,10 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap return this.datasourceSrv.get(this.panel.datasource).then(function (datasource) { var zabbixAPI = datasource.zabbix.zabbixAPI; return zabbixAPI.acknowledgeEvent(eventid, ack_message).then(function () { - _this3.refresh(); + _this6.refresh(); }); }); } - }, { - key: 'render', - value: function render() { - return _get(TriggerPanelCtrl.prototype.__proto__ || Object.getPrototypeOf(TriggerPanelCtrl.prototype), 'render', this).call(this, this.triggerList); - } }, { key: 'link', value: function link(scope, elem, attrs, ctrl) { @@ -436,7 +427,7 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap }]); return TriggerPanelCtrl; - }(MetricsPanelCtrl))); + }(PanelCtrl))); TriggerPanelCtrl.templateUrl = 'panel-triggers/module.html'; _export('TriggerPanelCtrl', TriggerPanelCtrl); diff --git a/dist/panel-triggers/module.js.map b/dist/panel-triggers/module.js.map index cef7dd9..d2620d3 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","MetricsPanelCtrl","triggerPanelEditor","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","scroll","pageSize","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","pageIndex","defaults","panel","cloneDeep","triggerList","currentPage","refreshData","addEditorTab","onMetricsPanelRefresh","otherPanelInFullscreenMode","error","loading","setTimeQueryStart","self","get","then","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","getTriggers","map","triggerObj","lastchangeUnix","Number","lastchange","timestamp","unix","customLastChangeFormat","format","lastChangeFormat","age","fromNow","hosts","length","name","hostTechName","eventids","lastEvent","eventid","getAcknowledges","each","event","find","events","acknowledges","ack","clock","time","user","alias","surname","markAckEvents","sortBy","reverse","slice","setTimeQueryEnd","render","showComment","message","grafana_user","ack_message","zabbixAPI","acknowledgeEvent","refresh","scope","elem","attrs","ctrl","data","pageCount","getTableHeight","panelHeight","height","switchPage","e","el","currentTarget","parseInt","startPos","endPos","Math","min","appendPaginationControls","footerElem","empty","ceil","startPage","max","endPage","paginationList","i","activeClass","pageLinkElem","append","renderPanel","panelElem","parents","rootElem","css","fontSize","addClass","on","unbindDestroy","$on","off","renderData","renderingCompleted","templateUrl"],"mappings":"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","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 * as utils from '../datasource-zabbix/utils';\nimport {MetricsPanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\nimport './css/panel_triggers.css!';\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 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};\n\nvar triggerStatusMap = {\n '0': 'OK',\n '1': 'Problem'\n};\n\nvar defaultTimeFormat = \"DD MMM YYYY HH:mm:ss\";\n\nclass TriggerPanelCtrl extends MetricsPanelCtrl {\n\n /** @ngInject */\n constructor($scope, $injector, $element, datasourceSrv, templateSrv, contextSrv) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\n this.triggerStatusMap = triggerStatusMap;\n this.defaultTimeFormat = defaultTimeFormat;\n\n this.pageIndex = 0;\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.triggerList = [];\n this.currentPage = [];\n this.refreshData();\n }\n\n /**\n * Override onInitMetricsPanelEditMode() method from MetricsPanelCtrl.\n * We don't need metric editor from Metrics Panel.\n */\n onInitMetricsPanelEditMode() {\n this.addEditorTab('Options', triggerPanelEditor, 2);\n }\n\n refresh() {\n this.onMetricsPanelRefresh();\n }\n\n onMetricsPanelRefresh() {\n // ignore fetching data if another panel is in fullscreen\n if (this.otherPanelInFullscreenMode()) { return; }\n\n this.refreshData();\n }\n\n refreshData() {\n // clear loading/error state\n delete this.error;\n this.loading = true;\n this.setTimeQueryStart();\n\n var self = this;\n\n // Load datasource\n return this.datasourceSrv.get(this.panel.datasource)\n .then(datasource => {\n var zabbix = datasource.zabbix;\n var showEvents = self.panel.showEvents.value;\n var triggerFilter = self.panel.triggers;\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 var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents);\n return getTriggers.then(triggers => {\n return _.map(triggers, 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 (self.panel.customLastChangeFormat) {\n // User defined format\n triggerObj.lastchange = timestamp.format(self.panel.lastChangeFormat);\n } else {\n triggerObj.lastchange = timestamp.format(self.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 = self.panel.triggerSeverity[trigger.priority].color;\n } else {\n // OK state\n triggerObj.color = self.panel.okEventColor;\n }\n\n triggerObj.severity = self.panel.triggerSeverity[trigger.priority].severity;\n return triggerObj;\n });\n })\n .then(triggerList => {\n\n // Request acknowledges for trigger\n var eventids = _.map(triggerList, trigger => {\n return trigger.lastEvent.eventid;\n });\n\n return 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 (self.panel.customLastChangeFormat) {\n ack.time = timestamp.format(self.panel.lastChangeFormat);\n } else {\n ack.time = timestamp.format(self.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 (self.panel.markAckEvents && trigger.acknowledges.length) {\n trigger.color = self.panel.ackEventColor;\n }\n }\n });\n\n // Filter triggers by description\n var triggerFilter = self.panel.triggers.trigger.filter;\n if (triggerFilter) {\n triggerList = filterTriggers(triggerList, triggerFilter);\n }\n\n // Filter acknowledged triggers\n if (self.panel.showTriggers === 'unacknowledged') {\n triggerList = _.filter(triggerList, trigger => {\n return !trigger.acknowledges;\n });\n } else if (self.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 self.panel.triggerSeverity[trigger.priority].show;\n });\n\n // Sort triggers\n if (self.panel.sortTriggersBy.value === 'priority') {\n triggerList = _.sortBy(triggerList, 'priority').reverse();\n } else {\n triggerList = _.sortBy(triggerList, 'lastchangeUnix').reverse();\n }\n\n // Limit triggers number\n self.triggerList = triggerList.slice(0, self.panel.limit);\n\n // Notify panel that request is finished\n self.setTimeQueryEnd();\n self.loading = false;\n\n this.panel.triggerList = this.triggerList;\n this.render();\n });\n });\n });\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 .then(() => {\n this.refresh();\n });\n });\n }\n\n render() {\n return super.render(this.triggerList);\n }\n\n link(scope, elem, attrs, ctrl) {\n var data;\n var panel = ctrl.panel;\n var pageCount = 0;\n // var formaters = [];\n data = ctrl.panel.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.currentPage = ctrl.triggerList.slice(startPos, endPos);\n ctrl.render();\n // renderPanel();\n }\n\n function appendPaginationControls(footerElem) {\n footerElem.empty();\n\n var pageSize = panel.pageSize || 5;\n pageCount = Math.ceil(ctrl.panel.triggerList.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 tbodyElem = elem.find('tbody');\n var footerElem = elem.find('.triggers-panel-footer');\n\n elem.css({'font-size': panel.fontSize});\n panelElem.addClass('triggers-panel-wrapper');\n\n // appendTableRows(tbodyElem);\n appendPaginationControls(footerElem);\n\n rootElem.css({'max-height': panel.scroll ? getTableHeight() : '' });\n // ctrl.render();\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","PanelCtrl","triggerPanelEditor","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","scroll","pageSize","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","pageIndex","defaults","panel","cloneDeep","triggerList","currentPage","events","on","onInitEditMode","bind","onRender","refreshData","addEditorTab","otherPanelInFullscreenMode","error","loading","then","slice","getTriggers","getAcknowledges","get","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","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","refresh","scope","elem","attrs","ctrl","data","pageCount","getTableHeight","panelHeight","height","switchPage","e","el","currentTarget","parseInt","startPos","endPos","Math","min","render","appendPaginationControls","footerElem","empty","ceil","startPage","max","endPage","paginationList","i","activeClass","pageLinkElem","append","renderPanel","panelElem","parents","rootElem","css","fontSize","addClass","unbindDestroy","$on","off","renderData","renderingCompleted","templateUrl"],"mappings":"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","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 * as utils from '../datasource-zabbix/utils';\nimport {PanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\nimport './css/panel_triggers.css!';\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 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};\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) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\n this.triggerStatusMap = triggerStatusMap;\n this.defaultTimeFormat = defaultTimeFormat;\n\n this.pageIndex = 0;\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.triggerList = [];\n this.currentPage = [];\n\n this.events.on('init-edit-mode', this.onInitEditMode.bind(this));\n this.events.on('render', this.onRender.bind(this));\n this.events.on('refresh', this.onRender.bind(this));\n\n this.refreshData();\n }\n\n /**\n * Override onInitMetricsPanelEditMode() method from MetricsPanelCtrl.\n * We don't need metric editor from Metrics Panel.\n */\n onInitEditMode() {\n this.addEditorTab('Options', triggerPanelEditor, 2);\n }\n\n onMetricsPanelRefresh() {\n // ignore fetching data if another panel is in fullscreen\n if (this.otherPanelInFullscreenMode()) { return; }\n\n this.refreshData();\n }\n\n onRender() {\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 // Notify panel that request is finished\n this.loading = false;\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\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 var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents);\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 .then(() => {\n this.refresh();\n });\n });\n }\n\n link(scope, elem, attrs, ctrl) {\n var data;\n var panel = ctrl.panel;\n var pageCount = 0;\n // var formaters = [];\n data = ctrl.panel.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.currentPage = ctrl.triggerList.slice(startPos, endPos);\n ctrl.render();\n // renderPanel();\n }\n\n function appendPaginationControls(footerElem) {\n footerElem.empty();\n\n var pageSize = panel.pageSize || 5;\n pageCount = Math.ceil(ctrl.panel.triggerList.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 tbodyElem = elem.find('tbody');\n var footerElem = elem.find('.triggers-panel-footer');\n\n elem.css({'font-size': panel.fontSize});\n panelElem.addClass('triggers-panel-wrapper');\n\n // appendTableRows(tbodyElem);\n appendPaginationControls(footerElem);\n\n rootElem.css({'max-height': panel.scroll ? getTableHeight() : '' });\n // ctrl.render();\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/src/panel-triggers/module.html b/src/panel-triggers/module.html index 244eca4..23c3ce0 100644 --- a/src/panel-triggers/module.html +++ b/src/panel-triggers/module.html @@ -35,7 +35,7 @@ - +
                diff --git a/src/panel-triggers/module.js b/src/panel-triggers/module.js index 4d6a226..dcc0476 100644 --- a/src/panel-triggers/module.js +++ b/src/panel-triggers/module.js @@ -15,7 +15,7 @@ import _ from 'lodash'; import $ from 'jquery'; import moment from 'moment'; import * as utils from '../datasource-zabbix/utils'; -import {MetricsPanelCtrl} from 'app/plugins/sdk'; +import {PanelCtrl} from 'app/plugins/sdk'; import {triggerPanelEditor} from './editor'; import './ack-tooltip.directive'; import './css/panel_triggers.css!'; @@ -61,7 +61,7 @@ var triggerStatusMap = { var defaultTimeFormat = "DD MMM YYYY HH:mm:ss"; -class TriggerPanelCtrl extends MetricsPanelCtrl { +class TriggerPanelCtrl extends PanelCtrl { /** @ngInject */ constructor($scope, $injector, $element, datasourceSrv, templateSrv, contextSrv) { @@ -81,6 +81,11 @@ class TriggerPanelCtrl extends MetricsPanelCtrl { this.triggerList = []; this.currentPage = []; + + this.events.on('init-edit-mode', this.onInitEditMode.bind(this)); + this.events.on('render', this.onRender.bind(this)); + this.events.on('refresh', this.onRender.bind(this)); + this.refreshData(); } @@ -88,14 +93,10 @@ class TriggerPanelCtrl extends MetricsPanelCtrl { * Override onInitMetricsPanelEditMode() method from MetricsPanelCtrl. * We don't need metric editor from Metrics Panel. */ - onInitMetricsPanelEditMode() { + onInitEditMode() { this.addEditorTab('Options', triggerPanelEditor, 2); } - refresh() { - this.onMetricsPanelRefresh(); - } - onMetricsPanelRefresh() { // ignore fetching data if another panel is in fullscreen if (this.otherPanelInFullscreenMode()) { return; } @@ -103,20 +104,34 @@ class TriggerPanelCtrl extends MetricsPanelCtrl { this.refreshData(); } - refreshData() { + onRender() { // clear loading/error state delete this.error; this.loading = true; - this.setTimeQueryStart(); - var self = this; + return this.refreshData() + .then(triggerList => { + // Limit triggers number + this.triggerList = triggerList.slice(0, this.panel.limit); - // Load datasource + // Notify panel that request is finished + this.loading = false; + }); + } + + refreshData() { + return this.getTriggers() + .then(this.getAcknowledges.bind(this)) + .then(this.filterTriggers.bind(this)); + } + + getTriggers() { return this.datasourceSrv.get(this.panel.datasource) .then(datasource => { var zabbix = datasource.zabbix; - var showEvents = self.panel.showEvents.value; - var triggerFilter = self.panel.triggers; + this.zabbix = zabbix; + var showEvents = this.panel.showEvents.value; + var triggerFilter = this.panel.triggers; // Replace template variables var groupFilter = datasource.replaceTemplateVars(triggerFilter.group.filter); @@ -125,117 +140,115 @@ class TriggerPanelCtrl extends MetricsPanelCtrl { var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents); return getTriggers.then(triggers => { - return _.map(triggers, trigger => { - let triggerObj = trigger; - - // Format last change and age - trigger.lastchangeUnix = Number(trigger.lastchange); - let timestamp = moment.unix(trigger.lastchangeUnix); - if (self.panel.customLastChangeFormat) { - // User defined format - triggerObj.lastchange = timestamp.format(self.panel.lastChangeFormat); - } else { - triggerObj.lastchange = timestamp.format(self.defaultTimeFormat); - } - triggerObj.age = timestamp.fromNow(true); - - // Set host that the trigger belongs - if (trigger.hosts.length) { - triggerObj.host = trigger.hosts[0].name; - triggerObj.hostTechName = trigger.hosts[0].host; - } - - // Set color - if (trigger.value === '1') { - // Problem state - triggerObj.color = self.panel.triggerSeverity[trigger.priority].color; - } else { - // OK state - triggerObj.color = self.panel.okEventColor; - } - - triggerObj.severity = self.panel.triggerSeverity[trigger.priority].severity; - return triggerObj; - }); - }) - .then(triggerList => { - - // Request acknowledges for trigger - var eventids = _.map(triggerList, trigger => { - return trigger.lastEvent.eventid; - }); - - return zabbix.getAcknowledges(eventids) - .then(events => { - - // Map events to triggers - _.each(triggerList, trigger => { - var event = _.find(events, event => { - return event.eventid === trigger.lastEvent.eventid; - }); - - if (event) { - trigger.acknowledges = _.map(event.acknowledges, ack => { - let timestamp = moment.unix(ack.clock); - if (self.panel.customLastChangeFormat) { - ack.time = timestamp.format(self.panel.lastChangeFormat); - } else { - ack.time = timestamp.format(self.defaultTimeFormat); - } - ack.user = ack.alias + ' (' + ack.name + ' ' + ack.surname + ')'; - return ack; - }); - - // Mark acknowledged triggers with different color - if (self.panel.markAckEvents && trigger.acknowledges.length) { - trigger.color = self.panel.ackEventColor; - } - } - }); - - // Filter triggers by description - var triggerFilter = self.panel.triggers.trigger.filter; - if (triggerFilter) { - triggerList = filterTriggers(triggerList, triggerFilter); - } - - // Filter acknowledged triggers - if (self.panel.showTriggers === 'unacknowledged') { - triggerList = _.filter(triggerList, trigger => { - return !trigger.acknowledges; - }); - } else if (self.panel.showTriggers === 'acknowledged') { - triggerList = _.filter(triggerList, 'acknowledges'); - } else { - triggerList = triggerList; - } - - // Filter triggers by severity - triggerList = _.filter(triggerList, trigger => { - return self.panel.triggerSeverity[trigger.priority].show; - }); - - // Sort triggers - if (self.panel.sortTriggersBy.value === 'priority') { - triggerList = _.sortBy(triggerList, 'priority').reverse(); - } else { - triggerList = _.sortBy(triggerList, 'lastchangeUnix').reverse(); - } - - // Limit triggers number - self.triggerList = triggerList.slice(0, self.panel.limit); - - // Notify panel that request is finished - self.setTimeQueryEnd(); - self.loading = false; - - this.panel.triggerList = this.triggerList; - this.render(); - }); + return _.map(triggers, this.formatTrigger.bind(this)); }); }); } + getAcknowledges(triggerList) { + // Request acknowledges for trigger + var eventids = _.map(triggerList, trigger => { + return trigger.lastEvent.eventid; + }); + + return this.zabbix.getAcknowledges(eventids) + .then(events => { + + // Map events to triggers + _.each(triggerList, trigger => { + var event = _.find(events, event => { + return event.eventid === trigger.lastEvent.eventid; + }); + + if (event) { + trigger.acknowledges = _.map(event.acknowledges, ack => { + let timestamp = moment.unix(ack.clock); + if (this.panel.customLastChangeFormat) { + ack.time = timestamp.format(this.panel.lastChangeFormat); + } else { + ack.time = timestamp.format(this.defaultTimeFormat); + } + ack.user = ack.alias + ' (' + ack.name + ' ' + ack.surname + ')'; + return ack; + }); + + // Mark acknowledged triggers with different color + if (this.panel.markAckEvents && trigger.acknowledges.length) { + trigger.color = this.panel.ackEventColor; + } + } + }); + + return triggerList; + }); + } + + filterTriggers(triggerList) { + // Filter triggers by description + var triggerFilter = this.panel.triggers.trigger.filter; + if (triggerFilter) { + triggerList = filterTriggers(triggerList, triggerFilter); + } + + // Filter acknowledged triggers + if (this.panel.showTriggers === 'unacknowledged') { + triggerList = _.filter(triggerList, trigger => { + return !trigger.acknowledges; + }); + } else if (this.panel.showTriggers === 'acknowledged') { + triggerList = _.filter(triggerList, 'acknowledges'); + } else { + triggerList = triggerList; + } + + // Filter triggers by severity + triggerList = _.filter(triggerList, trigger => { + return this.panel.triggerSeverity[trigger.priority].show; + }); + + // Sort triggers + if (this.panel.sortTriggersBy.value === 'priority') { + triggerList = _.sortBy(triggerList, 'priority').reverse(); + } else { + triggerList = _.sortBy(triggerList, 'lastchangeUnix').reverse(); + } + + return triggerList; + } + + formatTrigger(trigger) { + let triggerObj = trigger; + + // Format last change and age + trigger.lastchangeUnix = Number(trigger.lastchange); + let timestamp = moment.unix(trigger.lastchangeUnix); + if (this.panel.customLastChangeFormat) { + // User defined format + triggerObj.lastchange = timestamp.format(this.panel.lastChangeFormat); + } else { + triggerObj.lastchange = timestamp.format(this.defaultTimeFormat); + } + triggerObj.age = timestamp.fromNow(true); + + // Set host that the trigger belongs + if (trigger.hosts.length) { + triggerObj.host = trigger.hosts[0].name; + triggerObj.hostTechName = trigger.hosts[0].host; + } + + // Set color + if (trigger.value === '1') { + // Problem state + triggerObj.color = this.panel.triggerSeverity[trigger.priority].color; + } else { + // OK state + triggerObj.color = this.panel.okEventColor; + } + + triggerObj.severity = this.panel.triggerSeverity[trigger.priority].severity; + return triggerObj; + } + switchComment(trigger) { trigger.showComment = !trigger.showComment; } @@ -254,10 +267,6 @@ class TriggerPanelCtrl extends MetricsPanelCtrl { }); } - render() { - return super.render(this.triggerList); - } - link(scope, elem, attrs, ctrl) { var data; var panel = ctrl.panel; From 1eef99892344bc5f039096027f771919a6d008fc Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 10 Feb 2017 15:04:27 +0300 Subject: [PATCH 05/10] Fix table pagination, closes #229 --- dist/panel-triggers/module.html | 2 +- dist/panel-triggers/module.js | 50 ++++++++++++++++--------------- dist/panel-triggers/module.js.map | 2 +- src/panel-triggers/module.html | 2 +- src/panel-triggers/module.js | 47 +++++++++++++++-------------- 5 files changed, 54 insertions(+), 49 deletions(-) diff --git a/dist/panel-triggers/module.html b/dist/panel-triggers/module.html index 23c3ce0..7b5fefa 100644 --- a/dist/panel-triggers/module.html +++ b/dist/panel-triggers/module.html @@ -35,7 +35,7 @@ - +
                diff --git a/dist/panel-triggers/module.js b/dist/panel-triggers/module.js index fd636c6..319cdee 100644 --- a/dist/panel-triggers/module.js +++ b/dist/panel-triggers/module.js @@ -134,13 +134,10 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap _.defaults(_this.panel, _.cloneDeep(panelDefaults)); _this.triggerList = []; - _this.currentPage = []; + _this.currentTriggersPage = []; _this.events.on('init-edit-mode', _this.onInitEditMode.bind(_this)); - _this.events.on('render', _this.onRender.bind(_this)); - _this.events.on('refresh', _this.onRender.bind(_this)); - - _this.refreshData(); + _this.events.on('refresh', _this.onRefresh.bind(_this)); return _this; } @@ -166,8 +163,8 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap this.refreshData(); } }, { - key: 'onRender', - value: function onRender() { + key: 'onRefresh', + value: function onRefresh() { var _this2 = this; // clear loading/error state @@ -178,8 +175,12 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap // Limit triggers number _this2.triggerList = triggerList.slice(0, _this2.panel.limit); + _this2.getCurrentTriggersPage(); + // Notify panel that request is finished _this2.loading = false; + + _this2.render(_this2.triggerList); }); } }, { @@ -327,17 +328,22 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap }, { key: 'acknowledgeTrigger', value: function acknowledgeTrigger(trigger, message) { - var _this6 = this; - var eventid = trigger.lastEvent.eventid; var grafana_user = this.contextSrv.user.name; var ack_message = grafana_user + ' (Grafana): ' + message; return this.datasourceSrv.get(this.panel.datasource).then(function (datasource) { var zabbixAPI = datasource.zabbix.zabbixAPI; - return zabbixAPI.acknowledgeEvent(eventid, ack_message).then(function () { - _this6.refresh(); - }); - }); + return zabbixAPI.acknowledgeEvent(eventid, ack_message); + }).then(this.onRefresh.bind(this)); + } + }, { + key: 'getCurrentTriggersPage', + value: function getCurrentTriggersPage() { + var pageSize = this.panel.pageSize || 10; + var startPos = this.pageIndex * pageSize; + var endPos = Math.min(startPos + pageSize, this.triggerList.length); + this.currentTriggersPage = this.triggerList.slice(startPos, endPos); + return this.currentTriggersPage; } }, { key: 'link', @@ -345,8 +351,7 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap var data; var panel = ctrl.panel; var pageCount = 0; - // var formaters = []; - data = ctrl.panel.triggerList; + data = ctrl.triggerList; function getTableHeight() { var panelHeight = ctrl.height; @@ -365,16 +370,17 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap var pageSize = ctrl.panel.pageSize || 10; var startPos = ctrl.pageIndex * pageSize; var endPos = Math.min(startPos + pageSize, ctrl.triggerList.length); - ctrl.currentPage = ctrl.triggerList.slice(startPos, endPos); - ctrl.render(); - // renderPanel(); + ctrl.currentTriggersPage = ctrl.triggerList.slice(startPos, endPos); + + scope.$apply(); + renderPanel(); } function appendPaginationControls(footerElem) { footerElem.empty(); - var pageSize = panel.pageSize || 5; - pageCount = Math.ceil(ctrl.panel.triggerList.length / pageSize); + var pageSize = ctrl.panel.pageSize || 5; + pageCount = Math.ceil(data.length / pageSize); if (pageCount === 1) { return; } @@ -396,17 +402,13 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap function renderPanel() { var panelElem = elem.parents('.panel'); var rootElem = elem.find('.triggers-panel-scroll'); - // var tbodyElem = elem.find('tbody'); var footerElem = elem.find('.triggers-panel-footer'); elem.css({ 'font-size': panel.fontSize }); panelElem.addClass('triggers-panel-wrapper'); - - // appendTableRows(tbodyElem); appendPaginationControls(footerElem); rootElem.css({ 'max-height': panel.scroll ? getTableHeight() : '' }); - // ctrl.render(); } elem.on('click', '.triggers-panel-page-link', switchPage); diff --git a/dist/panel-triggers/module.js.map b/dist/panel-triggers/module.js.map index d2620d3..8fa09cf 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","PanelCtrl","triggerPanelEditor","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","scroll","pageSize","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","pageIndex","defaults","panel","cloneDeep","triggerList","currentPage","events","on","onInitEditMode","bind","onRender","refreshData","addEditorTab","otherPanelInFullscreenMode","error","loading","then","slice","getTriggers","getAcknowledges","get","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","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","refresh","scope","elem","attrs","ctrl","data","pageCount","getTableHeight","panelHeight","height","switchPage","e","el","currentTarget","parseInt","startPos","endPos","Math","min","render","appendPaginationControls","footerElem","empty","ceil","startPage","max","endPage","paginationList","i","activeClass","pageLinkElem","append","renderPanel","panelElem","parents","rootElem","css","fontSize","addClass","unbindDestroy","$on","off","renderData","renderingCompleted","templateUrl"],"mappings":"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","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 * as utils from '../datasource-zabbix/utils';\nimport {PanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\nimport './css/panel_triggers.css!';\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 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};\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) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\n this.triggerStatusMap = triggerStatusMap;\n this.defaultTimeFormat = defaultTimeFormat;\n\n this.pageIndex = 0;\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.triggerList = [];\n this.currentPage = [];\n\n this.events.on('init-edit-mode', this.onInitEditMode.bind(this));\n this.events.on('render', this.onRender.bind(this));\n this.events.on('refresh', this.onRender.bind(this));\n\n this.refreshData();\n }\n\n /**\n * Override onInitMetricsPanelEditMode() method from MetricsPanelCtrl.\n * We don't need metric editor from Metrics Panel.\n */\n onInitEditMode() {\n this.addEditorTab('Options', triggerPanelEditor, 2);\n }\n\n onMetricsPanelRefresh() {\n // ignore fetching data if another panel is in fullscreen\n if (this.otherPanelInFullscreenMode()) { return; }\n\n this.refreshData();\n }\n\n onRender() {\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 // Notify panel that request is finished\n this.loading = false;\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\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 var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents);\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 .then(() => {\n this.refresh();\n });\n });\n }\n\n link(scope, elem, attrs, ctrl) {\n var data;\n var panel = ctrl.panel;\n var pageCount = 0;\n // var formaters = [];\n data = ctrl.panel.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.currentPage = ctrl.triggerList.slice(startPos, endPos);\n ctrl.render();\n // renderPanel();\n }\n\n function appendPaginationControls(footerElem) {\n footerElem.empty();\n\n var pageSize = panel.pageSize || 5;\n pageCount = Math.ceil(ctrl.panel.triggerList.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 tbodyElem = elem.find('tbody');\n var footerElem = elem.find('.triggers-panel-footer');\n\n elem.css({'font-size': panel.fontSize});\n panelElem.addClass('triggers-panel-wrapper');\n\n // appendTableRows(tbodyElem);\n appendPaginationControls(footerElem);\n\n rootElem.css({'max-height': panel.scroll ? getTableHeight() : '' });\n // ctrl.render();\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","PanelCtrl","triggerPanelEditor","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","scroll","pageSize","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","pageIndex","defaults","panel","cloneDeep","triggerList","currentTriggersPage","events","on","onInitEditMode","bind","onRefresh","addEditorTab","otherPanelInFullscreenMode","refreshData","error","loading","then","slice","getCurrentTriggersPage","render","getTriggers","getAcknowledges","get","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","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","fontSize","addClass","unbindDestroy","$on","off","renderData","renderingCompleted","templateUrl"],"mappings":"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","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 * as utils from '../datasource-zabbix/utils';\nimport {PanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\nimport './css/panel_triggers.css!';\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 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};\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) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\n this.triggerStatusMap = triggerStatusMap;\n this.defaultTimeFormat = defaultTimeFormat;\n\n this.pageIndex = 0;\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.triggerList = [];\n this.currentTriggersPage = [];\n\n this.events.on('init-edit-mode', this.onInitEditMode.bind(this));\n this.events.on('refresh', this.onRefresh.bind(this));\n }\n\n /**\n * Override onInitMetricsPanelEditMode() method from MetricsPanelCtrl.\n * We don't need metric editor from Metrics Panel.\n */\n onInitEditMode() {\n this.addEditorTab('Options', triggerPanelEditor, 2);\n }\n\n onMetricsPanelRefresh() {\n // ignore fetching data if another panel is in fullscreen\n if (this.otherPanelInFullscreenMode()) { return; }\n\n this.refreshData();\n }\n\n onRefresh() {\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\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 var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents);\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 diff --git a/src/panel-triggers/module.html b/src/panel-triggers/module.html index 23c3ce0..7b5fefa 100644 --- a/src/panel-triggers/module.html +++ b/src/panel-triggers/module.html @@ -35,7 +35,7 @@ - +
                    diff --git a/src/panel-triggers/module.js b/src/panel-triggers/module.js index dcc0476..46f55fd 100644 --- a/src/panel-triggers/module.js +++ b/src/panel-triggers/module.js @@ -80,13 +80,10 @@ class TriggerPanelCtrl extends PanelCtrl { _.defaults(this.panel, _.cloneDeep(panelDefaults)); this.triggerList = []; - this.currentPage = []; + this.currentTriggersPage = []; this.events.on('init-edit-mode', this.onInitEditMode.bind(this)); - this.events.on('render', this.onRender.bind(this)); - this.events.on('refresh', this.onRender.bind(this)); - - this.refreshData(); + this.events.on('refresh', this.onRefresh.bind(this)); } /** @@ -104,7 +101,7 @@ class TriggerPanelCtrl extends PanelCtrl { this.refreshData(); } - onRender() { + onRefresh() { // clear loading/error state delete this.error; this.loading = true; @@ -114,8 +111,12 @@ class TriggerPanelCtrl extends PanelCtrl { // Limit triggers number this.triggerList = triggerList.slice(0, this.panel.limit); + this.getCurrentTriggersPage(); + // Notify panel that request is finished this.loading = false; + + this.render(this.triggerList); }); } @@ -260,19 +261,24 @@ class TriggerPanelCtrl extends PanelCtrl { return this.datasourceSrv.get(this.panel.datasource) .then(datasource => { let zabbixAPI = datasource.zabbix.zabbixAPI; - return zabbixAPI.acknowledgeEvent(eventid, ack_message) - .then(() => { - this.refresh(); - }); - }); + return zabbixAPI.acknowledgeEvent(eventid, ack_message); + }) + .then(this.onRefresh.bind(this)); + } + + getCurrentTriggersPage() { + let pageSize = this.panel.pageSize || 10; + let startPos = this.pageIndex * pageSize; + let endPos = Math.min(startPos + pageSize, this.triggerList.length); + this.currentTriggersPage = this.triggerList.slice(startPos, endPos); + return this.currentTriggersPage; } link(scope, elem, attrs, ctrl) { var data; var panel = ctrl.panel; var pageCount = 0; - // var formaters = []; - data = ctrl.panel.triggerList; + data = ctrl.triggerList; function getTableHeight() { var panelHeight = ctrl.height; @@ -291,16 +297,17 @@ class TriggerPanelCtrl extends PanelCtrl { let pageSize = ctrl.panel.pageSize || 10; let startPos = ctrl.pageIndex * pageSize; let endPos = Math.min(startPos + pageSize, ctrl.triggerList.length); - ctrl.currentPage = ctrl.triggerList.slice(startPos, endPos); - ctrl.render(); - // renderPanel(); + ctrl.currentTriggersPage = ctrl.triggerList.slice(startPos, endPos); + + scope.$apply(); + renderPanel(); } function appendPaginationControls(footerElem) { footerElem.empty(); - var pageSize = panel.pageSize || 5; - pageCount = Math.ceil(ctrl.panel.triggerList.length / pageSize); + var pageSize = ctrl.panel.pageSize || 5; + pageCount = Math.ceil(data.length / pageSize); if (pageCount === 1) { return; } @@ -322,17 +329,13 @@ class TriggerPanelCtrl extends PanelCtrl { function renderPanel() { var panelElem = elem.parents('.panel'); var rootElem = elem.find('.triggers-panel-scroll'); - // var tbodyElem = elem.find('tbody'); var footerElem = elem.find('.triggers-panel-footer'); elem.css({'font-size': panel.fontSize}); panelElem.addClass('triggers-panel-wrapper'); - - // appendTableRows(tbodyElem); appendPaginationControls(footerElem); rootElem.css({'max-height': panel.scroll ? getTableHeight() : '' }); - // ctrl.render(); } elem.on('click', '.triggers-panel-page-link', switchPage); From 437699372cad0d76522858cb6fd61129bd153381 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 10 Feb 2017 16:17:31 +0300 Subject: [PATCH 06/10] Clean up code. --- dist/panel-triggers/module.js | 22 ++-------------------- dist/panel-triggers/module.js.map | 2 +- src/panel-triggers/module.js | 17 ++--------------- 3 files changed, 5 insertions(+), 36 deletions(-) diff --git a/dist/panel-triggers/module.js b/dist/panel-triggers/module.js index 319cdee..e3c079d 100644 --- a/dist/panel-triggers/module.js +++ b/dist/panel-triggers/module.js @@ -125,43 +125,25 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap _this.contextSrv = contextSrv; _this.triggerStatusMap = triggerStatusMap; _this.defaultTimeFormat = defaultTimeFormat; - _this.pageIndex = 0; + _this.triggerList = []; + _this.currentTriggersPage = []; // Load panel defaults // _.cloneDeep() need for prevent changing shared defaultSeverity. // Load object "by value" istead "by reference". _.defaults(_this.panel, _.cloneDeep(panelDefaults)); - _this.triggerList = []; - _this.currentTriggersPage = []; - _this.events.on('init-edit-mode', _this.onInitEditMode.bind(_this)); _this.events.on('refresh', _this.onRefresh.bind(_this)); return _this; } - /** - * Override onInitMetricsPanelEditMode() method from MetricsPanelCtrl. - * We don't need metric editor from Metrics Panel. - */ - - _createClass(TriggerPanelCtrl, [{ key: 'onInitEditMode', value: function onInitEditMode() { this.addEditorTab('Options', triggerPanelEditor, 2); } - }, { - key: 'onMetricsPanelRefresh', - value: function onMetricsPanelRefresh() { - // ignore fetching data if another panel is in fullscreen - if (this.otherPanelInFullscreenMode()) { - return; - } - - this.refreshData(); - } }, { key: 'onRefresh', value: function onRefresh() { diff --git a/dist/panel-triggers/module.js.map b/dist/panel-triggers/module.js.map index 8fa09cf..5b9cbc2 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","PanelCtrl","triggerPanelEditor","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","scroll","pageSize","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","pageIndex","defaults","panel","cloneDeep","triggerList","currentTriggersPage","events","on","onInitEditMode","bind","onRefresh","addEditorTab","otherPanelInFullscreenMode","refreshData","error","loading","then","slice","getCurrentTriggersPage","render","getTriggers","getAcknowledges","get","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","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","fontSize","addClass","unbindDestroy","$on","off","renderData","renderingCompleted","templateUrl"],"mappings":"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","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 * as utils from '../datasource-zabbix/utils';\nimport {PanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\nimport './css/panel_triggers.css!';\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 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};\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) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\n this.triggerStatusMap = triggerStatusMap;\n this.defaultTimeFormat = defaultTimeFormat;\n\n this.pageIndex = 0;\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.triggerList = [];\n this.currentTriggersPage = [];\n\n this.events.on('init-edit-mode', this.onInitEditMode.bind(this));\n this.events.on('refresh', this.onRefresh.bind(this));\n }\n\n /**\n * Override onInitMetricsPanelEditMode() method from MetricsPanelCtrl.\n * We don't need metric editor from Metrics Panel.\n */\n onInitEditMode() {\n this.addEditorTab('Options', triggerPanelEditor, 2);\n }\n\n onMetricsPanelRefresh() {\n // ignore fetching data if another panel is in fullscreen\n if (this.otherPanelInFullscreenMode()) { return; }\n\n this.refreshData();\n }\n\n onRefresh() {\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\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 var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents);\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","PanelCtrl","triggerPanelEditor","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","scroll","pageSize","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","pageIndex","triggerList","currentTriggersPage","defaults","panel","cloneDeep","events","on","onInitEditMode","bind","onRefresh","addEditorTab","error","loading","refreshData","then","slice","getCurrentTriggersPage","render","getTriggers","getAcknowledges","get","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","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","fontSize","addClass","unbindDestroy","$on","off","renderData","renderingCompleted","templateUrl"],"mappings":"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","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 * as utils from '../datasource-zabbix/utils';\nimport {PanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\nimport './css/panel_triggers.css!';\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 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};\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) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\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 // 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\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 var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents);\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 diff --git a/src/panel-triggers/module.js b/src/panel-triggers/module.js index 46f55fd..56b967c 100644 --- a/src/panel-triggers/module.js +++ b/src/panel-triggers/module.js @@ -71,36 +71,23 @@ class TriggerPanelCtrl extends PanelCtrl { this.contextSrv = contextSrv; this.triggerStatusMap = triggerStatusMap; this.defaultTimeFormat = defaultTimeFormat; - this.pageIndex = 0; + this.triggerList = []; + this.currentTriggersPage = []; // Load panel defaults // _.cloneDeep() need for prevent changing shared defaultSeverity. // Load object "by value" istead "by reference". _.defaults(this.panel, _.cloneDeep(panelDefaults)); - this.triggerList = []; - this.currentTriggersPage = []; - this.events.on('init-edit-mode', this.onInitEditMode.bind(this)); this.events.on('refresh', this.onRefresh.bind(this)); } - /** - * Override onInitMetricsPanelEditMode() method from MetricsPanelCtrl. - * We don't need metric editor from Metrics Panel. - */ onInitEditMode() { this.addEditorTab('Options', triggerPanelEditor, 2); } - onMetricsPanelRefresh() { - // ignore fetching data if another panel is in fullscreen - if (this.otherPanelInFullscreenMode()) { return; } - - this.refreshData(); - } - onRefresh() { // clear loading/error state delete this.error; From 0e1069da2756bb57d634526409291a5129b95a29 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 10 Feb 2017 16:31:57 +0300 Subject: [PATCH 07/10] Triggers Panel: allow to change font size, closes #351. --- dist/panel-triggers/editor.html | 11 + dist/panel-triggers/editor.js | 3 +- dist/panel-triggers/editor.js.map | 2 +- dist/panel-triggers/module.js | 3 +- dist/panel-triggers/module.js.map | 2 +- dist/test/components/config.js | 13 + .../add-metric-function.directive.js | 116 ++++ dist/test/datasource-zabbix/dataProcessor.js | 330 ++++++++++ dist/test/datasource-zabbix/datasource.js | 582 ++++++++++++++++++ .../metric-function-editor.directive.js | 246 ++++++++ .../test/datasource-zabbix/metricFunctions.js | 292 +++++++++ dist/test/datasource-zabbix/migrations.js | 48 ++ dist/test/datasource-zabbix/module.js | 36 ++ .../datasource-zabbix/query.controller.js | 378 ++++++++++++ .../test/datasource-zabbix/responseHandler.js | 116 ++++ .../specs/datasource_specs.js | 317 ++++++++++ .../specs/modules/datemath.js | 135 ++++ .../test/datasource-zabbix/specs/test-main.js | 66 ++ dist/test/datasource-zabbix/utils.js | 151 +++++ dist/test/datasource-zabbix/zabbix.js | 266 ++++++++ .../datasource-zabbix/zabbixAPI.service.js | 436 +++++++++++++ .../zabbixAPICore.service.js | 142 +++++ .../zabbixCachingProxy.service.js | 215 +++++++ dist/test/module.js | 10 + .../panel-triggers/ack-tooltip.directive.js | 122 ++++ dist/test/panel-triggers/editor.js | 224 +++++++ dist/test/panel-triggers/module.js | 407 ++++++++++++ src/panel-triggers/editor.html | 11 + src/panel-triggers/editor.js | 3 +- src/panel-triggers/module.js | 3 +- 30 files changed, 4678 insertions(+), 8 deletions(-) create mode 100644 dist/test/components/config.js create mode 100644 dist/test/datasource-zabbix/add-metric-function.directive.js create mode 100644 dist/test/datasource-zabbix/dataProcessor.js create mode 100644 dist/test/datasource-zabbix/datasource.js create mode 100644 dist/test/datasource-zabbix/metric-function-editor.directive.js create mode 100644 dist/test/datasource-zabbix/metricFunctions.js create mode 100644 dist/test/datasource-zabbix/migrations.js create mode 100644 dist/test/datasource-zabbix/module.js create mode 100644 dist/test/datasource-zabbix/query.controller.js create mode 100644 dist/test/datasource-zabbix/responseHandler.js create mode 100644 dist/test/datasource-zabbix/specs/datasource_specs.js create mode 100644 dist/test/datasource-zabbix/specs/modules/datemath.js create mode 100644 dist/test/datasource-zabbix/specs/test-main.js create mode 100644 dist/test/datasource-zabbix/utils.js create mode 100644 dist/test/datasource-zabbix/zabbix.js create mode 100644 dist/test/datasource-zabbix/zabbixAPI.service.js create mode 100644 dist/test/datasource-zabbix/zabbixAPICore.service.js create mode 100644 dist/test/datasource-zabbix/zabbixCachingProxy.service.js create mode 100644 dist/test/module.js create mode 100644 dist/test/panel-triggers/ack-tooltip.directive.js create mode 100644 dist/test/panel-triggers/editor.js create mode 100644 dist/test/panel-triggers/module.js diff --git a/dist/panel-triggers/editor.html b/dist/panel-triggers/editor.html index 39e96b8..b0510db 100644 --- a/dist/panel-triggers/editor.html +++ b/dist/panel-triggers/editor.html @@ -137,6 +137,17 @@ ng-change="editor.panelCtrl.refresh()">
                        +
                        +
                        + +
                        + +
                        +
                        +
                        diff --git a/dist/panel-triggers/editor.js b/dist/panel-triggers/editor.js index ea74521..8cf9d99 100644 --- a/dist/panel-triggers/editor.js +++ b/dist/panel-triggers/editor.js @@ -78,10 +78,9 @@ System.register(['lodash', '../datasource-zabbix/utils', '../datasource-zabbix/c return _this.onVariableChange(); }); + this.fontSizes = ['80%', '90%', '100%', '110%', '120%', '130%', '150%', '160%', '180%', '200%', '220%', '250%']; this.ackFilters = ['all triggers', 'unacknowledged', 'acknowledged']; - this.sortByFields = [{ text: 'last change', value: 'lastchange' }, { text: 'severity', value: 'priority' }]; - this.showEventsFields = [{ text: 'All', value: [0, 1] }, { text: 'OK', value: [0] }, { text: 'Problems', value: 1 }]; // Load scope defaults diff --git a/dist/panel-triggers/editor.js.map b/dist/panel-triggers/editor.js.map index d016fb8..f3f2d45 100644 --- a/dist/panel-triggers/editor.js.map +++ b/dist/panel-triggers/editor.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/panel-triggers/editor.js"],"names":["getMetricNames","scope","metricList","_","uniq","map","metric","triggerPanelEditor","restrict","templateUrl","controller","TriggerPanelEditorCtrl","utils","$scope","$rootScope","uiSegmentSrv","datasourceSrv","templateSrv","popoverSrv","editor","panelCtrl","ctrl","panel","getGroupNames","partial","getHostNames","getApplicationNames","$on","onVariableChange","ackFilters","sortByFields","text","value","showEventsFields","scopeDefaults","inputStyles","oldTarget","cloneDeep","triggers","defaults","datasources","getZabbixDataSources","datasource","get","then","zabbix","queryBuilder","initFilters","refresh","Promise","all","suggestGroups","suggestHosts","suggestApps","getAllGroups","groupList","groups","groupFilter","replaceTemplateVars","group","filter","getAllHosts","hostList","hosts","hostFilter","host","getAllApps","appList","apps","isContainsVariables","targetChanged","some","isTemplateVariable","field","variables","newTarget","isEqual","each","triggerList","trigger","color","triggerSeverity","priority","severity","refreshTriggerSeverity","str","isRegex","ZABBIX_DS_ID","getMetricSources","meta","id"],"mappings":"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","file":"editor.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 * as utils from '../datasource-zabbix/utils';\n\nimport '../datasource-zabbix/css/query-editor.css!';\n\nclass TriggerPanelEditorCtrl {\n\n /** @ngInject */\n constructor($scope, $rootScope, uiSegmentSrv, datasourceSrv, templateSrv, popoverSrv) {\n $scope.editor = this;\n this.panelCtrl = $scope.ctrl;\n this.panel = this.panelCtrl.panel;\n\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.popoverSrv = popoverSrv;\n\n // Map functions for bs-typeahead\n this.getGroupNames = _.partial(getMetricNames, this, 'groupList');\n this.getHostNames = _.partial(getMetricNames, this, 'hostList');\n this.getApplicationNames = _.partial(getMetricNames, this, 'appList');\n\n // Update metric suggestion when template variable was changed\n $rootScope.$on('template-variable-value-updated', () => this.onVariableChange());\n\n this.ackFilters = [\n 'all triggers',\n 'unacknowledged',\n 'acknowledged'\n ];\n\n this.sortByFields = [\n { text: 'last change', value: 'lastchange' },\n { text: 'severity', value: 'priority' }\n ];\n\n this.showEventsFields = [\n { text: 'All', value: [0,1] },\n { text: 'OK', value: [0] },\n { text: 'Problems', value: 1 }\n ];\n\n // Load scope defaults\n var scopeDefaults = {\n metric: {},\n inputStyles: {},\n oldTarget: _.cloneDeep(this.panel.triggers)\n };\n _.defaults(this, scopeDefaults);\n\n // Set default datasource\n this.datasources = _.map(this.getZabbixDataSources(), 'name');\n if (!this.panel.datasource) {\n this.panel.datasource = this.datasources[0];\n }\n // Load datasource\n this.datasourceSrv.get(this.panel.datasource)\n .then(datasource => {\n this.datasource = datasource;\n this.zabbix = datasource.zabbix;\n this.queryBuilder = datasource.queryBuilder;\n this.initFilters();\n this.panelCtrl.refresh();\n });\n }\n\n initFilters() {\n return Promise.all([\n this.suggestGroups(),\n this.suggestHosts(),\n this.suggestApps()\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.datasource.replaceTemplateVars(this.panel.triggers.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.datasource.replaceTemplateVars(this.panel.triggers.group.filter);\n let hostFilter = this.datasource.replaceTemplateVars(this.panel.triggers.host.filter);\n return this.zabbix.getAllApps(groupFilter, hostFilter)\n .then(apps => {\n this.metric.appList = apps;\n return apps;\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 return utils.isTemplateVariable(this.panel.triggers[field].filter, this.templateSrv.variables);\n });\n }\n\n targetChanged() {\n this.initFilters();\n this.panelCtrl.refresh();\n }\n\n parseTarget() {\n this.initFilters();\n var newTarget = _.cloneDeep(this.panel.triggers);\n if (!_.isEqual(this.oldTarget, this.panel.triggers)) {\n this.oldTarget = newTarget;\n this.panelCtrl.refresh();\n }\n }\n\n refreshTriggerSeverity() {\n _.each(this.triggerList, function(trigger) {\n trigger.color = this.panel.triggerSeverity[trigger.priority].color;\n trigger.severity = this.panel.triggerSeverity[trigger.priority].severity;\n });\n this.panelCtrl.refresh();\n }\n\n datasourceChanged() {\n this.panelCtrl.refresh();\n }\n\n changeTriggerSeverityColor(trigger, color) {\n this.panel.triggerSeverity[trigger.priority].color = color;\n this.refreshTriggerSeverity();\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 getZabbixDataSources() {\n let ZABBIX_DS_ID = 'alexanderzobnin-zabbix-datasource';\n return _.filter(this.datasourceSrv.getMetricSources(), datasource => {\n return datasource.meta.id === ZABBIX_DS_ID && datasource.value;\n });\n }\n}\n\n// Get list of metric names for bs-typeahead directive\nfunction getMetricNames(scope, metricList) {\n return _.uniq(_.map(scope.metric[metricList], 'name'));\n}\n\nexport function triggerPanelEditor() {\n return {\n restrict: 'E',\n scope: true,\n templateUrl: 'public/plugins/alexanderzobnin-zabbix-app/panel-triggers/editor.html',\n controller: TriggerPanelEditorCtrl,\n };\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/panel-triggers/editor.js"],"names":["getMetricNames","scope","metricList","_","uniq","map","metric","triggerPanelEditor","restrict","templateUrl","controller","TriggerPanelEditorCtrl","utils","$scope","$rootScope","uiSegmentSrv","datasourceSrv","templateSrv","popoverSrv","editor","panelCtrl","ctrl","panel","getGroupNames","partial","getHostNames","getApplicationNames","$on","onVariableChange","fontSizes","ackFilters","sortByFields","text","value","showEventsFields","scopeDefaults","inputStyles","oldTarget","cloneDeep","triggers","defaults","datasources","getZabbixDataSources","datasource","get","then","zabbix","queryBuilder","initFilters","refresh","Promise","all","suggestGroups","suggestHosts","suggestApps","getAllGroups","groupList","groups","groupFilter","replaceTemplateVars","group","filter","getAllHosts","hostList","hosts","hostFilter","host","getAllApps","appList","apps","isContainsVariables","targetChanged","some","isTemplateVariable","field","variables","newTarget","isEqual","each","triggerList","trigger","color","triggerSeverity","priority","severity","refreshTriggerSeverity","str","isRegex","ZABBIX_DS_ID","getMetricSources","meta","id"],"mappings":"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","file":"editor.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 * as utils from '../datasource-zabbix/utils';\n\nimport '../datasource-zabbix/css/query-editor.css!';\n\nclass TriggerPanelEditorCtrl {\n\n /** @ngInject */\n constructor($scope, $rootScope, uiSegmentSrv, datasourceSrv, templateSrv, popoverSrv) {\n $scope.editor = this;\n this.panelCtrl = $scope.ctrl;\n this.panel = this.panelCtrl.panel;\n\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.popoverSrv = popoverSrv;\n\n // Map functions for bs-typeahead\n this.getGroupNames = _.partial(getMetricNames, this, 'groupList');\n this.getHostNames = _.partial(getMetricNames, this, 'hostList');\n this.getApplicationNames = _.partial(getMetricNames, this, 'appList');\n\n // Update metric suggestion when template variable was changed\n $rootScope.$on('template-variable-value-updated', () => this.onVariableChange());\n\n this.fontSizes = ['80%', '90%', '100%', '110%', '120%', '130%', '150%', '160%', '180%', '200%', '220%', '250%'];\n this.ackFilters = [\n 'all triggers',\n 'unacknowledged',\n 'acknowledged'\n ];\n this.sortByFields = [\n { text: 'last change', value: 'lastchange' },\n { text: 'severity', value: 'priority' }\n ];\n this.showEventsFields = [\n { text: 'All', value: [0,1] },\n { text: 'OK', value: [0] },\n { text: 'Problems', value: 1 }\n ];\n\n // Load scope defaults\n var scopeDefaults = {\n metric: {},\n inputStyles: {},\n oldTarget: _.cloneDeep(this.panel.triggers)\n };\n _.defaults(this, scopeDefaults);\n\n // Set default datasource\n this.datasources = _.map(this.getZabbixDataSources(), 'name');\n if (!this.panel.datasource) {\n this.panel.datasource = this.datasources[0];\n }\n // Load datasource\n this.datasourceSrv.get(this.panel.datasource)\n .then(datasource => {\n this.datasource = datasource;\n this.zabbix = datasource.zabbix;\n this.queryBuilder = datasource.queryBuilder;\n this.initFilters();\n this.panelCtrl.refresh();\n });\n }\n\n initFilters() {\n return Promise.all([\n this.suggestGroups(),\n this.suggestHosts(),\n this.suggestApps()\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.datasource.replaceTemplateVars(this.panel.triggers.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.datasource.replaceTemplateVars(this.panel.triggers.group.filter);\n let hostFilter = this.datasource.replaceTemplateVars(this.panel.triggers.host.filter);\n return this.zabbix.getAllApps(groupFilter, hostFilter)\n .then(apps => {\n this.metric.appList = apps;\n return apps;\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 return utils.isTemplateVariable(this.panel.triggers[field].filter, this.templateSrv.variables);\n });\n }\n\n targetChanged() {\n this.initFilters();\n this.panelCtrl.refresh();\n }\n\n parseTarget() {\n this.initFilters();\n var newTarget = _.cloneDeep(this.panel.triggers);\n if (!_.isEqual(this.oldTarget, this.panel.triggers)) {\n this.oldTarget = newTarget;\n this.panelCtrl.refresh();\n }\n }\n\n refreshTriggerSeverity() {\n _.each(this.triggerList, function(trigger) {\n trigger.color = this.panel.triggerSeverity[trigger.priority].color;\n trigger.severity = this.panel.triggerSeverity[trigger.priority].severity;\n });\n this.panelCtrl.refresh();\n }\n\n datasourceChanged() {\n this.panelCtrl.refresh();\n }\n\n changeTriggerSeverityColor(trigger, color) {\n this.panel.triggerSeverity[trigger.priority].color = color;\n this.refreshTriggerSeverity();\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 getZabbixDataSources() {\n let ZABBIX_DS_ID = 'alexanderzobnin-zabbix-datasource';\n return _.filter(this.datasourceSrv.getMetricSources(), datasource => {\n return datasource.meta.id === ZABBIX_DS_ID && datasource.value;\n });\n }\n}\n\n// Get list of metric names for bs-typeahead directive\nfunction getMetricNames(scope, metricList) {\n return _.uniq(_.map(scope.metric[metricList], 'name'));\n}\n\nexport function triggerPanelEditor() {\n return {\n restrict: 'E',\n scope: true,\n templateUrl: 'public/plugins/alexanderzobnin-zabbix-app/panel-triggers/editor.html',\n controller: TriggerPanelEditorCtrl,\n };\n}\n"]} \ No newline at end of file diff --git a/dist/panel-triggers/module.js b/dist/panel-triggers/module.js index e3c079d..1742270 100644 --- a/dist/panel-triggers/module.js +++ b/dist/panel-triggers/module.js @@ -103,7 +103,8 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap okEventColor: 'rgba(0, 245, 153, 0.45)', ackEventColor: 'rgba(0, 0, 0, 0)', scroll: true, - pageSize: 10 + pageSize: 10, + fontSize: '100%' }; triggerStatusMap = { '0': 'OK', diff --git a/dist/panel-triggers/module.js.map b/dist/panel-triggers/module.js.map index 5b9cbc2..a78c48b 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","PanelCtrl","triggerPanelEditor","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","scroll","pageSize","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","pageIndex","triggerList","currentTriggersPage","defaults","panel","cloneDeep","events","on","onInitEditMode","bind","onRefresh","addEditorTab","error","loading","refreshData","then","slice","getCurrentTriggersPage","render","getTriggers","getAcknowledges","get","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","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","fontSize","addClass","unbindDestroy","$on","off","renderData","renderingCompleted","templateUrl"],"mappings":"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","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 * as utils from '../datasource-zabbix/utils';\nimport {PanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\nimport './css/panel_triggers.css!';\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 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};\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) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\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 // 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\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 var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents);\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","PanelCtrl","triggerPanelEditor","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","scroll","pageSize","fontSize","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","pageIndex","triggerList","currentTriggersPage","defaults","panel","cloneDeep","events","on","onInitEditMode","bind","onRefresh","addEditorTab","error","loading","refreshData","then","slice","getCurrentTriggersPage","render","getTriggers","getAcknowledges","get","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","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":"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","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 * as utils from '../datasource-zabbix/utils';\nimport {PanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\nimport './css/panel_triggers.css!';\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 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) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\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 // 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\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 var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents);\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 diff --git a/dist/test/components/config.js b/dist/test/components/config.js new file mode 100644 index 0000000..ad0987c --- /dev/null +++ b/dist/test/components/config.js @@ -0,0 +1,13 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var ZabbixAppConfigCtrl = exports.ZabbixAppConfigCtrl = function ZabbixAppConfigCtrl() { + _classCallCheck(this, ZabbixAppConfigCtrl); +}; + +ZabbixAppConfigCtrl.templateUrl = 'components/config.html'; diff --git a/dist/test/datasource-zabbix/add-metric-function.directive.js b/dist/test/datasource-zabbix/add-metric-function.directive.js new file mode 100644 index 0000000..26b55cc --- /dev/null +++ b/dist/test/datasource-zabbix/add-metric-function.directive.js @@ -0,0 +1,116 @@ +'use strict'; + +var _angular = require('angular'); + +var _angular2 = _interopRequireDefault(_angular); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _jquery = require('jquery'); + +var _jquery2 = _interopRequireDefault(_jquery); + +var _metricFunctions = require('./metricFunctions'); + +var metricFunctions = _interopRequireWildcard(_metricFunctions); + +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 }; } + +/** @ngInject */ +_angular2.default.module('grafana.directives').directive('addMetricFunction', function ($compile) { + var inputTemplate = ''; + + var buttonTemplate = '' + ''; + + return { + link: function link($scope, elem) { + var categories = metricFunctions.getCategories(); + var allFunctions = getAllFunctionNames(categories); + + $scope.functionMenu = createFunctionDropDownMenu(categories); + + var $input = (0, _jquery2.default)(inputTemplate); + var $button = (0, _jquery2.default)(buttonTemplate); + $input.appendTo(elem); + $button.appendTo(elem); + + $input.attr('data-provide', 'typeahead'); + $input.typeahead({ + source: allFunctions, + minLength: 1, + items: 10, + updater: function updater(value) { + var funcDef = metricFunctions.getFuncDef(value); + if (!funcDef) { + // try find close match + value = value.toLowerCase(); + funcDef = _lodash2.default.find(allFunctions, function (funcName) { + return funcName.toLowerCase().indexOf(value) === 0; + }); + + if (!funcDef) { + return; + } + } + + $scope.$apply(function () { + $scope.addFunction(funcDef); + }); + + $input.trigger('blur'); + return ''; + } + }); + + $button.click(function () { + $button.hide(); + $input.show(); + $input.focus(); + }); + + $input.keyup(function () { + elem.toggleClass('open', $input.val() === ''); + }); + + $input.blur(function () { + // clicking the function dropdown menu wont + // work if you remove class at once + setTimeout(function () { + $input.val(''); + $input.hide(); + $button.show(); + elem.removeClass('open'); + }, 200); + }); + + $compile(elem.contents())($scope); + } + }; +}); + +function getAllFunctionNames(categories) { + return _lodash2.default.reduce(categories, function (list, category) { + _lodash2.default.each(category, function (func) { + list.push(func.name); + }); + return list; + }, []); +} + +function createFunctionDropDownMenu(categories) { + return _lodash2.default.map(categories, function (list, category) { + return { + text: category, + submenu: _lodash2.default.map(list, function (value) { + return { + text: value.name, + click: "ctrl.addFunction('" + value.name + "')" + }; + }) + }; + }); +} diff --git a/dist/test/datasource-zabbix/dataProcessor.js b/dist/test/datasource-zabbix/dataProcessor.js new file mode 100644 index 0000000..2ce1585 --- /dev/null +++ b/dist/test/datasource-zabbix/dataProcessor.js @@ -0,0 +1,330 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _utils = require('./utils'); + +var utils = _interopRequireWildcard(_utils); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Downsample datapoints series + */ +function downsampleSeries(datapoints, time_to, ms_interval, func) { + var downsampledSeries = []; + var timeWindow = { + from: time_to * 1000 - ms_interval, + to: time_to * 1000 + }; + + var points_sum = 0; + var points_num = 0; + var value_avg = 0; + var frame = []; + + for (var i = datapoints.length - 1; i >= 0; i -= 1) { + if (timeWindow.from < datapoints[i][1] && datapoints[i][1] <= timeWindow.to) { + points_sum += datapoints[i][0]; + points_num++; + frame.push(datapoints[i][0]); + } else { + value_avg = points_num ? points_sum / points_num : 0; + + if (func === "max") { + downsampledSeries.push([_lodash2.default.max(frame), timeWindow.to]); + } else if (func === "min") { + downsampledSeries.push([_lodash2.default.min(frame), timeWindow.to]); + } + + // avg by default + else { + downsampledSeries.push([value_avg, timeWindow.to]); + } + + // Shift time window + timeWindow.to = timeWindow.from; + timeWindow.from -= ms_interval; + + points_sum = 0; + points_num = 0; + frame = []; + + // Process point again + i++; + } + } + return downsampledSeries.reverse(); +} + +/** + * Group points by given time interval + * datapoints: [[, ], ...] + */ +function groupBy(interval, groupByCallback, datapoints) { + var ms_interval = utils.parseInterval(interval); + + // Calculate frame timestamps + var frames = _lodash2.default.groupBy(datapoints, function (point) { + // Calculate time for group of points + return Math.floor(point[1] / ms_interval) * ms_interval; + }); + + // frame: { '': [[, ], ...] } + // return [{ '': }, { '': }, ...] + var grouped = _lodash2.default.mapValues(frames, function (frame) { + var points = _lodash2.default.map(frame, function (point) { + return point[0]; + }); + return groupByCallback(points); + }); + + // Convert points to Grafana format + return sortByTime(_lodash2.default.map(grouped, function (value, timestamp) { + return [Number(value), Number(timestamp)]; + })); +} + +function sumSeries(timeseries) { + + // Calculate new points for interpolation + var new_timestamps = _lodash2.default.uniq(_lodash2.default.map(_lodash2.default.flatten(timeseries, true), function (point) { + return point[1]; + })); + new_timestamps = _lodash2.default.sortBy(new_timestamps); + + var interpolated_timeseries = _lodash2.default.map(timeseries, function (series) { + var timestamps = _lodash2.default.map(series, function (point) { + return point[1]; + }); + var new_points = _lodash2.default.map(_lodash2.default.difference(new_timestamps, timestamps), function (timestamp) { + return [null, timestamp]; + }); + var new_series = series.concat(new_points); + return sortByTime(new_series); + }); + + _lodash2.default.each(interpolated_timeseries, interpolateSeries); + + var new_timeseries = []; + var sum; + for (var i = new_timestamps.length - 1; i >= 0; i--) { + sum = 0; + for (var j = interpolated_timeseries.length - 1; j >= 0; j--) { + sum += interpolated_timeseries[j][i][0]; + } + new_timeseries.push([sum, new_timestamps[i]]); + } + + return sortByTime(new_timeseries); +} + +function limit(order, n, orderByFunc, timeseries) { + var orderByCallback = aggregationFunctions[orderByFunc]; + var sortByIteratee = function sortByIteratee(ts) { + var values = _lodash2.default.map(ts.datapoints, function (point) { + return point[0]; + }); + return orderByCallback(values); + }; + var sortedTimeseries = _lodash2.default.sortBy(timeseries, sortByIteratee); + if (order === 'bottom') { + return sortedTimeseries.slice(0, n); + } else { + return sortedTimeseries.slice(-n); + } +} + +function AVERAGE(values) { + var sum = 0; + _lodash2.default.each(values, function (value) { + sum += value; + }); + return sum / values.length; +} + +function MIN(values) { + return _lodash2.default.min(values); +} + +function MAX(values) { + return _lodash2.default.max(values); +} + +function MEDIAN(values) { + var sorted = _lodash2.default.sortBy(values); + return sorted[Math.floor(sorted.length / 2)]; +} + +function setAlias(alias, timeseries) { + timeseries.target = alias; + return timeseries; +} + +function setAliasByRegex(alias, timeseries) { + timeseries.target = extractText(timeseries.target, alias); + return timeseries; +} + +function extractText(str, pattern) { + var extractPattern = new RegExp(pattern); + var extractedValue = extractPattern.exec(str); + extractedValue = extractedValue[0]; + return extractedValue; +} + +function scale(factor, datapoints) { + return _lodash2.default.map(datapoints, function (point) { + return [point[0] * factor, point[1]]; + }); +} + +function delta(datapoints) { + var newSeries = []; + var deltaValue = void 0; + for (var i = 1; i < datapoints.length; i++) { + deltaValue = datapoints[i][0] - datapoints[i - 1][0]; + newSeries.push([deltaValue, datapoints[i][1]]); + } + return newSeries; +} + +function groupByWrapper(interval, groupFunc, datapoints) { + var groupByCallback = aggregationFunctions[groupFunc]; + return groupBy(interval, groupByCallback, datapoints); +} + +function aggregateByWrapper(interval, aggregateFunc, datapoints) { + // Flatten all points in frame and then just use groupBy() + var flattenedPoints = _lodash2.default.flatten(datapoints, true); + var groupByCallback = aggregationFunctions[aggregateFunc]; + return groupBy(interval, groupByCallback, flattenedPoints); +} + +function aggregateWrapper(groupByCallback, interval, datapoints) { + var flattenedPoints = _lodash2.default.flatten(datapoints, true); + return groupBy(interval, groupByCallback, flattenedPoints); +} + +function sortByTime(series) { + return _lodash2.default.sortBy(series, function (point) { + return point[1]; + }); +} + +/** + * Interpolate series with gaps + */ +function interpolateSeries(series) { + var left, right; + + // Interpolate series + for (var i = series.length - 1; i >= 0; i--) { + if (!series[i][0]) { + left = findNearestLeft(series, series[i]); + right = findNearestRight(series, series[i]); + if (!left) { + left = right; + } + if (!right) { + right = left; + } + series[i][0] = linearInterpolation(series[i][1], left, right); + } + } + return series; +} + +function linearInterpolation(timestamp, left, right) { + if (left[1] === right[1]) { + return (left[0] + right[0]) / 2; + } else { + return left[0] + (right[0] - left[0]) / (right[1] - left[1]) * (timestamp - left[1]); + } +} + +function findNearestRight(series, point) { + var point_index = _lodash2.default.indexOf(series, point); + var nearestRight; + for (var i = point_index; i < series.length; i++) { + if (series[i][0] !== null) { + return series[i]; + } + } + return nearestRight; +} + +function findNearestLeft(series, point) { + var point_index = _lodash2.default.indexOf(series, point); + var nearestLeft; + for (var i = point_index; i > 0; i--) { + if (series[i][0] !== null) { + return series[i]; + } + } + return nearestLeft; +} + +function timeShift(interval, range) { + var shift = utils.parseTimeShiftInterval(interval) / 1000; + return range.map(function (time) { + return time - shift; + }); +} + +function unShiftTimeSeries(interval, datapoints) { + var unshift = utils.parseTimeShiftInterval(interval); + return datapoints.map(function (dp) { + return [dp[0], dp[1] + unshift]; + }); +} + +var metricFunctions = { + groupBy: groupByWrapper, + scale: scale, + delta: delta, + aggregateBy: aggregateByWrapper, + average: _lodash2.default.partial(aggregateWrapper, AVERAGE), + min: _lodash2.default.partial(aggregateWrapper, MIN), + max: _lodash2.default.partial(aggregateWrapper, MAX), + median: _lodash2.default.partial(aggregateWrapper, MEDIAN), + sumSeries: sumSeries, + top: _lodash2.default.partial(limit, 'top'), + bottom: _lodash2.default.partial(limit, 'bottom'), + timeShift: timeShift, + setAlias: setAlias, + setAliasByRegex: setAliasByRegex +}; + +var aggregationFunctions = { + avg: AVERAGE, + min: MIN, + max: MAX, + median: MEDIAN +}; + +exports.default = { + downsampleSeries: downsampleSeries, + groupBy: groupBy, + AVERAGE: AVERAGE, + MIN: MIN, + MAX: MAX, + MEDIAN: MEDIAN, + unShiftTimeSeries: unShiftTimeSeries, + + get aggregationFunctions() { + return aggregationFunctions; + }, + + get metricFunctions() { + return metricFunctions; + } +}; diff --git a/dist/test/datasource-zabbix/datasource.js b/dist/test/datasource-zabbix/datasource.js new file mode 100644 index 0000000..2ecc64a --- /dev/null +++ b/dist/test/datasource-zabbix/datasource.js @@ -0,0 +1,582 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.zabbixTemplateFormat = exports.ZabbixAPIDatasource = undefined; + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +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; }; }(); //import angular from 'angular'; + + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _datemath = require('app/core/utils/datemath'); + +var dateMath = _interopRequireWildcard(_datemath); + +var _utils = require('./utils'); + +var utils = _interopRequireWildcard(_utils); + +var _migrations = require('./migrations'); + +var migrations = _interopRequireWildcard(_migrations); + +var _metricFunctions = require('./metricFunctions'); + +var metricFunctions = _interopRequireWildcard(_metricFunctions); + +var _dataProcessor = require('./dataProcessor'); + +var _dataProcessor2 = _interopRequireDefault(_dataProcessor); + +var _responseHandler = require('./responseHandler'); + +var _responseHandler2 = _interopRequireDefault(_responseHandler); + +require('./zabbix.js'); + +var _zabbixAPICoreService = require('./zabbixAPICore.service.js'); + +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 }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var ZabbixAPIDatasource = function () { + + /** @ngInject */ + function ZabbixAPIDatasource(instanceSettings, templateSrv, alertSrv, Zabbix) { + _classCallCheck(this, ZabbixAPIDatasource); + + this.templateSrv = templateSrv; + this.alertSrv = alertSrv; + + // General data source settings + this.name = instanceSettings.name; + this.url = instanceSettings.url; + this.basicAuth = instanceSettings.basicAuth; + this.withCredentials = instanceSettings.withCredentials; + + // Zabbix API credentials + this.username = instanceSettings.jsonData.username; + this.password = instanceSettings.jsonData.password; + + // Use trends instead history since specified time + this.trends = instanceSettings.jsonData.trends; + this.trendsFrom = instanceSettings.jsonData.trendsFrom || '7d'; + + // Set cache update interval + var ttl = instanceSettings.jsonData.cacheTTL || '1h'; + this.cacheTTL = utils.parseInterval(ttl); + + this.zabbix = new Zabbix(this.url, this.username, this.password, this.basicAuth, this.withCredentials, this.cacheTTL); + + // Use custom format for template variables + this.replaceTemplateVars = _lodash2.default.partial(replaceTemplateVars, this.templateSrv); + } + + //////////////////////// + // Datasource methods // + //////////////////////// + + /** + * Query panel data. Calls for each panel in dashboard. + * @param {Object} options Contains time range, targets and other info. + * @return {Object} Grafana metrics object with timeseries data for each target. + */ + + + _createClass(ZabbixAPIDatasource, [{ + key: 'query', + value: function query(options) { + var _this = this; + + var timeFrom = Math.ceil(dateMath.parse(options.range.from) / 1000); + var timeTo = Math.ceil(dateMath.parse(options.range.to) / 1000); + + var useTrendsFrom = Math.ceil(dateMath.parse('now-' + this.trendsFrom) / 1000); + var useTrends = timeFrom <= useTrendsFrom && this.trends; + + // Create request for each target + var promises = _lodash2.default.map(options.targets, function (target) { + // Prevent changes of original object + target = _lodash2.default.cloneDeep(target); + _this.replaceTargetVariables(target, options); + + // Apply Time-related functions (timeShift(), etc) + var timeFunctions = bindFunctionDefs(target.functions, 'Time'); + if (timeFunctions.length) { + var _sequence = sequence(timeFunctions)([timeFrom, timeTo]), + _sequence2 = _slicedToArray(_sequence, 2), + time_from = _sequence2[0], + time_to = _sequence2[1]; + + timeFrom = time_from; + timeTo = time_to; + } + + // Metrics or Text query mode + if (target.mode !== 1) { + // Migrate old targets + target = migrations.migrate(target); + + // Don't request undefined and hidden targets + if (target.hide || !target.group || !target.host || !target.item) { + return []; + } + + if (!target.mode || target.mode === 0) { + return _this.queryNumericData(target, timeFrom, timeTo, useTrends); + } else if (target.mode === 2) { + return _this.queryTextData(target, timeFrom, timeTo); + } + } + + // IT services mode + else if (target.mode === 1) { + // Don't show undefined and hidden targets + if (target.hide || !target.itservice || !target.slaProperty) { + return []; + } + + return _this.zabbix.getSLA(target.itservice.serviceid, timeFrom, timeTo).then(function (slaObject) { + return _responseHandler2.default.handleSLAResponse(target.itservice, target.slaProperty, slaObject); + }); + } + }); + + // Data for panel (all targets) + return Promise.all(_lodash2.default.flatten(promises)).then(_lodash2.default.flatten).then(function (timeseries_data) { + return downsampleSeries(timeseries_data, options); + }).then(function (data) { + return { data: data }; + }); + } + }, { + key: 'queryNumericData', + value: function queryNumericData(target, timeFrom, timeTo, useTrends) { + var _this2 = this; + + var options = { + itemtype: 'num' + }; + return this.zabbix.getItemsFromTarget(target, options).then(function (items) { + var getHistoryPromise = void 0; + + if (useTrends) { + (function () { + var valueType = _this2.getTrendValueType(target); + getHistoryPromise = _this2.zabbix.getTrend(items, timeFrom, timeTo).then(function (history) { + return _responseHandler2.default.handleTrends(history, items, valueType); + }); + })(); + } else { + // Use history + getHistoryPromise = _this2.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) { + return _responseHandler2.default.handleHistory(history, items); + }); + } + + return getHistoryPromise.then(function (timeseries_data) { + return _this2.applyDataProcessingFunctions(timeseries_data, target); + }); + }); + } + }, { + key: 'getTrendValueType', + value: function getTrendValueType(target) { + // Find trendValue() function and get specified trend value + var trendFunctions = _lodash2.default.map(metricFunctions.getCategories()['Trends'], 'name'); + var trendValueFunc = _lodash2.default.find(target.functions, function (func) { + return _lodash2.default.includes(trendFunctions, func.def.name); + }); + return trendValueFunc ? trendValueFunc.params[0] : "avg"; + } + }, { + key: 'applyDataProcessingFunctions', + value: function applyDataProcessingFunctions(timeseries_data, target) { + var transformFunctions = bindFunctionDefs(target.functions, 'Transform'); + var aggregationFunctions = bindFunctionDefs(target.functions, 'Aggregate'); + var filterFunctions = bindFunctionDefs(target.functions, 'Filter'); + var aliasFunctions = bindFunctionDefs(target.functions, 'Alias'); + + // Apply transformation functions + timeseries_data = _lodash2.default.map(timeseries_data, function (timeseries) { + timeseries.datapoints = sequence(transformFunctions)(timeseries.datapoints); + return timeseries; + }); + + // Apply filter functions + if (filterFunctions.length) { + timeseries_data = sequence(filterFunctions)(timeseries_data); + } + + // Apply aggregations + if (aggregationFunctions.length) { + (function () { + var dp = _lodash2.default.map(timeseries_data, 'datapoints'); + dp = sequence(aggregationFunctions)(dp); + + var aggFuncNames = _lodash2.default.map(metricFunctions.getCategories()['Aggregate'], 'name'); + var lastAgg = _lodash2.default.findLast(target.functions, function (func) { + return _lodash2.default.includes(aggFuncNames, func.def.name); + }); + + timeseries_data = [{ + target: lastAgg.text, + datapoints: dp + }]; + })(); + } + + // Apply alias functions + _lodash2.default.forEach(timeseries_data, sequence(aliasFunctions)); + + // Apply Time-related functions (timeShift(), etc) + // Find timeShift() function and get specified trend value + this.applyTimeShiftFunction(timeseries_data, target); + + return timeseries_data; + } + }, { + key: 'applyTimeShiftFunction', + value: function applyTimeShiftFunction(timeseries_data, target) { + // Find timeShift() function and get specified interval + var timeShiftFunc = _lodash2.default.find(target.functions, function (func) { + return func.def.name === 'timeShift'; + }); + if (timeShiftFunc) { + (function () { + var shift = timeShiftFunc.params[0]; + _lodash2.default.forEach(timeseries_data, function (series) { + series.datapoints = _dataProcessor2.default.unShiftTimeSeries(shift, series.datapoints); + }); + })(); + } + } + }, { + key: 'queryTextData', + value: function queryTextData(target, timeFrom, timeTo) { + var _this3 = this; + + var options = { + itemtype: 'text' + }; + return this.zabbix.getItemsFromTarget(target, options).then(function (items) { + if (items.length) { + return _this3.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) { + return _responseHandler2.default.convertHistory(history, items, false, function (point) { + var value = point.value; + + // Regex-based extractor + if (target.textFilter) { + value = extractText(point.value, target.textFilter, target.useCaptureGroups); + } + + return [value, point.clock * 1000]; + }); + }); + } else { + return Promise.resolve([]); + } + }); + } + + /** + * Test connection to Zabbix API + * @return {object} Connection status and Zabbix API version + */ + + }, { + key: 'testDatasource', + value: function testDatasource() { + var _this4 = this; + + var zabbixVersion = void 0; + return this.zabbix.getVersion().then(function (version) { + zabbixVersion = version; + return _this4.zabbix.login(); + }).then(function () { + return { + status: "success", + title: "Success", + message: "Zabbix API version: " + zabbixVersion + }; + }).catch(function (error) { + if (error instanceof _zabbixAPICoreService.ZabbixAPIError) { + return { + status: "error", + title: error.message, + message: error.data + }; + } else { + return { + status: "error", + title: "Connection failed", + message: "Could not connect to given url" + }; + } + }); + } + + //////////////// + // Templating // + //////////////// + + /** + * Find metrics from templated request. + * + * @param {string} query Query from Templating + * @return {string} Metric name - group, host, app or item or list + * of metrics in "{metric1,metcic2,...,metricN}" format. + */ + + }, { + key: 'metricFindQuery', + value: function metricFindQuery(query) { + var _this5 = this; + + var result = void 0; + var parts = []; + + // Split query. Query structure: group.host.app.item + _lodash2.default.each(query.split('.'), function (part) { + part = _this5.replaceTemplateVars(part, {}); + + // Replace wildcard to regex + if (part === '*') { + part = '/.*/'; + } + parts.push(part); + }); + var template = _lodash2.default.zipObject(['group', 'host', 'app', 'item'], parts); + + // Get items + if (parts.length === 4) { + // Search for all items, even it's not belong to any application + if (template.app === '/.*/') { + template.app = ''; + } + result = this.zabbix.getItems(template.group, template.host, template.app, template.item); + } else if (parts.length === 3) { + // Get applications + result = this.zabbix.getApps(template.group, template.host, template.app); + } else if (parts.length === 2) { + // Get hosts + result = this.zabbix.getHosts(template.group, template.host); + } else if (parts.length === 1) { + // Get groups + result = this.zabbix.getGroups(template.group); + } else { + result = Promise.resolve([]); + } + + return result.then(function (metrics) { + return metrics.map(formatMetric); + }); + } + + ///////////////// + // Annotations // + ///////////////// + + }, { + key: 'annotationQuery', + value: function annotationQuery(options) { + var _this6 = this; + + var timeFrom = Math.ceil(dateMath.parse(options.rangeRaw.from) / 1000); + var timeTo = Math.ceil(dateMath.parse(options.rangeRaw.to) / 1000); + var annotation = options.annotation; + var showOkEvents = annotation.showOkEvents ? [0, 1] : 1; + + // Show all triggers + var showTriggers = [0, 1]; + + var getTriggers = this.zabbix.getTriggers(this.replaceTemplateVars(annotation.group, {}), this.replaceTemplateVars(annotation.host, {}), this.replaceTemplateVars(annotation.application, {}), showTriggers); + + return getTriggers.then(function (triggers) { + + // Filter triggers by description + if (utils.isRegex(annotation.trigger)) { + triggers = _lodash2.default.filter(triggers, function (trigger) { + return utils.buildRegex(annotation.trigger).test(trigger.description); + }); + } else if (annotation.trigger) { + triggers = _lodash2.default.filter(triggers, function (trigger) { + return trigger.description === annotation.trigger; + }); + } + + // Remove events below the chose severity + triggers = _lodash2.default.filter(triggers, function (trigger) { + return Number(trigger.priority) >= Number(annotation.minseverity); + }); + + var objectids = _lodash2.default.map(triggers, 'triggerid'); + return _this6.zabbix.getEvents(objectids, timeFrom, timeTo, showOkEvents).then(function (events) { + var indexedTriggers = _lodash2.default.keyBy(triggers, 'triggerid'); + + // Hide acknowledged events if option enabled + if (annotation.hideAcknowledged) { + events = _lodash2.default.filter(events, function (event) { + return !event.acknowledges.length; + }); + } + + return _lodash2.default.map(events, function (event) { + var tags = void 0; + if (annotation.showHostname) { + tags = _lodash2.default.map(event.hosts, 'name'); + } + + // Show event type (OK or Problem) + var title = Number(event.value) ? 'Problem' : 'OK'; + + var formatted_acknowledges = utils.formatAcknowledges(event.acknowledges); + return { + annotation: annotation, + time: event.clock * 1000, + title: title, + tags: tags, + text: indexedTriggers[event.objectid].description + formatted_acknowledges + }; + }); + }); + }); + } + + // Replace template variables + + }, { + key: 'replaceTargetVariables', + value: function replaceTargetVariables(target, options) { + var _this7 = this; + + var parts = ['group', 'host', 'application', 'item']; + parts.forEach(function (p) { + if (target[p] && target[p].filter) { + target[p].filter = _this7.replaceTemplateVars(target[p].filter, options.scopedVars); + } + }); + target.textFilter = this.replaceTemplateVars(target.textFilter, options.scopedVars); + + _lodash2.default.forEach(target.functions, function (func) { + func.params = func.params.map(function (param) { + if (typeof param === 'number') { + return +_this7.templateSrv.replace(param.toString(), options.scopedVars); + } else { + return _this7.templateSrv.replace(param, options.scopedVars); + } + }); + }); + } + }]); + + return ZabbixAPIDatasource; +}(); + +function bindFunctionDefs(functionDefs, category) { + var aggregationFunctions = _lodash2.default.map(metricFunctions.getCategories()[category], 'name'); + var aggFuncDefs = _lodash2.default.filter(functionDefs, function (func) { + return _lodash2.default.includes(aggregationFunctions, func.def.name); + }); + + return _lodash2.default.map(aggFuncDefs, function (func) { + var funcInstance = metricFunctions.createFuncInstance(func.def, func.params); + return funcInstance.bindFunction(_dataProcessor2.default.metricFunctions); + }); +} + +function downsampleSeries(timeseries_data, options) { + 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); + } + return timeseries; + }); +} + +function formatMetric(metricObj) { + return { + text: metricObj.name, + expandable: false + }; +} + +/** + * Custom formatter for template variables. + * Default Grafana "regex" formatter returns + * value1|value2 + * This formatter returns + * (value1|value2) + * This format needed for using in complex regex with + * template variables, for example + * /CPU $cpu_item.*time/ where $cpu_item is system,user,iowait + */ +function zabbixTemplateFormat(value) { + if (typeof value === 'string') { + return utils.escapeRegex(value); + } + + var escapedValues = _lodash2.default.map(value, utils.escapeRegex); + return '(' + escapedValues.join('|') + ')'; +} + +/** + * If template variables are used in request, replace it using regex format + * and wrap with '/' for proper multi-value work. Example: + * $variable selected as a, b, c + * We use filter $variable + * $variable -> a|b|c -> /a|b|c/ + * /$variable/ -> /a|b|c/ -> /a|b|c/ + */ +function replaceTemplateVars(templateSrv, target, scopedVars) { + var replacedTarget = templateSrv.replace(target, scopedVars, zabbixTemplateFormat); + if (target !== replacedTarget && !utils.isRegex(replacedTarget)) { + replacedTarget = '/^' + replacedTarget + '$/'; + } + return replacedTarget; +} + +function extractText(str, pattern, useCaptureGroups) { + var extractPattern = new RegExp(pattern); + var extractedValue = extractPattern.exec(str); + if (extractedValue) { + if (useCaptureGroups) { + extractedValue = extractedValue[1]; + } else { + extractedValue = extractedValue[0]; + } + } + return extractedValue; +} + +// Apply function one by one: +// sequence([a(), b(), c()]) = c(b(a())); +function sequence(funcsArray) { + return function (result) { + for (var i = 0; i < funcsArray.length; i++) { + result = funcsArray[i].call(this, result); + } + return result; + }; +} + +exports.ZabbixAPIDatasource = ZabbixAPIDatasource; +exports.zabbixTemplateFormat = zabbixTemplateFormat; + +// Fix for backward compatibility with lodash 2.4 + +if (!_lodash2.default.includes) { + _lodash2.default.includes = _lodash2.default.contains; +} +if (!_lodash2.default.keyBy) { + _lodash2.default.keyBy = _lodash2.default.indexBy; +} diff --git a/dist/test/datasource-zabbix/metric-function-editor.directive.js b/dist/test/datasource-zabbix/metric-function-editor.directive.js new file mode 100644 index 0000000..02135e9 --- /dev/null +++ b/dist/test/datasource-zabbix/metric-function-editor.directive.js @@ -0,0 +1,246 @@ +'use strict'; + +var _angular = require('angular'); + +var _angular2 = _interopRequireDefault(_angular); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _jquery = require('jquery'); + +var _jquery2 = _interopRequireDefault(_jquery); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** @ngInject */ +_angular2.default.module('grafana.directives').directive('metricFunctionEditor', function ($compile, templateSrv) { + + var funcSpanTemplate = '{{func.def.name}}('; + var paramTemplate = ''; + + var funcControlsTemplate = '
                            ' + '' + '' + '' + '' + '
                            '; + + return { + restrict: 'A', + link: function postLink($scope, elem) { + var $funcLink = (0, _jquery2.default)(funcSpanTemplate); + var $funcControls = (0, _jquery2.default)(funcControlsTemplate); + var ctrl = $scope.ctrl; + var func = $scope.func; + var funcDef = func.def; + var scheduledRelink = false; + var paramCountAtLink = 0; + + function clickFuncParam(paramIndex) { + /*jshint validthis:true */ + + var $link = (0, _jquery2.default)(this); + var $input = $link.next(); + + $input.val(func.params[paramIndex]); + $input.css('width', $link.width() + 16 + 'px'); + + $link.hide(); + $input.show(); + $input.focus(); + $input.select(); + + var typeahead = $input.data('typeahead'); + if (typeahead) { + $input.val(''); + typeahead.lookup(); + } + } + + function scheduledRelinkIfNeeded() { + if (paramCountAtLink === func.params.length) { + return; + } + + if (!scheduledRelink) { + scheduledRelink = true; + setTimeout(function () { + relink(); + scheduledRelink = false; + }, 200); + } + } + + function inputBlur(paramIndex) { + /*jshint validthis:true */ + var $input = (0, _jquery2.default)(this); + var $link = $input.prev(); + var newValue = $input.val(); + + if (newValue !== '' || func.def.params[paramIndex].optional) { + $link.html(templateSrv.highlightVariablesAsHtml(newValue)); + + func.updateParam($input.val(), paramIndex); + scheduledRelinkIfNeeded(); + + $scope.$apply(function () { + ctrl.targetChanged(); + }); + + $input.hide(); + $link.show(); + } + } + + function inputKeyPress(paramIndex, e) { + /*jshint validthis:true */ + if (e.which === 13) { + inputBlur.call(this, paramIndex); + } + } + + function inputKeyDown() { + /*jshint validthis:true */ + this.style.width = (3 + this.value.length) * 8 + 'px'; + } + + function addTypeahead($input, paramIndex) { + $input.attr('data-provide', 'typeahead'); + + var options = funcDef.params[paramIndex].options; + if (funcDef.params[paramIndex].type === 'int' || funcDef.params[paramIndex].type === 'float') { + options = _lodash2.default.map(options, function (val) { + return val.toString(); + }); + } + + $input.typeahead({ + source: options, + minLength: 0, + items: 20, + updater: function updater(value) { + setTimeout(function () { + inputBlur.call($input[0], paramIndex); + }, 0); + return value; + } + }); + + var typeahead = $input.data('typeahead'); + typeahead.lookup = function () { + this.query = this.$element.val() || ''; + return this.process(this.source); + }; + } + + function toggleFuncControls() { + var targetDiv = elem.closest('.tight-form'); + + if (elem.hasClass('show-function-controls')) { + elem.removeClass('show-function-controls'); + targetDiv.removeClass('has-open-function'); + $funcControls.hide(); + return; + } + + elem.addClass('show-function-controls'); + targetDiv.addClass('has-open-function'); + + $funcControls.show(); + } + + function addElementsAndCompile() { + $funcControls.appendTo(elem); + $funcLink.appendTo(elem); + + _lodash2.default.each(funcDef.params, function (param, index) { + if (param.optional && func.params.length <= index) { + return; + } + + if (index > 0) { + (0, _jquery2.default)(', ').appendTo(elem); + } + + var paramValue = templateSrv.highlightVariablesAsHtml(func.params[index]); + var $paramLink = (0, _jquery2.default)('' + paramValue + ''); + var $input = (0, _jquery2.default)(paramTemplate); + + paramCountAtLink++; + + $paramLink.appendTo(elem); + $input.appendTo(elem); + + $input.blur(_lodash2.default.partial(inputBlur, index)); + $input.keyup(inputKeyDown); + $input.keypress(_lodash2.default.partial(inputKeyPress, index)); + $paramLink.click(_lodash2.default.partial(clickFuncParam, index)); + + if (funcDef.params[index].options) { + addTypeahead($input, index); + } + }); + + (0, _jquery2.default)(')').appendTo(elem); + + $compile(elem.contents())($scope); + } + + function ifJustAddedFocusFistParam() { + if ($scope.func.added) { + $scope.func.added = false; + setTimeout(function () { + elem.find('.graphite-func-param-link').first().click(); + }, 10); + } + } + + function registerFuncControlsToggle() { + $funcLink.click(toggleFuncControls); + } + + function registerFuncControlsActions() { + $funcControls.click(function (e) { + var $target = (0, _jquery2.default)(e.target); + if ($target.hasClass('fa-remove')) { + toggleFuncControls(); + $scope.$apply(function () { + ctrl.removeFunction($scope.func); + }); + return; + } + + if ($target.hasClass('fa-arrow-left')) { + $scope.$apply(function () { + _lodash2.default.move($scope.target.functions, $scope.$index, $scope.$index - 1); + ctrl.targetChanged(); + }); + return; + } + + if ($target.hasClass('fa-arrow-right')) { + $scope.$apply(function () { + _lodash2.default.move($scope.target.functions, $scope.$index, $scope.$index + 1); + ctrl.targetChanged(); + }); + return; + } + + if ($target.hasClass('fa-question-circle')) { + var docSite = "http://docs.grafana-zabbix.org/reference/functions/"; + window.open(docSite + '#' + funcDef.name.toLowerCase(), '_blank'); + return; + } + }); + } + + function relink() { + elem.children().remove(); + + addElementsAndCompile(); + ifJustAddedFocusFistParam(); + registerFuncControlsToggle(); + registerFuncControlsActions(); + } + + relink(); + } + }; +}); diff --git a/dist/test/datasource-zabbix/metricFunctions.js b/dist/test/datasource-zabbix/metricFunctions.js new file mode 100644 index 0000000..1a54a57 --- /dev/null +++ b/dist/test/datasource-zabbix/metricFunctions.js @@ -0,0 +1,292 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +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; }; }(); + +exports.createFuncInstance = createFuncInstance; +exports.getFuncDef = getFuncDef; +exports.getCategories = getCategories; + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _jquery = require('jquery'); + +var _jquery2 = _interopRequireDefault(_jquery); + +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 index = []; +var categories = { + Transform: [], + Aggregate: [], + Filter: [], + Trends: [], + Time: [], + Alias: [] +}; + +function addFuncDef(funcDef) { + funcDef.params = funcDef.params || []; + funcDef.defaultParams = funcDef.defaultParams || []; + + if (funcDef.category) { + categories[funcDef.category].push(funcDef); + } + index[funcDef.name] = funcDef; + index[funcDef.shortName || funcDef.name] = funcDef; +} + +// Transform + +addFuncDef({ + name: 'groupBy', + category: 'Transform', + params: [{ name: 'interval', type: 'string' }, { name: 'function', type: 'string', options: ['avg', 'min', 'max', 'median'] }], + defaultParams: ['1m', 'avg'] +}); + +addFuncDef({ + name: 'scale', + category: 'Transform', + params: [{ name: 'factor', type: 'float', options: [100, 0.01, 10, -1] }], + defaultParams: [100] +}); + +addFuncDef({ + name: 'delta', + category: 'Transform', + params: [], + defaultParams: [] +}); + +// Aggregate + +addFuncDef({ + name: 'sumSeries', + category: 'Aggregate', + params: [], + defaultParams: [] +}); + +addFuncDef({ + name: 'median', + category: 'Aggregate', + params: [{ name: 'interval', type: 'string' }], + defaultParams: ['1m'] +}); + +addFuncDef({ + name: 'average', + category: 'Aggregate', + params: [{ name: 'interval', type: 'string' }], + defaultParams: ['1m'] +}); + +addFuncDef({ + name: 'min', + category: 'Aggregate', + params: [{ name: 'interval', type: 'string' }], + defaultParams: ['1m'] +}); + +addFuncDef({ + name: 'max', + category: 'Aggregate', + params: [{ name: 'interval', type: 'string' }], + defaultParams: ['1m'] +}); + +addFuncDef({ + name: 'aggregateBy', + category: 'Aggregate', + params: [{ name: 'interval', type: 'string' }, { name: 'function', type: 'string', options: ['avg', 'min', 'max', 'median'] }], + defaultParams: ['1m', 'avg'] +}); + +// Filter + +addFuncDef({ + name: 'top', + category: 'Filter', + params: [{ name: 'number', type: 'int' }, { name: 'value', type: 'string', options: ['avg', 'min', 'max', 'median'] }], + defaultParams: [5, 'avg'] +}); + +addFuncDef({ + name: 'bottom', + category: 'Filter', + params: [{ name: 'number', type: 'int' }, { name: 'value', type: 'string', options: ['avg', 'min', 'max', 'median'] }], + defaultParams: [5, 'avg'] +}); + +// Trends + +addFuncDef({ + name: 'trendValue', + category: 'Trends', + params: [{ name: 'type', type: 'string', options: ['avg', 'min', 'max'] }], + defaultParams: ['avg'] +}); + +// Time + +addFuncDef({ + name: 'timeShift', + category: 'Time', + params: [{ name: 'interval', type: 'string', options: ['24h', '7d', '1M', '+24h', '-24h'] }], + defaultParams: ['24h'] +}); + +//Alias + +addFuncDef({ + name: 'setAlias', + category: 'Alias', + params: [{ name: 'alias', type: 'string' }], + defaultParams: [] +}); + +addFuncDef({ + name: 'setAliasByRegex', + category: 'Alias', + params: [{ name: 'aliasByRegex', type: 'string' }], + defaultParams: [] +}); + +_lodash2.default.each(categories, function (funcList, catName) { + categories[catName] = _lodash2.default.sortBy(funcList, 'name'); +}); + +var FuncInstance = function () { + function FuncInstance(funcDef, params) { + _classCallCheck(this, FuncInstance); + + this.def = funcDef; + + if (params) { + this.params = params; + } else { + // Create with default params + this.params = []; + this.params = funcDef.defaultParams.slice(0); + } + + this.updateText(); + } + + _createClass(FuncInstance, [{ + key: 'bindFunction', + value: function bindFunction(metricFunctions) { + var func = metricFunctions[this.def.name]; + if (func) { + + // Bind function arguments + var bindedFunc = func; + var param; + for (var i = 0; i < this.params.length; i++) { + param = this.params[i]; + + // Convert numeric params + if (this.def.params[i].type === 'int' || this.def.params[i].type === 'float') { + param = Number(param); + } + bindedFunc = _lodash2.default.partial(bindedFunc, param); + } + return bindedFunc; + } else { + throw { message: 'Method not found ' + this.def.name }; + } + } + }, { + key: 'render', + value: function render(metricExp) { + var str = this.def.name + '('; + var parameters = _lodash2.default.map(this.params, function (value, index) { + + var paramType = this.def.params[index].type; + if (paramType === 'int' || paramType === 'float' || paramType === 'value_or_series' || paramType === 'boolean') { + return value; + } else if (paramType === 'int_or_interval' && _jquery2.default.isNumeric(value)) { + return value; + } + + return "'" + value + "'"; + }, this); + + if (metricExp) { + parameters.unshift(metricExp); + } + + return str + parameters.join(', ') + ')'; + } + }, { + key: '_hasMultipleParamsInString', + value: function _hasMultipleParamsInString(strValue, index) { + if (strValue.indexOf(',') === -1) { + return false; + } + + return this.def.params[index + 1] && this.def.params[index + 1].optional; + } + }, { + key: 'updateParam', + value: function updateParam(strValue, index) { + // handle optional parameters + // if string contains ',' and next param is optional, split and update both + if (this._hasMultipleParamsInString(strValue, index)) { + _lodash2.default.each(strValue.split(','), function (partVal, idx) { + this.updateParam(partVal.trim(), idx); + }, this); + return; + } + + if (strValue === '' && this.def.params[index].optional) { + this.params.splice(index, 1); + } else { + this.params[index] = strValue; + } + + this.updateText(); + } + }, { + key: 'updateText', + value: function updateText() { + if (this.params.length === 0) { + this.text = this.def.name + '()'; + return; + } + + var text = this.def.name + '('; + text += this.params.join(', '); + text += ')'; + this.text = text; + } + }]); + + return FuncInstance; +}(); + +function createFuncInstance(funcDef, params) { + if (_lodash2.default.isString(funcDef)) { + if (!index[funcDef]) { + throw { message: 'Method not found ' + name }; + } + funcDef = index[funcDef]; + } + return new FuncInstance(funcDef, params); +} + +function getFuncDef(name) { + return index[name]; +} + +function getCategories() { + return categories; +} diff --git a/dist/test/datasource-zabbix/migrations.js b/dist/test/datasource-zabbix/migrations.js new file mode 100644 index 0000000..dc422c0 --- /dev/null +++ b/dist/test/datasource-zabbix/migrations.js @@ -0,0 +1,48 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isGrafana2target = isGrafana2target; +exports.migrateFrom2To3version = migrateFrom2To3version; +exports.migrate = migrate; +/** + * Query format migration. + * This module can detect query format version and make migration. + */ + +function isGrafana2target(target) { + if (!target.mode || target.mode === 0 || target.mode === 2) { + if ((target.hostFilter || target.itemFilter || target.downsampleFunction || target.host && target.host.host) && target.item.filter === undefined && target.host.filter === undefined) { + return true; + } else { + return false; + } + } else { + return false; + } +} + +function migrateFrom2To3version(target) { + target.group.filter = target.group.name === "*" ? "/.*/" : target.group.name; + target.host.filter = target.host.name === "*" ? convertToRegex(target.hostFilter) : target.host.name; + target.application.filter = target.application.name === "*" ? "" : target.application.name; + target.item.filter = target.item.name === "All" ? convertToRegex(target.itemFilter) : target.item.name; + return target; +} + +function migrate(target) { + if (isGrafana2target(target)) { + return migrateFrom2To3version(target); + } else { + return target; + } +} + +function convertToRegex(str) { + if (str) { + return '/' + str + '/'; + } else { + return '/.*/'; + } +} diff --git a/dist/test/datasource-zabbix/module.js b/dist/test/datasource-zabbix/module.js new file mode 100644 index 0000000..10f88d0 --- /dev/null +++ b/dist/test/datasource-zabbix/module.js @@ -0,0 +1,36 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AnnotationsQueryCtrl = exports.QueryOptionsCtrl = exports.QueryCtrl = exports.ConfigCtrl = exports.Datasource = undefined; + +var _datasource = require('./datasource'); + +var _query = require('./query.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); +}; + +ZabbixQueryOptionsController.templateUrl = 'datasource-zabbix/partials/query.options.html'; + +var ZabbixAnnotationsQueryController = function ZabbixAnnotationsQueryController() { + _classCallCheck(this, ZabbixAnnotationsQueryController); +}; + +ZabbixAnnotationsQueryController.templateUrl = 'datasource-zabbix/partials/annotations.editor.html'; + +exports.Datasource = _datasource.ZabbixAPIDatasource; +exports.ConfigCtrl = ZabbixConfigController; +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 new file mode 100644 index 0000000..24542f5 --- /dev/null +++ b/dist/test/datasource-zabbix/query.controller.js @@ -0,0 +1,378 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ZabbixQueryController = 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 _sdk = require('app/plugins/sdk'); + +var _angular = require('angular'); + +var _angular2 = _interopRequireDefault(_angular); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _utils = require('./utils'); + +var utils = _interopRequireWildcard(_utils); + +var _metricFunctions = require('./metricFunctions'); + +var metricFunctions = _interopRequireWildcard(_metricFunctions); + +var _migrations = require('./migrations'); + +var migrations = _interopRequireWildcard(_migrations); + +require('./add-metric-function.directive'); + +require('./metric-function-editor.directive'); + +require('./css/query-editor.css!'); + +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 }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var ZabbixQueryController = exports.ZabbixQueryController = function (_QueryCtrl) { + _inherits(ZabbixQueryController, _QueryCtrl); + + // ZabbixQueryCtrl constructor + function ZabbixQueryController($scope, $injector, $rootScope, $sce, templateSrv) { + _classCallCheck(this, ZabbixQueryController); + + var _this = _possibleConstructorReturn(this, (ZabbixQueryController.__proto__ || Object.getPrototypeOf(ZabbixQueryController)).call(this, $scope, $injector)); + + _this.zabbix = _this.datasource.zabbix; + + // Use custom format for template variables + _this.replaceTemplateVars = _this.datasource.replaceTemplateVars; + _this.templateSrv = templateSrv; + + _this.editorModes = { + 0: { value: 'num', text: 'Metrics', mode: 0 }, + 1: { value: 'itservice', text: 'IT Services', mode: 1 }, + 2: { value: 'text', text: 'Text', mode: 2 } + }; + + // Map functions for bs-typeahead + _this.getGroupNames = _lodash2.default.partial(getMetricNames, _this, 'groupList'); + _this.getHostNames = _lodash2.default.partial(getMetricNames, _this, 'hostList'); + _this.getApplicationNames = _lodash2.default.partial(getMetricNames, _this, 'appList'); + _this.getItemNames = _lodash2.default.partial(getMetricNames, _this, 'itemList'); + + // Update metric suggestion when template variable was changed + $rootScope.$on('template-variable-value-updated', function () { + return _this.onVariableChange(); + }); + + // Update metrics when item selected from dropdown + $scope.$on('typeahead-updated', function () { + _this.onTargetBlur(); + }); + + _this.init = function () { + var target = this.target; + + // Migrate old targets + target = migrations.migrate(target); + + var scopeDefaults = { + metric: {}, + oldTarget: _lodash2.default.cloneDeep(this.target), + queryOptionsText: this.renderQueryOptionsText() + }; + _lodash2.default.defaults(this, scopeDefaults); + + // Load default values + var targetDefaults = { + mode: 0, + group: { filter: "" }, + host: { filter: "" }, + application: { filter: "" }, + item: { filter: "" }, + functions: [], + options: { + showDisabledItems: false + } + }; + _lodash2.default.defaults(target, targetDefaults); + + // Create function instances from saved JSON + target.functions = _lodash2.default.map(target.functions, function (func) { + return metricFunctions.createFuncInstance(func.def, func.params); + }); + + if (target.mode === 0 || target.mode === 2) { + + this.downsampleFunctionList = [{ name: "avg", value: "avg" }, { name: "min", value: "min" }, { name: "max", value: "max" }]; + + this.initFilters(); + } else if (target.mode === 1) { + 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(); + } + }; + + _this.init(); + return _this; + } + + _createClass(ZabbixQueryController, [{ + key: 'initFilters', + value: function initFilters() { + var itemtype = this.editorModes[this.target.mode].value; + return Promise.all([this.suggestGroups(), this.suggestHosts(), this.suggestApps(), this.suggestItems(itemtype)]); + } + }, { + key: 'suggestGroups', + value: function suggestGroups() { + var _this2 = this; + + return this.zabbix.getAllGroups().then(function (groups) { + _this2.metric.groupList = groups; + return groups; + }); + } + }, { + key: 'suggestHosts', + value: function suggestHosts() { + var _this3 = this; + + var groupFilter = this.replaceTemplateVars(this.target.group.filter); + return this.zabbix.getAllHosts(groupFilter).then(function (hosts) { + _this3.metric.hostList = hosts; + return hosts; + }); + } + }, { + key: 'suggestApps', + value: function suggestApps() { + var _this4 = this; + + var groupFilter = this.replaceTemplateVars(this.target.group.filter); + var hostFilter = this.replaceTemplateVars(this.target.host.filter); + return this.zabbix.getAllApps(groupFilter, hostFilter).then(function (apps) { + _this4.metric.appList = apps; + return apps; + }); + } + }, { + key: 'suggestItems', + value: function suggestItems() { + var _this5 = this; + + var itemtype = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'num'; + + var groupFilter = this.replaceTemplateVars(this.target.group.filter); + var hostFilter = this.replaceTemplateVars(this.target.host.filter); + var appFilter = this.replaceTemplateVars(this.target.application.filter); + var options = { + itemtype: itemtype, + showDisabledItems: this.target.options.showDisabledItems + }; + + return this.zabbix.getAllItems(groupFilter, hostFilter, appFilter, options).then(function (items) { + _this5.metric.itemList = items; + return items; + }); + } + }, { + key: 'isRegex', + value: function isRegex(str) { + return utils.isRegex(str); + } + }, { + key: 'isVariable', + value: function isVariable(str) { + return utils.isTemplateVariable(str, this.templateSrv.variables); + } + }, { + key: 'onTargetBlur', + value: function onTargetBlur() { + var newTarget = _lodash2.default.cloneDeep(this.target); + if (!_lodash2.default.isEqual(this.oldTarget, this.target)) { + this.oldTarget = newTarget; + this.targetChanged(); + } + } + }, { + key: 'onVariableChange', + value: function onVariableChange() { + if (this.isContainsVariables()) { + this.targetChanged(); + } + } + + /** + * Check query for template variables + */ + + }, { + key: 'isContainsVariables', + value: function isContainsVariables() { + var _this6 = 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); + } else { + return false; + } + }); + } + }, { + key: 'parseTarget', + value: function parseTarget() {} + // Parse target + + + // Validate target and set validation info + + }, { + key: 'validateTarget', + value: function validateTarget() { + // validate + } + }, { + key: 'targetChanged', + value: function targetChanged() { + this.initFilters(); + this.parseTarget(); + this.panelCtrl.refresh(); + } + }, { + key: 'addFunction', + value: function addFunction(funcDef) { + var newFunc = metricFunctions.createFuncInstance(funcDef); + newFunc.added = true; + this.target.functions.push(newFunc); + + this.moveAliasFuncLast(); + + if (newFunc.params.length && newFunc.added || newFunc.def.params.length === 0) { + this.targetChanged(); + } + } + }, { + key: 'removeFunction', + value: function removeFunction(func) { + this.target.functions = _lodash2.default.without(this.target.functions, func); + this.targetChanged(); + } + }, { + key: 'moveAliasFuncLast', + value: function moveAliasFuncLast() { + var aliasFunc = _lodash2.default.find(this.target.functions, function (func) { + return func.def.name === 'alias' || func.def.name === 'aliasByNode' || func.def.name === 'aliasByMetric'; + }); + + if (aliasFunc) { + this.target.functions = _lodash2.default.without(this.target.functions, aliasFunc); + this.target.functions.push(aliasFunc); + } + } + }, { + key: 'toggleQueryOptions', + value: function toggleQueryOptions() { + this.showQueryOptions = !this.showQueryOptions; + } + }, { + key: 'onQueryOptionChange', + value: function onQueryOptionChange() { + this.queryOptionsText = this.renderQueryOptionsText(); + this.onTargetBlur(); + } + }, { + key: 'renderQueryOptionsText', + value: function renderQueryOptionsText() { + var optionsMap = { + showDisabledItems: "Show disabled items" + }; + var options = []; + _lodash2.default.forOwn(this.target.options, function (value, key) { + if (value) { + if (value === true) { + // Show only option name (if enabled) for boolean options + options.push(optionsMap[key]); + } else { + // Show "option = value" for another options + options.push(optionsMap[key] + " = " + value); + } + } + }); + return "Options: " + options.join(', '); + } + + /** + * Switch query editor to specified mode. + * Modes: + * 0 - items + * 1 - IT services + * 2 - Text metrics + */ + + }, { + key: 'switchEditorMode', + 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(); + } + } + }]); + + return ZabbixQueryController; +}(_sdk.QueryCtrl); + +// Set templateUrl as static property + + +ZabbixQueryController.templateUrl = 'datasource-zabbix/partials/query.editor.html'; + +// Get list of metric names for bs-typeahead directive +function getMetricNames(scope, metricList) { + return _lodash2.default.uniq(_lodash2.default.map(scope.metric[metricList], 'name')); +} diff --git a/dist/test/datasource-zabbix/responseHandler.js b/dist/test/datasource-zabbix/responseHandler.js new file mode 100644 index 0000000..8bad6f4 --- /dev/null +++ b/dist/test/datasource-zabbix/responseHandler.js @@ -0,0 +1,116 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Convert Zabbix API history.get response to Grafana format + * + * @return {Array} Array of timeseries in Grafana format + * { + * target: "Metric name", + * datapoints: [[, ], ...] + * } + */ +function convertHistory(history, items, addHostName, convertPointCallback) { + /** + * Response should be in the format: + * data: [ + * { + * target: "Metric name", + * datapoints: [[, ], ...] + * }, ... + * ] + */ + + // Group history by itemid + var grouped_history = _lodash2.default.groupBy(history, 'itemid'); + var hosts = _lodash2.default.uniqBy(_lodash2.default.flatten(_lodash2.default.map(items, 'hosts')), 'hostid'); //uniqBy is needed to deduplicate + + return _lodash2.default.map(grouped_history, function (hist, itemid) { + 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: _lodash2.default.map(hist, convertPointCallback) + }; + }); +} + +function handleHistory(history, items) { + var addHostName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; + + return convertHistory(history, items, addHostName, convertHistoryPoint); +} + +function handleTrends(history, items, valueType) { + var addHostName = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + + var convertPointCallback = _lodash2.default.partial(convertTrendPoint, valueType); + return convertHistory(history, items, addHostName, convertPointCallback); +} + +function handleSLAResponse(itservice, slaProperty, slaObject) { + var targetSLA = slaObject[itservice.serviceid].sla[0]; + if (slaProperty.property === 'status') { + var targetStatus = parseInt(slaObject[itservice.serviceid].status); + return { + target: itservice.name + ' ' + slaProperty.name, + datapoints: [[targetStatus, targetSLA.to * 1000]] + }; + } else { + return { + target: itservice.name + ' ' + slaProperty.name, + datapoints: [[targetSLA[slaProperty.property], targetSLA.from * 1000], [targetSLA[slaProperty.property], targetSLA.to * 1000]] + }; + } +} + +function convertHistoryPoint(point) { + // Value must be a number for properly work + return [Number(point.value), point.clock * 1000]; +} + +function convertTrendPoint(valueType, point) { + var value; + switch (valueType) { + case "min": + value = point.value_min; + break; + case "max": + value = point.value_max; + break; + case "avg": + value = point.value_avg; + break; + default: + value = point.value_avg; + } + + return [Number(value), point.clock * 1000]; +} + +exports.default = { + handleHistory: handleHistory, + convertHistory: convertHistory, + handleTrends: handleTrends, + handleSLAResponse: handleSLAResponse +}; + +// Fix for backward compatibility with lodash 2.4 + +if (!_lodash2.default.uniqBy) { + _lodash2.default.uniqBy = _lodash2.default.uniq; +} diff --git a/dist/test/datasource-zabbix/specs/datasource_specs.js b/dist/test/datasource-zabbix/specs/datasource_specs.js new file mode 100644 index 0000000..f34a105 --- /dev/null +++ b/dist/test/datasource-zabbix/specs/datasource_specs.js @@ -0,0 +1,317 @@ +"use strict"; + +var _module = require("../module"); + +var _datasource = require("../datasource"); + +var _q = require("q"); + +var _q2 = _interopRequireDefault(_q); + +var _sinon = require("sinon"); + +var _sinon2 = _interopRequireDefault(_sinon); + +var _lodash = require("lodash"); + +var _lodash2 = _interopRequireDefault(_lodash); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +describe('ZabbixDatasource', function () { + var ctx = {}; + var defined = _sinon2.default.match.defined; + + beforeEach(function () { + ctx.instanceSettings = { + jsonData: { + username: 'zabbix', + password: 'zabbix', + trends: true, + trendsFrom: '7d' + } + }; + ctx.templateSrv = {}; + ctx.alertSrv = {}; + ctx.zabbix = function () {}; + + ctx.ds = new _module.Datasource(ctx.instanceSettings, ctx.templateSrv, ctx.alertSrv, ctx.zabbix); + }); + + describe('When querying data', function () { + beforeEach(function () { + ctx.ds.replaceTemplateVars = function (str) { + return str; + }; + }); + + ctx.options = { + targets: [{ + group: { filter: "" }, + host: { filter: "" }, + application: { filter: "" }, + item: { filter: "" } + }], + range: { from: 'now-7d', to: 'now' } + }; + + it('should return an empty array when no targets are set', function (done) { + var options = { + targets: [], + range: { from: 'now-6h', to: 'now' } + }; + ctx.ds.query(options).then(function (result) { + expect(result.data).to.have.length(0); + done(); + }); + }); + + it('should use trends if it enabled and time more than trendsFrom', function (done) { + var ranges = ['now-7d', 'now-168h', 'now-1M', 'now-1y']; + + _lodash2.default.forEach(ranges, function (range) { + ctx.options.range.from = range; + ctx.ds.queryNumericData = _sinon2.default.spy(); + ctx.ds.query(ctx.options); + + // Check that useTrends options is true + expect(ctx.ds.queryNumericData).to.have.been.calledWith(defined, defined, defined, true); + }); + + done(); + }); + + it('shouldnt use trends if it enabled and time less than trendsFrom', function (done) { + var ranges = ['now-6d', 'now-167h', 'now-1h', 'now-30m', 'now-30s']; + + _lodash2.default.forEach(ranges, function (range) { + ctx.options.range.from = range; + ctx.ds.queryNumericData = _sinon2.default.spy(); + ctx.ds.query(ctx.options); + + // Check that useTrends options is false + expect(ctx.ds.queryNumericData).to.have.been.calledWith(defined, defined, defined, false); + }); + done(); + }); + }); + + describe('When replacing template variables', function () { + + function testReplacingVariable(target, varValue, expectedResult, done) { + ctx.ds.templateSrv.replace = function () { + return (0, _datasource.zabbixTemplateFormat)(varValue); + }; + + var result = ctx.ds.replaceTemplateVars(target); + expect(result).to.equal(expectedResult); + done(); + } + + /* + * Alphanumerics, spaces, dots, dashes and underscores + * are allowed in Zabbix host name. + * 'AaBbCc0123 .-_' + */ + it('should return properly escaped regex', function (done) { + var target = '$host'; + var template_var_value = 'AaBbCc0123 .-_'; + var expected_result = '/^AaBbCc0123 \\.-_$/'; + + testReplacingVariable(target, template_var_value, expected_result, done); + }); + + /* + * Single-value variable + * $host = backend01 + * $host => /^backend01|backend01$/ + */ + it('should return proper regex for single value', function (done) { + var target = '$host'; + var template_var_value = 'backend01'; + var expected_result = '/^backend01$/'; + + testReplacingVariable(target, template_var_value, expected_result, done); + }); + + /* + * Multi-value variable + * $host = [backend01, backend02] + * $host => /^(backend01|backend01)$/ + */ + it('should return proper regex for multi-value', function (done) { + var target = '$host'; + var template_var_value = ['backend01', 'backend02']; + var expected_result = '/^(backend01|backend02)$/'; + + testReplacingVariable(target, template_var_value, expected_result, done); + }); + }); + + describe('When invoking metricFindQuery()', function () { + beforeEach(function () { + ctx.ds.replaceTemplateVars = function (str) { + return str; + }; + ctx.ds.zabbix = { + getGroups: function getGroups() { + return _q2.default.when([]); + }, + getHosts: function getHosts() { + return _q2.default.when([]); + }, + getApps: function getApps() { + return _q2.default.when([]); + }, + getItems: function getItems() { + return _q2.default.when([]); + } + }; + }); + + it('should return groups', function (done) { + var tests = [{ query: '*', expect: '/.*/' }, { query: '', expect: '' }, { query: 'Backend', expect: 'Backend' }, { query: 'Back*', expect: 'Back*' }]; + + var getGroups = _sinon2.default.spy(ctx.ds.zabbix, 'getGroups'); + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = tests[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var test = _step.value; + + ctx.ds.metricFindQuery(test.query); + expect(getGroups).to.have.been.calledWith(test.expect); + getGroups.reset(); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + done(); + }); + + it('should return hosts', function (done) { + var tests = [{ query: '*.*', expect: '/.*/' }, { query: '.', expect: '' }, { query: 'Backend.*', expect: 'Backend' }, { query: 'Back*.', expect: 'Back*' }]; + + var getHosts = _sinon2.default.spy(ctx.ds.zabbix, 'getHosts'); + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for (var _iterator2 = tests[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var test = _step2.value; + + ctx.ds.metricFindQuery(test.query); + expect(getHosts).to.have.been.calledWith(test.expect); + getHosts.reset(); + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + + done(); + }); + + it('should return applications', function (done) { + var tests = [{ query: '*.*.*', expect: ['/.*/', '/.*/'] }, { query: '.*.', expect: ['', '/.*/'] }, { query: 'Backend.backend01.*', expect: ['Backend', 'backend01'] }, { query: 'Back*.*.', expect: ['Back*', '/.*/'] }]; + + var getApps = _sinon2.default.spy(ctx.ds.zabbix, 'getApps'); + var _iteratorNormalCompletion3 = true; + var _didIteratorError3 = false; + var _iteratorError3 = undefined; + + try { + for (var _iterator3 = tests[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { + var test = _step3.value; + + ctx.ds.metricFindQuery(test.query); + expect(getApps).to.have.been.calledWith(test.expect[0], test.expect[1]); + getApps.reset(); + } + } catch (err) { + _didIteratorError3 = true; + _iteratorError3 = err; + } finally { + try { + if (!_iteratorNormalCompletion3 && _iterator3.return) { + _iterator3.return(); + } + } finally { + if (_didIteratorError3) { + throw _iteratorError3; + } + } + } + + done(); + }); + + it('should return items', function (done) { + var tests = [{ query: '*.*.*.*', expect: ['/.*/', '/.*/', ''] }, { query: '.*.*.*', expect: ['', '/.*/', ''] }, { query: 'Backend.backend01.*.*', expect: ['Backend', 'backend01', ''] }, { query: 'Back*.*.cpu.*', expect: ['Back*', '/.*/', 'cpu'] }]; + + var getItems = _sinon2.default.spy(ctx.ds.zabbix, 'getItems'); + var _iteratorNormalCompletion4 = true; + var _didIteratorError4 = false; + var _iteratorError4 = undefined; + + try { + for (var _iterator4 = tests[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { + var test = _step4.value; + + ctx.ds.metricFindQuery(test.query); + expect(getItems).to.have.been.calledWith(test.expect[0], test.expect[1], test.expect[2]); + getItems.reset(); + } + } catch (err) { + _didIteratorError4 = true; + _iteratorError4 = err; + } finally { + try { + if (!_iteratorNormalCompletion4 && _iterator4.return) { + _iterator4.return(); + } + } finally { + if (_didIteratorError4) { + throw _iteratorError4; + } + } + } + + done(); + }); + + it('should invoke method with proper arguments', function (done) { + var query = '*.*'; + + var getHosts = _sinon2.default.spy(ctx.ds.zabbix, 'getHosts'); + ctx.ds.metricFindQuery(query); + expect(getHosts).to.have.been.calledWith('/.*/'); + done(); + }); + }); +}); diff --git a/dist/test/datasource-zabbix/specs/modules/datemath.js b/dist/test/datasource-zabbix/specs/modules/datemath.js new file mode 100644 index 0000000..063ad04 --- /dev/null +++ b/dist/test/datasource-zabbix/specs/modules/datemath.js @@ -0,0 +1,135 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.parse = parse; +exports.isValid = isValid; +exports.parseDateMath = parseDateMath; + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _moment = require('moment'); + +var _moment2 = _interopRequireDefault(_moment); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var units = ['y', 'M', 'w', 'd', 'h', 'm', 's']; + +function parse(text, roundUp) { + if (!text) { + return undefined; + } + if (_moment2.default.isMoment(text)) { + return text; + } + if (_lodash2.default.isDate(text)) { + return (0, _moment2.default)(text); + } + + var time; + var mathString = ''; + var index; + var parseString; + + if (text.substring(0, 3) === 'now') { + time = (0, _moment2.default)(); + mathString = text.substring('now'.length); + } else { + index = text.indexOf('||'); + if (index === -1) { + parseString = text; + mathString = ''; // nothing else + } else { + parseString = text.substring(0, index); + mathString = text.substring(index + 2); + } + // We're going to just require ISO8601 timestamps, k? + time = (0, _moment2.default)(parseString, _moment2.default.ISO_8601); + } + + if (!mathString.length) { + return time; + } + + return parseDateMath(mathString, time, roundUp); +} + +function isValid(text) { + var date = parse(text); + if (!date) { + return false; + } + + if (_moment2.default.isMoment(date)) { + return date.isValid(); + } + + return false; +} + +function parseDateMath(mathString, time, roundUp) { + var dateTime = time; + var i = 0; + var len = mathString.length; + + while (i < len) { + var c = mathString.charAt(i++); + var type; + var num; + var unit; + + if (c === '/') { + type = 0; + } else if (c === '+') { + type = 1; + } else if (c === '-') { + type = 2; + } else { + return undefined; + } + + if (isNaN(mathString.charAt(i))) { + num = 1; + } else if (mathString.length === 2) { + num = mathString.charAt(i); + } else { + var numFrom = i; + while (!isNaN(mathString.charAt(i))) { + i++; + if (i > 10) { + return undefined; + } + } + num = parseInt(mathString.substring(numFrom, i), 10); + } + + if (type === 0) { + // rounding is only allowed on whole, single, units (eg M or 1M, not 0.5M or 2M) + if (num !== 1) { + return undefined; + } + } + unit = mathString.charAt(i++); + + if (!_lodash2.default.includes(units, unit)) { + return undefined; + } else { + if (type === 0) { + if (roundUp) { + dateTime.endOf(unit); + } else { + dateTime.startOf(unit); + } + } else if (type === 1) { + dateTime.add(num, unit); + } else if (type === 2) { + dateTime.subtract(num, unit); + } + } + } + return dateTime; +} diff --git a/dist/test/datasource-zabbix/specs/test-main.js b/dist/test/datasource-zabbix/specs/test-main.js new file mode 100644 index 0000000..a80d33a --- /dev/null +++ b/dist/test/datasource-zabbix/specs/test-main.js @@ -0,0 +1,66 @@ +'use strict'; + +var _prunk = require('prunk'); + +var _prunk2 = _interopRequireDefault(_prunk); + +var _jsdom = require('jsdom'); + +var _chai = require('chai'); + +var _chai2 = _interopRequireDefault(_chai); + +var _sinonChai = require('sinon-chai'); + +var _sinonChai2 = _interopRequireDefault(_sinonChai); + +var _datemath = require('./modules/datemath'); + +var dateMath = _interopRequireWildcard(_datemath); + +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 }; } + +// Mock angular module + +// import sinon from 'sinon'; +var angularMocks = { + module: function module() { + return { + directive: function directive() {}, + service: function service() {}, + factory: function factory() {} + }; + } +}; // JSHint options +/* globals global: false */ + +var datemathMock = { + parse: dateMath.parse, + parseDateMath: dateMath.parseDateMath, + isValid: dateMath.isValid +}; + +// Mock Grafana modules that are not available outside of the core project +// Required for loading module.js +_prunk2.default.mock('./css/query-editor.css!', 'no css, dude.'); +_prunk2.default.mock('app/plugins/sdk', { + QueryCtrl: null +}); +_prunk2.default.mock('app/core/utils/datemath', datemathMock); +_prunk2.default.mock('angular', angularMocks); +_prunk2.default.mock('jquery', 'module not found'); + +// Setup jsdom +// Required for loading angularjs +global.document = (0, _jsdom.jsdom)(''); +global.window = global.document.parentWindow; +global.navigator = window.navigator = {}; +global.Node = window.Node; + +// Setup Chai +_chai2.default.should(); +_chai2.default.use(_sinonChai2.default); +global.assert = _chai2.default.assert; +global.expect = _chai2.default.expect; diff --git a/dist/test/datasource-zabbix/utils.js b/dist/test/datasource-zabbix/utils.js new file mode 100644 index 0000000..36eceb9 --- /dev/null +++ b/dist/test/datasource-zabbix/utils.js @@ -0,0 +1,151 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.regexPattern = undefined; +exports.expandItemName = expandItemName; +exports.isRegex = isRegex; +exports.isTemplateVariable = isTemplateVariable; +exports.buildRegex = buildRegex; +exports.escapeRegex = escapeRegex; +exports.parseInterval = parseInterval; +exports.parseTimeShiftInterval = parseTimeShiftInterval; +exports.formatAcknowledges = formatAcknowledges; +exports.convertToZabbixAPIUrl = convertToZabbixAPIUrl; +exports.callOnce = callOnce; + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _moment = require('moment'); + +var _moment2 = _interopRequireDefault(_moment); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Expand Zabbix item name + * + * @param {string} name item name, ie "CPU $2 time" + * @param {string} key item key, ie system.cpu.util[,system,avg1] + * @return {string} expanded name, ie "CPU system time" + */ +function expandItemName(name, key) { + + // extract params from key: + // "system.cpu.util[,system,avg1]" --> ["", "system", "avg1"] + var key_params = key.substring(key.indexOf('[') + 1, key.lastIndexOf(']')).split(','); + + // replace item parameters + for (var i = key_params.length; i >= 1; i--) { + name = name.replace('$' + i, key_params[i - 1]); + } + return name; +} + +// Pattern for testing regex +var regexPattern = exports.regexPattern = /^\/(.*)\/([gmi]*)$/m; + +function isRegex(str) { + return regexPattern.test(str); +} + +function isTemplateVariable(str, templateVariables) { + var variablePattern = /^\$\w+/; + if (variablePattern.test(str)) { + var variables = _lodash2.default.map(templateVariables, function (variable) { + return '$' + variable.name; + }); + return _lodash2.default.includes(variables, str); + } else { + return false; + } +} + +function buildRegex(str) { + var matches = str.match(regexPattern); + var pattern = matches[1]; + var flags = matches[2] !== "" ? matches[2] : undefined; + return new RegExp(pattern, flags); +} + +// Need for template variables replace +// From Grafana's templateSrv.js +function escapeRegex(value) { + return value.replace(/[\\^$*+?.()|[\]{}\/]/g, '\\$&'); +} + +function parseInterval(interval) { + var intervalPattern = /(^[\d]+)(y|M|w|d|h|m|s)/g; + var momentInterval = intervalPattern.exec(interval); + return _moment2.default.duration(Number(momentInterval[1]), momentInterval[2]).valueOf(); +} + +function parseTimeShiftInterval(interval) { + var intervalPattern = /^([\+\-]*)([\d]+)(y|M|w|d|h|m|s)/g; + var momentInterval = intervalPattern.exec(interval); + var duration = 0; + + if (momentInterval[1] === '+') { + duration = 0 - _moment2.default.duration(Number(momentInterval[2]), momentInterval[3]).valueOf(); + } else { + duration = _moment2.default.duration(Number(momentInterval[2]), momentInterval[3]).valueOf(); + } + + return duration; +} + +/** + * Format acknowledges. + * + * @param {array} acknowledges array of Zabbix acknowledge objects + * @return {string} HTML-formatted table + */ +function formatAcknowledges(acknowledges) { + if (acknowledges.length) { + var formatted_acknowledges = '

                            Acknowledges:
                            ' + ''; + _lodash2.default.each(_lodash2.default.map(acknowledges, function (ack) { + var timestamp = _moment2.default.unix(ack.clock); + return ''; + }), function (ack) { + formatted_acknowledges = formatted_acknowledges.concat(ack); + }); + formatted_acknowledges = formatted_acknowledges.concat('
                            TimeUserComments
                            ' + timestamp.format("DD MMM YYYY HH:mm:ss") + '' + ack.alias + ' (' + ack.name + ' ' + ack.surname + ')' + '' + ack.message + '
                            '); + return formatted_acknowledges; + } else { + return ''; + } +} + +function convertToZabbixAPIUrl(url) { + var zabbixAPIUrlPattern = /.*api_jsonrpc.php$/; + var trimSlashPattern = /(.*?)[\/]*$/; + if (url.match(zabbixAPIUrlPattern)) { + return url; + } else { + return url.replace(trimSlashPattern, "$1"); + } +} + +/** + * Wrap function to prevent multiple calls + * when waiting for result. + */ +function callOnce(func, promiseKeeper) { + return function () { + if (!promiseKeeper) { + promiseKeeper = Promise.resolve(func.apply(this, arguments).then(function (result) { + promiseKeeper = null; + return result; + })); + } + return promiseKeeper; + }; +} + +// Fix for backward compatibility with lodash 2.4 +if (!_lodash2.default.includes) { + _lodash2.default.includes = _lodash2.default.contains; +} diff --git a/dist/test/datasource-zabbix/zabbix.js b/dist/test/datasource-zabbix/zabbix.js new file mode 100644 index 0000000..627d107 --- /dev/null +++ b/dist/test/datasource-zabbix/zabbix.js @@ -0,0 +1,266 @@ +'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); + +var _utils = require('./utils'); + +var utils = _interopRequireWildcard(_utils); + +require('./zabbixAPI.service.js'); + +require('./zabbixCachingProxy.service.js'); + +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 }; } + +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +// 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) { + var Zabbix = function () { + function Zabbix(url, username, password, basicAuth, withCredentials, cacheTTL) { + _classCallCheck(this, Zabbix); + + // Initialize Zabbix API + var ZabbixAPI = zabbixAPIService; + this.zabbixAPI = new ZabbixAPI(url, username, password, basicAuth, withCredentials); + + // Initialize caching proxy for requests + var cacheOptions = { + enabled: true, + ttl: cacheTTL + }; + this.cachingProxy = new ZabbixCachingProxy(this.zabbixAPI, cacheOptions); + + // Proxy methods + this.getHistory = this.cachingProxy.getHistory.bind(this.cachingProxy); + + this.getTrend = this.zabbixAPI.getTrend.bind(this.zabbixAPI); + this.getEvents = this.zabbixAPI.getEvents.bind(this.zabbixAPI); + this.getAcknowledges = this.zabbixAPI.getAcknowledges.bind(this.zabbixAPI); + this.getITService = this.zabbixAPI.getITService.bind(this.zabbixAPI); + this.getSLA = this.zabbixAPI.getSLA.bind(this.zabbixAPI); + this.getVersion = this.zabbixAPI.getVersion.bind(this.zabbixAPI); + this.login = this.zabbixAPI.login.bind(this.zabbixAPI); + } + + _createClass(Zabbix, [{ + key: 'getItemsFromTarget', + value: function getItemsFromTarget(target, options) { + var parts = ['group', 'host', 'application', 'item']; + var filters = _lodash2.default.map(parts, function (p) { + return target[p].filter; + }); + return this.getItems.apply(this, _toConsumableArray(filters).concat([options])); + } + }, { + key: 'getAllGroups', + value: function getAllGroups() { + return this.cachingProxy.getGroups(); + } + }, { + key: 'getGroups', + value: function getGroups(groupFilter) { + return this.getAllGroups().then(function (groups) { + return findByFilter(groups, groupFilter); + }); + } + + /** + * Get list of host belonging to given groups. + */ + + }, { + key: 'getAllHosts', + value: function getAllHosts(groupFilter) { + var _this = this; + + return this.getGroups(groupFilter).then(function (groups) { + var groupids = _lodash2.default.map(groups, 'groupid'); + return _this.cachingProxy.getHosts(groupids); + }); + } + }, { + key: 'getHosts', + value: function getHosts(groupFilter, hostFilter) { + return this.getAllHosts(groupFilter).then(function (hosts) { + return findByFilter(hosts, hostFilter); + }); + } + + /** + * Get list of applications belonging to given groups and hosts. + */ + + }, { + key: 'getAllApps', + value: function getAllApps(groupFilter, hostFilter) { + var _this2 = this; + + return this.getHosts(groupFilter, hostFilter).then(function (hosts) { + var hostids = _lodash2.default.map(hosts, 'hostid'); + return _this2.cachingProxy.getApps(hostids); + }); + } + }, { + key: 'getApps', + value: function getApps(groupFilter, hostFilter, appFilter) { + var _this3 = this; + + return this.getHosts(groupFilter, hostFilter).then(function (hosts) { + var hostids = _lodash2.default.map(hosts, 'hostid'); + if (appFilter) { + return _this3.cachingProxy.getApps(hostids).then(function (apps) { + return filterByQuery(apps, appFilter); + }); + } else { + return { + appFilterEmpty: true, + hostids: hostids + }; + } + }); + } + }, { + key: 'getAllItems', + value: function getAllItems(groupFilter, hostFilter, appFilter) { + var _this4 = this; + + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + return this.getApps(groupFilter, hostFilter, appFilter).then(function (apps) { + if (apps.appFilterEmpty) { + return _this4.cachingProxy.getItems(apps.hostids, undefined, options.itemtype); + } else { + var appids = _lodash2.default.map(apps, 'applicationid'); + return _this4.cachingProxy.getItems(undefined, appids, options.itemtype); + } + }).then(function (items) { + if (!options.showDisabledItems) { + items = _lodash2.default.filter(items, { 'status': '0' }); + } + return items; + }); + } + }, { + key: 'getItems', + value: function getItems(groupFilter, hostFilter, appFilter, itemFilter) { + var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; + + return this.getAllItems(groupFilter, hostFilter, appFilter, options).then(function (items) { + return filterByQuery(items, itemFilter); + }); + } + + /** + * Build query - convert target filters to array of Zabbix items + */ + + }, { + key: 'getTriggers', + value: function getTriggers(groupFilter, hostFilter, appFilter, showTriggers) { + var _this5 = this; + + var promises = [this.getGroups(groupFilter), this.getHosts(groupFilter, hostFilter), this.getApps(groupFilter, hostFilter, appFilter)]; + + return Promise.all(promises).then(function (results) { + var filteredGroups = results[0]; + var filteredHosts = results[1]; + var filteredApps = results[2]; + var query = {}; + + if (appFilter) { + query.applicationids = _lodash2.default.flatten(_lodash2.default.map(filteredApps, 'applicationid')); + } + if (hostFilter) { + query.hostids = _lodash2.default.map(filteredHosts, 'hostid'); + } + if (groupFilter) { + query.groupids = _lodash2.default.map(filteredGroups, 'groupid'); + } + + return query; + }).then(function (query) { + return _this5.zabbixAPI.getTriggers(query.groupids, query.hostids, query.applicationids, showTriggers); + }); + } + }]); + + return Zabbix; + }(); + + return Zabbix; +} + +_angular2.default.module('grafana.services').factory('Zabbix', ZabbixFactory); + +/////////////////////////////////////////////////////////////////////////////// + +/** + * Find group, host, app or item by given name. + * @param list list of groups, apps or other + * @param name visible name + * @return array with finded element or undefined + */ +function findByName(list, name) { + var finded = _lodash2.default.find(list, { 'name': name }); + if (finded) { + return [finded]; + } else { + return undefined; + } +} + +/** + * Different hosts can contains applications and items with same name. + * For this reason use _.filter, which return all elements instead _.find, + * which return only first finded. + * @param {[type]} list list of elements + * @param {[type]} name app name + * @return {[type]} array with finded element or undefined + */ +function filterByName(list, name) { + var finded = _lodash2.default.filter(list, { 'name': name }); + if (finded) { + return finded; + } else { + return undefined; + } +} + +function filterByRegex(list, regex) { + var filterPattern = utils.buildRegex(regex); + return _lodash2.default.filter(list, function (zbx_obj) { + return filterPattern.test(zbx_obj.name); + }); +} + +function findByFilter(list, filter) { + if (utils.isRegex(filter)) { + return filterByRegex(list, filter); + } else { + return findByName(list, filter); + } +} + +function filterByQuery(list, filter) { + if (utils.isRegex(filter)) { + return filterByRegex(list, filter); + } else { + return filterByName(list, filter); + } +} diff --git a/dist/test/datasource-zabbix/zabbixAPI.service.js b/dist/test/datasource-zabbix/zabbixAPI.service.js new file mode 100644 index 0000000..cd82a13 --- /dev/null +++ b/dist/test/datasource-zabbix/zabbixAPI.service.js @@ -0,0 +1,436 @@ +'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); + +var _utils = require('./utils'); + +var utils = _interopRequireWildcard(_utils); + +require('./zabbixAPICore.service'); + +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 }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +/** @ngInject */ +function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) { + + /** + * Zabbix API Wrapper. + * Creates Zabbix API instance with given parameters (url, credentials and other). + * Wraps API calls and provides high-level methods. + */ + var ZabbixAPI = function () { + function ZabbixAPI(api_url, username, password, basicAuth, withCredentials) { + _classCallCheck(this, ZabbixAPI); + + this.url = api_url; + this.username = username; + this.password = password; + this.auth = ""; + + this.requestOptions = { + basicAuth: basicAuth, + withCredentials: withCredentials + }; + + this.loginPromise = null; + this.loginErrorCount = 0; + this.maxLoginAttempts = 3; + + this.alertSrv = alertSrv; + this.zabbixAPICore = zabbixAPICoreService; + + this.getTrend = this.getTrend_ZBXNEXT1193; + //getTrend = getTrend_30; + } + + ////////////////////////// + // Core method wrappers // + ////////////////////////// + + _createClass(ZabbixAPI, [{ + key: 'request', + value: function request(method, params) { + var _this = this; + + return this.zabbixAPICore.request(this.url, method, params, this.requestOptions, this.auth).catch(function (error) { + if (isNotAuthorized(error.data)) { + // Handle auth errors + _this.loginErrorCount++; + if (_this.loginErrorCount > _this.maxLoginAttempts) { + _this.loginErrorCount = 0; + return null; + } else { + return _this.loginOnce().then(function () { + return _this.request(method, params); + }); + } + } else { + // Handle API errors + var message = error.data ? error.data : error.statusText; + _this.alertAPIError(message); + } + }); + } + }, { + key: 'alertAPIError', + value: function alertAPIError(message) { + var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5000; + + this.alertSrv.set("Zabbix API Error", message, 'error', timeout); + } + + /** + * When API unauthenticated or auth token expired each request produce login() + * call. But auth token is common to all requests. This function wraps login() method + * and call it once. If login() already called just wait for it (return its promise). + * @return login promise + */ + + }, { + key: 'loginOnce', + value: function loginOnce() { + var _this2 = this; + + if (!this.loginPromise) { + this.loginPromise = Promise.resolve(this.login().then(function (auth) { + _this2.auth = auth; + _this2.loginPromise = null; + return auth; + })); + } + return this.loginPromise; + } + + /** + * Get authentication token. + */ + + }, { + key: 'login', + value: function login() { + return this.zabbixAPICore.login(this.url, this.username, this.password, this.requestOptions); + } + + /** + * Get Zabbix API version + */ + + }, { + key: 'getVersion', + value: function getVersion() { + return this.zabbixAPICore.getVersion(this.url, this.requestOptions); + } + + //////////////////////////////// + // Zabbix API method wrappers // + //////////////////////////////// + + }, { + key: 'acknowledgeEvent', + value: function acknowledgeEvent(eventid, message) { + var params = { + eventids: eventid, + message: message + }; + + return this.request('event.acknowledge', params); + } + }, { + key: 'getGroups', + value: function getGroups() { + var params = { + output: ['name'], + sortfield: 'name', + real_hosts: true + }; + + return this.request('hostgroup.get', params); + } + }, { + key: 'getHosts', + value: function getHosts(groupids) { + var params = { + output: ['name', 'host'], + sortfield: 'name' + }; + if (groupids) { + params.groupids = groupids; + } + + return this.request('host.get', params); + } + }, { + key: 'getApps', + value: function getApps(hostids) { + var params = { + output: ['applicationid', 'name'], + hostids: hostids + }; + + return this.request('application.get', params); + } + + /** + * Get Zabbix items + * @param {[type]} hostids host ids + * @param {[type]} appids application ids + * @param {String} itemtype 'num' or 'text' + * @return {[type]} array of items + */ + + }, { + key: 'getItems', + value: function getItems(hostids, appids, itemtype) { + var params = { + output: ['name', 'key_', 'value_type', 'hostid', 'status', 'state'], + sortfield: 'name', + webitems: true, + filter: {}, + selectHosts: ['hostid', 'name'] + }; + if (hostids) { + params.hostids = hostids; + } + if (appids) { + params.applicationids = appids; + } + if (itemtype === 'num') { + // Return only numeric metrics + params.filter.value_type = [0, 3]; + } + if (itemtype === 'text') { + // Return only text metrics + params.filter.value_type = [1, 2, 4]; + } + + return this.request('item.get', params).then(expandItems); + + function expandItems(items) { + items.forEach(function (item) { + item.item = item.name; + item.name = utils.expandItemName(item.item, item.key_); + return item; + }); + return items; + } + } + }, { + key: 'getLastValue', + value: function getLastValue(itemid) { + var params = { + output: ['lastvalue'], + itemids: itemid + }; + return this.request('item.get', params).then(function (items) { + return items.length ? items[0].lastvalue : null; + }); + } + + /** + * Perform history query from Zabbix API + * + * @param {Array} items Array of Zabbix item objects + * @param {Number} timeFrom Time in seconds + * @param {Number} timeTill Time in seconds + * @return {Array} Array of Zabbix history objects + */ + + }, { + key: 'getHistory', + value: function getHistory(items, timeFrom, timeTill) { + var _this3 = this; + + // 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'); + var params = { + output: 'extend', + history: value_type, + itemids: itemids, + sortfield: 'clock', + sortorder: 'ASC', + time_from: timeFrom + }; + + // Relative queries (e.g. last hour) don't include an end time + if (timeTill) { + params.time_till = timeTill; + } + + return _this3.request('history.get', params); + }); + + return Promise.all(promises).then(_lodash2.default.flatten); + } + + /** + * Perform trends query from Zabbix API + * Use trends api extension from ZBXNEXT-1193 patch. + * + * @param {Array} items Array of Zabbix item objects + * @param {Number} time_from Time in seconds + * @param {Number} time_till Time in seconds + * @return {Array} Array of Zabbix trend objects + */ + + }, { + key: 'getTrend_ZBXNEXT1193', + value: function getTrend_ZBXNEXT1193(items, timeFrom, timeTill) { + var _this4 = this; + + // 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'); + var params = { + output: 'extend', + trend: value_type, + itemids: itemids, + sortfield: 'clock', + sortorder: 'ASC', + time_from: timeFrom + }; + + // Relative queries (e.g. last hour) don't include an end time + if (timeTill) { + params.time_till = timeTill; + } + + return _this4.request('trend.get', params); + }); + + return Promise.all(promises).then(_lodash2.default.flatten); + } + }, { + key: 'getTrend_30', + value: function getTrend_30(items, time_from, time_till, value_type) { + var self = this; + var itemids = _lodash2.default.map(items, 'itemid'); + + var params = { + output: ["itemid", "clock", value_type], + itemids: itemids, + time_from: time_from + }; + + // Relative queries (e.g. last hour) don't include an end time + if (time_till) { + params.time_till = time_till; + } + + return self.request('trend.get', params); + } + }, { + key: 'getITService', + value: function getITService(serviceids) { + var params = { + output: 'extend', + serviceids: serviceids + }; + return this.request('service.get', params); + } + }, { + key: 'getSLA', + value: function getSLA(serviceids, timeFrom, timeTo) { + var params = { + serviceids: serviceids, + intervals: [{ + from: timeFrom, + to: timeTo + }] + }; + return this.request('service.getsla', params); + } + }, { + key: 'getTriggers', + value: function getTriggers(groupids, hostids, applicationids, showTriggers, timeFrom, timeTo) { + var params = { + output: 'extend', + groupids: groupids, + hostids: hostids, + applicationids: applicationids, + expandDescription: true, + expandData: true, + expandComment: true, + monitored: true, + skipDependent: true, + //only_true: true, + filter: { + value: 1 + }, + selectGroups: ['name'], + selectHosts: ['name', 'host'], + selectItems: ['name', 'key_', 'lastvalue'], + selectLastEvent: 'extend' + }; + + if (showTriggers) { + params.filter.value = showTriggers; + } + + if (timeFrom || timeTo) { + params.lastChangeSince = timeFrom; + params.lastChangeTill = timeTo; + } + + return this.request('trigger.get', params); + } + }, { + key: 'getEvents', + value: function getEvents(objectids, timeFrom, timeTo, showEvents) { + var params = { + output: 'extend', + time_from: timeFrom, + time_till: timeTo, + objectids: objectids, + select_acknowledges: 'extend', + selectHosts: 'extend', + value: showEvents + }; + + return this.request('event.get', params); + } + }, { + key: 'getAcknowledges', + value: function getAcknowledges(eventids) { + var params = { + output: 'extend', + eventids: eventids, + preservekeys: true, + select_acknowledges: 'extend', + sortfield: 'clock', + sortorder: 'DESC' + }; + + return this.request('event.get', params).then(function (events) { + return _lodash2.default.filter(events, function (event) { + return event.acknowledges.length; + }); + }); + } + }]); + + return ZabbixAPI; + }(); + + return ZabbixAPI; +} + +function isNotAuthorized(message) { + return message === "Session terminated, re-login, please." || message === "Not authorised." || message === "Not authorized."; +} + +_angular2.default.module('grafana.services').factory('zabbixAPIService', ZabbixAPIServiceFactory); diff --git a/dist/test/datasource-zabbix/zabbixAPICore.service.js b/dist/test/datasource-zabbix/zabbixAPICore.service.js new file mode 100644 index 0000000..075f149 --- /dev/null +++ b/dist/test/datasource-zabbix/zabbixAPICore.service.js @@ -0,0 +1,142 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ZabbixAPIError = 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; }; }(); /** + * General Zabbix API methods + */ + +var _angular = require('angular'); + +var _angular2 = _interopRequireDefault(_angular); + +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 ZabbixAPICoreService = function () { + + /** @ngInject */ + function ZabbixAPICoreService(backendSrv) { + _classCallCheck(this, ZabbixAPICoreService); + + this.backendSrv = backendSrv; + } + + /** + * Request data from Zabbix API + * @return {object} response.result + */ + + + _createClass(ZabbixAPICoreService, [{ + key: 'request', + value: function request(api_url, method, params, options, auth) { + var requestData = { + jsonrpc: '2.0', + method: method, + params: params, + id: 1 + }; + + if (auth === "") { + // Reject immediately if not authenticated + return Promise.reject(new ZabbixAPIError({ data: "Not authorised." })); + } else if (auth) { + // Set auth parameter only if it needed + requestData.auth = auth; + } + + var requestOptions = { + method: 'POST', + url: api_url, + data: requestData, + headers: { + 'Content-Type': 'application/json' + } + }; + + // Set request options for basic auth + if (options.basicAuth || options.withCredentials) { + requestOptions.withCredentials = true; + } + if (options.basicAuth) { + requestOptions.headers.Authorization = options.basicAuth; + } + + return this.datasourceRequest(requestOptions); + } + }, { + key: 'datasourceRequest', + value: function datasourceRequest(requestOptions) { + return this.backendSrv.datasourceRequest(requestOptions).then(function (response) { + if (!response.data) { + return Promise.reject(new ZabbixAPIError({ data: "General Error, no data" })); + } else if (response.data.error) { + + // Handle Zabbix API errors + return Promise.reject(new ZabbixAPIError(response.data.error)); + } + + // Success + return response.data.result; + }); + } + + /** + * Get authentication token. + * @return {string} auth token + */ + + }, { + key: 'login', + value: function login(api_url, username, password, options) { + var params = { + user: username, + password: password + }; + return this.request(api_url, 'user.login', params, options, null); + } + + /** + * Get Zabbix API version + * Matches the version of Zabbix starting from Zabbix 2.0.4 + */ + + }, { + key: 'getVersion', + value: function getVersion(api_url, options) { + return this.request(api_url, 'apiinfo.version', [], options); + } + }]); + + return ZabbixAPICoreService; +}(); + +// Define zabbix API exception type + + +var ZabbixAPIError = exports.ZabbixAPIError = function () { + function ZabbixAPIError(error) { + _classCallCheck(this, ZabbixAPIError); + + this.code = error.code; + this.name = error.data; + this.message = error.data; + this.data = error.data; + } + + _createClass(ZabbixAPIError, [{ + key: 'toString', + value: function toString() { + return this.name + ": " + this.message; + } + }]); + + return ZabbixAPIError; +}(); + +_angular2.default.module('grafana.services').service('zabbixAPICoreService', ZabbixAPICoreService); diff --git a/dist/test/datasource-zabbix/zabbixCachingProxy.service.js b/dist/test/datasource-zabbix/zabbixCachingProxy.service.js new file mode 100644 index 0000000..a378045 --- /dev/null +++ b/dist/test/datasource-zabbix/zabbixCachingProxy.service.js @@ -0,0 +1,215 @@ +'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 _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +// Use factory() instead service() for multiple datasources support. +// Each datasource instance must initialize its own cache. + +/** @ngInject */ +function ZabbixCachingProxyFactory() { + var ZabbixCachingProxy = function () { + function ZabbixCachingProxy(zabbixAPI, cacheOptions) { + _classCallCheck(this, ZabbixCachingProxy); + + this.zabbixAPI = zabbixAPI; + this.cacheEnabled = cacheOptions.enabled; + this.ttl = cacheOptions.ttl || 600000; // 10 minutes by default + + // Internal objects for data storing + this.cache = { + groups: {}, + hosts: {}, + applications: {}, + items: {}, + history: {}, + trends: {} + }; + + this.historyPromises = {}; + + // Don't run duplicated history requests + this.getHistory = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getHistory, this.zabbixAPI), this.historyPromises, getHistoryRequestHash); + + // Don't run duplicated requests + this.groupPromises = {}; + this.getGroupsOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getGroups, this.zabbixAPI), this.groupPromises, getRequestHash); + + this.hostPromises = {}; + this.getHostsOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getHosts, this.zabbixAPI), this.hostPromises, getRequestHash); + + this.appPromises = {}; + this.getAppsOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getApps, this.zabbixAPI), this.appPromises, getRequestHash); + + this.itemPromises = {}; + this.getItemsOnce = callAPIRequestOnce(_lodash2.default.bind(this.zabbixAPI.getItems, this.zabbixAPI), this.itemPromises, getRequestHash); + } + + _createClass(ZabbixCachingProxy, [{ + key: 'isExpired', + value: function isExpired(cacheObject) { + if (cacheObject) { + var object_age = Date.now() - cacheObject.timestamp; + return !(cacheObject.timestamp && object_age < this.ttl); + } else { + return true; + } + } + + /** + * Check that result is present in cache and up to date + * or send request to API. + */ + + }, { + key: 'proxyRequest', + value: function proxyRequest(request, params, cacheObject) { + var hash = getRequestHash(params); + if (this.cacheEnabled && !this.isExpired(cacheObject[hash])) { + return Promise.resolve(cacheObject[hash].value); + } else { + return request.apply(undefined, _toConsumableArray(params)).then(function (result) { + cacheObject[hash] = { + value: result, + timestamp: Date.now() + }; + return result; + }); + } + } + }, { + key: 'getGroups', + value: function getGroups() { + return this.proxyRequest(this.getGroupsOnce, [], this.cache.groups); + } + }, { + key: 'getHosts', + value: function getHosts(groupids) { + return this.proxyRequest(this.getHostsOnce, [groupids], this.cache.hosts); + } + }, { + key: 'getApps', + value: function getApps(hostids) { + return this.proxyRequest(this.getAppsOnce, [hostids], this.cache.applications); + } + }, { + key: 'getItems', + value: function getItems(hostids, appids, itemtype) { + var params = [hostids, appids, itemtype]; + return this.proxyRequest(this.getItemsOnce, params, this.cache.items); + } + }, { + key: 'getHistoryFromCache', + value: function getHistoryFromCache(items, time_from, time_till) { + var historyStorage = this.cache.history; + var full_history; + var expired = _lodash2.default.filter(_lodash2.default.keyBy(items, 'itemid'), function (item, itemid) { + return !historyStorage[itemid]; + }); + if (expired.length) { + return this.zabbixAPI.getHistory(expired, time_from, time_till).then(function (history) { + var grouped_history = _lodash2.default.groupBy(history, 'itemid'); + _lodash2.default.forEach(expired, function (item) { + var itemid = item.itemid; + historyStorage[itemid] = item; + historyStorage[itemid].time_from = time_from; + historyStorage[itemid].time_till = time_till; + historyStorage[itemid].history = grouped_history[itemid]; + }); + full_history = _lodash2.default.map(items, function (item) { + return historyStorage[item.itemid].history; + }); + return _lodash2.default.flatten(full_history, true); + }); + } else { + full_history = _lodash2.default.map(items, function (item) { + return historyStorage[item.itemid].history; + }); + return Promise.resolve(_lodash2.default.flatten(full_history, true)); + } + } + }, { + key: 'getHistoryFromAPI', + value: function getHistoryFromAPI(items, time_from, time_till) { + return this.zabbixAPI.getHistory(items, time_from, time_till); + } + }]); + + return ZabbixCachingProxy; + }(); + + return ZabbixCachingProxy; +} + +_angular2.default.module('grafana.services').factory('ZabbixCachingProxy', ZabbixCachingProxyFactory); + +/** + * Wrap zabbix API request to prevent multiple calls + * with same params when waiting for result. + */ +function callAPIRequestOnce(func, promiseKeeper, argsHashFunc) { + return function () { + var hash = argsHashFunc(arguments); + if (!promiseKeeper[hash]) { + promiseKeeper[hash] = Promise.resolve(func.apply(this, arguments).then(function (result) { + promiseKeeper[hash] = null; + return result; + })); + } + return promiseKeeper[hash]; + }; +} + +function getRequestHash(args) { + var requestStamp = _lodash2.default.map(args, function (arg) { + if (arg === undefined) { + return 'undefined'; + } else { + if (_lodash2.default.isArray(arg)) { + return arg.sort().toString(); + } else { + return arg.toString(); + } + } + }).join(); + return requestStamp.getHash(); +} + +function getHistoryRequestHash(args) { + var itemids = _lodash2.default.map(args[0], 'itemid'); + var stamp = itemids.join() + args[1] + args[2]; + return stamp.getHash(); +} + +String.prototype.getHash = function () { + var hash = 0, + i, + chr, + len; + if (this.length !== 0) { + for (i = 0, len = this.length; i < len; i++) { + chr = this.charCodeAt(i); + hash = (hash << 5) - hash + chr; + hash |= 0; // Convert to 32bit integer + } + } + return hash; +}; + +// Fix for backward compatibility with lodash 2.4 +if (!_lodash2.default.keyBy) { + _lodash2.default.keyBy = _lodash2.default.indexBy; +} diff --git a/dist/test/module.js b/dist/test/module.js new file mode 100644 index 0000000..ac26ed7 --- /dev/null +++ b/dist/test/module.js @@ -0,0 +1,10 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ConfigCtrl = undefined; + +var _config = require('./components/config'); + +exports.ConfigCtrl = _config.ZabbixAppConfigCtrl; diff --git a/dist/test/panel-triggers/ack-tooltip.directive.js b/dist/test/panel-triggers/ack-tooltip.directive.js new file mode 100644 index 0000000..e74683e --- /dev/null +++ b/dist/test/panel-triggers/ack-tooltip.directive.js @@ -0,0 +1,122 @@ +'use strict'; + +var _angular = require('angular'); + +var _angular2 = _interopRequireDefault(_angular); + +var _jquery = require('jquery'); + +var _jquery2 = _interopRequireDefault(_jquery); + +var _tetherDrop = require('tether-drop'); + +var _tetherDrop2 = _interopRequireDefault(_tetherDrop); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** @ngInject */ +_angular2.default.module('grafana.directives').directive('ackTooltip', function ($sanitize, $compile) { + var buttonTemplate = ''; + + return { + scope: { + ack: "=", + trigger: "=", + onAck: "=", + context: "=" + }, + link: function link(scope, element) { + var acknowledges = scope.ack; + var $button = (0, _jquery2.default)(buttonTemplate); + $button.appendTo(element); + + $button.click(function () { + var tooltip = '
                            '; + + if (acknowledges && acknowledges.length) { + tooltip += '' + '' + '' + '' + ''; + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = acknowledges[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var ack = _step.value; + + tooltip += '' + '' + ''; + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + tooltip += '
                            TimeUserComments
                            ' + ack.time + '' + ack.user + '' + ack.message + '
                            '; + } else { + tooltip += 'Add acknowledge'; + } + + var addAckButtonTemplate = '
                            ' + '
                            '; + tooltip += addAckButtonTemplate; + tooltip += '
                            '; + + var drop = new _tetherDrop2.default({ + target: element[0], + content: tooltip, + position: "bottom left", + classes: 'drop-popover ack-tooltip', + openOn: 'hover', + hoverCloseDelay: 500, + tetherOptions: { + constraints: [{ to: 'window', pin: true, attachment: "both" }] + } + }); + + drop.open(); + drop.on('close', closeDrop); + + (0, _jquery2.default)('#add-acknowledge-btn').on('click', onAddAckButtonClick); + + function onAddAckButtonClick() { + var inputTemplate = '
                            ' + '' + '' + '
                            '; + + var $input = (0, _jquery2.default)(inputTemplate); + var $addAckButton = (0, _jquery2.default)('.ack-tooltip .ack-add-button'); + $addAckButton.replaceWith($input); + (0, _jquery2.default)('.ack-tooltip #cancel-ack-button').on('click', onAckCancelButtonClick); + (0, _jquery2.default)('.ack-tooltip #send-ack-button').on('click', onAckSendlButtonClick); + } + + function onAckCancelButtonClick() { + (0, _jquery2.default)('.ack-tooltip .ack-input-group').replaceWith(addAckButtonTemplate); + (0, _jquery2.default)('#add-acknowledge-btn').on('click', onAddAckButtonClick); + } + + function onAckSendlButtonClick() { + var message = (0, _jquery2.default)('.ack-tooltip #ack-message')[0].value; + var onAck = scope.onAck.bind(scope.context); + onAck(scope.trigger, message).then(function () { + closeDrop(); + }); + } + + function closeDrop() { + setTimeout(function () { + drop.destroy(); + }); + } + }); + + $compile(element.contents())(scope); + } + }; +}); diff --git a/dist/test/panel-triggers/editor.js b/dist/test/panel-triggers/editor.js new file mode 100644 index 0000000..1403a32 --- /dev/null +++ b/dist/test/panel-triggers/editor.js @@ -0,0 +1,224 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +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; }; }(); /** + * Grafana-Zabbix + * Zabbix plugin for Grafana. + * http://github.com/alexanderzobnin/grafana-zabbix + * + * Trigger panel. + * This feature sponsored by CORE IT + * http://www.coreit.fr + * + * Copyright 2015 Alexander Zobnin alexanderzobnin@gmail.com + * Licensed under the Apache License, Version 2.0 + */ + +exports.triggerPanelEditor = triggerPanelEditor; + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _utils = require('../datasource-zabbix/utils'); + +var utils = _interopRequireWildcard(_utils); + +require('../datasource-zabbix/css/query-editor.css!'); + +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 }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var TriggerPanelEditorCtrl = function () { + + /** @ngInject */ + function TriggerPanelEditorCtrl($scope, $rootScope, uiSegmentSrv, datasourceSrv, templateSrv, popoverSrv) { + var _this = this; + + _classCallCheck(this, TriggerPanelEditorCtrl); + + $scope.editor = this; + this.panelCtrl = $scope.ctrl; + this.panel = this.panelCtrl.panel; + + this.datasourceSrv = datasourceSrv; + this.templateSrv = templateSrv; + this.popoverSrv = popoverSrv; + + // Map functions for bs-typeahead + this.getGroupNames = _lodash2.default.partial(getMetricNames, this, 'groupList'); + this.getHostNames = _lodash2.default.partial(getMetricNames, this, 'hostList'); + this.getApplicationNames = _lodash2.default.partial(getMetricNames, this, 'appList'); + + // Update metric suggestion when template variable was changed + $rootScope.$on('template-variable-value-updated', function () { + return _this.onVariableChange(); + }); + + this.fontSizes = ['80%', '90%', '100%', '110%', '120%', '130%', '150%', '160%', '180%', '200%', '220%', '250%']; + this.ackFilters = ['all triggers', 'unacknowledged', 'acknowledged']; + this.sortByFields = [{ text: 'last change', value: 'lastchange' }, { text: 'severity', value: 'priority' }]; + this.showEventsFields = [{ text: 'All', value: [0, 1] }, { text: 'OK', value: [0] }, { text: 'Problems', value: 1 }]; + + // Load scope defaults + var scopeDefaults = { + metric: {}, + inputStyles: {}, + oldTarget: _lodash2.default.cloneDeep(this.panel.triggers) + }; + _lodash2.default.defaults(this, scopeDefaults); + + // Set default datasource + this.datasources = _lodash2.default.map(this.getZabbixDataSources(), 'name'); + if (!this.panel.datasource) { + this.panel.datasource = this.datasources[0]; + } + // Load datasource + this.datasourceSrv.get(this.panel.datasource).then(function (datasource) { + _this.datasource = datasource; + _this.zabbix = datasource.zabbix; + _this.queryBuilder = datasource.queryBuilder; + _this.initFilters(); + _this.panelCtrl.refresh(); + }); + } + + _createClass(TriggerPanelEditorCtrl, [{ + key: 'initFilters', + value: function initFilters() { + return Promise.all([this.suggestGroups(), this.suggestHosts(), this.suggestApps()]); + } + }, { + key: 'suggestGroups', + value: function suggestGroups() { + var _this2 = this; + + return this.zabbix.getAllGroups().then(function (groups) { + _this2.metric.groupList = groups; + return groups; + }); + } + }, { + key: 'suggestHosts', + value: function suggestHosts() { + var _this3 = this; + + var groupFilter = this.datasource.replaceTemplateVars(this.panel.triggers.group.filter); + return this.zabbix.getAllHosts(groupFilter).then(function (hosts) { + _this3.metric.hostList = hosts; + return hosts; + }); + } + }, { + key: 'suggestApps', + value: function suggestApps() { + var _this4 = this; + + var groupFilter = this.datasource.replaceTemplateVars(this.panel.triggers.group.filter); + var hostFilter = this.datasource.replaceTemplateVars(this.panel.triggers.host.filter); + return this.zabbix.getAllApps(groupFilter, hostFilter).then(function (apps) { + _this4.metric.appList = apps; + return apps; + }); + } + }, { + key: 'onVariableChange', + value: function onVariableChange() { + if (this.isContainsVariables()) { + this.targetChanged(); + } + } + + /** + * Check query for template variables + */ + + }, { + key: 'isContainsVariables', + value: function isContainsVariables() { + var _this5 = this; + + return _lodash2.default.some(['group', 'host', 'application'], function (field) { + return utils.isTemplateVariable(_this5.panel.triggers[field].filter, _this5.templateSrv.variables); + }); + } + }, { + key: 'targetChanged', + value: function targetChanged() { + this.initFilters(); + this.panelCtrl.refresh(); + } + }, { + key: 'parseTarget', + value: function parseTarget() { + this.initFilters(); + var newTarget = _lodash2.default.cloneDeep(this.panel.triggers); + if (!_lodash2.default.isEqual(this.oldTarget, this.panel.triggers)) { + this.oldTarget = newTarget; + this.panelCtrl.refresh(); + } + } + }, { + key: 'refreshTriggerSeverity', + value: function refreshTriggerSeverity() { + _lodash2.default.each(this.triggerList, function (trigger) { + trigger.color = this.panel.triggerSeverity[trigger.priority].color; + trigger.severity = this.panel.triggerSeverity[trigger.priority].severity; + }); + this.panelCtrl.refresh(); + } + }, { + key: 'datasourceChanged', + value: function datasourceChanged() { + this.panelCtrl.refresh(); + } + }, { + key: 'changeTriggerSeverityColor', + value: function changeTriggerSeverityColor(trigger, color) { + this.panel.triggerSeverity[trigger.priority].color = color; + this.refreshTriggerSeverity(); + } + }, { + key: 'isRegex', + value: function isRegex(str) { + return utils.isRegex(str); + } + }, { + key: 'isVariable', + value: function isVariable(str) { + return utils.isTemplateVariable(str, this.templateSrv.variables); + } + }, { + key: 'getZabbixDataSources', + value: function getZabbixDataSources() { + var ZABBIX_DS_ID = 'alexanderzobnin-zabbix-datasource'; + return _lodash2.default.filter(this.datasourceSrv.getMetricSources(), function (datasource) { + return datasource.meta.id === ZABBIX_DS_ID && datasource.value; + }); + } + }]); + + return TriggerPanelEditorCtrl; +}(); + +// Get list of metric names for bs-typeahead directive + + +function getMetricNames(scope, metricList) { + return _lodash2.default.uniq(_lodash2.default.map(scope.metric[metricList], 'name')); +} + +function triggerPanelEditor() { + return { + restrict: 'E', + scope: true, + templateUrl: 'public/plugins/alexanderzobnin-zabbix-app/panel-triggers/editor.html', + controller: TriggerPanelEditorCtrl + }; +} diff --git a/dist/test/panel-triggers/module.js b/dist/test/panel-triggers/module.js new file mode 100644 index 0000000..201cd1d --- /dev/null +++ b/dist/test/panel-triggers/module.js @@ -0,0 +1,407 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PanelCtrl = exports.TriggerPanelCtrl = 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); + +var _jquery = require('jquery'); + +var _jquery2 = _interopRequireDefault(_jquery); + +var _moment = require('moment'); + +var _moment2 = _interopRequireDefault(_moment); + +var _utils = require('../datasource-zabbix/utils'); + +var utils = _interopRequireWildcard(_utils); + +var _sdk = require('app/plugins/sdk'); + +var _editor = require('./editor'); + +require('./ack-tooltip.directive'); + +require('./css/panel_triggers.css!'); + +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 }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** + * Grafana-Zabbix + * Zabbix plugin for Grafana. + * http://github.com/alexanderzobnin/grafana-zabbix + * + * Trigger panel. + * This feature sponsored by CORE IT + * http://www.coreit.fr + * + * Copyright 2015 Alexander Zobnin alexanderzobnin@gmail.com + * Licensed under the Apache License, Version 2.0 + */ + +var defaultSeverity = [{ priority: 0, severity: 'Not classified', color: '#B7DBAB', show: true }, { priority: 1, severity: 'Information', color: '#82B5D8', show: true }, { priority: 2, severity: 'Warning', color: '#E5AC0E', show: true }, { priority: 3, severity: 'Average', color: '#C15C17', show: true }, { priority: 4, severity: 'High', color: '#BF1B00', show: true }, { priority: 5, severity: 'Disaster', color: '#890F02', show: true }]; + +var panelDefaults = { + datasource: null, + triggers: { + group: { filter: "" }, + host: { filter: "" }, + application: { filter: "" }, + trigger: { filter: "" } + }, + hostField: true, + statusField: false, + severityField: false, + lastChangeField: true, + ageField: true, + infoField: true, + limit: 10, + showTriggers: 'all triggers', + sortTriggersBy: { text: 'last change', value: 'lastchange' }, + showEvents: { text: 'Problems', value: '1' }, + triggerSeverity: defaultSeverity, + okEventColor: 'rgba(0, 245, 153, 0.45)', + ackEventColor: 'rgba(0, 0, 0, 0)', + scroll: true, + pageSize: 10, + fontSize: '100%' +}; + +var triggerStatusMap = { + '0': 'OK', + '1': 'Problem' +}; + +var defaultTimeFormat = "DD MMM YYYY HH:mm:ss"; + +var TriggerPanelCtrl = function (_PanelCtrl) { + _inherits(TriggerPanelCtrl, _PanelCtrl); + + /** @ngInject */ + function TriggerPanelCtrl($scope, $injector, $element, datasourceSrv, templateSrv, contextSrv) { + _classCallCheck(this, TriggerPanelCtrl); + + var _this = _possibleConstructorReturn(this, (TriggerPanelCtrl.__proto__ || Object.getPrototypeOf(TriggerPanelCtrl)).call(this, $scope, $injector)); + + _this.datasourceSrv = datasourceSrv; + _this.templateSrv = templateSrv; + _this.contextSrv = contextSrv; + _this.triggerStatusMap = triggerStatusMap; + _this.defaultTimeFormat = defaultTimeFormat; + _this.pageIndex = 0; + _this.triggerList = []; + _this.currentTriggersPage = []; + + // Load panel defaults + // _.cloneDeep() need for prevent changing shared defaultSeverity. + // Load object "by value" istead "by reference". + _lodash2.default.defaults(_this.panel, _lodash2.default.cloneDeep(panelDefaults)); + + _this.events.on('init-edit-mode', _this.onInitEditMode.bind(_this)); + _this.events.on('refresh', _this.onRefresh.bind(_this)); + return _this; + } + + _createClass(TriggerPanelCtrl, [{ + key: 'onInitEditMode', + value: function onInitEditMode() { + this.addEditorTab('Options', _editor.triggerPanelEditor, 2); + } + }, { + key: 'onRefresh', + value: function onRefresh() { + var _this2 = this; + + // clear loading/error state + delete this.error; + this.loading = true; + + return this.refreshData().then(function (triggerList) { + // Limit triggers number + _this2.triggerList = triggerList.slice(0, _this2.panel.limit); + + _this2.getCurrentTriggersPage(); + + // Notify panel that request is finished + _this2.loading = false; + + _this2.render(_this2.triggerList); + }); + } + }, { + key: 'refreshData', + value: function refreshData() { + return this.getTriggers().then(this.getAcknowledges.bind(this)).then(this.filterTriggers.bind(this)); + } + }, { + key: 'getTriggers', + value: function getTriggers() { + var _this3 = this; + + return this.datasourceSrv.get(this.panel.datasource).then(function (datasource) { + var zabbix = datasource.zabbix; + _this3.zabbix = zabbix; + var showEvents = _this3.panel.showEvents.value; + var triggerFilter = _this3.panel.triggers; + + // Replace template variables + var groupFilter = datasource.replaceTemplateVars(triggerFilter.group.filter); + var hostFilter = datasource.replaceTemplateVars(triggerFilter.host.filter); + var appFilter = datasource.replaceTemplateVars(triggerFilter.application.filter); + + var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents); + return getTriggers.then(function (triggers) { + return _lodash2.default.map(triggers, _this3.formatTrigger.bind(_this3)); + }); + }); + } + }, { + key: 'getAcknowledges', + value: function getAcknowledges(triggerList) { + var _this4 = this; + + // Request acknowledges for trigger + var eventids = _lodash2.default.map(triggerList, function (trigger) { + return trigger.lastEvent.eventid; + }); + + return this.zabbix.getAcknowledges(eventids).then(function (events) { + + // Map events to triggers + _lodash2.default.each(triggerList, function (trigger) { + var event = _lodash2.default.find(events, function (event) { + return event.eventid === trigger.lastEvent.eventid; + }); + + if (event) { + trigger.acknowledges = _lodash2.default.map(event.acknowledges, function (ack) { + var timestamp = _moment2.default.unix(ack.clock); + if (_this4.panel.customLastChangeFormat) { + ack.time = timestamp.format(_this4.panel.lastChangeFormat); + } else { + ack.time = timestamp.format(_this4.defaultTimeFormat); + } + ack.user = ack.alias + ' (' + ack.name + ' ' + ack.surname + ')'; + return ack; + }); + + // Mark acknowledged triggers with different color + if (_this4.panel.markAckEvents && trigger.acknowledges.length) { + trigger.color = _this4.panel.ackEventColor; + } + } + }); + + return triggerList; + }); + } + }, { + key: 'filterTriggers', + value: function filterTriggers(triggerList) { + var _this5 = this; + + // Filter triggers by description + var triggerFilter = this.panel.triggers.trigger.filter; + if (triggerFilter) { + triggerList = _filterTriggers(triggerList, triggerFilter); + } + + // Filter acknowledged triggers + if (this.panel.showTriggers === 'unacknowledged') { + triggerList = _lodash2.default.filter(triggerList, function (trigger) { + return !trigger.acknowledges; + }); + } else if (this.panel.showTriggers === 'acknowledged') { + triggerList = _lodash2.default.filter(triggerList, 'acknowledges'); + } else { + triggerList = triggerList; + } + + // Filter triggers by severity + triggerList = _lodash2.default.filter(triggerList, function (trigger) { + return _this5.panel.triggerSeverity[trigger.priority].show; + }); + + // Sort triggers + if (this.panel.sortTriggersBy.value === 'priority') { + triggerList = _lodash2.default.sortBy(triggerList, 'priority').reverse(); + } else { + triggerList = _lodash2.default.sortBy(triggerList, 'lastchangeUnix').reverse(); + } + + return triggerList; + } + }, { + key: 'formatTrigger', + value: function formatTrigger(trigger) { + var triggerObj = trigger; + + // Format last change and age + trigger.lastchangeUnix = Number(trigger.lastchange); + var timestamp = _moment2.default.unix(trigger.lastchangeUnix); + if (this.panel.customLastChangeFormat) { + // User defined format + triggerObj.lastchange = timestamp.format(this.panel.lastChangeFormat); + } else { + triggerObj.lastchange = timestamp.format(this.defaultTimeFormat); + } + triggerObj.age = timestamp.fromNow(true); + + // Set host that the trigger belongs + if (trigger.hosts.length) { + triggerObj.host = trigger.hosts[0].name; + triggerObj.hostTechName = trigger.hosts[0].host; + } + + // Set color + if (trigger.value === '1') { + // Problem state + triggerObj.color = this.panel.triggerSeverity[trigger.priority].color; + } else { + // OK state + triggerObj.color = this.panel.okEventColor; + } + + triggerObj.severity = this.panel.triggerSeverity[trigger.priority].severity; + return triggerObj; + } + }, { + key: 'switchComment', + value: function switchComment(trigger) { + trigger.showComment = !trigger.showComment; + } + }, { + key: 'acknowledgeTrigger', + value: function acknowledgeTrigger(trigger, message) { + var eventid = trigger.lastEvent.eventid; + var grafana_user = this.contextSrv.user.name; + var ack_message = grafana_user + ' (Grafana): ' + message; + return this.datasourceSrv.get(this.panel.datasource).then(function (datasource) { + var zabbixAPI = datasource.zabbix.zabbixAPI; + return zabbixAPI.acknowledgeEvent(eventid, ack_message); + }).then(this.onRefresh.bind(this)); + } + }, { + key: 'getCurrentTriggersPage', + value: function getCurrentTriggersPage() { + var pageSize = this.panel.pageSize || 10; + var startPos = this.pageIndex * pageSize; + var endPos = Math.min(startPos + pageSize, this.triggerList.length); + this.currentTriggersPage = this.triggerList.slice(startPos, endPos); + return this.currentTriggersPage; + } + }, { + key: 'link', + value: function link(scope, elem, attrs, ctrl) { + var data; + var panel = ctrl.panel; + var pageCount = 0; + data = ctrl.triggerList; + + function getTableHeight() { + var panelHeight = ctrl.height; + + if (pageCount > 1) { + panelHeight -= 26; + } + + return panelHeight - 31 + 'px'; + } + + function switchPage(e) { + var el = (0, _jquery2.default)(e.currentTarget); + ctrl.pageIndex = parseInt(el.text(), 10) - 1; + + var pageSize = ctrl.panel.pageSize || 10; + var startPos = ctrl.pageIndex * pageSize; + var endPos = Math.min(startPos + pageSize, ctrl.triggerList.length); + ctrl.currentTriggersPage = ctrl.triggerList.slice(startPos, endPos); + + scope.$apply(); + renderPanel(); + } + + function appendPaginationControls(footerElem) { + footerElem.empty(); + + var pageSize = ctrl.panel.pageSize || 5; + pageCount = Math.ceil(data.length / pageSize); + if (pageCount === 1) { + return; + } + + var startPage = Math.max(ctrl.pageIndex - 3, 0); + var endPage = Math.min(pageCount, startPage + 9); + + var paginationList = (0, _jquery2.default)('
                              '); + + for (var i = startPage; i < endPage; i++) { + var activeClass = i === ctrl.pageIndex ? 'active' : ''; + var pageLinkElem = (0, _jquery2.default)('
                            • ' + (i + 1) + '
                            • '); + paginationList.append(pageLinkElem); + } + + footerElem.append(paginationList); + } + + function renderPanel() { + var panelElem = elem.parents('.panel'); + var rootElem = elem.find('.triggers-panel-scroll'); + var footerElem = elem.find('.triggers-panel-footer'); + + elem.css({ 'font-size': panel.fontSize }); + panelElem.addClass('triggers-panel-wrapper'); + appendPaginationControls(footerElem); + + rootElem.css({ 'max-height': panel.scroll ? getTableHeight() : '' }); + } + + elem.on('click', '.triggers-panel-page-link', switchPage); + + var unbindDestroy = scope.$on('$destroy', function () { + elem.off('click', '.triggers-panel-page-link'); + unbindDestroy(); + }); + + ctrl.events.on('render', function (renderData) { + data = renderData || data; + if (data) { + renderPanel(); + } + ctrl.renderingCompleted(); + }); + } + }]); + + return TriggerPanelCtrl; +}(_sdk.PanelCtrl); + +TriggerPanelCtrl.templateUrl = 'panel-triggers/module.html'; + +function _filterTriggers(triggers, triggerFilter) { + if (utils.isRegex(triggerFilter)) { + return _lodash2.default.filter(triggers, function (trigger) { + return utils.buildRegex(triggerFilter).test(trigger.description); + }); + } else { + return _lodash2.default.filter(triggers, function (trigger) { + return trigger.description === triggerFilter; + }); + } +} + +exports.TriggerPanelCtrl = TriggerPanelCtrl; +exports.PanelCtrl = TriggerPanelCtrl; diff --git a/src/panel-triggers/editor.html b/src/panel-triggers/editor.html index 39e96b8..b0510db 100644 --- a/src/panel-triggers/editor.html +++ b/src/panel-triggers/editor.html @@ -137,6 +137,17 @@ ng-change="editor.panelCtrl.refresh()">
                              +
                              +
                              + +
                              + +
                              +
                              +
                              diff --git a/src/panel-triggers/editor.js b/src/panel-triggers/editor.js index d8f2736..9bdf60f 100644 --- a/src/panel-triggers/editor.js +++ b/src/panel-triggers/editor.js @@ -36,17 +36,16 @@ class TriggerPanelEditorCtrl { // Update metric suggestion when template variable was changed $rootScope.$on('template-variable-value-updated', () => this.onVariableChange()); + this.fontSizes = ['80%', '90%', '100%', '110%', '120%', '130%', '150%', '160%', '180%', '200%', '220%', '250%']; this.ackFilters = [ 'all triggers', 'unacknowledged', 'acknowledged' ]; - this.sortByFields = [ { text: 'last change', value: 'lastchange' }, { text: 'severity', value: 'priority' } ]; - this.showEventsFields = [ { text: 'All', value: [0,1] }, { text: 'OK', value: [0] }, diff --git a/src/panel-triggers/module.js b/src/panel-triggers/module.js index 56b967c..1d9eab1 100644 --- a/src/panel-triggers/module.js +++ b/src/panel-triggers/module.js @@ -51,7 +51,8 @@ var panelDefaults = { okEventColor: 'rgba(0, 245, 153, 0.45)', ackEventColor: 'rgba(0, 0, 0, 0)', scroll: true, - pageSize: 10 + pageSize: 10, + fontSize: '100%', }; var triggerStatusMap = { From a68548ddbb9da60fa2b539c2ac2b5cfe04de9f98 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 10 Feb 2017 16:33:08 +0300 Subject: [PATCH 08/10] Grunt: fix watch task. --- Gruntfile.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index fd3051f..b9a0460 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -140,9 +140,9 @@ module.exports = function(grunt) { 'clean', 'copy:src_to_dist', 'copy:pluginDef', - 'jshint', - 'jscs', 'sass', - 'babel:dist' + 'babel', + 'jshint', + 'jscs' ]); }; From 5d33462d8e744e024d448896064fd3c4fd3be670 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 10 Feb 2017 16:57:13 +0300 Subject: [PATCH 09/10] Triggers Panel: allow to hide hosts in maintenance, closes #186 --- dist/datasource-zabbix/zabbix.js | 4 ++-- dist/datasource-zabbix/zabbix.js.map | 2 +- dist/datasource-zabbix/zabbixAPI.service.js | 6 +++++- dist/datasource-zabbix/zabbixAPI.service.js.map | 2 +- dist/panel-triggers/editor.html | 10 ++++++++-- dist/panel-triggers/module.js | 4 +++- dist/panel-triggers/module.js.map | 2 +- dist/test/datasource-zabbix/zabbix.js | 4 ++-- dist/test/datasource-zabbix/zabbixAPI.service.js | 6 +++++- dist/test/panel-triggers/module.js | 4 +++- src/datasource-zabbix/zabbix.js | 4 ++-- src/datasource-zabbix/zabbixAPI.service.js | 6 +++++- src/panel-triggers/editor.html | 10 ++++++++-- src/panel-triggers/module.js | 4 +++- 14 files changed, 49 insertions(+), 19 deletions(-) diff --git a/dist/datasource-zabbix/zabbix.js b/dist/datasource-zabbix/zabbix.js index 83e8875..2f20188 100644 --- a/dist/datasource-zabbix/zabbix.js +++ b/dist/datasource-zabbix/zabbix.js @@ -154,7 +154,7 @@ System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './za } }, { key: 'getTriggers', - value: function getTriggers(groupFilter, hostFilter, appFilter, showTriggers) { + value: function getTriggers(groupFilter, hostFilter, appFilter, showTriggers, hideHostsInMaintenance) { var _this5 = this; var promises = [this.getGroups(groupFilter), this.getHosts(groupFilter, hostFilter), this.getApps(groupFilter, hostFilter, appFilter)]; @@ -177,7 +177,7 @@ System.register(['angular', 'lodash', './utils', './zabbixAPI.service.js', './za return query; }).then(function (query) { - return _this5.zabbixAPI.getTriggers(query.groupids, query.hostids, query.applicationids, showTriggers); + return _this5.zabbixAPI.getTriggers(query.groupids, query.hostids, query.applicationids, showTriggers, hideHostsInMaintenance); }); } }]); diff --git a/dist/datasource-zabbix/zabbix.js.map b/dist/datasource-zabbix/zabbix.js.map index 8450b5d..456ee8f 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","getTrend","getEvents","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","itemFilter","getAllItems","showTriggers","promises","Promise","all","filteredGroups","results","filteredHosts","filteredApps","query","applicationids","flatten","getTriggers","findByName","list","name","finded","find","filterByName","filterByRegex","regex","filterPattern","utils","buildRegex","zbx_obj","test","isRegex","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\n this.getTrend = this.zabbixAPI.getTrend.bind(this.zabbixAPI);\n this.getEvents = this.zabbixAPI.getEvents.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 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, showTriggers) {\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\n .getTriggers(query.groupids, query.hostids, query.applicationids, showTriggers);\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 undefined\n */\nfunction findByName(list, name) {\n var finded = _.find(list, {'name': name});\n if (finded) {\n return [finded];\n } else {\n return undefined;\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 undefined\n */\nfunction filterByName(list, name) {\n var finded = _.filter(list, {'name': name});\n if (finded) {\n return finded;\n } else {\n return undefined;\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"]} \ No newline at end of file +{"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","getTrend","getEvents","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","itemFilter","getAllItems","showTriggers","hideHostsInMaintenance","promises","Promise","all","filteredGroups","results","filteredHosts","filteredApps","query","applicationids","flatten","getTriggers","findByName","list","name","finded","find","filterByName","filterByRegex","regex","filterPattern","utils","buildRegex","zbx_obj","test","isRegex","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\n this.getTrend = this.zabbixAPI.getTrend.bind(this.zabbixAPI);\n this.getEvents = this.zabbixAPI.getEvents.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 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, showTriggers, hideHostsInMaintenance) {\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\n .getTriggers(query.groupids, query.hostids, query.applicationids, showTriggers, hideHostsInMaintenance);\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 undefined\n */\nfunction findByName(list, name) {\n var finded = _.find(list, {'name': name});\n if (finded) {\n return [finded];\n } else {\n return undefined;\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 undefined\n */\nfunction filterByName(list, name) {\n var finded = _.filter(list, {'name': name});\n if (finded) {\n return finded;\n } else {\n return undefined;\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"]} \ No newline at end of file diff --git a/dist/datasource-zabbix/zabbixAPI.service.js b/dist/datasource-zabbix/zabbixAPI.service.js index 83395c3..fe8a766 100644 --- a/dist/datasource-zabbix/zabbixAPI.service.js +++ b/dist/datasource-zabbix/zabbixAPI.service.js @@ -286,7 +286,7 @@ System.register(['angular', 'lodash', './utils', './zabbixAPICore.service'], fun } }, { key: 'getTriggers', - value: function getTriggers(groupids, hostids, applicationids, showTriggers, timeFrom, timeTo) { + value: function getTriggers(groupids, hostids, applicationids, showTriggers, hideHostsInMaintenance, timeFrom, timeTo) { var params = { output: 'extend', groupids: groupids, @@ -311,6 +311,10 @@ System.register(['angular', 'lodash', './utils', './zabbixAPICore.service'], fun params.filter.value = showTriggers; } + if (hideHostsInMaintenance) { + params.maintenance = false; + } + if (timeFrom || timeTo) { params.lastChangeSince = timeFrom; params.lastChangeTill = timeTo; diff --git a/dist/datasource-zabbix/zabbixAPI.service.js.map b/dist/datasource-zabbix/zabbixAPI.service.js.map index 5d8dfe9..e430416 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_","itemid","itemids","length","lastvalue","timeFrom","timeTill","grouped_items","_","groupBy","promises","map","history","sortorder","time_from","time_till","all","flatten","trend","self","serviceids","timeTo","intervals","from","to","showTriggers","expandDescription","expandData","expandComment","monitored","skipDependent","value","selectGroups","selectItems","selectLastEvent","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 items.forEach(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 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, timeFrom, timeTo) {\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, showTriggers, timeFrom, timeTo) {\n var 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 (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 }\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","expandItems","items","forEach","item","name","utils","expandItemName","key_","itemid","itemids","length","lastvalue","timeFrom","timeTill","grouped_items","_","groupBy","promises","map","history","sortorder","time_from","time_till","all","flatten","trend","self","serviceids","timeTo","intervals","from","to","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 items.forEach(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 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, timeFrom, timeTo) {\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, showTriggers, hideHostsInMaintenance, timeFrom, timeTo) {\n var 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 }\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/panel-triggers/editor.html b/dist/panel-triggers/editor.html index b0510db..0f3aace 100644 --- a/dist/panel-triggers/editor.html +++ b/dist/panel-triggers/editor.html @@ -138,15 +138,21 @@
                              -
                              +
                              -
                              +
                              + +
                              diff --git a/dist/panel-triggers/module.js b/dist/panel-triggers/module.js index 1742270..abceff1 100644 --- a/dist/panel-triggers/module.js +++ b/dist/panel-triggers/module.js @@ -97,6 +97,7 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap infoField: true, limit: 10, showTriggers: 'all triggers', + hideHostsInMaintenance: false, sortTriggersBy: { text: 'last change', value: 'lastchange' }, showEvents: { text: 'Problems', value: '1' }, triggerSeverity: defaultSeverity, @@ -181,13 +182,14 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap _this3.zabbix = zabbix; var showEvents = _this3.panel.showEvents.value; var triggerFilter = _this3.panel.triggers; + var hideHostsInMaintenance = _this3.panel.hideHostsInMaintenance; // Replace template variables var groupFilter = datasource.replaceTemplateVars(triggerFilter.group.filter); var hostFilter = datasource.replaceTemplateVars(triggerFilter.host.filter); var appFilter = datasource.replaceTemplateVars(triggerFilter.application.filter); - var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents); + var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents, hideHostsInMaintenance); return getTriggers.then(function (triggers) { return _.map(triggers, _this3.formatTrigger.bind(_this3)); }); diff --git a/dist/panel-triggers/module.js.map b/dist/panel-triggers/module.js.map index a78c48b..a96118a 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","PanelCtrl","triggerPanelEditor","defaultSeverity","priority","severity","color","show","panelDefaults","datasource","group","host","application","hostField","statusField","severityField","lastChangeField","ageField","infoField","limit","showTriggers","sortTriggersBy","text","value","showEvents","triggerSeverity","okEventColor","ackEventColor","scroll","pageSize","fontSize","triggerStatusMap","defaultTimeFormat","TriggerPanelCtrl","$scope","$injector","$element","datasourceSrv","templateSrv","contextSrv","pageIndex","triggerList","currentTriggersPage","defaults","panel","cloneDeep","events","on","onInitEditMode","bind","onRefresh","addEditorTab","error","loading","refreshData","then","slice","getCurrentTriggersPage","render","getTriggers","getAcknowledges","get","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2VA,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;;;;AAxVMG,O;;AACAM,O;;AACAC,Y;;AACKT,W;;AACJU,e,kBAAAA,S;;AACAC,wB,WAAAA,kB;;;;;;;;;;;;;;;;;;;;;AAIJC,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;AAElBpB,kBAAU;AACRqB,iBAAO,EAAChB,QAAQ,EAAT,EADC;AAERiB,gBAAM,EAACjB,QAAQ,EAAT,EAFE;AAGRkB,uBAAa,EAAClB,QAAQ,EAAT,EAHL;AAIRC,mBAAS,EAACD,QAAQ,EAAT;AAJD,SAFQ;AAQlBmB,mBAAW,IARO;AASlBC,qBAAa,KATK;AAUlBC,uBAAe,KAVG;AAWlBC,yBAAiB,IAXC;AAYlBC,kBAAU,IAZQ;AAalBC,mBAAW,IAbO;AAclBC,eAAO,EAdW;AAelBC,sBAAc,cAfI;AAgBlBC,wBAAgB,EAAEC,MAAM,aAAR,EAAuBC,OAAO,YAA9B,EAhBE;AAiBlBC,oBAAY,EAAEF,MAAM,UAAR,EAAoBC,OAAO,GAA3B,EAjBM;AAkBlBE,yBAAiBtB,eAlBC;AAmBlBuB,sBAAc,yBAnBI;AAoBlBC,uBAAe,kBApBG;AAqBlBC,gBAAQ,IArBU;AAsBlBC,kBAAU,EAtBQ;AAuBlBC,kBAAU;AAvBQ,O;AA0BhBC,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,EAAiF;AAAA;;AAAA,0IACzEL,MADyE,EACjEC,SADiE;;AAE/E,gBAAKE,aAAL,GAAqBA,aAArB;AACA,gBAAKC,WAAL,GAAmBA,WAAnB;AACA,gBAAKC,UAAL,GAAkBA,UAAlB;AACA,gBAAKR,gBAAL,GAAwBA,gBAAxB;AACA,gBAAKC,iBAAL,GAAyBA,iBAAzB;AACA,gBAAKQ,SAAL,GAAiB,CAAjB;AACA,gBAAKC,WAAL,GAAmB,EAAnB;AACA,gBAAKC,mBAAL,GAA2B,EAA3B;;AAEA;AACA;AACA;AACAjD,YAAEkD,QAAF,CAAW,MAAKC,KAAhB,EAAuBnD,EAAEoD,SAAF,CAAYrC,aAAZ,CAAvB;;AAEA,gBAAKsC,MAAL,CAAYC,EAAZ,CAAe,gBAAf,EAAiC,MAAKC,cAAL,CAAoBC,IAApB,OAAjC;AACA,gBAAKH,MAAL,CAAYC,EAAZ,CAAe,SAAf,EAA0B,MAAKG,SAAL,CAAeD,IAAf,OAA1B;AAjB+E;AAkBhF;;;;2CAEgB;AACf,iBAAKE,YAAL,CAAkB,SAAlB,EAA6BjD,kBAA7B,EAAiD,CAAjD;AACD;;;sCAEW;AAAA;;AACV;AACA,mBAAO,KAAKkD,KAAZ;AACA,iBAAKC,OAAL,GAAe,IAAf;;AAEA,mBAAO,KAAKC,WAAL,GACNC,IADM,CACD,uBAAe;AACnB;AACA,qBAAKd,WAAL,GAAoBA,YAAYe,KAAZ,CAAkB,CAAlB,EAAqB,OAAKZ,KAAL,CAAWzB,KAAhC,CAApB;;AAEA,qBAAKsC,sBAAL;;AAEA;AACA,qBAAKJ,OAAL,GAAe,KAAf;;AAEA,qBAAKK,MAAL,CAAY,OAAKjB,WAAjB;AACD,aAXM,CAAP;AAYD;;;wCAEa;AACZ,mBAAO,KAAKkB,WAAL,GACNJ,IADM,CACD,KAAKK,eAAL,CAAqBX,IAArB,CAA0B,IAA1B,CADC,EAENM,IAFM,CAED,KAAKnE,cAAL,CAAoB6D,IAApB,CAAyB,IAAzB,CAFC,CAAP;AAGD;;;wCAEa;AAAA;;AACZ,mBAAO,KAAKZ,aAAL,CAAmBwB,GAAnB,CAAuB,KAAKjB,KAAL,CAAWnC,UAAlC,EACN8C,IADM,CACD,sBAAc;AAClB,kBAAIO,SAASrD,WAAWqD,MAAxB;AACA,qBAAKA,MAAL,GAAcA,MAAd;AACA,kBAAItC,aAAa,OAAKoB,KAAL,CAAWpB,UAAX,CAAsBD,KAAvC;AACA,kBAAIjC,gBAAgB,OAAKsD,KAAL,CAAWvD,QAA/B;;AAEA;AACA,kBAAI0E,cAActD,WAAWuD,mBAAX,CAA+B1E,cAAcoB,KAAd,CAAoBhB,MAAnD,CAAlB;AACA,kBAAIuE,aAAaxD,WAAWuD,mBAAX,CAA+B1E,cAAcqB,IAAd,CAAmBjB,MAAlD,CAAjB;AACA,kBAAIwE,YAAYzD,WAAWuD,mBAAX,CAA+B1E,cAAcsB,WAAd,CAA0BlB,MAAzD,CAAhB;;AAEA,kBAAIiE,cAAcG,OAAOH,WAAP,CAAmBI,WAAnB,EAAgCE,UAAhC,EAA4CC,SAA5C,EAAuD1C,UAAvD,CAAlB;AACA,qBAAOmC,YAAYJ,IAAZ,CAAiB,oBAAY;AAClC,uBAAO9D,EAAE0E,GAAF,CAAM9E,QAAN,EAAgB,OAAK+E,aAAL,CAAmBnB,IAAnB,QAAhB,CAAP;AACD,eAFM,CAAP;AAGD,aAhBM,CAAP;AAiBD;;;0CAEeR,W,EAAa;AAAA;;AAC3B;AACA,gBAAI4B,WAAW5E,EAAE0E,GAAF,CAAM1B,WAAN,EAAmB,mBAAW;AAC3C,qBAAO9C,QAAQ2E,SAAR,CAAkBC,OAAzB;AACD,aAFc,CAAf;;AAIA,mBAAO,KAAKT,MAAL,CAAYF,eAAZ,CAA4BS,QAA5B,EACNd,IADM,CACD,kBAAU;;AAEd;AACA9D,gBAAE+E,IAAF,CAAO/B,WAAP,EAAoB,mBAAW;AAC7B,oBAAIgC,QAAQhF,EAAEiF,IAAF,CAAO5B,MAAP,EAAe,iBAAS;AAClC,yBAAO2B,MAAMF,OAAN,KAAkB5E,QAAQ2E,SAAR,CAAkBC,OAA3C;AACD,iBAFW,CAAZ;;AAIA,oBAAIE,KAAJ,EAAW;AACT9E,0BAAQgF,YAAR,GAAuBlF,EAAE0E,GAAF,CAAMM,MAAME,YAAZ,EAA0B,eAAO;AACtD,wBAAIC,YAAY5E,OAAO6E,IAAP,CAAYC,IAAIC,KAAhB,CAAhB;AACA,wBAAI,OAAKnC,KAAL,CAAWoC,sBAAf,EAAuC;AACrCF,0BAAIG,IAAJ,GAAWL,UAAUM,MAAV,CAAiB,OAAKtC,KAAL,CAAWuC,gBAA5B,CAAX;AACD,qBAFD,MAEO;AACLL,0BAAIG,IAAJ,GAAWL,UAAUM,MAAV,CAAiB,OAAKlD,iBAAtB,CAAX;AACD;AACD8C,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,OAAKlC,KAAL,CAAW4C,aAAX,IAA4B7F,QAAQgF,YAAR,CAAqBc,MAArD,EAA6D;AAC3D9F,4BAAQW,KAAR,GAAgB,OAAKsC,KAAL,CAAWjB,aAA3B;AACD;AACF;AACF,eAtBD;;AAwBA,qBAAOc,WAAP;AACD,aA7BM,CAAP;AA8BD;;;yCAEcA,W,EAAa;AAAA;;AAC1B;AACA,gBAAInD,gBAAgB,KAAKsD,KAAL,CAAWvD,QAAX,CAAoBM,OAApB,CAA4BD,MAAhD;AACA,gBAAIJ,aAAJ,EAAmB;AACjBmD,4BAAcrD,gBAAeqD,WAAf,EAA4BnD,aAA5B,CAAd;AACD;;AAED;AACA,gBAAI,KAAKsD,KAAL,CAAWxB,YAAX,KAA4B,gBAAhC,EAAkD;AAChDqB,4BAAchD,EAAEC,MAAF,CAAS+C,WAAT,EAAsB,mBAAW;AAC7C,uBAAO,CAAC9C,QAAQgF,YAAhB;AACD,eAFa,CAAd;AAGD,aAJD,MAIO,IAAI,KAAK/B,KAAL,CAAWxB,YAAX,KAA4B,cAAhC,EAAgD;AACrDqB,4BAAchD,EAAEC,MAAF,CAAS+C,WAAT,EAAsB,cAAtB,CAAd;AACD,aAFM,MAEA;AACLA,4BAAcA,WAAd;AACD;;AAED;AACAA,0BAAchD,EAAEC,MAAF,CAAS+C,WAAT,EAAsB,mBAAW;AAC7C,qBAAO,OAAKG,KAAL,CAAWnB,eAAX,CAA2B9B,QAAQS,QAAnC,EAA6CG,IAApD;AACD,aAFa,CAAd;;AAIA;AACA,gBAAI,KAAKqC,KAAL,CAAWvB,cAAX,CAA0BE,KAA1B,KAAoC,UAAxC,EAAoD;AAClDkB,4BAAchD,EAAEiG,MAAF,CAASjD,WAAT,EAAsB,UAAtB,EAAkCkD,OAAlC,EAAd;AACD,aAFD,MAEO;AACLlD,4BAAchD,EAAEiG,MAAF,CAASjD,WAAT,EAAsB,gBAAtB,EAAwCkD,OAAxC,EAAd;AACD;;AAED,mBAAOlD,WAAP;AACD;;;wCAEa9C,O,EAAS;AACrB,gBAAIiG,aAAajG,OAAjB;;AAEA;AACAA,oBAAQkG,cAAR,GAAyBC,OAAOnG,QAAQoG,UAAf,CAAzB;AACA,gBAAInB,YAAY5E,OAAO6E,IAAP,CAAYlF,QAAQkG,cAApB,CAAhB;AACA,gBAAI,KAAKjD,KAAL,CAAWoC,sBAAf,EAAuC;AACrC;AACAY,yBAAWG,UAAX,GAAwBnB,UAAUM,MAAV,CAAiB,KAAKtC,KAAL,CAAWuC,gBAA5B,CAAxB;AACD,aAHD,MAGO;AACLS,yBAAWG,UAAX,GAAwBnB,UAAUM,MAAV,CAAiB,KAAKlD,iBAAtB,CAAxB;AACD;AACD4D,uBAAWI,GAAX,GAAiBpB,UAAUqB,OAAV,CAAkB,IAAlB,CAAjB;;AAEA;AACA,gBAAItG,QAAQuG,KAAR,CAAcT,MAAlB,EAA0B;AACxBG,yBAAWjF,IAAX,GAAkBhB,QAAQuG,KAAR,CAAc,CAAd,EAAiBZ,IAAnC;AACAM,yBAAWO,YAAX,GAA0BxG,QAAQuG,KAAR,CAAc,CAAd,EAAiBvF,IAA3C;AACD;;AAED;AACA,gBAAIhB,QAAQ4B,KAAR,KAAkB,GAAtB,EAA2B;AACzB;AACAqE,yBAAWtF,KAAX,GAAmB,KAAKsC,KAAL,CAAWnB,eAAX,CAA2B9B,QAAQS,QAAnC,EAA6CE,KAAhE;AACD,aAHD,MAGO;AACL;AACAsF,yBAAWtF,KAAX,GAAmB,KAAKsC,KAAL,CAAWlB,YAA9B;AACD;;AAEDkE,uBAAWvF,QAAX,GAAsB,KAAKuC,KAAL,CAAWnB,eAAX,CAA2B9B,QAAQS,QAAnC,EAA6CC,QAAnE;AACA,mBAAOuF,UAAP;AACD;;;wCAEajG,O,EAAS;AACrBA,oBAAQyG,WAAR,GAAsB,CAACzG,QAAQyG,WAA/B;AACD;;;6CAEkBzG,O,EAAS0G,O,EAAS;AACnC,gBAAI9B,UAAU5E,QAAQ2E,SAAR,CAAkBC,OAAhC;AACA,gBAAI+B,eAAe,KAAK/D,UAAL,CAAgB6C,IAAhB,CAAqBE,IAAxC;AACA,gBAAIiB,cAAcD,eAAe,cAAf,GAAgCD,OAAlD;AACA,mBAAO,KAAKhE,aAAL,CAAmBwB,GAAnB,CAAuB,KAAKjB,KAAL,CAAWnC,UAAlC,EACN8C,IADM,CACD,sBAAc;AAClB,kBAAIiD,YAAY/F,WAAWqD,MAAX,CAAkB0C,SAAlC;AACA,qBAAOA,UAAUC,gBAAV,CAA2BlC,OAA3B,EAAoCgC,WAApC,CAAP;AACD,aAJM,EAKNhD,IALM,CAKD,KAAKL,SAAL,CAAeD,IAAf,CAAoB,IAApB,CALC,CAAP;AAMD;;;mDAEwB;AACvB,gBAAIpB,WAAW,KAAKe,KAAL,CAAWf,QAAX,IAAuB,EAAtC;AACA,gBAAI6E,WAAW,KAAKlE,SAAL,GAAiBX,QAAhC;AACA,gBAAI8E,SAASC,KAAKC,GAAL,CAASH,WAAW7E,QAApB,EAA8B,KAAKY,WAAL,CAAiBgD,MAA/C,CAAb;AACA,iBAAK/C,mBAAL,GAA2B,KAAKD,WAAL,CAAiBe,KAAjB,CAAuBkD,QAAvB,EAAiCC,MAAjC,CAA3B;AACA,mBAAO,KAAKjE,mBAAZ;AACD;;;+BAEIoE,K,EAAOC,I,EAAMC,K,EAAOC,I,EAAM;AAC7B,gBAAIC,IAAJ;AACA,gBAAItE,QAAQqE,KAAKrE,KAAjB;AACA,gBAAIuE,YAAY,CAAhB;AACAD,mBAAOD,KAAKxE,WAAZ;;AAEA,qBAAS2E,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,KAAK1H,EAAEyH,EAAEE,aAAJ,CAAT;AACAT,mBAAKzE,SAAL,GAAkBmF,SAASF,GAAGnG,IAAH,EAAT,EAAoB,EAApB,IAAwB,CAA1C;;AAEA,kBAAIO,WAAWoF,KAAKrE,KAAL,CAAWf,QAAX,IAAuB,EAAtC;AACA,kBAAI6E,WAAWO,KAAKzE,SAAL,GAAiBX,QAAhC;AACA,kBAAI8E,SAASC,KAAKC,GAAL,CAASH,WAAW7E,QAApB,EAA8BoF,KAAKxE,WAAL,CAAiBgD,MAA/C,CAAb;AACAwB,mBAAKvE,mBAAL,GAA2BuE,KAAKxE,WAAL,CAAiBe,KAAjB,CAAuBkD,QAAvB,EAAiCC,MAAjC,CAA3B;;AAEAG,oBAAMc,MAAN;AACAC;AACD;;AAED,qBAASC,wBAAT,CAAkCC,UAAlC,EAA8C;AAC5CA,yBAAWC,KAAX;;AAEA,kBAAInG,WAAWoF,KAAKrE,KAAL,CAAWf,QAAX,IAAuB,CAAtC;AACAsF,0BAAYP,KAAKqB,IAAL,CAAUf,KAAKzB,MAAL,GAAc5D,QAAxB,CAAZ;AACA,kBAAIsF,cAAc,CAAlB,EAAqB;AACnB;AACD;;AAED,kBAAIe,YAAYtB,KAAKuB,GAAL,CAASlB,KAAKzE,SAAL,GAAiB,CAA1B,EAA6B,CAA7B,CAAhB;AACA,kBAAI4F,UAAUxB,KAAKC,GAAL,CAASM,SAAT,EAAoBe,YAAY,CAAhC,CAAd;;AAEA,kBAAIG,iBAAiBtI,EAAE,WAAF,CAArB;;AAEA,mBAAK,IAAIuI,IAAIJ,SAAb,EAAwBI,IAAIF,OAA5B,EAAqCE,GAArC,EAA0C;AACxC,oBAAIC,cAAcD,MAAMrB,KAAKzE,SAAX,GAAuB,QAAvB,GAAkC,EAApD;AACA,oBAAIgG,eAAezI,EAAE,oDAAoDwI,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,aAAajG,MAAMd,QAApB,EAAT;AACA4G,wBAAUI,QAAV,CAAmB,wBAAnB;AACAhB,uCAAyBC,UAAzB;;AAEAa,uBAASC,GAAT,CAAa,EAAC,cAAcjG,MAAMhB,MAAN,GAAewF,gBAAf,GAAkC,EAAjD,EAAb;AACD;;AAEDL,iBAAKhE,EAAL,CAAQ,OAAR,EAAiB,2BAAjB,EAA8CwE,UAA9C;;AAEA,gBAAIwB,gBAAgBjC,MAAMkC,GAAN,CAAU,UAAV,EAAsB,YAAW;AACnDjC,mBAAKkC,GAAL,CAAS,OAAT,EAAkB,2BAAlB;AACAF;AACD,aAHmB,CAApB;;AAKA9B,iBAAKnE,MAAL,CAAYC,EAAZ,CAAe,QAAf,EAAyB,UAACmG,UAAD,EAAgB;AACvChC,qBAAOgC,cAAchC,IAArB;AACA,kBAAIA,IAAJ,EAAU;AACRW;AACD;AACDZ,mBAAKkC,kBAAL;AACD,aAND;AAOD;;;;QAtR4BlJ,S;;AAyR/BgC,uBAAiBmH,WAAjB,GAA+B,4BAA/B;kCAeEnH,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 * as utils from '../datasource-zabbix/utils';\nimport {PanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\nimport './css/panel_triggers.css!';\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 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) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\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 // 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\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 var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents);\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","PanelCtrl","triggerPanelEditor","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","pageIndex","triggerList","currentTriggersPage","defaults","panel","cloneDeep","events","on","onInitEditMode","bind","onRefresh","addEditorTab","error","loading","refreshData","then","slice","getCurrentTriggersPage","render","getTriggers","getAcknowledges","get","zabbix","groupFilter","replaceTemplateVars","hostFilter","appFilter","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":"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","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 * as utils from '../datasource-zabbix/utils';\nimport {PanelCtrl} from 'app/plugins/sdk';\nimport {triggerPanelEditor} from './editor';\nimport './ack-tooltip.directive';\nimport './css/panel_triggers.css!';\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) {\n super($scope, $injector);\n this.datasourceSrv = datasourceSrv;\n this.templateSrv = templateSrv;\n this.contextSrv = contextSrv;\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 // 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 var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents, hideHostsInMaintenance);\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 diff --git a/dist/test/datasource-zabbix/zabbix.js b/dist/test/datasource-zabbix/zabbix.js index 627d107..a34593f 100644 --- a/dist/test/datasource-zabbix/zabbix.js +++ b/dist/test/datasource-zabbix/zabbix.js @@ -172,7 +172,7 @@ function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy) { }, { key: 'getTriggers', - value: function getTriggers(groupFilter, hostFilter, appFilter, showTriggers) { + value: function getTriggers(groupFilter, hostFilter, appFilter, showTriggers, hideHostsInMaintenance) { var _this5 = this; var promises = [this.getGroups(groupFilter), this.getHosts(groupFilter, hostFilter), this.getApps(groupFilter, hostFilter, appFilter)]; @@ -195,7 +195,7 @@ function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy) { return query; }).then(function (query) { - return _this5.zabbixAPI.getTriggers(query.groupids, query.hostids, query.applicationids, showTriggers); + return _this5.zabbixAPI.getTriggers(query.groupids, query.hostids, query.applicationids, showTriggers, hideHostsInMaintenance); }); } }]); diff --git a/dist/test/datasource-zabbix/zabbixAPI.service.js b/dist/test/datasource-zabbix/zabbixAPI.service.js index cd82a13..ac0d3a6 100644 --- a/dist/test/datasource-zabbix/zabbixAPI.service.js +++ b/dist/test/datasource-zabbix/zabbixAPI.service.js @@ -356,7 +356,7 @@ function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) { } }, { key: 'getTriggers', - value: function getTriggers(groupids, hostids, applicationids, showTriggers, timeFrom, timeTo) { + value: function getTriggers(groupids, hostids, applicationids, showTriggers, hideHostsInMaintenance, timeFrom, timeTo) { var params = { output: 'extend', groupids: groupids, @@ -381,6 +381,10 @@ function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) { params.filter.value = showTriggers; } + if (hideHostsInMaintenance) { + params.maintenance = false; + } + if (timeFrom || timeTo) { params.lastChangeSince = timeFrom; params.lastChangeTill = timeTo; diff --git a/dist/test/panel-triggers/module.js b/dist/test/panel-triggers/module.js index 201cd1d..ba6fbe5 100644 --- a/dist/test/panel-triggers/module.js +++ b/dist/test/panel-triggers/module.js @@ -70,6 +70,7 @@ var panelDefaults = { infoField: true, limit: 10, showTriggers: 'all triggers', + hideHostsInMaintenance: false, sortTriggersBy: { text: 'last change', value: 'lastchange' }, showEvents: { text: 'Problems', value: '1' }, triggerSeverity: defaultSeverity, @@ -156,13 +157,14 @@ var TriggerPanelCtrl = function (_PanelCtrl) { _this3.zabbix = zabbix; var showEvents = _this3.panel.showEvents.value; var triggerFilter = _this3.panel.triggers; + var hideHostsInMaintenance = _this3.panel.hideHostsInMaintenance; // Replace template variables var groupFilter = datasource.replaceTemplateVars(triggerFilter.group.filter); var hostFilter = datasource.replaceTemplateVars(triggerFilter.host.filter); var appFilter = datasource.replaceTemplateVars(triggerFilter.application.filter); - var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents); + var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents, hideHostsInMaintenance); return getTriggers.then(function (triggers) { return _lodash2.default.map(triggers, _this3.formatTrigger.bind(_this3)); }); diff --git a/src/datasource-zabbix/zabbix.js b/src/datasource-zabbix/zabbix.js index 254d79b..23e91f2 100644 --- a/src/datasource-zabbix/zabbix.js +++ b/src/datasource-zabbix/zabbix.js @@ -120,7 +120,7 @@ function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy) { /** * Build query - convert target filters to array of Zabbix items */ - getTriggers(groupFilter, hostFilter, appFilter, showTriggers) { + getTriggers(groupFilter, hostFilter, appFilter, showTriggers, hideHostsInMaintenance) { let promises = [ this.getGroups(groupFilter), this.getHosts(groupFilter, hostFilter), @@ -147,7 +147,7 @@ function ZabbixFactory(zabbixAPIService, ZabbixCachingProxy) { return query; }).then(query => { return this.zabbixAPI - .getTriggers(query.groupids, query.hostids, query.applicationids, showTriggers); + .getTriggers(query.groupids, query.hostids, query.applicationids, showTriggers, hideHostsInMaintenance); }); } } diff --git a/src/datasource-zabbix/zabbixAPI.service.js b/src/datasource-zabbix/zabbixAPI.service.js index 735888b..3f7d804 100644 --- a/src/datasource-zabbix/zabbixAPI.service.js +++ b/src/datasource-zabbix/zabbixAPI.service.js @@ -316,7 +316,7 @@ function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) { return this.request('service.getsla', params); } - getTriggers(groupids, hostids, applicationids, showTriggers, timeFrom, timeTo) { + getTriggers(groupids, hostids, applicationids, showTriggers, hideHostsInMaintenance, timeFrom, timeTo) { var params = { output: 'extend', groupids: groupids, @@ -341,6 +341,10 @@ function ZabbixAPIServiceFactory(alertSrv, zabbixAPICoreService) { params.filter.value = showTriggers; } + if (hideHostsInMaintenance) { + params.maintenance = false; + } + if (timeFrom || timeTo) { params.lastChangeSince = timeFrom; params.lastChangeTill = timeTo; diff --git a/src/panel-triggers/editor.html b/src/panel-triggers/editor.html index b0510db..0f3aace 100644 --- a/src/panel-triggers/editor.html +++ b/src/panel-triggers/editor.html @@ -138,15 +138,21 @@
                                  -
                                  +
                                  -
                                  +
                                  + +
                                  diff --git a/src/panel-triggers/module.js b/src/panel-triggers/module.js index 1d9eab1..b4a977f 100644 --- a/src/panel-triggers/module.js +++ b/src/panel-triggers/module.js @@ -45,6 +45,7 @@ var panelDefaults = { infoField: true, limit: 10, showTriggers: 'all triggers', + hideHostsInMaintenance: false, sortTriggersBy: { text: 'last change', value: 'lastchange' }, showEvents: { text: 'Problems', value: '1' }, triggerSeverity: defaultSeverity, @@ -121,13 +122,14 @@ class TriggerPanelCtrl extends PanelCtrl { this.zabbix = zabbix; var showEvents = this.panel.showEvents.value; var triggerFilter = this.panel.triggers; + var hideHostsInMaintenance = this.panel.hideHostsInMaintenance; // Replace template variables var groupFilter = datasource.replaceTemplateVars(triggerFilter.group.filter); var hostFilter = datasource.replaceTemplateVars(triggerFilter.host.filter); var appFilter = datasource.replaceTemplateVars(triggerFilter.application.filter); - var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents); + var getTriggers = zabbix.getTriggers(groupFilter, hostFilter, appFilter, showEvents, hideHostsInMaintenance); return getTriggers.then(triggers => { return _.map(triggers, this.formatTrigger.bind(this)); }); From 248a98832602f71c8c80b8e56cc6c89fee8c35ac Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Fri, 10 Feb 2017 17:06:36 +0300 Subject: [PATCH 10/10] Triggers Panel: rearrange options. --- dist/panel-triggers/editor.html | 54 ++++++++++++++++----------------- src/panel-triggers/editor.html | 54 ++++++++++++++++----------------- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/dist/panel-triggers/editor.html b/dist/panel-triggers/editor.html index 0f3aace..aa60aea 100644 --- a/dist/panel-triggers/editor.html +++ b/dist/panel-triggers/editor.html @@ -82,7 +82,7 @@
                                  -
                                  +
                                  -
                                  + +
                                  -
                                  +
                                  +
                                  + + +
                                  -
                                  - - -
                                  -
                                  - +
                                  +
                                  - - +
                                  + + +
                                  diff --git a/src/panel-triggers/editor.html b/src/panel-triggers/editor.html index 0f3aace..aa60aea 100644 --- a/src/panel-triggers/editor.html +++ b/src/panel-triggers/editor.html @@ -82,7 +82,7 @@
                                  -
                                  +
                                  -
                                  + +
                                  -
                                  +
                                  +
                                  + + +
                                  -
                                  - - -
                                  -
                                  - +
                                  +
                                  - - +
                                  + + +