From e4bbecb18b189c7fe549631db8f1ca78f3fbf8a5 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Thu, 7 Mar 2019 10:35:36 +0300 Subject: [PATCH] fix multiple agg functions handling, closes #530 --- src/datasource-zabbix/dataProcessor.js | 6 ++--- src/datasource-zabbix/specs/utils.spec.js | 27 +++++++++++++++++++++++ src/datasource-zabbix/timeseries.js | 12 +++++++++- src/datasource-zabbix/utils.js | 11 +++++++++ 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/datasource-zabbix/dataProcessor.js b/src/datasource-zabbix/dataProcessor.js index 2d29bd48b..1c5942ebc 100644 --- a/src/datasource-zabbix/dataProcessor.js +++ b/src/datasource-zabbix/dataProcessor.js @@ -107,7 +107,7 @@ function groupByWrapper(interval, groupFunc, datapoints) { function aggregateByWrapper(interval, aggregateFunc, datapoints) { // Flatten all points in frame and then just use groupBy() - const flattenedPoints = _.flatten(datapoints, true); + const flattenedPoints = ts.flattenDatapoints(datapoints); // groupBy_perf works with sorted series only const sortedPoints = ts.sortByTime(flattenedPoints); let groupByCallback = aggregationFunctions[aggregateFunc]; @@ -115,14 +115,14 @@ function aggregateByWrapper(interval, aggregateFunc, datapoints) { } function aggregateWrapper(groupByCallback, interval, datapoints) { - var flattenedPoints = _.flatten(datapoints, true); + var flattenedPoints = ts.flattenDatapoints(datapoints); // groupBy_perf works with sorted series only const sortedPoints = ts.sortByTime(flattenedPoints); return groupBy(sortedPoints, interval, groupByCallback); } function percentil(interval, n, datapoints) { - var flattenedPoints = _.flatten(datapoints, true); + var flattenedPoints = ts.flattenDatapoints(datapoints); var groupByCallback = _.partial(PERCENTIL, n); return groupBy(flattenedPoints, interval, groupByCallback); } diff --git a/src/datasource-zabbix/specs/utils.spec.js b/src/datasource-zabbix/specs/utils.spec.js index d460baa27..3367f1f9e 100644 --- a/src/datasource-zabbix/specs/utils.spec.js +++ b/src/datasource-zabbix/specs/utils.spec.js @@ -138,4 +138,31 @@ describe('Utils', () => { done(); }); }); + + describe('getArrayDepth()', () => { + it('should calculate proper array depth', () => { + const test_cases = [ + { + array: [], + depth: 1 + }, + { + array: [1, 2, 3], + depth: 1 + }, + { + array: [[1, 2], [3, 4]], + depth: 2 + }, + { + array: [ [[1, 2], [3, 4]], [[1, 2], [3, 4]] ], + depth: 3 + }, + ]; + + for (const test_case of test_cases) { + expect(utils.getArrayDepth(test_case.array)).toBe(test_case.depth); + } + }); + }); }); diff --git a/src/datasource-zabbix/timeseries.js b/src/datasource-zabbix/timeseries.js index 9390c3f1d..1e2311452 100644 --- a/src/datasource-zabbix/timeseries.js +++ b/src/datasource-zabbix/timeseries.js @@ -478,6 +478,15 @@ function findNearestLeft(series, pointIndex) { return null; } +function flattenDatapoints(datapoints) { + const depth = utils.getArrayDepth(datapoints); + if (depth <= 2) { + // Don't process if datapoints already flattened + return datapoints; + } + return _.flatten(datapoints); +} + //////////// // Export // //////////// @@ -501,7 +510,8 @@ const exportedFunctions = { MAX, MEDIAN, PERCENTIL, - sortByTime + sortByTime, + flattenDatapoints, }; export default exportedFunctions; diff --git a/src/datasource-zabbix/utils.js b/src/datasource-zabbix/utils.js index ab6639ed2..517569f75 100644 --- a/src/datasource-zabbix/utils.js +++ b/src/datasource-zabbix/utils.js @@ -265,6 +265,17 @@ export function compactQuery(query) { return query.replace(/\s+/g, ' ').trim(); } +export function getArrayDepth(a, level = 0) { + if (a.length === 0) { + return 1; + } + const elem = a[0]; + if (_.isArray(elem)) { + return getArrayDepth(elem, level + 1); + } + return level + 1; +} + // Fix for backward compatibility with lodash 2.4 if (!_.includes) { _.includes = _.contains;