diff --git a/zabbix/datasource.js b/zabbix/datasource.js
index bb3d3ed..ddbdc1c 100644
--- a/zabbix/datasource.js
+++ b/zabbix/datasource.js
@@ -25,6 +25,10 @@ function (angular, _, kbn) {
this.username = datasource.meta.username;
this.password = datasource.meta.password;
+ // Use trends instead history since specified time
+ this.trends = datasource.meta.trends;
+ this.trendsFrom = datasource.meta.trendsFrom || '7d';
+
// Limit metrics per panel for templated request
this.limitmetrics = datasource.meta.limitmetrics || 50;
}
@@ -44,6 +48,7 @@ function (angular, _, kbn) {
// get from & to in seconds
var from = Math.ceil(kbn.parseDate(options.range.from).getTime() / 1000);
var to = Math.ceil(kbn.parseDate(options.range.to).getTime() / 1000);
+ var useTrendsFrom = Math.ceil(kbn.parseDate('now-' + this.trendsFrom).getTime() / 1000);
// Create request for each target
var promises = _.map(options.targets, function(target) {
@@ -93,8 +98,14 @@ function (angular, _, kbn) {
return [];
} else {
items = _.flatten(items);
- return self.performTimeSeriesQuery(items, from, to)
- .then(_.partial(self.handleHistoryResponse, items));
+
+ if ((from < useTrendsFrom) && self.trends) {
+ return self.getTrends(items, from, to)
+ .then(_.partial(self.handleTrendResponse, items));
+ } else {
+ return self.performTimeSeriesQuery(items, from, to)
+ .then(_.partial(self.handleHistoryResponse, items));
+ }
}
});
}, this);
@@ -142,6 +153,58 @@ function (angular, _, kbn) {
};
+ ZabbixAPIDatasource.prototype.getTrends = function(items, start, end) {
+ // Group items by value type
+ var grouped_items = _.groupBy(items, 'value_type');
+
+ // Perform request for each value type
+ return $q.all(_.map(grouped_items, function (items, value_type) {
+ var itemids = _.map(items, 'itemid');
+ var params = {
+ output: 'extend',
+ trend: value_type,
+ itemids: itemids,
+ sortfield: 'clock',
+ sortorder: 'ASC',
+ time_from: start
+ };
+
+ // Relative queries (e.g. last hour) don't include an end time
+ if (end) {
+ params.time_till = end;
+ }
+
+ return this.performZabbixAPIRequest('trend.get', params);
+ }, this)).then(function (results) {
+ return _.flatten(results);
+ });
+ };
+
+
+ ZabbixAPIDatasource.prototype.handleTrendResponse = function(items, trends) {
+
+ // Group items and trends by itemid
+ var indexed_items = _.indexBy(items, 'itemid');
+ var grouped_history = _.groupBy(trends, 'itemid');
+
+ return $q.when(_.map(grouped_history, function (trends, itemid) {
+ var item = indexed_items[itemid];
+ var series = {
+ target: (item.hosts ? item.hosts[0].name+': ' : '') + expandItemName(item),
+ datapoints: _.map(trends, function (p) {
+
+ // Value must be a number for properly work
+ var value = Number(p.value_avg);
+ return [value, p.clock * 1000];
+ })
+ };
+ return series;
+ })).then(function (result) {
+ return _.sortBy(result, 'target');
+ });
+ };
+
+
/**
* Convert Zabbix API data to Grafana format
*
@@ -618,31 +681,37 @@ function (angular, _, kbn) {
search: {
'description': annotation.query
},
+ searchWildcardsEnabled: true,
+ expandDescription: true
};
return this.performZabbixAPIRequest('trigger.get', params)
.then(function (result) {
if(result) {
- var obs = {};
- obs = _.indexBy(result, 'triggerid');
-
+ var objects = _.indexBy(result, 'triggerid');
var params = {
output: 'extend',
- sortorder: 'DESC',
time_from: from,
time_till: to,
- objectids: _.keys(obs)
+ objectids: _.keys(objects),
+ select_acknowledges: 'extend'
};
+ // Show problem events only
+ if (!annotation.showOkEvents) {
+ params.value = 1;
+ }
+
return self.performZabbixAPIRequest('event.get', params)
.then(function (result) {
var events = [];
_.each(result, function(e) {
+ var formatted_acknowledges = formatAcknowledges(e.acknowledges);;
events.push({
annotation: annotation,
time: e.clock * 1000,
- title: obs[e.objectid].description,
- text: e.eventid,
+ title: Number(e.value) ? 'Problem' : 'OK',
+ text: objects[e.objectid].description + formatted_acknowledges,
});
});
return events;
@@ -692,4 +761,44 @@ function expandItemName(item) {
name = name.replace('$' + i, key_params[i - 1]);
};
return name;
-};
\ No newline at end of file
+}
+
+
+/**
+ * Convert Date object to local time in format
+ * YYYY-MM-DD HH:mm:ss
+ *
+ * @param {Date} date Date object
+ * @return {string} formatted local time YYYY-MM-DD HH:mm:ss
+ */
+function getShortTime(date) {
+ var MM = date.getMonth() < 10 ? '0' + date.getMonth() : date.getMonth();
+ var DD = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
+ var HH = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
+ var mm = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
+ var ss = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
+ return date.getFullYear() + '-' + MM + '-' + DD + ' ' + HH + ':' + mm + ':' + ss;
+}
+
+
+/**
+ * Format acknowledges.
+ *
+ * @param {array} acknowledges array of Zabbix acknowledge objects
+ * @return {string} HTML-formatted table
+ */
+function formatAcknowledges(acknowledges) {
+ if (acknowledges.length) {
+ var formatted_acknowledges = '
Acknowledges:
| Time | User | Comments |
| ' + getShortTime(time) + ' | ' + ack.alias + ' (' + ack.name+ ' ' + ack.surname + ')' + ' | ' + ack.message + ' |