diff --git a/src/datasource-zabbix/dataProcessor.js b/src/datasource-zabbix/dataProcessor.js index 2d29bd4..1c5942e 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 d460baa..3367f1f 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 9390c3f..1e23114 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 ab6639e..517569f 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;