Add thresholds to panels from zabbix triggers.

This commit is contained in:
Alexander Zobnin
2017-03-06 11:46:53 +03:00
parent 2f385faa1b
commit f2896fe1e4
6 changed files with 227 additions and 34 deletions

View File

@@ -104,6 +104,18 @@ System.register(['lodash', 'jquery', 'app/core/utils/datemath', './utils', './mi
}); });
} }
function getTriggerThreshold(expression) {
var thresholdPattern = /.*[<>]([\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 { return {
setters: [function (_lodash) { setters: [function (_lodash) {
_ = _lodash.default; _ = _lodash.default;
@@ -209,7 +221,9 @@ System.register(['lodash', 'jquery', 'app/core/utils/datemath', './utils', './mi
var ttl = instanceSettings.jsonData.cacheTTL || '1h'; var ttl = instanceSettings.jsonData.cacheTTL || '1h';
this.cacheTTL = utils.parseInterval(ttl); this.cacheTTL = utils.parseInterval(ttl);
// Alerting options
this.alertingEnabled = instanceSettings.jsonData.alerting; this.alertingEnabled = instanceSettings.jsonData.alerting;
this.addThresholds = instanceSettings.jsonData.addThresholds;
this.zabbix = new Zabbix(this.url, this.username, this.password, this.basicAuth, this.withCredentials, this.cacheTTL); this.zabbix = new Zabbix(this.url, this.username, this.password, this.basicAuth, this.withCredentials, this.cacheTTL);
@@ -243,6 +257,12 @@ System.register(['lodash', 'jquery', 'app/core/utils/datemath', './utils', './mi
if (this.alertingEnabled) { if (this.alertingEnabled) {
this.alertQuery(options).then(function (alert) { this.alertQuery(options).then(function (alert) {
_this.setPanelAlertState(options.panelId, alert.state); _this.setPanelAlertState(options.panelId, alert.state);
if (_this.addThresholds) {
_.forEach(alert.thresholds, function (threshold) {
_this.setPanelThreshold(options.panelId, threshold);
});
}
}); });
} }
@@ -600,9 +620,14 @@ System.register(['lodash', 'jquery', 'app/core/utils/datemath', './utils', './mi
state = 'alerting'; state = 'alerting';
} }
var thresholds = _.map(triggers, function (trigger) {
return getTriggerThreshold(trigger.expression);
});
return { return {
panelId: options.panelId, panelId: options.panelId,
state: state state: state,
thresholds: thresholds
}; };
}); });
} }
@@ -613,14 +638,7 @@ System.register(['lodash', 'jquery', 'app/core/utils/datemath', './utils', './mi
return elem.clientHeight && elem.clientWidth; return elem.clientHeight && elem.clientWidth;
}); });
var panelModels = _.flatten(_.map(this.dashboardSrv.dash.rows, function (row) { var panelModels = this.getPanelModels();
if (row.collapse) {
return [];
} else {
return row.panels;
}
}));
var panelIndex = _.findIndex(panelModels, function (panel) { var panelIndex = _.findIndex(panelModels, function (panel) {
return panel.id === panelId; return panel.id === panelId;
}); });
@@ -642,6 +660,46 @@ System.register(['lodash', 'jquery', 'app/core/utils/datemath', './utils', './mi
} }
} }
} }
}, {
key: 'getPanelModels',
value: function getPanelModels() {
return _.flatten(_.map(this.dashboardSrv.dash.rows, function (row) {
if (row.collapse) {
return [];
} else {
return row.panels;
}
}));
}
}, {
key: 'getPanelModel',
value: function getPanelModel(panelId) {
var panelModels = this.getPanelModels();
return _.find(panelModels, function (panel) {
return panel.id === panelId;
});
}
}, {
key: 'setPanelThreshold',
value: function setPanelThreshold(panelId, threshold) {
var panel = this.getPanelModel(panelId);
var containsThreshold = _.find(panel.thresholds, { value: threshold });
if (panel && !containsThreshold) {
var thresholdOptions = {
colorMode: "custom",
fill: false,
line: true,
lineColor: "rgb(255, 0, 0)",
op: "gt",
value: threshold,
source: "zabbix"
};
panel.thresholds.push(thresholdOptions);
}
}
}, { }, {
key: 'replaceTargetVariables', key: 'replaceTargetVariables',
value: function replaceTargetVariables(target, options) { value: function replaceTargetVariables(target, options) {

File diff suppressed because one or more lines are too long

View File

@@ -31,9 +31,10 @@
<div class="gf-form"> <div class="gf-form">
<label class="gf-form-label width-7">Trends</label> <label class="gf-form-label width-7">Trends</label>
</div> </div>
<gf-form-switch class="gf-form" <gf-form-switch class="gf-form" label-class="width-5"
label="Enable" label="Enable"
checked="ctrl.current.jsonData.trends" switch-class="max-width-6"> checked="ctrl.current.jsonData.trends"
switch-class="max-width-6">
</gf-form-switch> </gf-form-switch>
<div class="gf-form" ng-if="ctrl.current.jsonData.trends"> <div class="gf-form" ng-if="ctrl.current.jsonData.trends">
<span class="gf-form-label width-7"> <span class="gf-form-label width-7">
@@ -61,8 +62,12 @@
<div class="gf-form-group"> <div class="gf-form-group">
<h3 class="page-heading">Alerting</h3> <h3 class="page-heading">Alerting</h3>
<gf-form-switch class="gf-form width-8" <gf-form-switch class="gf-form" label-class="width-8"
label="Enable alerting" label="Enable alerting"
checked="ctrl.current.jsonData.alerting"> checked="ctrl.current.jsonData.alerting">
</gf-form-switch> </gf-form-switch>
<gf-form-switch class="gf-form" label-class="width-8"
label="Add thresholds"
checked="ctrl.current.jsonData.addThresholds">
</gf-form-switch>
</div> </div>

View File

@@ -79,7 +79,9 @@ var ZabbixAPIDatasource = function () {
var ttl = instanceSettings.jsonData.cacheTTL || '1h'; var ttl = instanceSettings.jsonData.cacheTTL || '1h';
this.cacheTTL = utils.parseInterval(ttl); this.cacheTTL = utils.parseInterval(ttl);
// Alerting options
this.alertingEnabled = instanceSettings.jsonData.alerting; this.alertingEnabled = instanceSettings.jsonData.alerting;
this.addThresholds = instanceSettings.jsonData.addThresholds;
this.zabbix = new Zabbix(this.url, this.username, this.password, this.basicAuth, this.withCredentials, this.cacheTTL); this.zabbix = new Zabbix(this.url, this.username, this.password, this.basicAuth, this.withCredentials, this.cacheTTL);
@@ -113,6 +115,12 @@ var ZabbixAPIDatasource = function () {
if (this.alertingEnabled) { if (this.alertingEnabled) {
this.alertQuery(options).then(function (alert) { this.alertQuery(options).then(function (alert) {
_this.setPanelAlertState(options.panelId, alert.state); _this.setPanelAlertState(options.panelId, alert.state);
if (_this.addThresholds) {
_lodash2.default.forEach(alert.thresholds, function (threshold) {
_this.setPanelThreshold(options.panelId, threshold);
});
}
}); });
} }
@@ -467,6 +475,13 @@ var ZabbixAPIDatasource = function () {
}); });
}); });
} }
/**
* Get triggers and its details for panel's targets
* Returns alert state ('ok' if no fired triggers, or 'alerting' if at least 1 trigger is fired)
* or empty object if no related triggers are finded.
*/
}, { }, {
key: 'alertQuery', key: 'alertQuery',
value: function alertQuery(options) { value: function alertQuery(options) {
@@ -494,9 +509,14 @@ var ZabbixAPIDatasource = function () {
state = 'alerting'; state = 'alerting';
} }
var thresholds = _lodash2.default.map(triggers, function (trigger) {
return getTriggerThreshold(trigger.expression);
});
return { return {
panelId: options.panelId, panelId: options.panelId,
state: state state: state,
thresholds: thresholds
}; };
}); });
} }
@@ -507,14 +527,7 @@ var ZabbixAPIDatasource = function () {
return elem.clientHeight && elem.clientWidth; return elem.clientHeight && elem.clientWidth;
}); });
var panelModels = _lodash2.default.flatten(_lodash2.default.map(this.dashboardSrv.dash.rows, function (row) { var panelModels = this.getPanelModels();
if (row.collapse) {
return [];
} else {
return row.panels;
}
}));
var panelIndex = _lodash2.default.findIndex(panelModels, function (panel) { var panelIndex = _lodash2.default.findIndex(panelModels, function (panel) {
return panel.id === panelId; return panel.id === panelId;
}); });
@@ -536,6 +549,46 @@ var ZabbixAPIDatasource = function () {
} }
} }
} }
}, {
key: 'getPanelModels',
value: function getPanelModels() {
return _lodash2.default.flatten(_lodash2.default.map(this.dashboardSrv.dash.rows, function (row) {
if (row.collapse) {
return [];
} else {
return row.panels;
}
}));
}
}, {
key: 'getPanelModel',
value: function getPanelModel(panelId) {
var panelModels = this.getPanelModels();
return _lodash2.default.find(panelModels, function (panel) {
return panel.id === panelId;
});
}
}, {
key: 'setPanelThreshold',
value: function setPanelThreshold(panelId, threshold) {
var panel = this.getPanelModel(panelId);
var containsThreshold = _lodash2.default.find(panel.thresholds, { value: threshold });
if (panel && !containsThreshold) {
var thresholdOptions = {
colorMode: "custom",
fill: false,
line: true,
lineColor: "rgb(255, 0, 0)",
op: "gt",
value: threshold,
source: "zabbix"
};
panel.thresholds.push(thresholdOptions);
}
}
// Replace template variables // Replace template variables
@@ -660,6 +713,18 @@ function filterEnabledTargets(targets) {
}); });
} }
function getTriggerThreshold(expression) {
var thresholdPattern = /.*[<>]([\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;
}
}
exports.ZabbixAPIDatasource = ZabbixAPIDatasource; exports.ZabbixAPIDatasource = ZabbixAPIDatasource;
exports.zabbixTemplateFormat = zabbixTemplateFormat; exports.zabbixTemplateFormat = zabbixTemplateFormat;

View File

@@ -35,7 +35,9 @@ class ZabbixAPIDatasource {
var ttl = instanceSettings.jsonData.cacheTTL || '1h'; var ttl = instanceSettings.jsonData.cacheTTL || '1h';
this.cacheTTL = utils.parseInterval(ttl); this.cacheTTL = utils.parseInterval(ttl);
// Alerting options
this.alertingEnabled = instanceSettings.jsonData.alerting; this.alertingEnabled = instanceSettings.jsonData.alerting;
this.addThresholds = instanceSettings.jsonData.addThresholds;
this.zabbix = new Zabbix(this.url, this.username, this.password, this.basicAuth, this.withCredentials, this.cacheTTL); this.zabbix = new Zabbix(this.url, this.username, this.password, this.basicAuth, this.withCredentials, this.cacheTTL);
@@ -63,6 +65,12 @@ class ZabbixAPIDatasource {
if (this.alertingEnabled) { if (this.alertingEnabled) {
this.alertQuery(options).then(alert => { this.alertQuery(options).then(alert => {
this.setPanelAlertState(options.panelId, alert.state); this.setPanelAlertState(options.panelId, alert.state);
if (this.addThresholds) {
_.forEach(alert.thresholds, threshold => {
this.setPanelThreshold(options.panelId, threshold);
});
}
}); });
} }
@@ -404,6 +412,11 @@ class ZabbixAPIDatasource {
}); });
} }
/**
* Get triggers and its details for panel's targets
* Returns alert state ('ok' if no fired triggers, or 'alerting' if at least 1 trigger is fired)
* or empty object if no related triggers are finded.
*/
alertQuery(options) { alertQuery(options) {
let enabled_targets = filterEnabledTargets(options.targets); let enabled_targets = filterEnabledTargets(options.targets);
let getPanelItems = _.map(enabled_targets, target => { let getPanelItems = _.map(enabled_targets, target => {
@@ -429,9 +442,14 @@ class ZabbixAPIDatasource {
state = 'alerting'; state = 'alerting';
} }
let thresholds = _.map(triggers, trigger => {
return getTriggerThreshold(trigger.expression);
});
return { return {
panelId: options.panelId, panelId: options.panelId,
state: state state: state,
thresholds: thresholds
}; };
}); });
} }
@@ -441,14 +459,7 @@ class ZabbixAPIDatasource {
return elem.clientHeight && elem.clientWidth; return elem.clientHeight && elem.clientWidth;
}); });
let panelModels = _.flatten(_.map(this.dashboardSrv.dash.rows, row => { let panelModels = this.getPanelModels();
if (row.collapse) {
return [];
} else {
return row.panels;
}
}));
let panelIndex = _.findIndex(panelModels, panel => { let panelIndex = _.findIndex(panelModels, panel => {
return panel.id === panelId; return panel.id === panelId;
}); });
@@ -471,6 +482,43 @@ class ZabbixAPIDatasource {
} }
} }
getPanelModels() {
return _.flatten(_.map(this.dashboardSrv.dash.rows, row => {
if (row.collapse) {
return [];
} else {
return row.panels;
}
}));
}
getPanelModel(panelId) {
let panelModels = this.getPanelModels();
return _.find(panelModels, panel => {
return panel.id === panelId;
});
}
setPanelThreshold(panelId, threshold) {
let panel = this.getPanelModel(panelId);
let containsThreshold = _.find(panel.thresholds, {value: threshold});
if (panel && !containsThreshold) {
let thresholdOptions = {
colorMode : "custom",
fill : false,
line : true,
lineColor: "rgb(255, 0, 0)",
op: "gt",
value: threshold,
source: "zabbix"
};
panel.thresholds.push(thresholdOptions);
}
}
// Replace template variables // Replace template variables
replaceTargetVariables(target, options) { replaceTargetVariables(target, options) {
let parts = ['group', 'host', 'application', 'item']; let parts = ['group', 'host', 'application', 'item'];
@@ -588,6 +636,18 @@ function filterEnabledTargets(targets) {
}); });
} }
function getTriggerThreshold(expression) {
let thresholdPattern = /.*[<>]([\d\.]+)/;
let finded_thresholds = expression.match(thresholdPattern);
if (finded_thresholds && finded_thresholds.length >= 2) {
let threshold = finded_thresholds[1];
threshold = Number(threshold);
return threshold;
} else {
return null;
}
}
export {ZabbixAPIDatasource, zabbixTemplateFormat}; export {ZabbixAPIDatasource, zabbixTemplateFormat};
// Fix for backward compatibility with lodash 2.4 // Fix for backward compatibility with lodash 2.4

View File

@@ -31,9 +31,10 @@
<div class="gf-form"> <div class="gf-form">
<label class="gf-form-label width-7">Trends</label> <label class="gf-form-label width-7">Trends</label>
</div> </div>
<gf-form-switch class="gf-form" <gf-form-switch class="gf-form" label-class="width-5"
label="Enable" label="Enable"
checked="ctrl.current.jsonData.trends" switch-class="max-width-6"> checked="ctrl.current.jsonData.trends"
switch-class="max-width-6">
</gf-form-switch> </gf-form-switch>
<div class="gf-form" ng-if="ctrl.current.jsonData.trends"> <div class="gf-form" ng-if="ctrl.current.jsonData.trends">
<span class="gf-form-label width-7"> <span class="gf-form-label width-7">
@@ -61,8 +62,12 @@
<div class="gf-form-group"> <div class="gf-form-group">
<h3 class="page-heading">Alerting</h3> <h3 class="page-heading">Alerting</h3>
<gf-form-switch class="gf-form width-8" <gf-form-switch class="gf-form" label-class="width-8"
label="Enable alerting" label="Enable alerting"
checked="ctrl.current.jsonData.alerting"> checked="ctrl.current.jsonData.alerting">
</gf-form-switch> </gf-form-switch>
<gf-form-switch class="gf-form" label-class="width-8"
label="Add thresholds"
checked="ctrl.current.jsonData.addThresholds">
</gf-form-switch>
</div> </div>