Merge branch 'master' into refactor
This commit is contained in:
13
CHANGELOG.md
13
CHANGELOG.md
@@ -6,11 +6,22 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
|||||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [3.9.1] - 2018-05-02
|
||||||
|
### Fixed
|
||||||
|
- Datasource fails when "Direct DB connection" enabled [#564](https://github.com/alexanderzobnin/grafana-zabbix/issues/564)
|
||||||
|
- Alerting and health icons on panels [#556](https://github.com/alexanderzobnin/grafana-zabbix/issues/556)
|
||||||
|
- Alerting threshold error [#549](https://github.com/alexanderzobnin/grafana-zabbix/issues/549)
|
||||||
|
|
||||||
|
## [3.9.0] - 2018-03-23
|
||||||
### Added
|
### Added
|
||||||
- Table format support for text data, [#492](https://github.com/alexanderzobnin/grafana-zabbix/issues/492)
|
- Table format support for text data [#492](https://github.com/alexanderzobnin/grafana-zabbix/issues/492)
|
||||||
|
- Option to enable triggers background highlighting [#532](https://github.com/alexanderzobnin/grafana-zabbix/issues/532)
|
||||||
|
- Option to disable acknowledges for read-only users [#481](https://github.com/alexanderzobnin/grafana-zabbix/issues/481)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Triggers panel has broken styles in Grafana 5.0 [#522](https://github.com/alexanderzobnin/grafana-zabbix/issues/522)
|
- Triggers panel has broken styles in Grafana 5.0 [#522](https://github.com/alexanderzobnin/grafana-zabbix/issues/522)
|
||||||
|
- Undefined username in acknowledges [#393](https://github.com/alexanderzobnin/grafana-zabbix/issues/393)
|
||||||
|
|
||||||
## [3.8.1] - 2017-12-21
|
## [3.8.1] - 2017-12-21
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
27
dist/css/grafana-zabbix.dark.css
vendored
27
dist/css/grafana-zabbix.dark.css
vendored
@@ -24,8 +24,6 @@
|
|||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
padding: 1px 6px;
|
padding: 1px 6px;
|
||||||
cursor: pointer; }
|
cursor: pointer; }
|
||||||
.triggers-panel-container .alert-list-footer {
|
|
||||||
justify-content: flex-start; }
|
|
||||||
.triggers-panel-container .trigger-info-block {
|
.triggers-panel-container .trigger-info-block {
|
||||||
display: flex; }
|
display: flex; }
|
||||||
.triggers-panel-container .trigger-info-block i, .triggers-panel-container .trigger-info-block a {
|
.triggers-panel-container .trigger-info-block i, .triggers-panel-container .trigger-info-block a {
|
||||||
@@ -37,8 +35,6 @@
|
|||||||
font-weight: 500; }
|
font-weight: 500; }
|
||||||
.triggers-panel-container .zabbix-trigger-source .gicon-datasources {
|
.triggers-panel-container .zabbix-trigger-source .gicon-datasources {
|
||||||
opacity: 0.4; }
|
opacity: 0.4; }
|
||||||
.triggers-panel-container .card-item-wrapper {
|
|
||||||
padding-left: 4px; }
|
|
||||||
|
|
||||||
.zbx-trigger-card {
|
.zbx-trigger-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -51,11 +47,19 @@
|
|||||||
.zbx-maintenance-icon {
|
.zbx-maintenance-icon {
|
||||||
color: #eb7b18; }
|
color: #eb7b18; }
|
||||||
|
|
||||||
@keyframes zabbix-triggers-panel {
|
.zbx-trigger-highlighted {
|
||||||
100% {
|
color: #fff; }
|
||||||
opacity: 1;
|
.zbx-trigger-highlighted .alert-rule-item__body,
|
||||||
box-shadow: 0 0 10px 0px #d44a3a;
|
.zbx-trigger-highlighted .alert-rule-item__header,
|
||||||
border-bottom-color: rgba(212, 74, 58, 0.25); } }
|
.zbx-trigger-highlighted .alert-rule-item__time,
|
||||||
|
.zbx-trigger-highlighted .zabbix-hostname,
|
||||||
|
.zbx-trigger-highlighted .zbx-description {
|
||||||
|
color: #fff; }
|
||||||
|
.zbx-trigger-highlighted .alert-rule-item__text .zbx-trigger-state,
|
||||||
|
.zbx-trigger-highlighted .alert-rule-item__text .zbx-trigger-severity {
|
||||||
|
color: #fff; }
|
||||||
|
.zbx-trigger-highlighted .zbx-trigger-lastchange .trigger-info-block.zbx-status-icons a, .zbx-trigger-highlighted .zbx-trigger-lastchange .trigger-info-block.zbx-status-icons i {
|
||||||
|
color: #fff; }
|
||||||
|
|
||||||
@keyframes zabbix-triggers-icon {
|
@keyframes zabbix-triggers-icon {
|
||||||
100% {
|
100% {
|
||||||
@@ -107,8 +111,9 @@
|
|||||||
margin-left: 1rem; }
|
margin-left: 1rem; }
|
||||||
|
|
||||||
.triggers-severity-config.gf-form-label {
|
.triggers-severity-config.gf-form-label {
|
||||||
padding-top: 4px;
|
padding-top: 5px;
|
||||||
padding-bottom: 4px; }
|
padding-bottom: 5px;
|
||||||
|
border-radius: 0px; }
|
||||||
|
|
||||||
.triggers-severity-config .icon-gf {
|
.triggers-severity-config .icon-gf {
|
||||||
font-size: 200%; }
|
font-size: 200%; }
|
||||||
|
|||||||
2
dist/css/grafana-zabbix.dark.css.map
vendored
2
dist/css/grafana-zabbix.dark.css.map
vendored
@@ -9,6 +9,6 @@
|
|||||||
"../../src/sass/_panel-triggers.scss",
|
"../../src/sass/_panel-triggers.scss",
|
||||||
"../../src/sass/_query_editor.scss"
|
"../../src/sass/_query_editor.scss"
|
||||||
],
|
],
|
||||||
"mappings": "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",
|
"mappings": "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",
|
||||||
"names": []
|
"names": []
|
||||||
}
|
}
|
||||||
27
dist/css/grafana-zabbix.light.css
vendored
27
dist/css/grafana-zabbix.light.css
vendored
@@ -24,8 +24,6 @@
|
|||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
padding: 1px 6px;
|
padding: 1px 6px;
|
||||||
cursor: pointer; }
|
cursor: pointer; }
|
||||||
.triggers-panel-container .alert-list-footer {
|
|
||||||
justify-content: flex-start; }
|
|
||||||
.triggers-panel-container .trigger-info-block {
|
.triggers-panel-container .trigger-info-block {
|
||||||
display: flex; }
|
display: flex; }
|
||||||
.triggers-panel-container .trigger-info-block i, .triggers-panel-container .trigger-info-block a {
|
.triggers-panel-container .trigger-info-block i, .triggers-panel-container .trigger-info-block a {
|
||||||
@@ -37,8 +35,6 @@
|
|||||||
font-weight: 500; }
|
font-weight: 500; }
|
||||||
.triggers-panel-container .zabbix-trigger-source .gicon-datasources {
|
.triggers-panel-container .zabbix-trigger-source .gicon-datasources {
|
||||||
opacity: 0.4; }
|
opacity: 0.4; }
|
||||||
.triggers-panel-container .card-item-wrapper {
|
|
||||||
padding-left: 4px; }
|
|
||||||
|
|
||||||
.zbx-trigger-card {
|
.zbx-trigger-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -51,11 +47,19 @@
|
|||||||
.zbx-maintenance-icon {
|
.zbx-maintenance-icon {
|
||||||
color: #ff7941; }
|
color: #ff7941; }
|
||||||
|
|
||||||
@keyframes zabbix-triggers-panel {
|
.zbx-trigger-highlighted {
|
||||||
100% {
|
color: #000; }
|
||||||
opacity: 1;
|
.zbx-trigger-highlighted .alert-rule-item__body,
|
||||||
box-shadow: 0 0 10px 0px #d44939;
|
.zbx-trigger-highlighted .alert-rule-item__header,
|
||||||
border-bottom-color: rgba(212, 73, 57, 0.25); } }
|
.zbx-trigger-highlighted .alert-rule-item__time,
|
||||||
|
.zbx-trigger-highlighted .zabbix-hostname,
|
||||||
|
.zbx-trigger-highlighted .zbx-description {
|
||||||
|
color: #000; }
|
||||||
|
.zbx-trigger-highlighted .alert-rule-item__text .zbx-trigger-state,
|
||||||
|
.zbx-trigger-highlighted .alert-rule-item__text .zbx-trigger-severity {
|
||||||
|
color: #000; }
|
||||||
|
.zbx-trigger-highlighted .zbx-trigger-lastchange .trigger-info-block.zbx-status-icons a, .zbx-trigger-highlighted .zbx-trigger-lastchange .trigger-info-block.zbx-status-icons i {
|
||||||
|
color: #000; }
|
||||||
|
|
||||||
@keyframes zabbix-triggers-icon {
|
@keyframes zabbix-triggers-icon {
|
||||||
100% {
|
100% {
|
||||||
@@ -107,8 +111,9 @@
|
|||||||
margin-left: 1rem; }
|
margin-left: 1rem; }
|
||||||
|
|
||||||
.triggers-severity-config.gf-form-label {
|
.triggers-severity-config.gf-form-label {
|
||||||
padding-top: 4px;
|
padding-top: 5px;
|
||||||
padding-bottom: 4px; }
|
padding-bottom: 5px;
|
||||||
|
border-radius: 0px; }
|
||||||
|
|
||||||
.triggers-severity-config .icon-gf {
|
.triggers-severity-config .icon-gf {
|
||||||
font-size: 200%; }
|
font-size: 200%; }
|
||||||
|
|||||||
2
dist/css/grafana-zabbix.light.css.map
vendored
2
dist/css/grafana-zabbix.light.css.map
vendored
@@ -9,6 +9,6 @@
|
|||||||
"../../src/sass/_panel-triggers.scss",
|
"../../src/sass/_panel-triggers.scss",
|
||||||
"../../src/sass/_query_editor.scss"
|
"../../src/sass/_query_editor.scss"
|
||||||
],
|
],
|
||||||
"mappings": "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",
|
"mappings": "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",
|
||||||
"names": []
|
"names": []
|
||||||
}
|
}
|
||||||
865
dist/datasource-zabbix/datasource.js
vendored
865
dist/datasource-zabbix/datasource.js
vendored
@@ -1,865 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
System.register(['lodash', 'app/core/utils/datemath', './utils', './migrations', './metricFunctions', './constants', './dataProcessor', './responseHandler', './zabbixAlerting.service.js', './zabbix/zabbix', './zabbix/connectors/zabbix_api/zabbixAPICore'], function (_export, _context) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var _, dateMath, utils, migrations, metricFunctions, c, dataProcessor, responseHandler, Zabbix, ZabbixAPIError, _slicedToArray, _createClass, ZabbixAPIDatasource;
|
|
||||||
|
|
||||||
function _classCallCheck(instance, Constructor) {
|
|
||||||
if (!(instance instanceof Constructor)) {
|
|
||||||
throw new TypeError("Cannot call a class as a function");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function bindFunctionDefs(functionDefs, category) {
|
|
||||||
var aggregationFunctions = _.map(metricFunctions.getCategories()[category], 'name');
|
|
||||||
var aggFuncDefs = _.filter(functionDefs, function (func) {
|
|
||||||
return _.includes(aggregationFunctions, func.def.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
return _.map(aggFuncDefs, function (func) {
|
|
||||||
var funcInstance = metricFunctions.createFuncInstance(func.def, func.params);
|
|
||||||
return funcInstance.bindFunction(dataProcessor.metricFunctions);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getConsolidateBy(target) {
|
|
||||||
var consolidateBy = 'avg';
|
|
||||||
var funcDef = _.find(target.functions, function (func) {
|
|
||||||
return func.def.name === 'consolidateBy';
|
|
||||||
});
|
|
||||||
if (funcDef && funcDef.params && funcDef.params.length) {
|
|
||||||
consolidateBy = funcDef.params[0];
|
|
||||||
}
|
|
||||||
return consolidateBy;
|
|
||||||
}
|
|
||||||
|
|
||||||
function downsampleSeries(timeseries_data, options) {
|
|
||||||
var defaultAgg = dataProcessor.aggregationFunctions['avg'];
|
|
||||||
var consolidateByFunc = dataProcessor.aggregationFunctions[options.consolidateBy] || defaultAgg;
|
|
||||||
return _.map(timeseries_data, function (timeseries) {
|
|
||||||
if (timeseries.datapoints.length > options.maxDataPoints) {
|
|
||||||
timeseries.datapoints = dataProcessor.groupBy(options.interval, consolidateByFunc, 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 = _.map(value, utils.escapeRegex);
|
|
||||||
return '(' + escapedValues.join('|') + ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
function zabbixItemIdsTemplateFormat(value) {
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
return value.join(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If template variables are used in request, replace it using regex format
|
|
||||||
* and wrap with '/' for proper multi-value work. Example:
|
|
||||||
* $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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterEnabledTargets(targets) {
|
|
||||||
return _.filter(targets, function (target) {
|
|
||||||
return !(target.hide || !target.group || !target.host || !target.item);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTriggerThreshold(expression) {
|
|
||||||
var thresholdPattern = /.*[<>=]{1,2}([\d\.]+)/;
|
|
||||||
var finded_thresholds = expression.match(thresholdPattern);
|
|
||||||
if (finded_thresholds && finded_thresholds.length >= 2) {
|
|
||||||
var threshold = finded_thresholds[1];
|
|
||||||
threshold = Number(threshold);
|
|
||||||
return threshold;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
setters: [function (_lodash) {
|
|
||||||
_ = _lodash.default;
|
|
||||||
}, function (_appCoreUtilsDatemath) {
|
|
||||||
dateMath = _appCoreUtilsDatemath;
|
|
||||||
}, function (_utils) {
|
|
||||||
utils = _utils;
|
|
||||||
}, function (_migrations) {
|
|
||||||
migrations = _migrations;
|
|
||||||
}, function (_metricFunctions) {
|
|
||||||
metricFunctions = _metricFunctions;
|
|
||||||
}, function (_constants) {
|
|
||||||
c = _constants;
|
|
||||||
}, function (_dataProcessor) {
|
|
||||||
dataProcessor = _dataProcessor.default;
|
|
||||||
}, function (_responseHandler) {
|
|
||||||
responseHandler = _responseHandler.default;
|
|
||||||
}, function (_zabbixAlertingServiceJs) {}, function (_zabbixZabbix) {
|
|
||||||
Zabbix = _zabbixZabbix.Zabbix;
|
|
||||||
}, function (_zabbixConnectorsZabbix_apiZabbixAPICore) {
|
|
||||||
ZabbixAPIError = _zabbixConnectorsZabbix_apiZabbixAPICore.ZabbixAPIError;
|
|
||||||
}],
|
|
||||||
execute: function () {
|
|
||||||
_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");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}();
|
|
||||||
|
|
||||||
_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;
|
|
||||||
};
|
|
||||||
}();
|
|
||||||
|
|
||||||
_export('ZabbixAPIDatasource', ZabbixAPIDatasource = function () {
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
function ZabbixAPIDatasource(instanceSettings, templateSrv, alertSrv, dashboardSrv, backendSrv, datasourceSrv, zabbixAlertingSrv) {
|
|
||||||
_classCallCheck(this, ZabbixAPIDatasource);
|
|
||||||
|
|
||||||
this.templateSrv = templateSrv;
|
|
||||||
this.alertSrv = alertSrv;
|
|
||||||
this.dashboardSrv = dashboardSrv;
|
|
||||||
this.zabbixAlertingSrv = zabbixAlertingSrv;
|
|
||||||
|
|
||||||
// Use custom format for template variables
|
|
||||||
this.replaceTemplateVars = _.partial(replaceTemplateVars, this.templateSrv);
|
|
||||||
|
|
||||||
// General data source settings
|
|
||||||
this.name = instanceSettings.name;
|
|
||||||
this.url = instanceSettings.url;
|
|
||||||
this.basicAuth = instanceSettings.basicAuth;
|
|
||||||
this.withCredentials = instanceSettings.withCredentials;
|
|
||||||
|
|
||||||
var jsonData = instanceSettings.jsonData;
|
|
||||||
|
|
||||||
// Zabbix API credentials
|
|
||||||
this.username = jsonData.username;
|
|
||||||
this.password = jsonData.password;
|
|
||||||
|
|
||||||
// Use trends instead history since specified time
|
|
||||||
this.trends = jsonData.trends;
|
|
||||||
this.trendsFrom = jsonData.trendsFrom || '7d';
|
|
||||||
this.trendsRange = jsonData.trendsRange || '4d';
|
|
||||||
|
|
||||||
// Set cache update interval
|
|
||||||
var ttl = jsonData.cacheTTL || '1h';
|
|
||||||
this.cacheTTL = utils.parseInterval(ttl);
|
|
||||||
|
|
||||||
// Alerting options
|
|
||||||
this.alertingEnabled = jsonData.alerting;
|
|
||||||
this.addThresholds = jsonData.addThresholds;
|
|
||||||
this.alertingMinSeverity = jsonData.alertingMinSeverity || c.SEV_WARNING;
|
|
||||||
|
|
||||||
// Direct DB Connection options
|
|
||||||
var dbConnectionOptions = jsonData.dbConnection || {};
|
|
||||||
this.enableDirectDBConnection = dbConnectionOptions.enable;
|
|
||||||
this.sqlDatasourceId = dbConnectionOptions.datasourceId;
|
|
||||||
|
|
||||||
var zabbixOptions = {
|
|
||||||
username: this.username,
|
|
||||||
password: this.password,
|
|
||||||
basicAuth: this.basicAuth,
|
|
||||||
withCredentials: this.withCredentials,
|
|
||||||
cacheTTL: this.cacheTTL,
|
|
||||||
enableDirectDBConnection: this.enableDirectDBConnection,
|
|
||||||
sqlDatasourceId: this.sqlDatasourceId
|
|
||||||
};
|
|
||||||
|
|
||||||
this.zabbix = new Zabbix(this.url, zabbixOptions, backendSrv, datasourceSrv);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// Get alerts for current panel
|
|
||||||
if (this.alertingEnabled) {
|
|
||||||
this.alertQuery(options).then(function (alert) {
|
|
||||||
_this.zabbixAlertingSrv.setPanelAlertState(options.panelId, alert.state);
|
|
||||||
|
|
||||||
_this.zabbixAlertingSrv.removeZabbixThreshold(options.panelId);
|
|
||||||
if (_this.addThresholds) {
|
|
||||||
_.forEach(alert.thresholds, function (threshold) {
|
|
||||||
_this.zabbixAlertingSrv.setPanelThreshold(options.panelId, threshold);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create request for each target
|
|
||||||
var promises = _.map(options.targets, function (t) {
|
|
||||||
// Don't request undefined and hidden targets
|
|
||||||
if (t.hide) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
var timeFrom = Math.ceil(dateMath.parse(options.range.from) / 1000);
|
|
||||||
var timeTo = Math.ceil(dateMath.parse(options.range.to) / 1000);
|
|
||||||
|
|
||||||
// Prevent changes of original object
|
|
||||||
var target = _.cloneDeep(t);
|
|
||||||
_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;
|
|
||||||
}
|
|
||||||
var timeRange = [timeFrom, timeTo];
|
|
||||||
|
|
||||||
var useTrends = _this.isUseTrends(timeRange);
|
|
||||||
|
|
||||||
// Metrics or Text query mode
|
|
||||||
if (!target.mode || target.mode === c.MODE_METRICS || target.mode === c.MODE_TEXT) {
|
|
||||||
// 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 === c.MODE_METRICS) {
|
|
||||||
return _this.queryNumericData(target, timeRange, useTrends, options);
|
|
||||||
} else if (target.mode === c.MODE_TEXT) {
|
|
||||||
return _this.queryTextData(target, timeRange);
|
|
||||||
}
|
|
||||||
} else if (target.mode === c.MODE_ITEMID) {
|
|
||||||
// Item ID mode
|
|
||||||
if (!target.itemids) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return _this.queryItemIdData(target, timeRange, useTrends, options);
|
|
||||||
} else if (target.mode === c.MODE_ITSERVICE) {
|
|
||||||
// IT services mode
|
|
||||||
return _this.queryITServiceData(target, timeRange, options);
|
|
||||||
} else if (target.mode === c.MODE_TRIGGERS) {
|
|
||||||
// Triggers mode
|
|
||||||
return _this.queryTriggersData(target, timeRange);
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Data for panel (all targets)
|
|
||||||
return Promise.all(_.flatten(promises)).then(_.flatten).then(function (data) {
|
|
||||||
return { data: data };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'queryNumericData',
|
|
||||||
value: function queryNumericData(target, timeRange, useTrends, options) {
|
|
||||||
var _this2 = this;
|
|
||||||
|
|
||||||
var getItemOptions = {
|
|
||||||
itemtype: 'num'
|
|
||||||
};
|
|
||||||
return this.zabbix.getItemsFromTarget(target, getItemOptions).then(function (items) {
|
|
||||||
return _this2.queryNumericDataForItems(items, target, timeRange, useTrends, options);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'queryNumericDataForItems',
|
|
||||||
value: function queryNumericDataForItems(items, target, timeRange, useTrends, options) {
|
|
||||||
var _this3 = this;
|
|
||||||
|
|
||||||
var _timeRange = _slicedToArray(timeRange, 2),
|
|
||||||
timeFrom = _timeRange[0],
|
|
||||||
timeTo = _timeRange[1];
|
|
||||||
|
|
||||||
var getHistoryPromise = void 0;
|
|
||||||
options.consolidateBy = getConsolidateBy(target);
|
|
||||||
|
|
||||||
if (useTrends) {
|
|
||||||
if (this.enableDirectDBConnection) {
|
|
||||||
getHistoryPromise = this.zabbix.getTrendsDB(items, timeFrom, timeTo, options).then(function (history) {
|
|
||||||
return _this3.zabbix.dbConnector.handleGrafanaTSResponse(history, items);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
var valueType = this.getTrendValueType(target);
|
|
||||||
getHistoryPromise = this.zabbix.getTrend(items, timeFrom, timeTo).then(function (history) {
|
|
||||||
return responseHandler.handleTrends(history, items, valueType);
|
|
||||||
}).then(function (timeseries) {
|
|
||||||
// Sort trend data, issue #202
|
|
||||||
_.forEach(timeseries, function (series) {
|
|
||||||
series.datapoints = _.sortBy(series.datapoints, function (point) {
|
|
||||||
return point[c.DATAPOINT_TS];
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return timeseries;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Use history
|
|
||||||
if (this.enableDirectDBConnection) {
|
|
||||||
getHistoryPromise = this.zabbix.getHistoryDB(items, timeFrom, timeTo, options).then(function (history) {
|
|
||||||
return _this3.zabbix.dbConnector.handleGrafanaTSResponse(history, items);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
getHistoryPromise = this.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
|
|
||||||
return responseHandler.handleHistory(history, items);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return getHistoryPromise.then(function (timeseries) {
|
|
||||||
return _this3.applyDataProcessingFunctions(timeseries, target);
|
|
||||||
}).then(function (timeseries) {
|
|
||||||
return downsampleSeries(timeseries, options);
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
return [];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getTrendValueType',
|
|
||||||
value: function getTrendValueType(target) {
|
|
||||||
// Find trendValue() function and get specified trend value
|
|
||||||
var trendFunctions = _.map(metricFunctions.getCategories()['Trends'], 'name');
|
|
||||||
var trendValueFunc = _.find(target.functions, function (func) {
|
|
||||||
return _.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 = _.cloneDeep(_.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) {
|
|
||||||
var dp = _.map(timeseries_data, 'datapoints');
|
|
||||||
dp = sequence(aggregationFunctions)(dp);
|
|
||||||
|
|
||||||
var aggFuncNames = _.map(metricFunctions.getCategories()['Aggregate'], 'name');
|
|
||||||
var lastAgg = _.findLast(target.functions, function (func) {
|
|
||||||
return _.includes(aggFuncNames, func.def.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
timeseries_data = [{
|
|
||||||
target: lastAgg.text,
|
|
||||||
datapoints: dp
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply alias functions
|
|
||||||
_.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 = _.find(target.functions, function (func) {
|
|
||||||
return func.def.name === 'timeShift';
|
|
||||||
});
|
|
||||||
if (timeShiftFunc) {
|
|
||||||
var shift = timeShiftFunc.params[0];
|
|
||||||
_.forEach(timeseries_data, function (series) {
|
|
||||||
series.datapoints = dataProcessor.unShiftTimeSeries(shift, series.datapoints);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'queryTextData',
|
|
||||||
value: function queryTextData(target, timeRange) {
|
|
||||||
var _this4 = this;
|
|
||||||
|
|
||||||
var _timeRange2 = _slicedToArray(timeRange, 2),
|
|
||||||
timeFrom = _timeRange2[0],
|
|
||||||
timeTo = _timeRange2[1];
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
itemtype: 'text'
|
|
||||||
};
|
|
||||||
return this.zabbix.getItemsFromTarget(target, options).then(function (items) {
|
|
||||||
if (items.length) {
|
|
||||||
return _this4.zabbix.getHistory(items, timeFrom, timeTo).then(function (history) {
|
|
||||||
if (target.resultFormat === 'table') {
|
|
||||||
return responseHandler.handleHistoryAsTable(history, items, target);
|
|
||||||
} else {
|
|
||||||
return responseHandler.handleText(history, items, target);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Promise.resolve([]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'queryItemIdData',
|
|
||||||
value: function queryItemIdData(target, timeRange, useTrends, options) {
|
|
||||||
var _this5 = this;
|
|
||||||
|
|
||||||
var itemids = target.itemids;
|
|
||||||
itemids = this.templateSrv.replace(itemids, options.scopedVars, zabbixItemIdsTemplateFormat);
|
|
||||||
itemids = _.map(itemids.split(','), function (itemid) {
|
|
||||||
return itemid.trim();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!itemids) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.zabbix.getItemsByIDs(itemids).then(function (items) {
|
|
||||||
return _this5.queryNumericDataForItems(items, target, timeRange, useTrends, options);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'queryITServiceData',
|
|
||||||
value: function queryITServiceData(target, timeRange, options) {
|
|
||||||
var _this6 = this;
|
|
||||||
|
|
||||||
// Don't show undefined and hidden targets
|
|
||||||
if (target.hide || !target.itservice && !target.itServiceFilter || !target.slaProperty) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
var itServiceIds = [];
|
|
||||||
var itServices = [];
|
|
||||||
var itServiceFilter = void 0;
|
|
||||||
var isOldVersion = target.itservice && !target.itServiceFilter;
|
|
||||||
|
|
||||||
if (isOldVersion) {
|
|
||||||
// Backward compatibility
|
|
||||||
itServiceFilter = '/.*/';
|
|
||||||
} else {
|
|
||||||
itServiceFilter = this.replaceTemplateVars(target.itServiceFilter, options.scopedVars);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.zabbix.getITServices(itServiceFilter).then(function (itservices) {
|
|
||||||
itServices = itservices;
|
|
||||||
if (isOldVersion) {
|
|
||||||
itServices = _.filter(itServices, { 'serviceid': target.itservice.serviceid });
|
|
||||||
}
|
|
||||||
|
|
||||||
itServiceIds = _.map(itServices, 'serviceid');
|
|
||||||
return itServiceIds;
|
|
||||||
}).then(function (serviceids) {
|
|
||||||
return _this6.zabbix.getSLA(serviceids, timeRange);
|
|
||||||
}).then(function (slaResponse) {
|
|
||||||
return _.map(itServiceIds, function (serviceid) {
|
|
||||||
var itservice = _.find(itServices, { 'serviceid': serviceid });
|
|
||||||
return responseHandler.handleSLAResponse(itservice, target.slaProperty, slaResponse);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'queryTriggersData',
|
|
||||||
value: function queryTriggersData(target, timeRange) {
|
|
||||||
var _this7 = this;
|
|
||||||
|
|
||||||
var _timeRange3 = _slicedToArray(timeRange, 2),
|
|
||||||
timeFrom = _timeRange3[0],
|
|
||||||
timeTo = _timeRange3[1];
|
|
||||||
|
|
||||||
return this.zabbix.getHostsFromTarget(target).then(function (results) {
|
|
||||||
var _results = _slicedToArray(results, 2),
|
|
||||||
hosts = _results[0],
|
|
||||||
apps = _results[1];
|
|
||||||
|
|
||||||
if (hosts.length) {
|
|
||||||
var hostids = _.map(hosts, 'hostid');
|
|
||||||
var appids = _.map(apps, 'applicationid');
|
|
||||||
var options = {
|
|
||||||
minSeverity: target.triggers.minSeverity,
|
|
||||||
acknowledged: target.triggers.acknowledged,
|
|
||||||
count: target.triggers.count,
|
|
||||||
timeFrom: timeFrom,
|
|
||||||
timeTo: timeTo
|
|
||||||
};
|
|
||||||
return _this7.zabbix.getHostAlerts(hostids, appids, options).then(function (triggers) {
|
|
||||||
return responseHandler.handleTriggersResponse(triggers, timeRange);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Promise.resolve([]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'testDatasource',
|
|
||||||
value: function testDatasource() {
|
|
||||||
var _this8 = this;
|
|
||||||
|
|
||||||
var zabbixVersion = void 0;
|
|
||||||
return this.zabbix.getVersion().then(function (version) {
|
|
||||||
zabbixVersion = version;
|
|
||||||
return _this8.zabbix.login();
|
|
||||||
}).then(function () {
|
|
||||||
if (_this8.enableDirectDBConnection) {
|
|
||||||
return _this8.zabbix.dbConnector.testSQLDataSource();
|
|
||||||
} else {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
}).then(function () {
|
|
||||||
return {
|
|
||||||
status: "success",
|
|
||||||
title: "Success",
|
|
||||||
message: "Zabbix API version: " + zabbixVersion
|
|
||||||
};
|
|
||||||
}).catch(function (error) {
|
|
||||||
if (error instanceof ZabbixAPIError) {
|
|
||||||
return {
|
|
||||||
status: "error",
|
|
||||||
title: error.message,
|
|
||||||
message: error.message
|
|
||||||
};
|
|
||||||
} else if (error.data && error.data.message) {
|
|
||||||
return {
|
|
||||||
status: "error",
|
|
||||||
title: "Connection failed",
|
|
||||||
message: "Connection failed: " + error.data.message
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
status: "error",
|
|
||||||
title: "Connection failed",
|
|
||||||
message: "Could not connect to given url"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'metricFindQuery',
|
|
||||||
value: function metricFindQuery(query) {
|
|
||||||
var _this9 = this;
|
|
||||||
|
|
||||||
var result = void 0;
|
|
||||||
var parts = [];
|
|
||||||
|
|
||||||
// Split query. Query structure: group.host.app.item
|
|
||||||
_.each(utils.splitTemplateQuery(query), function (part) {
|
|
||||||
part = _this9.replaceTemplateVars(part, {});
|
|
||||||
|
|
||||||
// Replace wildcard to regex
|
|
||||||
if (part === '*') {
|
|
||||||
part = '/.*/';
|
|
||||||
}
|
|
||||||
parts.push(part);
|
|
||||||
});
|
|
||||||
var template = _.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 _.map(metrics, formatMetric);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'annotationQuery',
|
|
||||||
value: function annotationQuery(options) {
|
|
||||||
var _this10 = 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 ? c.SHOW_ALL_EVENTS : c.SHOW_OK_EVENTS;
|
|
||||||
|
|
||||||
// Show all triggers
|
|
||||||
var triggersOptions = {
|
|
||||||
showTriggers: c.SHOW_ALL_TRIGGERS,
|
|
||||||
hideHostsInMaintenance: false
|
|
||||||
};
|
|
||||||
|
|
||||||
var getTriggers = this.zabbix.getTriggers(this.replaceTemplateVars(annotation.group, {}), this.replaceTemplateVars(annotation.host, {}), this.replaceTemplateVars(annotation.application, {}), triggersOptions);
|
|
||||||
|
|
||||||
return getTriggers.then(function (triggers) {
|
|
||||||
|
|
||||||
// Filter triggers by description
|
|
||||||
var triggerName = _this10.replaceTemplateVars(annotation.trigger, {});
|
|
||||||
if (utils.isRegex(triggerName)) {
|
|
||||||
triggers = _.filter(triggers, function (trigger) {
|
|
||||||
return utils.buildRegex(triggerName).test(trigger.description);
|
|
||||||
});
|
|
||||||
} else if (triggerName) {
|
|
||||||
triggers = _.filter(triggers, function (trigger) {
|
|
||||||
return trigger.description === triggerName;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove events below the chose severity
|
|
||||||
triggers = _.filter(triggers, function (trigger) {
|
|
||||||
return Number(trigger.priority) >= Number(annotation.minseverity);
|
|
||||||
});
|
|
||||||
|
|
||||||
var objectids = _.map(triggers, 'triggerid');
|
|
||||||
return _this10.zabbix.getEvents(objectids, timeFrom, timeTo, showOkEvents).then(function (events) {
|
|
||||||
var indexedTriggers = _.keyBy(triggers, 'triggerid');
|
|
||||||
|
|
||||||
// Hide acknowledged events if option enabled
|
|
||||||
if (annotation.hideAcknowledged) {
|
|
||||||
events = _.filter(events, function (event) {
|
|
||||||
return !event.acknowledges.length;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return _.map(events, function (event) {
|
|
||||||
var tags = void 0;
|
|
||||||
if (annotation.showHostname) {
|
|
||||||
tags = _.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
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'alertQuery',
|
|
||||||
value: function alertQuery(options) {
|
|
||||||
var _this11 = this;
|
|
||||||
|
|
||||||
var enabled_targets = filterEnabledTargets(options.targets);
|
|
||||||
var getPanelItems = _.map(enabled_targets, function (t) {
|
|
||||||
var target = _.cloneDeep(t);
|
|
||||||
_this11.replaceTargetVariables(target, options);
|
|
||||||
return _this11.zabbix.getItemsFromTarget(target, { itemtype: 'num' });
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(getPanelItems).then(function (results) {
|
|
||||||
var items = _.flatten(results);
|
|
||||||
var itemids = _.map(items, 'itemid');
|
|
||||||
|
|
||||||
if (itemids.length === 0) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return _this11.zabbix.getAlerts(itemids);
|
|
||||||
}).then(function (triggers) {
|
|
||||||
triggers = _.filter(triggers, function (trigger) {
|
|
||||||
return trigger.priority >= _this11.alertingMinSeverity;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!triggers || triggers.length === 0) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
var state = 'ok';
|
|
||||||
|
|
||||||
var firedTriggers = _.filter(triggers, { value: '1' });
|
|
||||||
if (firedTriggers.length) {
|
|
||||||
state = 'alerting';
|
|
||||||
}
|
|
||||||
|
|
||||||
var thresholds = _.map(triggers, function (trigger) {
|
|
||||||
return getTriggerThreshold(trigger.expression);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
panelId: options.panelId,
|
|
||||||
state: state,
|
|
||||||
thresholds: thresholds
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'replaceTargetVariables',
|
|
||||||
value: function replaceTargetVariables(target, options) {
|
|
||||||
var _this12 = this;
|
|
||||||
|
|
||||||
var parts = ['group', 'host', 'application', 'item'];
|
|
||||||
_.forEach(parts, function (p) {
|
|
||||||
if (target[p] && target[p].filter) {
|
|
||||||
target[p].filter = _this12.replaceTemplateVars(target[p].filter, options.scopedVars);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
target.textFilter = this.replaceTemplateVars(target.textFilter, options.scopedVars);
|
|
||||||
|
|
||||||
_.forEach(target.functions, function (func) {
|
|
||||||
func.params = _.map(func.params, function (param) {
|
|
||||||
if (typeof param === 'number') {
|
|
||||||
return +_this12.templateSrv.replace(param.toString(), options.scopedVars);
|
|
||||||
} else {
|
|
||||||
return _this12.templateSrv.replace(param, options.scopedVars);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'isUseTrends',
|
|
||||||
value: function isUseTrends(timeRange) {
|
|
||||||
var _timeRange4 = _slicedToArray(timeRange, 2),
|
|
||||||
timeFrom = _timeRange4[0],
|
|
||||||
timeTo = _timeRange4[1];
|
|
||||||
|
|
||||||
var useTrendsFrom = Math.ceil(dateMath.parse('now-' + this.trendsFrom) / 1000);
|
|
||||||
var useTrendsRange = Math.ceil(utils.parseInterval(this.trendsRange) / 1000);
|
|
||||||
var useTrends = this.trends && (timeFrom <= useTrendsFrom || timeTo - timeFrom >= useTrendsRange);
|
|
||||||
return useTrends;
|
|
||||||
}
|
|
||||||
}]);
|
|
||||||
|
|
||||||
return ZabbixAPIDatasource;
|
|
||||||
}());
|
|
||||||
|
|
||||||
_export('ZabbixAPIDatasource', ZabbixAPIDatasource);
|
|
||||||
|
|
||||||
_export('zabbixTemplateFormat', zabbixTemplateFormat);
|
|
||||||
|
|
||||||
// Fix for backward compatibility with lodash 2.4
|
|
||||||
if (!_.includes) {
|
|
||||||
_.includes = _.contains;
|
|
||||||
}
|
|
||||||
if (!_.keyBy) {
|
|
||||||
_.keyBy = _.indexBy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
//# sourceMappingURL=datasource.js.map
|
|
||||||
1
dist/datasource-zabbix/datasource.js.map
vendored
1
dist/datasource-zabbix/datasource.js.map
vendored
File diff suppressed because one or more lines are too long
8
dist/datasource-zabbix/partials/config.html
vendored
8
dist/datasource-zabbix/partials/config.html
vendored
@@ -126,3 +126,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form-group">
|
||||||
|
<h3 class="page-heading">Other</h3>
|
||||||
|
<gf-form-switch class="gf-form" label-class="width-20"
|
||||||
|
label="Disable acknowledges for read-only users"
|
||||||
|
checked="ctrl.current.jsonData.disableReadOnlyUsersAck">
|
||||||
|
</gf-form-switch>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -1,291 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
System.register(['lodash'], function (_export, _context) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var _, _createClass, DEFAULT_QUERY_LIMIT, HISTORY_TO_TABLE_MAP, TREND_TO_TABLE_MAP, consolidateByFunc, consolidateByTrendColumns, ZabbixDBConnector, TEST_MYSQL_QUERY, itemid_format, TEST_POSTGRES_QUERY;
|
|
||||||
|
|
||||||
function _classCallCheck(instance, Constructor) {
|
|
||||||
if (!(instance instanceof Constructor)) {
|
|
||||||
throw new TypeError("Cannot call a class as a function");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function convertGrafanaTSResponse(time_series, items, addHostName) {
|
|
||||||
var hosts = _.uniqBy(_.flatten(_.map(items, 'hosts')), 'hostid'); //uniqBy is needed to deduplicate
|
|
||||||
var grafanaSeries = _.map(time_series, function (series) {
|
|
||||||
var itemid = series.name;
|
|
||||||
var item = _.find(items, { 'itemid': itemid });
|
|
||||||
var alias = item.name;
|
|
||||||
if (_.keys(hosts).length > 1 && addHostName) {
|
|
||||||
//only when actual multi hosts selected
|
|
||||||
var host = _.find(hosts, { 'hostid': item.hostid });
|
|
||||||
alias = host.name + ": " + alias;
|
|
||||||
}
|
|
||||||
// CachingProxy deduplicates requests and returns one time series for equal queries.
|
|
||||||
// Clone is needed to prevent changing of series object shared between all targets.
|
|
||||||
var datapoints = _.cloneDeep(series.points);
|
|
||||||
return {
|
|
||||||
target: alias,
|
|
||||||
datapoints: datapoints
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return _.sortBy(grafanaSeries, 'target');
|
|
||||||
}
|
|
||||||
|
|
||||||
function compactSQLQuery(query) {
|
|
||||||
return query.replace(/\s+/g, ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildSQLHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
|
||||||
var dialect = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : 'mysql';
|
|
||||||
|
|
||||||
if (dialect === 'postgres') {
|
|
||||||
return buildPostgresHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction);
|
|
||||||
} else {
|
|
||||||
return buildMysqlHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildSQLTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
|
||||||
var dialect = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 'mysql';
|
|
||||||
|
|
||||||
if (dialect === 'postgres') {
|
|
||||||
return buildPostgresTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn);
|
|
||||||
} else {
|
|
||||||
return buildMysqlTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// MySQL //
|
|
||||||
///////////
|
|
||||||
|
|
||||||
function buildMysqlHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
|
||||||
var time_expression = 'clock DIV ' + intervalSec + ' * ' + intervalSec;
|
|
||||||
var query = '\n SELECT itemid AS metric, ' + time_expression + ' AS time_sec, ' + aggFunction + '(value) AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY ' + time_expression + ', metric\n ORDER BY time_sec ASC\n ';
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildMysqlTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
|
||||||
var time_expression = 'clock DIV ' + intervalSec + ' * ' + intervalSec;
|
|
||||||
var query = '\n SELECT itemid AS metric, ' + time_expression + ' AS time_sec, ' + aggFunction + '(' + valueColumn + ') AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY ' + time_expression + ', metric\n ORDER BY time_sec ASC\n ';
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildPostgresHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
|
||||||
var time_expression = 'clock / ' + intervalSec + ' * ' + intervalSec;
|
|
||||||
var query = '\n SELECT to_char(itemid, \'' + itemid_format + '\') AS metric, ' + time_expression + ' AS time, ' + aggFunction + '(value) AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY 1, 2\n ORDER BY time ASC\n ';
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildPostgresTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
|
||||||
var time_expression = 'clock / ' + intervalSec + ' * ' + intervalSec;
|
|
||||||
var query = '\n SELECT to_char(itemid, \'' + itemid_format + '\') AS metric, ' + time_expression + ' AS time, ' + aggFunction + '(' + valueColumn + ') AS value\n FROM ' + table + '\n WHERE itemid IN (' + itemids + ')\n AND clock > ' + timeFrom + ' AND clock < ' + timeTill + '\n GROUP BY 1, 2\n ORDER BY time ASC\n ';
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
setters: [function (_lodash) {
|
|
||||||
_ = _lodash.default;
|
|
||||||
}],
|
|
||||||
execute: function () {
|
|
||||||
_createClass = function () {
|
|
||||||
function defineProperties(target, props) {
|
|
||||||
for (var i = 0; i < props.length; i++) {
|
|
||||||
var descriptor = props[i];
|
|
||||||
descriptor.enumerable = descriptor.enumerable || false;
|
|
||||||
descriptor.configurable = true;
|
|
||||||
if ("value" in descriptor) descriptor.writable = true;
|
|
||||||
Object.defineProperty(target, descriptor.key, descriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return function (Constructor, protoProps, staticProps) {
|
|
||||||
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
|
||||||
if (staticProps) defineProperties(Constructor, staticProps);
|
|
||||||
return Constructor;
|
|
||||||
};
|
|
||||||
}();
|
|
||||||
|
|
||||||
DEFAULT_QUERY_LIMIT = 10000;
|
|
||||||
HISTORY_TO_TABLE_MAP = {
|
|
||||||
'0': 'history',
|
|
||||||
'1': 'history_str',
|
|
||||||
'2': 'history_log',
|
|
||||||
'3': 'history_uint',
|
|
||||||
'4': 'history_text'
|
|
||||||
};
|
|
||||||
TREND_TO_TABLE_MAP = {
|
|
||||||
'0': 'trends',
|
|
||||||
'3': 'trends_uint'
|
|
||||||
};
|
|
||||||
consolidateByFunc = {
|
|
||||||
'avg': 'AVG',
|
|
||||||
'min': 'MIN',
|
|
||||||
'max': 'MAX',
|
|
||||||
'sum': 'SUM',
|
|
||||||
'count': 'COUNT'
|
|
||||||
};
|
|
||||||
consolidateByTrendColumns = {
|
|
||||||
'avg': 'value_avg',
|
|
||||||
'min': 'value_min',
|
|
||||||
'max': 'value_max'
|
|
||||||
};
|
|
||||||
|
|
||||||
_export('ZabbixDBConnector', ZabbixDBConnector = function () {
|
|
||||||
function ZabbixDBConnector(sqlDataSourceId, options, backendSrv, datasourceSrv) {
|
|
||||||
_classCallCheck(this, ZabbixDBConnector);
|
|
||||||
|
|
||||||
this.backendSrv = backendSrv;
|
|
||||||
this.datasourceSrv = datasourceSrv;
|
|
||||||
|
|
||||||
var limit = options.limit;
|
|
||||||
this.sqlDataSourceId = sqlDataSourceId;
|
|
||||||
this.limit = limit || DEFAULT_QUERY_LIMIT;
|
|
||||||
|
|
||||||
this.loadSQLDataSource(sqlDataSourceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to load DS with given id to check it's exist.
|
|
||||||
* @param {*} datasourceId ID of SQL data source
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
_createClass(ZabbixDBConnector, [{
|
|
||||||
key: 'loadSQLDataSource',
|
|
||||||
value: function loadSQLDataSource(datasourceId) {
|
|
||||||
var _this = this;
|
|
||||||
|
|
||||||
var ds = _.find(this.datasourceSrv.getAll(), { 'id': datasourceId });
|
|
||||||
if (ds) {
|
|
||||||
return this.datasourceSrv.loadDatasource(ds.name).then(function (ds) {
|
|
||||||
_this.sqlDataSourceType = ds.meta.id;
|
|
||||||
return ds;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Promise.reject('SQL Data Source with ID ' + datasourceId + ' not found');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'testSQLDataSource',
|
|
||||||
value: function testSQLDataSource() {
|
|
||||||
var testQuery = TEST_MYSQL_QUERY;
|
|
||||||
if (this.sqlDataSourceType === 'postgres') {
|
|
||||||
testQuery = TEST_POSTGRES_QUERY;
|
|
||||||
}
|
|
||||||
return this.invokeSQLQuery(testQuery);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getHistory',
|
|
||||||
value: function getHistory(items, timeFrom, timeTill, options) {
|
|
||||||
var _this2 = this;
|
|
||||||
|
|
||||||
var intervalMs = options.intervalMs,
|
|
||||||
consolidateBy = options.consolidateBy;
|
|
||||||
|
|
||||||
var intervalSec = Math.ceil(intervalMs / 1000);
|
|
||||||
|
|
||||||
consolidateBy = consolidateBy || 'avg';
|
|
||||||
var aggFunction = consolidateByFunc[consolidateBy];
|
|
||||||
|
|
||||||
// Group items by value type and perform request for each value type
|
|
||||||
var grouped_items = _.groupBy(items, 'value_type');
|
|
||||||
var promises = _.map(grouped_items, function (items, value_type) {
|
|
||||||
var itemids = _.map(items, 'itemid').join(', ');
|
|
||||||
var table = HISTORY_TO_TABLE_MAP[value_type];
|
|
||||||
|
|
||||||
var dialect = _this2.sqlDataSourceType;
|
|
||||||
var query = buildSQLHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, dialect);
|
|
||||||
|
|
||||||
query = compactSQLQuery(query);
|
|
||||||
return _this2.invokeSQLQuery(query);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises).then(function (results) {
|
|
||||||
return _.flatten(results);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'getTrends',
|
|
||||||
value: function getTrends(items, timeFrom, timeTill, options) {
|
|
||||||
var _this3 = this;
|
|
||||||
|
|
||||||
var intervalMs = options.intervalMs,
|
|
||||||
consolidateBy = options.consolidateBy;
|
|
||||||
|
|
||||||
var intervalSec = Math.ceil(intervalMs / 1000);
|
|
||||||
|
|
||||||
consolidateBy = consolidateBy || 'avg';
|
|
||||||
var aggFunction = consolidateByFunc[consolidateBy];
|
|
||||||
|
|
||||||
// Group items by value type and perform request for each value type
|
|
||||||
var grouped_items = _.groupBy(items, 'value_type');
|
|
||||||
var promises = _.map(grouped_items, function (items, value_type) {
|
|
||||||
var itemids = _.map(items, 'itemid').join(', ');
|
|
||||||
var table = TREND_TO_TABLE_MAP[value_type];
|
|
||||||
var valueColumn = _.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg';
|
|
||||||
valueColumn = consolidateByTrendColumns[valueColumn];
|
|
||||||
|
|
||||||
var dialect = _this3.sqlDataSourceType;
|
|
||||||
var query = buildSQLTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn, dialect);
|
|
||||||
|
|
||||||
query = compactSQLQuery(query);
|
|
||||||
return _this3.invokeSQLQuery(query);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises).then(function (results) {
|
|
||||||
return _.flatten(results);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'handleGrafanaTSResponse',
|
|
||||||
value: function handleGrafanaTSResponse(history, items) {
|
|
||||||
var addHostName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
|
||||||
|
|
||||||
return convertGrafanaTSResponse(history, items, addHostName);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: 'invokeSQLQuery',
|
|
||||||
value: function invokeSQLQuery(query) {
|
|
||||||
var queryDef = {
|
|
||||||
refId: 'A',
|
|
||||||
format: 'time_series',
|
|
||||||
datasourceId: this.sqlDataSourceId,
|
|
||||||
rawSql: query,
|
|
||||||
maxDataPoints: this.limit
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.backendSrv.datasourceRequest({
|
|
||||||
url: '/api/tsdb/query',
|
|
||||||
method: 'POST',
|
|
||||||
data: {
|
|
||||||
queries: [queryDef]
|
|
||||||
}
|
|
||||||
}).then(function (response) {
|
|
||||||
var results = response.data.results;
|
|
||||||
if (results['A']) {
|
|
||||||
return results['A'].series;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}]);
|
|
||||||
|
|
||||||
return ZabbixDBConnector;
|
|
||||||
}());
|
|
||||||
|
|
||||||
_export('ZabbixDBConnector', ZabbixDBConnector);
|
|
||||||
|
|
||||||
TEST_MYSQL_QUERY = 'SELECT itemid AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1';
|
|
||||||
itemid_format = 'FM99999999999999999999';
|
|
||||||
TEST_POSTGRES_QUERY = '\n SELECT to_char(itemid, \'' + itemid_format + '\') AS metric, clock AS time, value_avg AS value\n FROM trends_uint LIMIT 1\n';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
//# sourceMappingURL=zabbixDBConnector.js.map
|
|
||||||
10
dist/datasource-zabbix/zabbixAlerting.service.js
vendored
10
dist/datasource-zabbix/zabbixAlerting.service.js
vendored
@@ -91,13 +91,9 @@ System.register(['lodash', 'jquery', 'angular'], function (_export, _context) {
|
|||||||
}, {
|
}, {
|
||||||
key: 'getPanelModels',
|
key: 'getPanelModels',
|
||||||
value: function getPanelModels() {
|
value: function getPanelModels() {
|
||||||
return _.flatten(_.map(this.dashboardSrv.dash.rows, function (row) {
|
return _.filter(this.dashboardSrv.dash.panels, function (panel) {
|
||||||
if (row.collapse) {
|
return panel.type !== 'row';
|
||||||
return [];
|
});
|
||||||
} else {
|
|
||||||
return row.panels;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: 'getPanelModel',
|
key: 'getPanelModel',
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
14
dist/panel-triggers/partials/module.html
vendored
14
dist/panel-triggers/partials/module.html
vendored
@@ -3,10 +3,12 @@
|
|||||||
<section class="card-section card-list-layout-list">
|
<section class="card-section card-list-layout-list">
|
||||||
<ol class="alert-rule-list">
|
<ol class="alert-rule-list">
|
||||||
<!-- Trigger list item -->
|
<!-- Trigger list item -->
|
||||||
<li class="alert-rule-item zbx-trigger-card" ng-repeat="trigger in ctrl.currentTriggersPage">
|
<li class="alert-rule-item zbx-trigger-card" ng-repeat="trigger in ctrl.currentTriggersPage"
|
||||||
|
ng-class="{'zbx-trigger-highlighted': ctrl.panel.highlightBackground}"
|
||||||
|
ng-style="ctrl.panel.highlightBackground && {background: ctrl.getBackground(trigger)}">
|
||||||
|
|
||||||
<!-- Heart icon -->
|
<!-- Heart icon -->
|
||||||
<div class="alert-rule-item__icon" ng-style="{color: trigger.color}">
|
<div class="alert-rule-item__icon" ng-style="!ctrl.panel.highlightBackground && {color: trigger.color}">
|
||||||
<i class="icon-gf" ng-class="ctrl.getAlertIconClass(trigger)"></i>
|
<i class="icon-gf" ng-class="ctrl.getAlertIconClass(trigger)"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -32,11 +34,13 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="alert-rule-item__text">
|
<div class="alert-rule-item__text">
|
||||||
<span ng-if="ctrl.panel.statusField" ng-class="ctrl.getAlertStateClass(trigger)">
|
<span ng-if="ctrl.panel.statusField" class="zbx-trigger-state"
|
||||||
|
ng-class="ctrl.getAlertStateClass(trigger)">
|
||||||
{{ctrl.triggerStatusMap[trigger.value]}}
|
{{ctrl.triggerStatusMap[trigger.value]}}
|
||||||
</span>
|
</span>
|
||||||
<span ng-if="ctrl.panel.severityField" ng-class="ctrl.getAlertStateClass(trigger)"
|
<span ng-if="ctrl.panel.severityField" class="zbx-trigger-severity"
|
||||||
ng-style="{color: trigger.color}">
|
ng-class="ctrl.getAlertStateClass(trigger)"
|
||||||
|
ng-style="!ctrl.panel.highlightBackground && {color: trigger.color}">
|
||||||
{{trigger.severity}}
|
{{trigger.severity}}
|
||||||
</span>
|
</span>
|
||||||
<span class="alert-rule-item__time">
|
<span class="alert-rule-item__time">
|
||||||
|
|||||||
@@ -116,6 +116,12 @@
|
|||||||
ng-model="ctrl.panel.pageSize"
|
ng-model="ctrl.panel.pageSize"
|
||||||
ng-model-onblur ng-change="ctrl.render()">
|
ng-model-onblur ng-change="ctrl.render()">
|
||||||
</div>
|
</div>
|
||||||
|
<gf-form-switch class="gf-form"
|
||||||
|
label-class="width-10"
|
||||||
|
label="Highlight background"
|
||||||
|
checked="ctrl.panel.highlightBackground"
|
||||||
|
on-change="ctrl.render()">
|
||||||
|
</gf-form-switch>
|
||||||
<gf-form-switch class="gf-form"
|
<gf-form-switch class="gf-form"
|
||||||
label-class="width-10"
|
label-class="width-10"
|
||||||
label="Highlight new events"
|
label="Highlight new events"
|
||||||
@@ -157,7 +163,7 @@
|
|||||||
<label class="gf-form-label width-3">{{ trigger.priority }}</label>
|
<label class="gf-form-label width-3">{{ trigger.priority }}</label>
|
||||||
<label class="gf-form-label triggers-severity-config"
|
<label class="gf-form-label triggers-severity-config"
|
||||||
ng-style="{color: trigger.color}">
|
ng-style="{color: trigger.color}">
|
||||||
<i class="icon-gf" ng-class="ctrl.getAlertIconClass(trigger)"></i>
|
<i class="icon-gf" ng-class="ctrl.getAlertIconClassBySeverity(trigger)"></i>
|
||||||
</label>
|
</label>
|
||||||
<input type="text"
|
<input type="text"
|
||||||
class="gf-form-input width-12"
|
class="gf-form-input width-12"
|
||||||
|
|||||||
20
dist/panel-triggers/specs/panel_ctrl.spec.js
vendored
20
dist/panel-triggers/specs/panel_ctrl.spec.js
vendored
@@ -187,6 +187,26 @@ describe('TriggerPanelCtrl', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('When formatting acknowledges', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
ctx.panelCtrl = createPanelCtrl();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should build proper user name', () => {
|
||||||
|
const ack = {
|
||||||
|
alias: 'alias', name: 'name', surname: 'surname'
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatted = ctx.panelCtrl.formatAcknowledge(ack);
|
||||||
|
expect(formatted.user).toBe('alias (name surname)');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty name if it is not defined', () => {
|
||||||
|
const formatted = ctx.panelCtrl.formatAcknowledge({});
|
||||||
|
expect(formatted.user).toBe('');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultTrigger = {
|
const defaultTrigger = {
|
||||||
|
|||||||
56
dist/panel-triggers/triggers_panel_ctrl.js
vendored
56
dist/panel-triggers/triggers_panel_ctrl.js
vendored
@@ -149,7 +149,8 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap
|
|||||||
// View options
|
// View options
|
||||||
fontSize: '100%',
|
fontSize: '100%',
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
highlightNewEvents: true,
|
highlightBackground: false,
|
||||||
|
highlightNewEvents: false,
|
||||||
highlightNewerThan: '1h',
|
highlightNewerThan: '1h',
|
||||||
customLastChangeFormat: false,
|
customLastChangeFormat: false,
|
||||||
lastChangeFormat: "",
|
lastChangeFormat: "",
|
||||||
@@ -366,16 +367,7 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (event) {
|
if (event) {
|
||||||
trigger.acknowledges = _.map(event.acknowledges, function (ack) {
|
trigger.acknowledges = _.map(event.acknowledges, _this6.formatAcknowledge.bind(_this6));
|
||||||
var timestamp = moment.unix(ack.clock);
|
|
||||||
if (_this6.panel.customLastChangeFormat) {
|
|
||||||
ack.time = timestamp.format(_this6.panel.lastChangeFormat);
|
|
||||||
} else {
|
|
||||||
ack.time = timestamp.format(_this6.defaultTimeFormat);
|
|
||||||
}
|
|
||||||
ack.user = ack.alias + ' (' + ack.name + ' ' + ack.surname + ')';
|
|
||||||
return ack;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!trigger.lastEvent.eventid) {
|
if (!trigger.lastEvent.eventid) {
|
||||||
@@ -386,6 +378,22 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap
|
|||||||
return triggerList;
|
return triggerList;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: 'formatAcknowledge',
|
||||||
|
value: function formatAcknowledge(ack) {
|
||||||
|
var 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 || '';
|
||||||
|
if (ack.name || ack.surname) {
|
||||||
|
var fullName = (ack.name || '') + ' ' + (ack.surname || '');
|
||||||
|
ack.user += ' (' + fullName + ')';
|
||||||
|
}
|
||||||
|
return ack;
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
key: 'filterTriggersPre',
|
key: 'filterTriggersPre',
|
||||||
value: function filterTriggersPre(triggerList, ds) {
|
value: function filterTriggersPre(triggerList, ds) {
|
||||||
@@ -595,6 +603,10 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap
|
|||||||
var grafana_user = this.contextSrv.user.name;
|
var grafana_user = this.contextSrv.user.name;
|
||||||
var ack_message = grafana_user + ' (Grafana): ' + message;
|
var ack_message = grafana_user + ' (Grafana): ' + message;
|
||||||
return this.datasourceSrv.get(trigger.datasource).then(function (datasource) {
|
return this.datasourceSrv.get(trigger.datasource).then(function (datasource) {
|
||||||
|
var userIsEditor = _this8.contextSrv.isEditor || _this8.contextSrv.isGrafanaAdmin;
|
||||||
|
if (datasource.disableReadOnlyUsersAck && !userIsEditor) {
|
||||||
|
return Promise.reject({ message: 'You have no permissions to acknowledge events.' });
|
||||||
|
}
|
||||||
if (eventid) {
|
if (eventid) {
|
||||||
return datasource.zabbix.zabbixAPI.acknowledgeEvent(eventid, ack_message);
|
return datasource.zabbix.zabbixAPI.acknowledgeEvent(eventid, ack_message);
|
||||||
} else {
|
} else {
|
||||||
@@ -641,9 +653,8 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap
|
|||||||
}, {
|
}, {
|
||||||
key: 'getAlertIconClass',
|
key: 'getAlertIconClass',
|
||||||
value: function getAlertIconClass(trigger) {
|
value: function getAlertIconClass(trigger) {
|
||||||
var triggerValue = Number(trigger.value);
|
|
||||||
var iconClass = '';
|
var iconClass = '';
|
||||||
if (triggerValue || trigger.color) {
|
if (trigger.value === '1') {
|
||||||
if (trigger.priority >= 3) {
|
if (trigger.priority >= 3) {
|
||||||
iconClass = 'icon-gf-critical';
|
iconClass = 'icon-gf-critical';
|
||||||
} else {
|
} else {
|
||||||
@@ -658,6 +669,15 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap
|
|||||||
}
|
}
|
||||||
return iconClass;
|
return iconClass;
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getAlertIconClassBySeverity',
|
||||||
|
value: function getAlertIconClassBySeverity(triggerSeverity) {
|
||||||
|
var iconClass = 'icon-gf-warning';
|
||||||
|
if (triggerSeverity.priority >= 3) {
|
||||||
|
iconClass = 'icon-gf-critical';
|
||||||
|
}
|
||||||
|
return iconClass;
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
key: 'getAlertStateClass',
|
key: 'getAlertStateClass',
|
||||||
value: function getAlertStateClass(trigger) {
|
value: function getAlertStateClass(trigger) {
|
||||||
@@ -675,6 +695,16 @@ System.register(['lodash', 'jquery', 'moment', '../datasource-zabbix/utils', 'ap
|
|||||||
|
|
||||||
return statusClass;
|
return statusClass;
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getBackground',
|
||||||
|
value: function getBackground(trigger) {
|
||||||
|
var mainColor = trigger.color;
|
||||||
|
var secondColor = this.contextSrv.user.lightTheme ? '#dde4ed' : '#262628';
|
||||||
|
if (this.contextSrv.user.lightTheme) {
|
||||||
|
return 'linear-gradient(135deg, ' + secondColor + ', ' + mainColor + ')';
|
||||||
|
}
|
||||||
|
return 'linear-gradient(135deg, ' + mainColor + ', ' + secondColor + ')';
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
key: 'isNewTrigger',
|
key: 'isNewTrigger',
|
||||||
value: function isNewTrigger(trigger) {
|
value: function isNewTrigger(trigger) {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
6
dist/plugin.json
vendored
6
dist/plugin.json
vendored
@@ -26,8 +26,8 @@
|
|||||||
{"name": "Metric Editor", "path": "img/screenshot-metric_editor.png"},
|
{"name": "Metric Editor", "path": "img/screenshot-metric_editor.png"},
|
||||||
{"name": "Triggers", "path": "img/screenshot-triggers.png"}
|
{"name": "Triggers", "path": "img/screenshot-triggers.png"}
|
||||||
],
|
],
|
||||||
"version": "3.8.1",
|
"version": "3.9.1",
|
||||||
"updated": "2017-12-21"
|
"updated": "2018-05-02"
|
||||||
},
|
},
|
||||||
|
|
||||||
"includes": [
|
"includes": [
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
],
|
],
|
||||||
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"grafanaVersion": "3.x 4.x",
|
"grafanaVersion": "5.x",
|
||||||
"plugins": []
|
"plugins": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class ZabbixAPIDatasource {
|
|||||||
this.basicAuth = instanceSettings.basicAuth;
|
this.basicAuth = instanceSettings.basicAuth;
|
||||||
this.withCredentials = instanceSettings.withCredentials;
|
this.withCredentials = instanceSettings.withCredentials;
|
||||||
|
|
||||||
const jsonData = instanceSettings.jsonData;
|
const jsonData = instanceSettings.jsonData || {};
|
||||||
|
|
||||||
// Zabbix API credentials
|
// Zabbix API credentials
|
||||||
this.username = jsonData.username;
|
this.username = jsonData.username;
|
||||||
@@ -48,6 +48,9 @@ class ZabbixAPIDatasource {
|
|||||||
this.addThresholds = jsonData.addThresholds;
|
this.addThresholds = jsonData.addThresholds;
|
||||||
this.alertingMinSeverity = jsonData.alertingMinSeverity || c.SEV_WARNING;
|
this.alertingMinSeverity = jsonData.alertingMinSeverity || c.SEV_WARNING;
|
||||||
|
|
||||||
|
// Other options
|
||||||
|
this.disableReadOnlyUsersAck = jsonData.disableReadOnlyUsersAck;
|
||||||
|
|
||||||
// Direct DB Connection options
|
// Direct DB Connection options
|
||||||
let dbConnectionOptions = jsonData.dbConnection || {};
|
let dbConnectionOptions = jsonData.dbConnection || {};
|
||||||
this.enableDirectDBConnection = dbConnectionOptions.enable;
|
this.enableDirectDBConnection = dbConnectionOptions.enable;
|
||||||
@@ -206,11 +209,7 @@ class ZabbixAPIDatasource {
|
|||||||
|
|
||||||
return getHistoryPromise
|
return getHistoryPromise
|
||||||
.then(timeseries => this.applyDataProcessingFunctions(timeseries, target))
|
.then(timeseries => this.applyDataProcessingFunctions(timeseries, target))
|
||||||
.then(timeseries => downsampleSeries(timeseries, options))
|
.then(timeseries => downsampleSeries(timeseries, options));
|
||||||
.catch(error => {
|
|
||||||
console.log(error);
|
|
||||||
return [];
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getTrendValueType(target) {
|
getTrendValueType(target) {
|
||||||
|
|||||||
@@ -126,3 +126,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form-group">
|
||||||
|
<h3 class="page-heading">Other</h3>
|
||||||
|
<gf-form-switch class="gf-form" label-class="width-20"
|
||||||
|
label="Disable acknowledges for read-only users"
|
||||||
|
checked="ctrl.current.jsonData.disableReadOnlyUsersAck">
|
||||||
|
</gf-form-switch>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ function buildSQLTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, ag
|
|||||||
function buildMysqlHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
function buildMysqlHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
||||||
let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`;
|
let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`;
|
||||||
let query = `
|
let query = `
|
||||||
SELECT itemid AS metric, ${time_expression} AS time_sec, ${aggFunction}(value) AS value
|
SELECT CAST(itemid AS CHAR) AS metric, ${time_expression} AS time_sec, ${aggFunction}(value) AS value
|
||||||
FROM ${table}
|
FROM ${table}
|
||||||
WHERE itemid IN (${itemids})
|
WHERE itemid IN (${itemids})
|
||||||
AND clock > ${timeFrom} AND clock < ${timeTill}
|
AND clock > ${timeFrom} AND clock < ${timeTill}
|
||||||
@@ -216,7 +216,7 @@ function buildMysqlHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec,
|
|||||||
function buildMysqlTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
function buildMysqlTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
||||||
let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`;
|
let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`;
|
||||||
let query = `
|
let query = `
|
||||||
SELECT itemid AS metric, ${time_expression} AS time_sec, ${aggFunction}(${valueColumn}) AS value
|
SELECT CAST(itemid AS CHAR) AS metric, ${time_expression} AS time_sec, ${aggFunction}(${valueColumn}) AS value
|
||||||
FROM ${table}
|
FROM ${table}
|
||||||
WHERE itemid IN (${itemids})
|
WHERE itemid IN (${itemids})
|
||||||
AND clock > ${timeFrom} AND clock < ${timeTill}
|
AND clock > ${timeFrom} AND clock < ${timeTill}
|
||||||
@@ -226,7 +226,7 @@ function buildMysqlTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec,
|
|||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TEST_MYSQL_QUERY = `SELECT itemid AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1`;
|
const TEST_MYSQL_QUERY = `SELECT CAST(itemid AS CHAR) AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1`;
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
// PostgreSQL //
|
// PostgreSQL //
|
||||||
|
|||||||
@@ -49,13 +49,7 @@ class ZabbixAlertingService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getPanelModels() {
|
getPanelModels() {
|
||||||
return _.flatten(_.map(this.dashboardSrv.dash.rows, row => {
|
return _.filter(this.dashboardSrv.dash.panels, panel => panel.type !== 'row');
|
||||||
if (row.collapse) {
|
|
||||||
return [];
|
|
||||||
} else {
|
|
||||||
return row.panels;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getPanelModel(panelId) {
|
getPanelModel(panelId) {
|
||||||
|
|||||||
@@ -3,10 +3,12 @@
|
|||||||
<section class="card-section card-list-layout-list">
|
<section class="card-section card-list-layout-list">
|
||||||
<ol class="alert-rule-list">
|
<ol class="alert-rule-list">
|
||||||
<!-- Trigger list item -->
|
<!-- Trigger list item -->
|
||||||
<li class="alert-rule-item zbx-trigger-card" ng-repeat="trigger in ctrl.currentTriggersPage">
|
<li class="alert-rule-item zbx-trigger-card" ng-repeat="trigger in ctrl.currentTriggersPage"
|
||||||
|
ng-class="{'zbx-trigger-highlighted': ctrl.panel.highlightBackground}"
|
||||||
|
ng-style="ctrl.panel.highlightBackground && {background: ctrl.getBackground(trigger)}">
|
||||||
|
|
||||||
<!-- Heart icon -->
|
<!-- Heart icon -->
|
||||||
<div class="alert-rule-item__icon" ng-style="{color: trigger.color}">
|
<div class="alert-rule-item__icon" ng-style="!ctrl.panel.highlightBackground && {color: trigger.color}">
|
||||||
<i class="icon-gf" ng-class="ctrl.getAlertIconClass(trigger)"></i>
|
<i class="icon-gf" ng-class="ctrl.getAlertIconClass(trigger)"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -32,11 +34,13 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="alert-rule-item__text">
|
<div class="alert-rule-item__text">
|
||||||
<span ng-if="ctrl.panel.statusField" ng-class="ctrl.getAlertStateClass(trigger)">
|
<span ng-if="ctrl.panel.statusField" class="zbx-trigger-state"
|
||||||
|
ng-class="ctrl.getAlertStateClass(trigger)">
|
||||||
{{ctrl.triggerStatusMap[trigger.value]}}
|
{{ctrl.triggerStatusMap[trigger.value]}}
|
||||||
</span>
|
</span>
|
||||||
<span ng-if="ctrl.panel.severityField" ng-class="ctrl.getAlertStateClass(trigger)"
|
<span ng-if="ctrl.panel.severityField" class="zbx-trigger-severity"
|
||||||
ng-style="{color: trigger.color}">
|
ng-class="ctrl.getAlertStateClass(trigger)"
|
||||||
|
ng-style="!ctrl.panel.highlightBackground && {color: trigger.color}">
|
||||||
{{trigger.severity}}
|
{{trigger.severity}}
|
||||||
</span>
|
</span>
|
||||||
<span class="alert-rule-item__time">
|
<span class="alert-rule-item__time">
|
||||||
|
|||||||
@@ -116,6 +116,12 @@
|
|||||||
ng-model="ctrl.panel.pageSize"
|
ng-model="ctrl.panel.pageSize"
|
||||||
ng-model-onblur ng-change="ctrl.render()">
|
ng-model-onblur ng-change="ctrl.render()">
|
||||||
</div>
|
</div>
|
||||||
|
<gf-form-switch class="gf-form"
|
||||||
|
label-class="width-10"
|
||||||
|
label="Highlight background"
|
||||||
|
checked="ctrl.panel.highlightBackground"
|
||||||
|
on-change="ctrl.render()">
|
||||||
|
</gf-form-switch>
|
||||||
<gf-form-switch class="gf-form"
|
<gf-form-switch class="gf-form"
|
||||||
label-class="width-10"
|
label-class="width-10"
|
||||||
label="Highlight new events"
|
label="Highlight new events"
|
||||||
@@ -157,7 +163,7 @@
|
|||||||
<label class="gf-form-label width-3">{{ trigger.priority }}</label>
|
<label class="gf-form-label width-3">{{ trigger.priority }}</label>
|
||||||
<label class="gf-form-label triggers-severity-config"
|
<label class="gf-form-label triggers-severity-config"
|
||||||
ng-style="{color: trigger.color}">
|
ng-style="{color: trigger.color}">
|
||||||
<i class="icon-gf" ng-class="ctrl.getAlertIconClass(trigger)"></i>
|
<i class="icon-gf" ng-class="ctrl.getAlertIconClassBySeverity(trigger)"></i>
|
||||||
</label>
|
</label>
|
||||||
<input type="text"
|
<input type="text"
|
||||||
class="gf-form-input width-12"
|
class="gf-form-input width-12"
|
||||||
|
|||||||
@@ -187,6 +187,26 @@ describe('TriggerPanelCtrl', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('When formatting acknowledges', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
ctx.panelCtrl = createPanelCtrl();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should build proper user name', () => {
|
||||||
|
const ack = {
|
||||||
|
alias: 'alias', name: 'name', surname: 'surname'
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatted = ctx.panelCtrl.formatAcknowledge(ack);
|
||||||
|
expect(formatted.user).toBe('alias (name surname)');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty name if it is not defined', () => {
|
||||||
|
const formatted = ctx.panelCtrl.formatAcknowledge({});
|
||||||
|
expect(formatted.user).toBe('');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultTrigger = {
|
const defaultTrigger = {
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ export const PANEL_DEFAULTS = {
|
|||||||
// View options
|
// View options
|
||||||
fontSize: '100%',
|
fontSize: '100%',
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
highlightNewEvents: true,
|
highlightBackground: false,
|
||||||
|
highlightNewEvents: false,
|
||||||
highlightNewerThan: '1h',
|
highlightNewerThan: '1h',
|
||||||
customLastChangeFormat: false,
|
customLastChangeFormat: false,
|
||||||
lastChangeFormat: "",
|
lastChangeFormat: "",
|
||||||
@@ -242,16 +243,7 @@ export class TriggerPanelCtrl extends PanelCtrl {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (event) {
|
if (event) {
|
||||||
trigger.acknowledges = _.map(event.acknowledges, ack => {
|
trigger.acknowledges = _.map(event.acknowledges, this.formatAcknowledge.bind(this));
|
||||||
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;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!trigger.lastEvent.eventid) {
|
if (!trigger.lastEvent.eventid) {
|
||||||
@@ -263,6 +255,21 @@ export class TriggerPanelCtrl extends PanelCtrl {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
formatAcknowledge(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 || '';
|
||||||
|
if (ack.name || ack.surname) {
|
||||||
|
const fullName = `${ack.name || ''} ${ack.surname || ''}`;
|
||||||
|
ack.user += ` (${fullName})`;
|
||||||
|
}
|
||||||
|
return ack;
|
||||||
|
}
|
||||||
|
|
||||||
filterTriggersPre(triggerList, ds) {
|
filterTriggersPre(triggerList, ds) {
|
||||||
// Filter triggers by description
|
// Filter triggers by description
|
||||||
let triggerFilter = this.panel.targets[ds].trigger.filter;
|
let triggerFilter = this.panel.targets[ds].trigger.filter;
|
||||||
@@ -446,6 +453,10 @@ export class TriggerPanelCtrl extends PanelCtrl {
|
|||||||
let ack_message = grafana_user + ' (Grafana): ' + message;
|
let ack_message = grafana_user + ' (Grafana): ' + message;
|
||||||
return this.datasourceSrv.get(trigger.datasource)
|
return this.datasourceSrv.get(trigger.datasource)
|
||||||
.then(datasource => {
|
.then(datasource => {
|
||||||
|
const userIsEditor = this.contextSrv.isEditor || this.contextSrv.isGrafanaAdmin;
|
||||||
|
if (datasource.disableReadOnlyUsersAck && !userIsEditor) {
|
||||||
|
return Promise.reject({message: 'You have no permissions to acknowledge events.'});
|
||||||
|
}
|
||||||
if (eventid) {
|
if (eventid) {
|
||||||
return datasource.zabbix.zabbixAPI.acknowledgeEvent(eventid, ack_message);
|
return datasource.zabbix.zabbixAPI.acknowledgeEvent(eventid, ack_message);
|
||||||
} else {
|
} else {
|
||||||
@@ -490,9 +501,8 @@ export class TriggerPanelCtrl extends PanelCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getAlertIconClass(trigger) {
|
getAlertIconClass(trigger) {
|
||||||
const triggerValue = Number(trigger.value);
|
|
||||||
let iconClass = '';
|
let iconClass = '';
|
||||||
if (triggerValue || trigger.color) {
|
if (trigger.value === '1') {
|
||||||
if (trigger.priority >= 3) {
|
if (trigger.priority >= 3) {
|
||||||
iconClass = 'icon-gf-critical';
|
iconClass = 'icon-gf-critical';
|
||||||
} else {
|
} else {
|
||||||
@@ -508,6 +518,14 @@ export class TriggerPanelCtrl extends PanelCtrl {
|
|||||||
return iconClass;
|
return iconClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAlertIconClassBySeverity(triggerSeverity) {
|
||||||
|
let iconClass = 'icon-gf-warning';
|
||||||
|
if (triggerSeverity.priority >= 3) {
|
||||||
|
iconClass = 'icon-gf-critical';
|
||||||
|
}
|
||||||
|
return iconClass;
|
||||||
|
}
|
||||||
|
|
||||||
getAlertStateClass(trigger) {
|
getAlertStateClass(trigger) {
|
||||||
let statusClass = '';
|
let statusClass = '';
|
||||||
|
|
||||||
@@ -524,6 +542,15 @@ export class TriggerPanelCtrl extends PanelCtrl {
|
|||||||
return statusClass;
|
return statusClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getBackground(trigger) {
|
||||||
|
const mainColor = trigger.color;
|
||||||
|
const secondColor = this.contextSrv.user.lightTheme ? '#dde4ed' : '#262628';
|
||||||
|
if (this.contextSrv.user.lightTheme) {
|
||||||
|
return `linear-gradient(135deg, ${secondColor}, ${mainColor})`;
|
||||||
|
}
|
||||||
|
return `linear-gradient(135deg, ${mainColor}, ${secondColor})`;
|
||||||
|
}
|
||||||
|
|
||||||
isNewTrigger(trigger) {
|
isNewTrigger(trigger) {
|
||||||
try {
|
try {
|
||||||
const highlightIntervalMs = utils.parseInterval(this.panel.highlightNewerThan || PANEL_DEFAULTS.highlightNewerThan);
|
const highlightIntervalMs = utils.parseInterval(this.panel.highlightNewerThan || PANEL_DEFAULTS.highlightNewerThan);
|
||||||
|
|||||||
@@ -26,8 +26,8 @@
|
|||||||
{"name": "Metric Editor", "path": "img/screenshot-metric_editor.png"},
|
{"name": "Metric Editor", "path": "img/screenshot-metric_editor.png"},
|
||||||
{"name": "Triggers", "path": "img/screenshot-triggers.png"}
|
{"name": "Triggers", "path": "img/screenshot-triggers.png"}
|
||||||
],
|
],
|
||||||
"version": "3.8.1",
|
"version": "3.9.1",
|
||||||
"updated": "2017-12-21"
|
"updated": "2018-05-02"
|
||||||
},
|
},
|
||||||
|
|
||||||
"includes": [
|
"includes": [
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
],
|
],
|
||||||
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"grafanaVersion": "3.x 4.x",
|
"grafanaVersion": "5.x",
|
||||||
"plugins": []
|
"plugins": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,10 +38,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-list-footer {
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.trigger-info-block {
|
.trigger-info-block {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
@@ -59,10 +55,6 @@
|
|||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-item-wrapper {
|
|
||||||
padding-left: 4px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.zbx-trigger-card {
|
.zbx-trigger-card {
|
||||||
@@ -81,12 +73,28 @@
|
|||||||
color: $orange;
|
color: $orange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.zbx-trigger-highlighted {
|
||||||
|
color: $zbx-text-highlighted;
|
||||||
|
|
||||||
@keyframes zabbix-triggers-panel {
|
.alert-rule-item__body,
|
||||||
100% {
|
.alert-rule-item__header,
|
||||||
opacity: 1;
|
.alert-rule-item__time,
|
||||||
box-shadow: 0 0 10px 0px rgba($red, 1);
|
.zabbix-hostname,
|
||||||
border-bottom-color: rgba($red, 0.25);
|
.zbx-description {
|
||||||
|
color: $zbx-text-highlighted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-rule-item__text {
|
||||||
|
.zbx-trigger-state,
|
||||||
|
.zbx-trigger-severity {
|
||||||
|
color: $zbx-text-highlighted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.zbx-trigger-lastchange .trigger-info-block.zbx-status-icons {
|
||||||
|
a, i {
|
||||||
|
color: $zbx-text-highlighted;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,8 +172,9 @@
|
|||||||
|
|
||||||
.triggers-severity-config {
|
.triggers-severity-config {
|
||||||
&.gf-form-label {
|
&.gf-form-label {
|
||||||
padding-top: 4px;
|
padding-top: 5px;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 5px;
|
||||||
|
border-radius: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-gf {
|
.icon-gf {
|
||||||
|
|||||||
@@ -37,3 +37,4 @@ $tight-form-func-bg: #333;
|
|||||||
$grafanaListAccent: lighten($dark-2, 2%);
|
$grafanaListAccent: lighten($dark-2, 2%);
|
||||||
|
|
||||||
$zbx-tag-color: $gray-5;
|
$zbx-tag-color: $gray-5;
|
||||||
|
$zbx-text-highlighted: $white;
|
||||||
|
|||||||
@@ -36,3 +36,4 @@ $tight-form-func-bg: $gray-5;
|
|||||||
$grafanaListAccent: $gray-5;
|
$grafanaListAccent: $gray-5;
|
||||||
|
|
||||||
$zbx-tag-color: $gray-6;
|
$zbx-tag-color: $gray-6;
|
||||||
|
$zbx-text-highlighted: $black;
|
||||||
|
|||||||
Reference in New Issue
Block a user