+
+
+
+
+
+
+
Customize triggers severity and colors
+
+
+
+
diff --git a/src/panel-triggers/editor.js b/src/panel-triggers/editor.js
new file mode 100644
index 000000000..df53ff536
--- /dev/null
+++ b/src/panel-triggers/editor.js
@@ -0,0 +1,198 @@
+/**
+ * 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
+ */
+
+import _ from 'lodash';
+import $ from 'jquery';
+
+class TriggerPanelEditorCtrl{
+
+ /** @ngInject */
+ constructor($scope, $q, uiSegmentSrv, datasourceSrv, templateSrv, popoverSrv) {
+ $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 = _.partial(getMetricNames, this, 'groupList');
+ this.getHostNames = _.partial(getMetricNames, this, 'filteredHosts');
+ this.getApplicationNames = _.partial(getMetricNames, this, 'filteredApplications');
+ this.getItemNames = _.partial(getMetricNames, this, 'filteredItems');
+
+ 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: _.cloneDeep(this.panel.triggers)
+ };
+ _.defaults(this, scopeDefaults);
+
+ var self = this;
+
+ // Get zabbix data sources
+ var datasources = _.filter(this.datasourceSrv.getMetricSources(), datasource => {
+ return datasource.meta.id === 'zabbix-datasource';
+ });
+ this.datasources = _.map(datasources, 'name');
+
+ // Set default datasource
+ if (!this.panel.datasource) {
+ this.panel.datasource = this.datasources[0];
+ }
+ // Load datasource
+ this.datasourceSrv.get(this.panel.datasource).then(function (datasource) {
+ self.datasource = datasource;
+ self.initFilters();
+ self.panelCtrl.refresh();
+ });
+ }
+
+ initFilters() {
+ this.filterGroups();
+ this.filterHosts();
+ this.filterApplications();
+ }
+
+ filterGroups() {
+ var self = this;
+ this.datasource.queryProcessor.getGroups().then(function(groups) {
+ self.metric.groupList = groups;
+ });
+ }
+
+ filterHosts() {
+ var self = this;
+ var groupFilter = this.templateSrv.replace(this.panel.triggers.group.filter);
+ this.datasource.queryProcessor.getHosts(groupFilter).then(function(hosts) {
+ self.metric.filteredHosts = hosts;
+ });
+ }
+
+ filterApplications() {
+ var self = this;
+ var groupFilter = this.templateSrv.replace(this.panel.triggers.group.filter);
+ var hostFilter = this.templateSrv.replace(this.panel.triggers.host.filter);
+ this.datasource.queryProcessor.getApps(groupFilter, hostFilter)
+ .then(function(apps) {
+ self.metric.filteredApplications = apps;
+ });
+ }
+
+ onTargetPartChange(targetPart) {
+ var regexStyle = {'color': '#CCA300'};
+ targetPart.isRegex = isRegex(targetPart.filter);
+ targetPart.style = targetPart.isRegex ? regexStyle : {};
+ }
+
+ parseTarget() {
+ this.initFilters();
+ var newTarget = _.cloneDeep(this.panel.triggers);
+ if (!_.isEqual(this.oldTarget, this.panel.triggers)) {
+ this.oldTarget = newTarget;
+ this.panelCtrl.refresh();
+ }
+ }
+
+ refreshTriggerSeverity() {
+ _.each(this.triggerList, function(trigger) {
+ trigger.color = this.panel.triggerSeverity[trigger.priority].color;
+ trigger.severity = this.panel.triggerSeverity[trigger.priority].severity;
+ });
+ this.panelCtrl.refresh();
+ }
+
+ datasourceChanged() {
+ this.panelCtrl.refresh();
+ }
+
+ changeTriggerSeverityColor(trigger, color) {
+ this.panel.triggerSeverity[trigger.priority].color = color;
+ this.refreshTriggerSeverity();
+ }
+
+ openTriggerColorSelector(event) {
+ var el = $(event.currentTarget);
+ var index = getTriggerIndexForElement(el);
+ var popoverScope = this.$new();
+ popoverScope.trigger = this.panel.triggerSeverity[index];
+ popoverScope.changeTriggerSeverityColor = this.changeTriggerSeverityColor;
+
+ this.popoverSrv.show({
+ element: el,
+ placement: 'top',
+ templateUrl: 'public/plugins/zabbix-app/panel-triggers/trigger.colorpicker.html',
+ scope: popoverScope
+ });
+ }
+
+ openOkEventColorSelector(event) {
+ var el = $(event.currentTarget);
+ var popoverScope = this.$new();
+ popoverScope.trigger = {color: this.panel.okEventColor};
+ popoverScope.changeTriggerSeverityColor = function(trigger, color) {
+ this.panel.okEventColor = color;
+ this.refreshTriggerSeverity();
+ };
+
+ this.popoverSrv.show({
+ element: el,
+ placement: 'top',
+ templateUrl: 'public/plugins/zabbix-app/panel-triggers/trigger.colorpicker.html',
+ scope: popoverScope
+ });
+ }
+}
+
+// Get list of metric names for bs-typeahead directive
+function getMetricNames(scope, metricList) {
+ return _.uniq(_.map(scope.metric[metricList], 'name'));
+}
+
+function getTriggerIndexForElement(el) {
+ return el.parents('[data-trigger-index]').data('trigger-index');
+}
+
+function isRegex(str) {
+ // Pattern for testing regex
+ var regexPattern = /^\/(.*)\/([gmi]*)$/m;
+ return regexPattern.test(str);
+}
+
+export function triggerPanelEditor() {
+ return {
+ restrict: 'E',
+ scope: true,
+ templateUrl: 'public/plugins/zabbix-app/panel-triggers/editor.html',
+ controller: TriggerPanelEditorCtrl,
+ };
+}
diff --git a/src/panel-triggers/module.html b/src/panel-triggers/module.html
new file mode 100644
index 000000000..fddc00481
--- /dev/null
+++ b/src/panel-triggers/module.html
@@ -0,0 +1,136 @@
+
+
diff --git a/src/panel-triggers/module.js b/src/panel-triggers/module.js
new file mode 100644
index 000000000..b29c0b048
--- /dev/null
+++ b/src/panel-triggers/module.js
@@ -0,0 +1,259 @@
+/**
+ * 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
+ */
+
+import _ from 'lodash';
+import moment from 'moment';
+import {MetricsPanelCtrl} from 'app/plugins/sdk';
+import {triggerPanelEditor} from './editor';
+import './css/panel_triggers.css!';
+
+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)',
+};
+
+var triggerStatusMap = {
+ '0': 'OK',
+ '1': 'Problem'
+};
+
+var defaultTimeFormat = "DD MMM YYYY HH:mm:ss";
+
+class TriggerPanelCtrl extends MetricsPanelCtrl {
+
+ /** @ngInject */
+ constructor($scope, $injector, $q, $element, datasourceSrv, templateSrv) {
+ super($scope, $injector);
+ this.datasourceSrv = datasourceSrv;
+ this.templateSrv = templateSrv;
+ this.triggerStatusMap = triggerStatusMap;
+ this.defaultTimeFormat = defaultTimeFormat;
+
+ // Load panel defaults
+ _.defaults(this.panel, panelDefaults);
+
+ this.triggerList = [];
+ this.refreshData();
+ }
+
+ /**
+ * Override onInitMetricsPanelEditMode() method from MetricsPanelCtrl.
+ * We don't need metric editor from Metrics Panel.
+ */
+ onInitMetricsPanelEditMode() {
+ this.addEditorTab('Options', triggerPanelEditor, 2);
+ }
+
+ refresh() {
+ this.onMetricsPanelRefresh();
+ }
+
+ onMetricsPanelRefresh() {
+ // ignore fetching data if another panel is in fullscreen
+ if (this.otherPanelInFullscreenMode()) { return; }
+
+ // clear loading/error state
+ delete this.error;
+ this.loading = true;
+ this.setTimeQueryStart();
+
+ this.refreshData();
+ }
+
+ refreshData() {
+ var self = this;
+
+ // Load datasource
+ return this.datasourceSrv.get(this.panel.datasource).then(datasource => {
+ var zabbix = datasource.zabbixAPI;
+ var queryProcessor = datasource.queryProcessor;
+ var showEvents = self.panel.showEvents.value;
+ var triggerFilter = self.panel.triggers;
+
+ // Replace template variables
+ var groupFilter = self.templateSrv.replace(triggerFilter.group.filter);
+ var hostFilter = self.templateSrv.replace(triggerFilter.host.filter);
+ var appFilter = self.templateSrv.replace(triggerFilter.application.filter);
+
+ var buildQuery = queryProcessor.buildTriggerQuery(groupFilter, hostFilter, appFilter);
+ return buildQuery.then(query => {
+ return zabbix.getTriggers(query.groupids,
+ query.hostids,
+ query.applicationids,
+ showEvents)
+ .then(triggers => {
+ return _.map(triggers, 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;
+ }
+
+ // 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 => {
+ var time = new Date(+ack.clock * 1000);
+ ack.time = time.toLocaleString();
+ ack.user = ack.alias + ' (' + ack.name + ' ' + ack.surname + ')';
+ return ack;
+ });
+ }
+ });
+
+ // 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 = _.first(triggerList, self.panel.limit);
+
+ this.setTimeQueryEnd();
+ this.loading = false;
+ });
+ });
+ });
+ });
+ }
+
+ switchComment(trigger) {
+ trigger.showComment = !trigger.showComment;
+ }
+
+ switchAcknowledges(trigger) {
+ trigger.showAcknowledges = !trigger.showAcknowledges;
+ }
+}
+
+TriggerPanelCtrl.templateUrl = 'panel-triggers/module.html';
+
+function filterTriggers(triggers, triggerFilter) {
+ if (isRegex(triggerFilter)) {
+ return _.filter(triggers, function(trigger) {
+ return buildRegex(triggerFilter).test(trigger.description);
+ });
+ } else {
+ return _.filter(triggers, function(trigger) {
+ return trigger.description === triggerFilter;
+ });
+ }
+}
+
+function isRegex(str) {
+ // Pattern for testing regex
+ var regexPattern = /^\/(.*)\/([gmi]*)$/m;
+ return regexPattern.test(str);
+}
+
+function buildRegex(str) {
+ var regexPattern = /^\/(.*)\/([gmi]*)$/m;
+ var matches = str.match(regexPattern);
+ var pattern = matches[1];
+ var flags = matches[2] !== "" ? matches[2] : undefined;
+ return new RegExp(pattern, flags);
+}
+
+export {
+ TriggerPanelCtrl,
+ TriggerPanelCtrl as PanelCtrl
+};
diff --git a/src/panel-triggers/plugin.json b/src/panel-triggers/plugin.json
new file mode 100644
index 000000000..0e8bdbd92
--- /dev/null
+++ b/src/panel-triggers/plugin.json
@@ -0,0 +1,12 @@
+{
+ "type": "panel",
+ "name": "Zabbix Triggers",
+ "id": "zabbix-triggers-panel",
+
+ "info": {
+ "author": {
+ "name": "Alexander Zobnin",
+ "url": "http://grafana-zabbix.org"
+ }
+ }
+}
diff --git a/src/panel-triggers/sass/panel_triggers.scss b/src/panel-triggers/sass/panel_triggers.scss
new file mode 100644
index 000000000..478f7dd2a
--- /dev/null
+++ b/src/panel-triggers/sass/panel_triggers.scss
@@ -0,0 +1,108 @@
+$tight-form-func-bg: #333;
+$blue: #33B5E5;
+$dark-2: #1f1d1d;
+$body-bg: rgb(20,20,20);
+
+$grafanaListAccent: lighten($dark-2, 2%);
+
+.triggers-panel-wrapper {
+ .panel-content {
+ padding: 0;
+ }
+ .panel-title-container {
+ padding-bottom: 4px;
+ }
+}
+
+.triggers-panel-scroll {
+ overflow: auto;
+}
+
+.triggers-panel-container {
+ padding-top: 2.2em;
+ position: relative;
+}
+
+.triggers-panel-footer {
+ text-align: center;
+ font-size: 90%;
+ line-height: 2px;
+
+ ul {
+ position: relative;
+ display: inline-block;
+ margin-left: 0;
+ margin-bottom: 0;
+ }
+ ul > li {
+ display: inline; // Remove list-style and block-level defaults
+ }
+ ul > li > a {
+ float: left; // Collapse white-space
+ padding: 4px 12px;
+ text-decoration: none;
+ border-left-width: 0;
+
+ &:hover {
+ background-color: $tight-form-func-bg;
+ }
+
+ &.active {
+ font-weight: bold;
+ color: $blue;
+ }
+ }
+}
+
+.triggers-panel-table {
+ width: 100%;
+ border-collapse: collapse;
+
+ th {
+ padding: 0;
+
+ &:first-child {
+ .triggers-panel-table-header-inner {
+ padding-left: 15px;
+ }
+ }
+ }
+
+ td {
+ padding: 0.45em 0 0.45em 1.1em;
+ border-bottom: 2px solid $body-bg;
+ border-right: 2px solid $body-bg;
+
+ &:first-child {
+ padding-left: 15px;
+ }
+ &:last-child {
+ border-right: none;
+ }
+ }
+}
+
+.triggers-panel-header-bg {
+ background: $grafanaListAccent;
+ border-top: 2px solid $body-bg;
+ border-bottom: 2px solid $body-bg;
+ height: 2.0em;
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+}
+
+.triggers-panel-table-header-inner {
+ padding: 0.45em 0 0.45em 1.1em;
+ text-align: left;
+ color: $blue;
+ position: absolute;
+ top: 0;
+}
+
+.triggers-panel-width-hack {
+ visibility: hidden;
+ height: 0px;
+ line-height: 0px;
+}
diff --git a/src/panel-triggers/trigger.colorpicker.html b/src/panel-triggers/trigger.colorpicker.html
new file mode 100644
index 000000000..4f878d0d9
--- /dev/null
+++ b/src/panel-triggers/trigger.colorpicker.html
@@ -0,0 +1,13 @@
+
+
diff --git a/src/plugin.json b/src/plugin.json
new file mode 100644
index 000000000..1f030c984
--- /dev/null
+++ b/src/plugin.json
@@ -0,0 +1,47 @@
+{
+ "type": "app",
+ "name": "Zabbix App",
+ "id": "zabbix-app",
+
+ "css": {
+ "dark": "css/dark.css",
+ "light": "css/light.css"
+ },
+
+ "info": {
+ "description": "Zabbix plugin for Grafana",
+ "author": {
+ "name": "Alexander Zobnin",
+ "url": "http://grafana-zabbix.org"
+ },
+ "keywords": ["zabbix"],
+ "links": [
+ {"name": "Project site", "url": "https://github.com/alexanderzobnin/grafana-zabbix"},
+ {"name": "License & Terms", "url": "https://github.com/alexanderzobnin/grafana-zabbix/blob/master/LICENSE.md"}
+ ],
+ "version": "1.0.0-beta1",
+ "updated": "2016-03-31"
+ },
+
+ "includes": [
+ {
+ "type": "datasource",
+ "name": "Zabbix Datasource"
+ },
+ {
+ "type": "panel",
+ "name": "Triggers Panel"
+ },
+ {
+ "type": "dashboard",
+ "name": "Zabbix Server Dashboard",
+ "path": "dashboards/zabbix_server_dashboard.json",
+ "addToNav": true
+ }
+ ],
+
+ "dependencies": {
+ "grafanaVersion": "3.x.x",
+ "plugins": []
+ }
+}
diff --git a/zabbix/datasource.js b/zabbix/datasource.js
deleted file mode 100644
index 447d82719..000000000
--- a/zabbix/datasource.js
+++ /dev/null
@@ -1,398 +0,0 @@
-define([
- 'angular',
- 'lodash',
- 'app/core/utils/datemath',
- './directives',
- './zabbixAPIWrapper',
- './helperFunctions',
- './queryCtrl'
-],
-function (angular, _, dateMath) {
- 'use strict';
-
- var module = angular.module('grafana.services');
-
- module.factory('ZabbixAPIDatasource', function($q, backendSrv, templateSrv, alertSrv, ZabbixAPI, zabbixHelperSrv) {
-
- /**
- * Datasource initialization. Calls when you refresh page, add
- * or modify datasource.
- *
- * @param {Object} datasource Grafana datasource object.
- */
- function ZabbixAPIDatasource(datasource) {
- this.name = datasource.name;
- this.url = datasource.url;
- this.basicAuth = datasource.basicAuth;
- this.withCredentials = datasource.withCredentials;
-
- if (datasource.jsonData) {
- this.username = datasource.jsonData.username;
- this.password = datasource.jsonData.password;
-
- // Use trends instead history since specified time
- this.trends = datasource.jsonData.trends;
- this.trendsFrom = datasource.jsonData.trendsFrom || '7d';
-
- // Limit metrics per panel for templated request
- this.limitmetrics = datasource.jsonData.limitMetrics || 100;
- } else {
- // DEPRECATED. Loads settings from plugin.json file.
- // For backward compatibility only.
- this.username = datasource.meta.username;
- this.password = datasource.meta.password;
- this.trends = datasource.meta.trends;
- this.trendsFrom = datasource.meta.trendsFrom || '7d';
- this.limitmetrics = datasource.meta.limitmetrics || 100;
- }
-
- // Initialize Zabbix API
- this.zabbixAPI = new ZabbixAPI(this.url, this.username, this.password, this.basicAuth, this.withCredentials);
- }
-
- /**
- * Test connection to Zabbix API
- *
- * @return {object} Connection status and Zabbix API version
- */
- ZabbixAPIDatasource.prototype.testDatasource = function() {
- var self = this;
- return this.zabbixAPI.getZabbixAPIVersion().then(function (apiVersion) {
- return self.zabbixAPI.performZabbixAPILogin().then(function (auth) {
- if (auth) {
- return {
- status: "success",
- title: "Success",
- message: "Zabbix API version: " + apiVersion
- };
- } else {
- return {
- status: "error",
- title: "Invalid user name or password",
- message: "Zabbix API version: " + apiVersion
- };
- }
- });
- }, function(error) {
- return {
- status: "error",
- title: "Connection failed",
- message: "Could not connect to " + error.config.url
- };
- });
- };
-
- /**
- * Calls for each panel in dashboard.
- *
- * @param {Object} options Query options. Contains time range, targets
- * and other info.
- *
- * @return {Object} Grafana metrics object with timeseries data
- * for each target.
- */
- ZabbixAPIDatasource.prototype.query = function(options) {
-
- // get from & to in seconds
- var from = Math.ceil(dateMath.parse(options.range.from) / 1000);
- var to = Math.ceil(dateMath.parse(options.range.to) / 1000);
- var useTrendsFrom = Math.ceil(dateMath.parse('now-' + this.trendsFrom) / 1000);
-
- // Create request for each target
- var promises = _.map(options.targets, function(target) {
-
- if (target.mode !== 1) {
- // Don't show undefined and hidden targets
- if (target.hide || !target.group || !target.host
- || !target.application || !target.item) {
- return [];
- }
-
- // Replace templated variables
- var groupname = templateSrv.replace(target.group.name, options.scopedVars);
- var hostname = templateSrv.replace(target.host.name, options.scopedVars);
- var appname = templateSrv.replace(target.application.name, options.scopedVars);
- var itemname = templateSrv.replace(target.item.name, options.scopedVars);
-
- // Extract zabbix groups, hosts and apps from string:
- // "{host1,host2,...,hostN}" --> [host1, host2, ..., hostN]
- var groups = zabbixHelperSrv.splitMetrics(groupname);
- var hosts = zabbixHelperSrv.splitMetrics(hostname);
- var apps = zabbixHelperSrv.splitMetrics(appname);
-
- // Remove hostnames from item names and then
- // extract item names
- // "hostname: itemname" --> "itemname"
- var delete_hostname_pattern = /(?:\[[\w\.]+]:\s)/g;
- var itemnames = zabbixHelperSrv.splitMetrics(itemname.replace(delete_hostname_pattern, ''));
-
- var self = this;
-
- // Query numeric data
- if (!target.mode) {
-
- // Find items by item names and perform queries
- return this.zabbixAPI.itemFindQuery(groups, hosts, apps)
- .then(function (items) {
-
- // Filter hosts by regex
- if (target.host.visible_name === 'All') {
- if (target.hostFilter && _.every(items, _.identity.hosts)) {
-
- // Use templated variables in filter
- var host_pattern = new RegExp(templateSrv.replace(target.hostFilter, options.scopedVars));
- items = _.filter(items, function (item) {
- return _.some(item.hosts, function (host) {
- return host_pattern.test(host.name);
- });
- });
- }
- }
-
- if (itemnames[0] === 'All') {
-
- // Filter items by regex
- if (target.itemFilter) {
-
- // Use templated variables in filter
- var item_pattern = new RegExp(templateSrv.replace(target.itemFilter, options.scopedVars));
- return _.filter(items, function (item) {
- return item_pattern.test(zabbixHelperSrv.expandItemName(item));
- });
- } else {
- return items;
- }
- } else {
-
- // Filtering items
- return _.filter(items, function (item) {
- return _.contains(itemnames, zabbixHelperSrv.expandItemName(item));
- });
- }
- }).then(function (items) {
-
- // Don't perform query for high number of items
- // to prevent Grafana slowdown
- if (items.length > self.limitmetrics) {
- var message = "Try to increase limitmetrics parameter in datasource config.
"
- + "Current limitmetrics value is " + self.limitmetrics;
- alertSrv.set("Metrics limit exceeded", message, "warning", 10000);
- return [];
- } else {
- items = _.flatten(items);
-
- // Use alias only for single metric, otherwise use item names
- var alias = target.item.name === 'All' || itemnames.length > 1 ?
- undefined : templateSrv.replace(target.alias, options.scopedVars);
-
- var history;
- if ((from < useTrendsFrom) && self.trends) {
- var points = target.downsampleFunction ? target.downsampleFunction.value : "avg";
- history = self.zabbixAPI.getTrends(items, from, to)
- .then(_.bind(zabbixHelperSrv.handleTrendResponse, zabbixHelperSrv, items, alias, target.scale, points));
- } else {
- history = self.zabbixAPI.getHistory(items, from, to)
- .then(_.bind(zabbixHelperSrv.handleHistoryResponse, zabbixHelperSrv, items, alias, target.scale));
- }
-
- return history.then(function (timeseries) {
- var timeseries_data = _.flatten(timeseries);
- return _.map(timeseries_data, function (timeseries) {
-
- // Series downsampling
- if (timeseries.datapoints.length > options.maxDataPoints) {
- var ms_interval = Math.floor((to - from) / options.maxDataPoints) * 1000;
- var downsampleFunc = target.downsampleFunction ? target.downsampleFunction.value : "avg";
- timeseries.datapoints = zabbixHelperSrv.downsampleSeries(timeseries.datapoints, to, ms_interval, downsampleFunc);
- }
- return timeseries;
- });
- });
- }
- });
- }
-
- // Query text data
- else if (target.mode === 2) {
-
- // Find items by item names and perform queries
- return this.zabbixAPI.itemFindQuery(groups, hosts, apps, "text")
- .then(function (items) {
- items = _.filter(items, function (item) {
- return _.contains(itemnames, zabbixHelperSrv.expandItemName(item));
- });
- return self.zabbixAPI.getHistory(items, from, to).then(function(history) {
- return {
- target: target.item.name,
- datapoints: _.map(history, function (p) {
- return [p.value, p.clock * 1000];
- })
- };
- });
- });
- }
- }
-
- // IT services mode
- else if (target.mode === 1) {
- // Don't show undefined and hidden targets
- if (target.hide || !target.itservice || !target.slaProperty) {
- return [];
- } else {
- return this.zabbixAPI.getSLA(target.itservice.serviceid, from, to)
- .then(_.bind(zabbixHelperSrv.handleSLAResponse, zabbixHelperSrv, target.itservice, target.slaProperty));
- }
- }
- }, this);
-
- return $q.all(_.flatten(promises)).then(function (results) {
- var timeseries_data = _.flatten(results);
- return { data: timeseries_data };
- });
- };
-
- ////////////////
- // 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.
- */
- ZabbixAPIDatasource.prototype.metricFindQuery = function (query) {
- // Split query. Query structure:
- // group.host.app.item
- var parts = [];
- _.each(query.split('.'), function (part) {
- part = templateSrv.replace(part);
- if (part[0] === '{') {
- // Convert multiple mettrics to array
- // "{metric1,metcic2,...,metricN}" --> [metric1, metcic2,..., metricN]
- parts.push(zabbixHelperSrv.splitMetrics(part));
- } else {
- parts.push(part);
- }
- });
- var template = _.object(['group', 'host', 'app', 'item'], parts);
-
- // Get items
- if (parts.length === 4) {
- return this.zabbixAPI.itemFindQuery(template.group, template.host, template.app)
- .then(function (result) {
- return _.map(result, function (item) {
- var itemname = zabbixHelperSrv.expandItemName(item);
- return {
- text: itemname,
- expandable: false
- };
- });
- });
- }
- // Get applications
- else if (parts.length === 3) {
- return this.zabbixAPI.appFindQuery(template.host, template.group).then(function (result) {
- return _.map(result, function (app) {
- return {
- text: app.name,
- expandable: false
- };
- });
- });
- }
- // Get hosts
- else if (parts.length === 2) {
- return this.zabbixAPI.hostFindQuery(template.group).then(function (result) {
- return _.map(result, function (host) {
- return {
- text: host.name,
- expandable: false
- };
- });
- });
- }
- // Get groups
- else if (parts.length === 1) {
- return this.zabbixAPI.getGroupByName(template.group).then(function (result) {
- return _.map(result, function (hostgroup) {
- return {
- text: hostgroup.name,
- expandable: false
- };
- });
- });
- }
- // Return empty object for invalid request
- else {
- var d = $q.defer();
- d.resolve([]);
- return d.promise;
- }
- };
-
- /////////////////
- // Annotations //
- /////////////////
-
- ZabbixAPIDatasource.prototype.annotationQuery = function(annotation, rangeUnparsed) {
- var from = Math.ceil(dateMath.parse(rangeUnparsed.from) / 1000);
- var to = Math.ceil(dateMath.parse(rangeUnparsed.to) / 1000);
- var self = this;
-
- var params = {
- output: ['triggerid', 'description'],
- search: {
- 'description': annotation.trigger
- },
- searchWildcardsEnabled: true,
- expandDescription: true
- };
- if (annotation.host) {
- params.host = templateSrv.replace(annotation.host);
- }
- else if (annotation.group) {
- params.group = templateSrv.replace(annotation.group);
- }
-
- return this.zabbixAPI.performZabbixAPIRequest('trigger.get', params)
- .then(function (result) {
- if(result) {
- var objects = _.indexBy(result, 'triggerid');
- var params = {
- output: 'extend',
- time_from: from,
- time_till: to,
- objectids: _.keys(objects),
- select_acknowledges: 'extend'
- };
-
- // Show problem events only
- if (!annotation.showOkEvents) {
- params.value = 1;
- }
-
- return self.zabbixAPI.performZabbixAPIRequest('event.get', params)
- .then(function (result) {
- var events = [];
- _.each(result, function(e) {
- var formatted_acknowledges = zabbixHelperSrv.formatAcknowledges(e.acknowledges);
- events.push({
- annotation: annotation,
- time: e.clock * 1000,
- title: Number(e.value) ? 'Problem' : 'OK',
- text: objects[e.objectid].description + formatted_acknowledges
- });
- });
- return events;
- });
- } else {
- return [];
- }
- });
- };
-
- return ZabbixAPIDatasource;
- });
-});
diff --git a/zabbix/directives.js b/zabbix/directives.js
deleted file mode 100644
index 071d4be3a..000000000
--- a/zabbix/directives.js
+++ /dev/null
@@ -1,21 +0,0 @@
-define([
- 'angular'
- ],
- function (angular) {
- 'use strict';
-
- var module = angular.module('grafana.directives');
-
- module.directive('metricQueryEditorZabbix', function() {
- return {controller: 'ZabbixAPIQueryCtrl', templateUrl: 'app/plugins/datasource/zabbix/partials/query.editor.html'};
- });
-
- module.directive('metricQueryOptionsZabbix', function() {
- return {templateUrl: 'app/plugins/datasource/zabbix/partials/query.options.html'};
- });
-
- module.directive('annotationsQueryEditorZabbix', function() {
- return {templateUrl: 'app/plugins/datasource/zabbix/partials/annotations.editor.html'};
- });
-
- });
diff --git a/zabbix/helperFunctions.js b/zabbix/helperFunctions.js
deleted file mode 100644
index f59a4708a..000000000
--- a/zabbix/helperFunctions.js
+++ /dev/null
@@ -1,283 +0,0 @@
-define([
- 'angular',
- 'lodash'
-],
-function (angular, _) {
- 'use strict';
-
- var module = angular.module('grafana.services');
-
- module.service('zabbixHelperSrv', function($q) {
- var self = this;
-
- /**
- * Convert Zabbix API history.get response to Grafana format
- *
- * @param {Array} items Array of Zabbix Items
- * @param alias
- * @param scale
- * @param {Array} history Array of Zabbix History
- *
- * @return {Array} Array of timeseries in Grafana format
- * {
- * target: "Metric name",
- * datapoints: [[
, ], ...]
- * }
- */
- this.handleHistoryResponse = function(items, alias, scale, history) {
- /**
- * Response should be in the format:
- * data: [
- * {
- * target: "Metric name",
- * datapoints: [[, ], ...]
- * },
- * {
- * target: "Metric name",
- * datapoints: [[, ], ...]
- * },
- * ]
- */
-
- // Group items and history by itemid
- var indexed_items = _.indexBy(items, 'itemid');
- var grouped_history = _.groupBy(history, 'itemid');
-
- var self = this;
- return $q.when(_.map(grouped_history, function (history, itemid) {
- var item = indexed_items[itemid];
- return {
- target: (item.hosts ? item.hosts[0].name+': ' : '')
- + (alias ? alias : self.expandItemName(item)),
- datapoints: _.map(history, function (p) {
-
- // Value must be a number for properly work
- var value = Number(p.value);
-
- // Apply scale
- if (scale) {
- value *= scale;
- }
- return [value, p.clock * 1000];
- })
- };
- })).then(function (result) {
- return _.sortBy(result, 'target');
- });
- };
-
- /**
- * Convert Zabbix API trends.get response to Grafana format
- *
- * @param {Array} items Array of Zabbix Items
- * @param alias
- * @param scale
- * @param {string} points Point value to return: min, max or avg
- * @param {Array} trends Array of Zabbix Trends
- *
- * @return {Array} Array of timeseries in Grafana format
- * {
- * target: "Metric name",
- * datapoints: [[, ], ...]
- * }
- */
- this.handleTrendResponse = function (items, alias, scale, points, trends) {
-
- // Group items and trends by itemid
- var indexed_items = _.indexBy(items, 'itemid');
- var grouped_trends = _.groupBy(trends, 'itemid');
-
- var self = this;
- return $q.when(_.map(grouped_trends, function (trends, itemid) {
- var item = indexed_items[itemid];
- return {
- target: (item.hosts ? item.hosts[0].name+': ' : '')
- + (alias ? alias : self.expandItemName(item)),
- datapoints: _.map(trends, function (p) {
-
- // Value must be a number for properly work
- var value;
- if (points === "min") {
- value = Number(p.value_min);
- }
- else if (points === "max") {
- value = Number(p.value_max);
- }
- else {
- value = Number(p.value_avg);
- }
-
- // Apply scale
- if (scale) {
- value *= scale;
- }
- return [value, p.clock * 1000];
- })
- };
- })).then(function (result) {
- return _.sortBy(result, 'target');
- });
- };
-
- /**
- * Convert Zabbix API service.getsla response to Grafana format
- *
- * @param itservice
- * @param slaProperty
- * @param slaObject
- * @returns {{target: *, datapoints: *[]}}
- */
- this.handleSLAResponse = function (itservice, slaProperty, slaObject) {
- var targetSLA = slaObject[itservice.serviceid].sla[0];
- if (slaProperty.property === 'status') {
- var targetStatus = 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]
- ]
- };
- }
- };
-
- /**
- * Expand item parameters, for example:
- * CPU $2 time ($3) --> CPU system time (avg1)
- *
- * @param item: zabbix api item object
- * @return {string} expanded item name (string)
- */
- this.expandItemName = function(item) {
- var name = item.name;
- var key = item.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;
- };
-
- /**
- * Convert multiple mettrics to array
- * "{metric1,metcic2,...,metricN}" --> [metric1, metcic2,..., metricN]
- *
- * @param {string} metrics "{metric1,metcic2,...,metricN}"
- * @return {Array} [metric1, metcic2,..., metricN]
- */
- this.splitMetrics = function(metrics) {
- var remove_brackets_pattern = /^{|}$/g;
- var metric_split_pattern = /,(?!\s)/g;
- return metrics.replace(remove_brackets_pattern, '').split(metric_split_pattern);
- };
-
- /**
- * Convert Date object to local time in format
- * YYYY-MM-DD HH:mm:ss
- *
- * @param {Date} date Date object
- * @return {string} formatted local time YYYY-MM-DD HH:mm:ss
- */
- this.getShortTime = function(date) {
- var MM = date.getMonth() < 10 ? '0' + date.getMonth() : date.getMonth();
- var DD = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
- var HH = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
- var mm = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
- var ss = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
- return date.getFullYear() + '-' + MM + '-' + DD + ' ' + HH + ':' + mm + ':' + ss;
- };
-
- /**
- * Format acknowledges.
- *
- * @param {array} acknowledges array of Zabbix acknowledge objects
- * @return {string} HTML-formatted table
- */
- this.formatAcknowledges = function(acknowledges) {
- if (acknowledges.length) {
- var formatted_acknowledges = '
Acknowledges:
Time | '
- + 'User | Comments |
';
- _.each(_.map(acknowledges, function (ack) {
- var time = new Date(ack.clock * 1000);
- return '' + self.getShortTime(time) + ' | ' + ack.alias
- + ' (' + ack.name + ' ' + ack.surname + ')' + ' | ' + ack.message + ' |
';
- }), function (ack) {
- formatted_acknowledges = formatted_acknowledges.concat(ack);
- });
- formatted_acknowledges = formatted_acknowledges.concat('
');
- return formatted_acknowledges;
- } else {
- return '';
- }
- };
-
- /**
- * Downsample datapoints series
- *
- * @param {Object[]} datapoints [[, ], ...]
- * @param {integer} time_to Panel time to
- * @param {integer} ms_interval Interval in milliseconds for grouping datapoints
- * @param {string} func Value to return: min, max or avg
- * @return {Object[]} [[, ], ...]
- */
- this.downsampleSeries = function(datapoints, time_to, ms_interval, func) {
- 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([_.max(frame), timeWindow.to]);
- }
- else if (func === "min") {
- downsampledSeries.push([_.min(frame), timeWindow.to]);
- }
-
- // avg by default
- else {
- downsampledSeries.push([value_avg, timeWindow.to]);
- }
-
- // Shift time window
- timeWindow.to = timeWindow.from;
- timeWindow.from -= ms_interval;
-
- points_sum = 0;
- points_num = 0;
- frame = [];
-
- // Process point again
- i++;
- }
- }
- return downsampledSeries.reverse();
- };
- });
-});
\ No newline at end of file
diff --git a/zabbix/partials/annotations.editor.html b/zabbix/partials/annotations.editor.html
deleted file mode 100644
index 1a95b3651..000000000
--- a/zabbix/partials/annotations.editor.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
Options
-
-
-
-
diff --git a/zabbix/partials/config.html b/zabbix/partials/config.html
deleted file mode 100644
index a0a7f5074..000000000
--- a/zabbix/partials/config.html
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
-
-Zabbix API details
-
-
-
-
diff --git a/zabbix/partials/query.editor.html b/zabbix/partials/query.editor.html
deleted file mode 100644
index 5a85dc54c..000000000
--- a/zabbix/partials/query.editor.html
+++ /dev/null
@@ -1,227 +0,0 @@
-
-
-
-
diff --git a/zabbix/plugin.json b/zabbix/plugin.json
deleted file mode 100644
index b5a3489d0..000000000
--- a/zabbix/plugin.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "pluginType": "datasource",
- "name": "Zabbix",
-
- "type": "zabbix",
- "serviceName": "ZabbixAPIDatasource",
-
- "module": "app/plugins/datasource/zabbix/datasource",
-
- "partials": {
- "config": "app/plugins/datasource/zabbix/partials/config.html"
- },
-
- "metrics": true,
- "annotations": true
-}
diff --git a/zabbix/queryCtrl.js b/zabbix/queryCtrl.js
deleted file mode 100644
index e3cd92949..000000000
--- a/zabbix/queryCtrl.js
+++ /dev/null
@@ -1,273 +0,0 @@
-define([
- 'angular',
- 'lodash',
- './helperFunctions'
- ],
- function (angular, _) {
- 'use strict';
-
- var module = angular.module('grafana.controllers');
- var targetLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
-
- module.controller('ZabbixAPIQueryCtrl', function ($scope, $sce, templateSrv, zabbixHelperSrv) {
-
- $scope.init = function () {
- $scope.targetLetters = targetLetters;
- if (!$scope.target.mode || $scope.target.mode !== 1) {
- $scope.downsampleFunctionList = [
- {name: "avg", value: "avg"},
- {name: "min", value: "min"},
- {name: "max", value: "max"}
- ];
-
- // Set avg by default
- if (!$scope.target.downsampleFunction) {
- $scope.target.downsampleFunction = $scope.downsampleFunctionList[0];
- }
- if (!$scope.metric) {
- $scope.metric = {
- hostGroupList: [],
- hostList: [{name: '*', visible_name: 'All'}],
- applicationList: [{name: '*', visible_name: 'All'}],
- itemList: [{name: 'All'}]
- };
- }
-
- // Update host group, host, application and item lists
- $scope.updateGroupList();
- $scope.updateHostList();
- $scope.updateAppList();
- $scope.updateItemList();
-
- setItemAlias();
- }
- else if ($scope.target.mode === 1) {
- $scope.slaPropertyList = [
- {name: "Status", property: "status"},
- {name: "SLA", property: "sla"},
- {name: "OK time", property: "okTime"},
- {name: "Problem time", property: "problemTime"},
- {name: "Down time", property: "downtimeTime"}
- ];
- $scope.itserviceList = [{name: "test"}];
- $scope.updateITServiceList();
- }
-
- $scope.target.errors = validateTarget($scope.target);
- };
-
- /**
- * Switch query editor to specified mode.
- * Modes:
- * 0 - items
- * 1 - IT services
- */
- $scope.switchEditorMode = function (mode) {
- $scope.target.mode = mode;
- $scope.init();
- };
-
- /**
- * Take alias from item name by default
- */
- function setItemAlias() {
- if (!$scope.target.alias && $scope.target.item) {
- $scope.target.alias = $scope.target.item.name;
- }
- }
-
- $scope.targetBlur = function () {
- setItemAlias();
- $scope.target.errors = validateTarget($scope.target);
- if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
- $scope.oldTarget = angular.copy($scope.target);
- $scope.get_data();
- }
- };
-
- /**
- * Call when IT service is selected.
- */
- $scope.selectITService = function () {
- $scope.target.errors = validateTarget($scope.target);
- if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
- $scope.oldTarget = angular.copy($scope.target);
- $scope.get_data();
- }
- };
-
- /**
- * Call when host group selected
- */
- $scope.selectHostGroup = function () {
- $scope.updateHostList();
- $scope.updateAppList();
- $scope.updateItemList();
-
- $scope.target.errors = validateTarget($scope.target);
- if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
- $scope.oldTarget = angular.copy($scope.target);
- $scope.get_data();
- }
- };
-
- /**
- * Call when host selected
- */
- $scope.selectHost = function () {
- $scope.updateAppList();
- $scope.updateItemList();
-
- $scope.target.errors = validateTarget($scope.target);
- if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
- $scope.oldTarget = angular.copy($scope.target);
- $scope.get_data();
- }
- };
-
- /**
- * Call when application selected
- */
- $scope.selectApplication = function () {
- $scope.updateItemList();
-
- $scope.target.errors = validateTarget($scope.target);
- if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
- $scope.oldTarget = angular.copy($scope.target);
- $scope.get_data();
- }
- };
-
- /**
- * Call when item selected
- */
- $scope.selectItem = function () {
- setItemAlias();
- $scope.target.errors = validateTarget($scope.target);
- if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
- $scope.oldTarget = angular.copy($scope.target);
- $scope.get_data();
- }
- };
-
- $scope.duplicate = function () {
- var clone = angular.copy($scope.target);
- $scope.panel.targets.push(clone);
- };
-
- $scope.moveMetricQuery = function (fromIndex, toIndex) {
- _.move($scope.panel.targets, fromIndex, toIndex);
- };
-
- //////////////////////////////
- // SUGGESTION QUERIES
- //////////////////////////////
-
- /**
- * Update list of IT services
- */
- $scope.updateITServiceList = function () {
- $scope.datasource.zabbixAPI.getITService().then(function (iteservices) {
- $scope.itserviceList = [];
- $scope.itserviceList = $scope.itserviceList.concat(iteservices);
- });
- };
-
- /**
- * Update list of host groups
- */
- $scope.updateGroupList = function () {
- $scope.datasource.zabbixAPI.performHostGroupSuggestQuery().then(function (groups) {
- $scope.metric.groupList = [{name: '*', visible_name: 'All'}];
- addTemplatedVariables($scope.metric.groupList);
- $scope.metric.groupList = $scope.metric.groupList.concat(groups);
- });
- };
-
- /**
- * Update list of hosts
- */
- $scope.updateHostList = function () {
- var groups = $scope.target.group ? zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.group.name)) : undefined;
- if (groups) {
- $scope.datasource.zabbixAPI.hostFindQuery(groups).then(function (hosts) {
- $scope.metric.hostList = [{name: '*', visible_name: 'All'}];
- addTemplatedVariables($scope.metric.hostList);
- $scope.metric.hostList = $scope.metric.hostList.concat(hosts);
- });
- }
- };
-
- /**
- * Update list of host applications
- */
- $scope.updateAppList = function () {
- var groups = $scope.target.group ? zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.group.name)) : undefined;
- var hosts = $scope.target.host ? zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.host.name)) : undefined;
- if (groups && hosts) {
- $scope.datasource.zabbixAPI.appFindQuery(hosts, groups).then(function (apps) {
- apps = _.map(_.uniq(_.map(apps, 'name')), function (appname) {
- return {name: appname};
- });
- $scope.metric.applicationList = [{name: '*', visible_name: 'All'}];
- addTemplatedVariables($scope.metric.applicationList);
- $scope.metric.applicationList = $scope.metric.applicationList.concat(apps);
- });
- }
- };
-
- /**
- * Update list of items
- */
- $scope.updateItemList = function () {
- var groups = $scope.target.group ? zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.group.name)) : undefined;
- var hosts = $scope.target.host ? zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.host.name)) : undefined;
- var apps = $scope.target.application ?
- zabbixHelperSrv.splitMetrics(templateSrv.replace($scope.target.application.name)) : undefined;
- var itemtype = $scope.target.mode === 2 ? "text" : "numeric";
- if (groups && hosts && apps) {
- $scope.datasource.zabbixAPI.itemFindQuery(groups, hosts, apps, itemtype).then(function (items) {
- // Show only unique item names
- var uniq_items = _.map(_.uniq(items, function (item) {
- return zabbixHelperSrv.expandItemName(item);
- }), function (item) {
- return {name: zabbixHelperSrv.expandItemName(item)};
- });
- $scope.metric.itemList = [{name: 'All'}];
- addTemplatedVariables($scope.metric.itemList);
- $scope.metric.itemList = $scope.metric.itemList.concat(uniq_items);
- });
- }
- };
-
- /**
- * Add templated variables to list of available metrics
- *
- * @param {Array} metricList List of metrics which variables add to
- */
- function addTemplatedVariables(metricList) {
- _.each(templateSrv.variables, function (variable) {
- metricList.push({
- name: '$' + variable.name,
- templated: true
- });
- });
- }
-
- //////////////////////////////
- // VALIDATION
- //////////////////////////////
-
- function validateTarget(target) {
- var errs = {};
- if (!target) {
- errs = 'Not defined';
- }
- return errs;
- }
-
- $scope.init();
-
- });
-
- });
diff --git a/zabbix/zabbixAPIWrapper.js b/zabbix/zabbixAPIWrapper.js
deleted file mode 100644
index 8a89ccc02..000000000
--- a/zabbix/zabbixAPIWrapper.js
+++ /dev/null
@@ -1,538 +0,0 @@
-define([
- 'angular',
- 'lodash'
- ],
-function (angular, _) {
- 'use strict';
-
- var module = angular.module('grafana.services');
-
- module.factory('ZabbixAPI', function($q, backendSrv) {
-
- function ZabbixAPI(api_url, username, password, basicAuth, withCredentials) {
- // Initialize API parameters.
- this.url = api_url;
- this.username = username;
- this.password = password;
- this.basicAuth = basicAuth;
- this.withCredentials = withCredentials;
- }
-
- var p = ZabbixAPI.prototype;
-
- //////////////////
- // Core methods //
- //////////////////
-
- /**
- * Request data from Zabbix API
- *
- * @param {string} method Zabbix API method name
- * @param {object} params method params
- * @return {object} data.result field or []
- */
- p.performZabbixAPIRequest = function(method, params) {
- var options = {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- url: this.url,
- data: {
- jsonrpc: '2.0',
- method: method,
- params: params,
- auth: this.auth,
- id: 1
- }
- };
-
- if (this.basicAuth || this.withCredentials) {
- options.withCredentials = true;
- }
- if (this.basicAuth) {
- options.headers.Authorization = this.basicAuth;
- }
-
- var self = this;
- return backendSrv.datasourceRequest(options).then(function (response) {
- if (!response.data) {
- return [];
- }
- // Handle Zabbix API errors
- else if (response.data.error) {
-
- // Handle auth errors
- if (response.data.error.data === "Session terminated, re-login, please." ||
- response.data.error.data === "Not authorised." ||
- response.data.error.data === "Not authorized") {
- return self.performZabbixAPILogin().then(function (response) {
- self.auth = response;
- return self.performZabbixAPIRequest(method, params);
- });
- }
- }
- return response.data.result;
- });
- };
-
- /**
- * Get authentication token.
- *
- * @return {string} auth token
- */
- p.performZabbixAPILogin = function() {
- var options = {
- url : this.url,
- method : 'POST',
- data: {
- jsonrpc: '2.0',
- method: 'user.login',
- params: {
- user: this.username,
- password: this.password
- },
- auth: null,
- id: 1
- }
- };
-
- if (this.basicAuth || this.withCredentials) {
- options.withCredentials = true;
- }
- if (this.basicAuth) {
- options.headers = options.headers || {};
- options.headers.Authorization = this.basicAuth;
- }
-
- return backendSrv.datasourceRequest(options).then(function (result) {
- if (!result.data) {
- return null;
- }
- return result.data.result;
- });
- };
-
- /////////////////////////
- // API method wrappers //
- /////////////////////////
-
- /**
- * Request version of the Zabbix API.
- *
- * @return {string} Zabbix API version
- */
- p.getZabbixAPIVersion = function() {
- var options = {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- url: this.url,
- data: {
- jsonrpc: '2.0',
- method: 'apiinfo.version',
- params: [],
- id: 1
- }
- };
-
- if (this.basicAuth || this.withCredentials) {
- options.withCredentials = true;
- }
- if (this.basicAuth) {
- options.headers = options.headers || {};
- options.headers.Authorization = this.basicAuth;
- }
-
- return backendSrv.datasourceRequest(options).then(function (result) {
- if (!result.data) {
- return null;
- }
- return result.data.result;
- });
- };
-
- /**
- * Perform history query from Zabbix API
- *
- * @param {Array} items Array of Zabbix item objects
- * @param {Number} start Time in seconds
- * @param {Number} end Time in seconds
- * @return {Array} Array of Zabbix history objects
- */
- p.getHistory = function(items, start, end) {
- // Group items by value type
- var grouped_items = _.groupBy(items, 'value_type');
-
- // Perform request for each value type
- return $q.all(_.map(grouped_items, function (items, value_type) {
- var itemids = _.map(items, 'itemid');
- var params = {
- output: 'extend',
- history: value_type,
- itemids: itemids,
- sortfield: 'clock',
- sortorder: 'ASC',
- time_from: start
- };
-
- // Relative queries (e.g. last hour) don't include an end time
- if (end) {
- params.time_till = end;
- }
-
- return this.performZabbixAPIRequest('history.get', params);
- }, this)).then(function (results) {
- return _.flatten(results);
- });
- };
-
- /**
- * Perform trends query from Zabbix API
- * Use trends api extension from ZBXNEXT-1193 patch.
- *
- * @param {Array} items Array of Zabbix item objects
- * @param {Number} start Time in seconds
- * @param {Number} end Time in seconds
- * @return {Array} Array of Zabbix trend objects
- */
- p.getTrends = function(items, start, end) {
- // Group items by value type
- var grouped_items = _.groupBy(items, 'value_type');
-
- // Perform request for each value type
- return $q.all(_.map(grouped_items, function (items, value_type) {
- var itemids = _.map(items, 'itemid');
- var params = {
- output: 'extend',
- trend: value_type,
- itemids: itemids,
- sortfield: 'clock',
- sortorder: 'ASC',
- time_from: start
- };
-
- // Relative queries (e.g. last hour) don't include an end time
- if (end) {
- params.time_till = end;
- }
-
- return this.performZabbixAPIRequest('trend.get', params);
- }, this)).then(function (results) {
- return _.flatten(results);
- });
- };
-
- /**
- * Get the list of host groups
- *
- * @return {array} array of Zabbix hostgroup objects
- */
- p.performHostGroupSuggestQuery = function() {
- var params = {
- output: ['name'],
- sortfield: 'name',
- // Return only host groups that contain hosts
- real_hosts: true,
- // Return only host groups that contain monitored hosts.
- monitored_hosts: true
- };
-
- return this.performZabbixAPIRequest('hostgroup.get', params);
- };
-
- /**
- * Get the list of hosts
- *
- * @param {string|string[]} groupids
- * @return {Object} array of Zabbix host objects
- */
- p.performHostSuggestQuery = function(groupids) {
- var params = {
- output: ['name', 'host'],
- sortfield: 'name',
- // Return only hosts that have items with numeric type of information.
- with_simple_graph_items: true,
- // Return only monitored hosts.
- monitored_hosts: true
- };
- // Return only hosts in given group
- if (groupids) {
- params.groupids = groupids;
- }
- return this.performZabbixAPIRequest('host.get', params);
- };
-
- /**
- * Get the list of applications
- *
- * @param {array} hostids
- * @param {array} groupids
- * @return {Object} array of Zabbix application objects
- */
- p.performAppSuggestQuery = function(hostids, /* optional */ groupids) {
- var params = {
- output: ['name'],
- sortfield: 'name'
- };
- if (hostids) {
- params.hostids = hostids;
- }
- else if (groupids) {
- params.groupids = groupids;
- }
-
- return this.performZabbixAPIRequest('application.get', params);
- };
-
- /**
- * Items request
- *
- * @param {string|string[]} hostids ///////////////////////////
- * @param {string|string[]} applicationids // Zabbix API parameters //
- * @param {string|string[]} groupids ///////////////////////////
- * @return {string|string[]} Array of Zabbix API item objects
- */
- p.performItemSuggestQuery = function(hostids, applicationids, groupids, itemtype) {
- var params = {
- output: ['name', 'key_', 'value_type', 'delay'],
- sortfield: 'name',
- //Include web items in the result
- webitems: true,
- // Return only numeric items
- filter: {
- value_type: [0, 3]
- },
- // Return only enabled items
- monitored: true,
- searchByAny: true
- };
-
- if (itemtype === "text") {
- params.filter.value_type = [1, 2, 4];
- }
-
- // Filter by hosts or by groups
- if (hostids) {
- params.hostids = hostids;
- } else if (groupids) {
- params.groupids = groupids;
- }
-
- // If application selected return only relative items
- if (applicationids) {
- params.applicationids = applicationids;
- }
-
- // Return host property for multiple hosts
- if (!hostids || (_.isArray(hostids) && hostids.length > 1)) {
- params.selectHosts = ['name'];
- }
-
- return this.performZabbixAPIRequest('item.get', params);
- };
-
- /**
- * Get groups by names
- *
- * @param {string or array} group group names
- * @return {array} array of Zabbix API hostgroup objects
- */
- p.getGroupByName = function (group) {
- var params = {
- output: ['name']
- };
- if (group && group[0] !== '*') {
- params.filter = {
- name: group
- };
- }
- return this.performZabbixAPIRequest('hostgroup.get', params);
- };
-
- /**
- * Search group by name.
- *
- * @param {string} group group name
- * @return {array} groups
- */
- p.searchGroup = function (group) {
- var params = {
- output: ['name'],
- search: {
- name: group
- },
- searchWildcardsEnabled: true
- };
- return this.performZabbixAPIRequest('hostgroup.get', params);
- };
-
- /**
- * Get hosts by names
- *
- * @param {string or array} hostnames hosts names
- * @return {array} array of Zabbix API host objects
- */
- p.getHostByName = function (hostnames) {
- var params = {
- output: ['host', 'name']
- };
- if (hostnames && hostnames[0] !== '*') {
- params.filter = {
- name: hostnames
- };
- }
- return this.performZabbixAPIRequest('host.get', params);
- };
-
- /**
- * Get applications by names
- *
- * @param {string or array} application applications names
- * @return {array} array of Zabbix API application objects
- */
- p.getAppByName = function (application) {
- var params = {
- output: ['name']
- };
- if (application && application[0] !== '*') {
- params.filter = {
- name: application
- };
- }
- return this.performZabbixAPIRequest('application.get', params);
- };
-
- /**
- * Get items belongs to passed groups, hosts and
- * applications
- *
- * @param {string or array} groups
- * @param {string or array} hosts
- * @param {string or array} apps
- * @return {array} array of Zabbix API item objects
- */
- p.itemFindQuery = function(groups, hosts, apps, itemtype) {
- var promises = [];
-
- // Get hostids from names
- if (hosts && hosts[0] !== '*') {
- promises.push(this.getHostByName(hosts));
- }
- // Get groupids from names
- else if (groups) {
- promises.push(this.getGroupByName(groups));
- }
- // Get applicationids from names
- if (apps && apps[0] !== '*') {
- promises.push(this.getAppByName(apps));
- }
-
- var self = this;
- return $q.all(promises).then(function (results) {
- results = _.flatten(results);
- var groupids;
- var hostids;
- var applicationids;
- if (groups) {
- groupids = _.map(_.filter(results, function (object) {
- return object.groupid;
- }), 'groupid');
- }
- if (hosts && hosts[0] !== '*') {
- hostids = _.map(_.filter(results, function (object) {
- return object.hostid;
- }), 'hostid');
- }
- if (apps && apps[0] !== '*') {
- applicationids = _.map(_.filter(results, function (object) {
- return object.applicationid;
- }), 'applicationid');
- }
-
- return self.performItemSuggestQuery(hostids, applicationids, groupids, itemtype);
- });
- };
-
- /**
- * Find applications belongs to passed groups and hosts
- *
- * @param {string or array} hosts
- * @param {string or array} groups
- * @return {array} array of Zabbix API application objects
- */
- p.appFindQuery = function(hosts, groups) {
- var promises = [];
-
- // Get hostids from names
- if (hosts && hosts[0] !== '*') {
- promises.push(this.getHostByName(hosts));
- }
- // Get groupids from names
- else if (groups) {
- promises.push(this.getGroupByName(groups));
- }
-
- var self = this;
- return $q.all(promises).then(function (results) {
- results = _.flatten(results);
- var groupids;
- var hostids;
- if (groups) {
- groupids = _.map(_.filter(results, function (object) {
- return object.groupid;
- }), 'groupid');
- }
- if (hosts && hosts[0] !== '*') {
- hostids = _.map(_.filter(results, function (object) {
- return object.hostid;
- }), 'hostid');
- }
-
- return self.performAppSuggestQuery(hostids, groupids);
- });
- };
-
- /**
- * Find hosts belongs to passed groups
- *
- * @param {string or array} groups
- * @return {array} array of Zabbix API host objects
- */
- p.hostFindQuery = function(groups) {
- var self = this;
- return this.getGroupByName(groups).then(function (results) {
- results = _.flatten(results);
- var groupids = _.map(_.filter(results, function (object) {
- return object.groupid;
- }), 'groupid');
-
- return self.performHostSuggestQuery(groupids);
- });
- };
-
- p.getITService = function(/* optional */ serviceids) {
- var params = {
- output: 'extend',
- serviceids: serviceids
- };
- return this.performZabbixAPIRequest('service.get', params);
- };
-
- p.getSLA = function(serviceids, from, to) {
- var params = {
- serviceids: serviceids,
- intervals: [{
- from: from,
- to: to
- }]
- };
- return this.performZabbixAPIRequest('service.getsla', params);
- };
-
- return ZabbixAPI;
-
- });
-
-});