Merge branch 'develop'

This commit is contained in:
Alexander Zobnin
2016-09-24 14:02:49 +03:00
7 changed files with 134 additions and 21 deletions

View File

@@ -30,6 +30,13 @@ scale(100)
scale(0.01) scale(0.01)
``` ```
### delta
```
delta()
```
Convert absolute values to delta, for example, bits to bits/sec.
Aggregate Aggregate
--------- ---------
@@ -71,6 +78,38 @@ max(interval)
``` ```
**Deprecated**, use `aggregateBy(interval, max)` instead. **Deprecated**, use `aggregateBy(interval, max)` instead.
Filter
---------
### top
```
top(N, value)
```
Returns top N series, sorted by _value_, which can be one of: _avg_, _min_, _max_, _median_.
Examples:
```
top(10, avg)
top(5, max)
```
### bottom
```
bottom(N, value)
```
Returns bottom N series, sorted by _value_, which can be one of: _avg_, _min_, _max_, _median_.
Examples:
```
bottom(5, avg)
```
## Trends ## Trends
### trendValue ### trendValue

View File

@@ -116,6 +116,22 @@ export default class DataProcessor {
return sortByTime(new_timeseries); return sortByTime(new_timeseries);
} }
static limit(order, n, orderByFunc, timeseries) {
let orderByCallback = DataProcessor.aggregationFunctions[orderByFunc];
let sortByIteratee = (ts) => {
let values = _.map(ts.datapoints, (point) => {
return point[0];
});
return orderByCallback(values);
};
let sortedTimeseries = _.sortBy(timeseries, sortByIteratee);
if (order === 'bottom') {
return sortedTimeseries.slice(0, n);
} else {
return sortedTimeseries.slice(-n);
}
}
static AVERAGE(values) { static AVERAGE(values) {
var sum = 0; var sum = 0;
_.each(values, function(value) { _.each(values, function(value) {
@@ -151,6 +167,16 @@ export default class DataProcessor {
}); });
} }
static delta(datapoints) {
let newSeries = [];
let deltaValue;
for (var i = 1; i < datapoints.length; i++) {
deltaValue = datapoints[i][0] - datapoints[i - 1][0];
newSeries.push([deltaValue, datapoints[i][1]]);
}
return newSeries;
}
static groupByWrapper(interval, groupFunc, datapoints) { static groupByWrapper(interval, groupFunc, datapoints) {
var groupByCallback = DataProcessor.aggregationFunctions[groupFunc]; var groupByCallback = DataProcessor.aggregationFunctions[groupFunc];
return DataProcessor.groupBy(interval, groupByCallback, datapoints); return DataProcessor.groupBy(interval, groupByCallback, datapoints);
@@ -181,12 +207,15 @@ export default class DataProcessor {
return { return {
groupBy: this.groupByWrapper, groupBy: this.groupByWrapper,
scale: this.scale, scale: this.scale,
delta: this.delta,
aggregateBy: this.aggregateByWrapper, aggregateBy: this.aggregateByWrapper,
average: _.partial(this.aggregateWrapper, this.AVERAGE), average: _.partial(this.aggregateWrapper, this.AVERAGE),
min: _.partial(this.aggregateWrapper, this.MIN), min: _.partial(this.aggregateWrapper, this.MIN),
max: _.partial(this.aggregateWrapper, this.MAX), max: _.partial(this.aggregateWrapper, this.MAX),
median: _.partial(this.aggregateWrapper, this.MEDIAN), median: _.partial(this.aggregateWrapper, this.MEDIAN),
sumSeries: this.sumSeries, sumSeries: this.sumSeries,
top: _.partial(this.limit, 'top'),
bottom: _.partial(this.limit, 'bottom'),
setAlias: this.setAlias, setAlias: this.setAlias,
}; };
} }

View File

@@ -92,7 +92,11 @@ export class ZabbixAPIDatasource {
_.forEach(target.functions, func => { _.forEach(target.functions, func => {
func.params = _.map(func.params, param => { func.params = _.map(func.params, param => {
return this.templateSrv.replace(param, options.scopedVars); if (typeof param === 'number') {
return +this.templateSrv.replace(param.toString(), options.scopedVars);
} else {
return this.templateSrv.replace(param, options.scopedVars);
}
}); });
}); });
@@ -181,6 +185,7 @@ export class ZabbixAPIDatasource {
return getHistory.then(timeseries_data => { return getHistory.then(timeseries_data => {
let transformFunctions = bindFunctionDefs(target.functions, 'Transform'); let transformFunctions = bindFunctionDefs(target.functions, 'Transform');
let aggregationFunctions = bindFunctionDefs(target.functions, 'Aggregate'); let aggregationFunctions = bindFunctionDefs(target.functions, 'Aggregate');
let filterFunctions = bindFunctionDefs(target.functions, 'Filter');
let aliasFunctions = bindFunctionDefs(target.functions, 'Alias'); let aliasFunctions = bindFunctionDefs(target.functions, 'Alias');
// Apply transformation functions // Apply transformation functions
@@ -189,6 +194,11 @@ export class ZabbixAPIDatasource {
return timeseries; return timeseries;
}); });
// Apply filter functions
if (filterFunctions.length) {
timeseries_data = sequence(filterFunctions)(timeseries_data);
}
// Apply aggregations // Apply aggregations
if (aggregationFunctions.length) { if (aggregationFunctions.length) {
let dp = _.map(timeseries_data, 'datapoints'); let dp = _.map(timeseries_data, 'datapoints');

View File

@@ -5,6 +5,7 @@ var index = [];
var categories = { var categories = {
Transform: [], Transform: [],
Aggregate: [], Aggregate: [],
Filter: [],
Trends: [], Trends: [],
Alias: [] Alias: []
}; };
@@ -39,6 +40,13 @@ addFuncDef({
defaultParams: [100], defaultParams: [100],
}); });
addFuncDef({
name: 'delta',
category: 'Transform',
params: [],
defaultParams: [],
});
addFuncDef({ addFuncDef({
name: 'sumSeries', name: 'sumSeries',
category: 'Aggregate', category: 'Aggregate',
@@ -92,6 +100,26 @@ addFuncDef({
defaultParams: ['1m', 'avg'], defaultParams: ['1m', 'avg'],
}); });
addFuncDef({
name: 'top',
category: 'Filter',
params: [
{ name: 'number', type: 'int' },
{ name: 'value', type: 'string', options: ['avg', 'min', 'max', 'median'] }
],
defaultParams: [5, 'avg'],
});
addFuncDef({
name: 'bottom',
category: 'Filter',
params: [
{ name: 'number', type: 'int' },
{ name: 'value', type: 'string', options: ['avg', 'min', 'max', 'median'] }
],
defaultParams: [5, 'avg'],
});
addFuncDef({ addFuncDef({
name: 'trendValue', name: 'trendValue',
category: 'Trends', category: 'Trends',

View File

@@ -230,13 +230,13 @@ angular.module('grafana.services').factory('QueryProcessor', function($q) {
// Group history by itemid // Group history by itemid
var grouped_history = _.groupBy(history, 'itemid'); var grouped_history = _.groupBy(history, 'itemid');
var hosts = _.groupBy(_.flatten(_.map(items, 'hosts')), 'hostid'); var hosts = _.flatten(_.map(items, 'hosts'));
return _.map(grouped_history, function(hist, itemid) { return _.map(grouped_history, function(hist, itemid) {
var item = _.find(items, {'itemid': itemid}); var item = _.find(items, {'itemid': itemid});
var alias = item.name; var alias = item.name;
if (_.keys(hosts).length > 1 || addHostName) { if (_.keys(hosts).length > 1 || addHostName) {
var host = hosts[item.hostid]; var host = _.find(hosts, {'hostid': item.hostid});
alias = host.name + ": " + alias; alias = host.name + ": " + alias;
} }
return { return {

View File

@@ -41,12 +41,12 @@ function ZabbixAPIService($q, alertSrv, zabbixAPICoreService) {
request(method, params) { request(method, params) {
var self = this; var self = this;
return this.zabbixAPICore.request(this.url, method, params, this.requestOptions, this.auth) return this.zabbixAPICore
.then(function(result) { .request(this.url, method, params, this.requestOptions, this.auth)
.then((result) => {
return result; return result;
}, }, (error) => {
// Handle API errors // Handle API errors
function(error) {
if (isNotAuthorized(error.data)) { if (isNotAuthorized(error.data)) {
return self.loginOnce().then( return self.loginOnce().then(
function() { function() {
@@ -56,15 +56,18 @@ function ZabbixAPIService($q, alertSrv, zabbixAPICoreService) {
function(error) { function(error) {
self.alertAPIError(error.data); self.alertAPIError(error.data);
}); });
} else {
this.alertSrv.set("Connection Error", error.data, 'error', 5000);
} }
}); });
} }
alertAPIError(message) { alertAPIError(message, timeout = 5000) {
this.alertSrv.set( this.alertSrv.set(
"Zabbix API Error", "Zabbix API Error",
message, message,
'error' 'error',
timeout
); );
} }

View File

@@ -51,19 +51,23 @@ class ZabbixAPICoreService {
requestOptions.headers.Authorization = options.basicAuth; requestOptions.headers.Authorization = options.basicAuth;
} }
this.backendSrv.datasourceRequest(requestOptions).then(function (response) { this.backendSrv.datasourceRequest(requestOptions)
// General connection issues .then((response) => {
if (!response.data) { // General connection issues
deferred.reject(response); if (!response.data) {
} deferred.reject(response);
}
// Handle Zabbix API errors // Handle Zabbix API errors
else if (response.data.error) { else if (response.data.error) {
deferred.reject(response.data.error); deferred.reject(response.data.error);
} }
deferred.resolve(response.data.result);
}, (error) => {
deferred.reject(error.err);
});
deferred.resolve(response.data.result);
});
return deferred.promise; return deferred.promise;
} }