From aa882d752ecc1335e5b00985e32264ee97dccd3a Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Sat, 24 Sep 2016 12:44:22 +0300 Subject: [PATCH] Add top N and bottom N filter functions, closes #241. --- docs/sources/reference/functions.md | 32 ++++++++++++++++++++++++ src/datasource-zabbix/DataProcessor.js | 18 +++++++++++++ src/datasource-zabbix/datasource.js | 12 ++++++++- src/datasource-zabbix/metricFunctions.js | 21 ++++++++++++++++ 4 files changed, 82 insertions(+), 1 deletion(-) diff --git a/docs/sources/reference/functions.md b/docs/sources/reference/functions.md index 10db01f..c620ca7 100644 --- a/docs/sources/reference/functions.md +++ b/docs/sources/reference/functions.md @@ -78,6 +78,38 @@ max(interval) ``` **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 ### trendValue diff --git a/src/datasource-zabbix/DataProcessor.js b/src/datasource-zabbix/DataProcessor.js index 020132f..cb6c4c2 100644 --- a/src/datasource-zabbix/DataProcessor.js +++ b/src/datasource-zabbix/DataProcessor.js @@ -116,6 +116,22 @@ export default class DataProcessor { 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) { var sum = 0; _.each(values, function(value) { @@ -198,6 +214,8 @@ export default class DataProcessor { max: _.partial(this.aggregateWrapper, this.MAX), median: _.partial(this.aggregateWrapper, this.MEDIAN), sumSeries: this.sumSeries, + top: _.partial(this.limit, 'top'), + bottom: _.partial(this.limit, 'bottom'), setAlias: this.setAlias, }; } diff --git a/src/datasource-zabbix/datasource.js b/src/datasource-zabbix/datasource.js index 2e914a4..c9db4bb 100644 --- a/src/datasource-zabbix/datasource.js +++ b/src/datasource-zabbix/datasource.js @@ -92,7 +92,11 @@ export class ZabbixAPIDatasource { _.forEach(target.functions, func => { 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 => { let transformFunctions = bindFunctionDefs(target.functions, 'Transform'); let aggregationFunctions = bindFunctionDefs(target.functions, 'Aggregate'); + let filterFunctions = bindFunctionDefs(target.functions, 'Filter'); let aliasFunctions = bindFunctionDefs(target.functions, 'Alias'); // Apply transformation functions @@ -189,6 +194,11 @@ export class ZabbixAPIDatasource { return timeseries; }); + // Apply filter functions + if (filterFunctions.length) { + timeseries_data = sequence(filterFunctions)(timeseries_data); + } + // Apply aggregations if (aggregationFunctions.length) { let dp = _.map(timeseries_data, 'datapoints'); diff --git a/src/datasource-zabbix/metricFunctions.js b/src/datasource-zabbix/metricFunctions.js index ac332ef..5d467f4 100644 --- a/src/datasource-zabbix/metricFunctions.js +++ b/src/datasource-zabbix/metricFunctions.js @@ -5,6 +5,7 @@ var index = []; var categories = { Transform: [], Aggregate: [], + Filter: [], Trends: [], Alias: [] }; @@ -99,6 +100,26 @@ addFuncDef({ 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({ name: 'trendValue', category: 'Trends',