Merge branch 'develop-1.9' into develop
Conflicts: .gitignore zabbix/datasource.js zabbix/partials/query.editor.html zabbix/queryCtrl.js
This commit is contained in:
41
README.md
41
README.md
@@ -1,2 +1,43 @@
|
|||||||
# grafana-zabbix
|
# grafana-zabbix
|
||||||
Zabbix API datasource for Grafana dashboard
|
Zabbix API datasource for Grafana dashboard
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
Query editor allows to add metric by step-by-step selection from host group, host, application dropdown menus.
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Grafana 1.9.x
|
||||||
|
|
||||||
|
Download latest release and unpack into `<your grafana installation>/plugins/datasource/`. Then edit Grafana config.js:
|
||||||
|
* Add dependencies
|
||||||
|
|
||||||
|
```
|
||||||
|
plugins: {
|
||||||
|
panels: [],
|
||||||
|
dependencies: ['datasource/zabbix/datasource', 'datasource/zabbix/queryCtrl'],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
* Add datasource and setup your Zabbix API url, username and password
|
||||||
|
|
||||||
|
```
|
||||||
|
datasources: {
|
||||||
|
...
|
||||||
|
},
|
||||||
|
zabbix: {
|
||||||
|
type: 'ZabbixAPIDatasource',
|
||||||
|
url: 'http://www.zabbix.org/zabbix/api_jsonrpc.php',
|
||||||
|
username: 'guest',
|
||||||
|
password: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
### Grafana 2.0.x
|
||||||
|
Now in development.
|
||||||
|
|||||||
@@ -39,14 +39,14 @@ function (angular, _, kbn) {
|
|||||||
// Need for find target alias
|
// Need for find target alias
|
||||||
var targets = options.targets;
|
var targets = options.targets;
|
||||||
|
|
||||||
// TODO: remove undefined targets from request
|
// Remove undefined and hidden targets
|
||||||
// Check that all targets defined
|
var displayedTargets = _.filter(targets, function (target) {
|
||||||
var targetsDefined = options.targets.every(function (target, index, array) {
|
return (!target.hide && target.item);
|
||||||
return target.item;
|
|
||||||
});
|
});
|
||||||
if (targetsDefined) {
|
|
||||||
|
if (displayedTargets.length) {
|
||||||
// Extract zabbix api item objects from targets
|
// Extract zabbix api item objects from targets
|
||||||
var target_items = _.map(options.targets, 'item');
|
var target_items = _.map(displayedTargets, 'item');
|
||||||
} else {
|
} else {
|
||||||
// No valid targets, return the empty dataset
|
// No valid targets, return the empty dataset
|
||||||
var d = $q.defer();
|
var d = $q.defer();
|
||||||
@@ -75,13 +75,15 @@ function (angular, _, kbn) {
|
|||||||
// Index returned datapoints by item/metric id
|
// Index returned datapoints by item/metric id
|
||||||
var indexed_result = _.groupBy(response, 'itemid');
|
var indexed_result = _.groupBy(response, 'itemid');
|
||||||
|
|
||||||
|
// TODO: realize correct timeseries reduce
|
||||||
|
/*
|
||||||
// Reduce timeseries to the same size for stacking and tooltip work properly
|
// Reduce timeseries to the same size for stacking and tooltip work properly
|
||||||
var min_length = _.min(_.map(indexed_result, function (history) {
|
var min_length = _.min(_.map(indexed_result, function (history) {
|
||||||
return history.length;
|
return history.length;
|
||||||
}));
|
}));
|
||||||
_.each(indexed_result, function (item) {
|
_.each(indexed_result, function (item) {
|
||||||
item.splice(0, item.length - min_length);
|
item.splice(0, item.length - min_length);
|
||||||
});
|
});*/
|
||||||
|
|
||||||
// Sort result as the same as targets for display
|
// Sort result as the same as targets for display
|
||||||
// stacked timeseries in proper order
|
// stacked timeseries in proper order
|
||||||
@@ -120,7 +122,7 @@ function (angular, _, kbn) {
|
|||||||
|
|
||||||
|
|
||||||
// Request data from Zabbix API
|
// Request data from Zabbix API
|
||||||
ZabbixAPIDatasource.prototype.doZabbixAPIRequest = function(request_data) {
|
ZabbixAPIDatasource.prototype.performZabbixAPIRequest = function(request_data) {
|
||||||
var options = {
|
var options = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@@ -180,7 +182,7 @@ function (angular, _, kbn) {
|
|||||||
itemids: item_ids,
|
itemids: item_ids,
|
||||||
sortfield: 'clock',
|
sortfield: 'clock',
|
||||||
sortorder: 'ASC',
|
sortorder: 'ASC',
|
||||||
limit: self.limitMetrics,
|
limit: self.limitmetrics,
|
||||||
time_from: start,
|
time_from: start,
|
||||||
},
|
},
|
||||||
auth: self.auth,
|
auth: self.auth,
|
||||||
@@ -192,7 +194,7 @@ function (angular, _, kbn) {
|
|||||||
data.params.time_till = end;
|
data.params.time_till = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
apiRequests.push(self.doZabbixAPIRequest(data));
|
apiRequests.push(self.performZabbixAPIRequest(data));
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.handleMultipleRequest(apiRequests);
|
return this.handleMultipleRequest(apiRequests);
|
||||||
@@ -265,7 +267,7 @@ function (angular, _, kbn) {
|
|||||||
id: 1
|
id: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.doZabbixAPIRequest(data);
|
return this.performZabbixAPIRequest(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -285,7 +287,7 @@ function (angular, _, kbn) {
|
|||||||
data.params.groupids = groupid;
|
data.params.groupids = groupid;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.doZabbixAPIRequest(data);
|
return this.performZabbixAPIRequest(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -303,7 +305,7 @@ function (angular, _, kbn) {
|
|||||||
id: 1
|
id: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.doZabbixAPIRequest(data);
|
return this.performZabbixAPIRequest(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -329,7 +331,7 @@ function (angular, _, kbn) {
|
|||||||
data.params.applicationids = applicationid;
|
data.params.applicationids = applicationid;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.doZabbixAPIRequest(data);
|
return this.performZabbixAPIRequest(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -349,7 +351,7 @@ function (angular, _, kbn) {
|
|||||||
params: {
|
params: {
|
||||||
output: ['triggerid', 'description'],
|
output: ['triggerid', 'description'],
|
||||||
itemids: annotation.aids.split(','), // TODO: validate / pull automatically from dashboard.
|
itemids: annotation.aids.split(','), // TODO: validate / pull automatically from dashboard.
|
||||||
limit: self.limitMetrics,
|
limit: self.limitmetrics,
|
||||||
},
|
},
|
||||||
auth: self.auth,
|
auth: self.auth,
|
||||||
id: 1
|
id: 1
|
||||||
@@ -372,7 +374,7 @@ function (angular, _, kbn) {
|
|||||||
time_from: from,
|
time_from: from,
|
||||||
time_till: to,
|
time_till: to,
|
||||||
objectids: _.keys(obs),
|
objectids: _.keys(obs),
|
||||||
limit: self.limitMetrics,
|
limit: self.limitmetrics,
|
||||||
},
|
},
|
||||||
auth: self.auth,
|
auth: self.auth,
|
||||||
id: 1
|
id: 1
|
||||||
|
|||||||
@@ -35,10 +35,20 @@ function (angular, _) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setItemAlias();
|
||||||
|
|
||||||
$scope.target.errors = validateTarget($scope.target);
|
$scope.target.errors = validateTarget($scope.target);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Take alias from item name by default
|
||||||
|
function setItemAlias() {
|
||||||
|
if (!$scope.target.alias && $scope.target.item) {
|
||||||
|
$scope.target.alias = $scope.target.item.expandedName;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
$scope.targetBlur = function() {
|
$scope.targetBlur = function() {
|
||||||
|
setItemAlias();
|
||||||
$scope.target.errors = validateTarget($scope.target);
|
$scope.target.errors = validateTarget($scope.target);
|
||||||
if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
|
if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
|
||||||
$scope.oldTarget = angular.copy($scope.target);
|
$scope.oldTarget = angular.copy($scope.target);
|
||||||
@@ -65,7 +75,7 @@ function (angular, _) {
|
|||||||
|
|
||||||
// Call when host selected
|
// Call when host selected
|
||||||
$scope.selectHost = function() {
|
$scope.selectHost = function() {
|
||||||
|
if ($scope.target.host) {
|
||||||
// Update item list
|
// Update item list
|
||||||
if ($scope.target.application) {
|
if ($scope.target.application) {
|
||||||
$scope.updateItemList($scope.target.host.hostid, $scope.target.application.applicationid);
|
$scope.updateItemList($scope.target.host.hostid, $scope.target.application.applicationid);
|
||||||
@@ -75,6 +85,7 @@ function (angular, _) {
|
|||||||
|
|
||||||
// Update application list
|
// Update application list
|
||||||
$scope.updateAppList($scope.target.host.hostid);
|
$scope.updateAppList($scope.target.host.hostid);
|
||||||
|
}
|
||||||
|
|
||||||
$scope.target.errors = validateTarget($scope.target);
|
$scope.target.errors = validateTarget($scope.target);
|
||||||
if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
|
if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
|
||||||
@@ -104,6 +115,7 @@ function (angular, _) {
|
|||||||
|
|
||||||
// Call when item selected
|
// Call when item selected
|
||||||
$scope.selectItem = function() {
|
$scope.selectItem = function() {
|
||||||
|
setItemAlias();
|
||||||
$scope.target.errors = validateTarget($scope.target);
|
$scope.target.errors = validateTarget($scope.target);
|
||||||
if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
|
if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
|
||||||
$scope.oldTarget = angular.copy($scope.target);
|
$scope.oldTarget = angular.copy($scope.target);
|
||||||
|
|||||||
Reference in New Issue
Block a user