From 332ecd483f7c7b9215758b9e86a9b27a1190efd1 Mon Sep 17 00:00:00 2001 From: Sofia Papagiannaki Date: Sat, 12 Jan 2019 17:18:51 +0200 Subject: [PATCH 1/5] Optionally set histogram x-axis min/max --- .../app/plugins/panel/graph/axes_editor.html | 11 ++++ public/app/plugins/panel/graph/graph.ts | 4 +- .../plugins/panel/graph/specs/graph.test.ts | 64 +++++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/public/app/plugins/panel/graph/axes_editor.html b/public/app/plugins/panel/graph/axes_editor.html index 6ec64015746..4186111a41c 100644 --- a/public/app/plugins/panel/graph/axes_editor.html +++ b/public/app/plugins/panel/graph/axes_editor.html @@ -67,6 +67,17 @@ +
+
+ + +
+
+ + +
+
+

Y-Axes
diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index 4033e4b3778..98330196ca2 100755 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -337,8 +337,8 @@ class GraphElement { let bucketSize: number; if (this.data.length) { - const histMin = _.min(_.map(this.data, s => s.stats.min)); - const histMax = _.max(_.map(this.data, s => s.stats.max)); + const histMin = panel.xaxis.min ? panel.xaxis.min : _.min(_.map(this.data, s => s.stats.min)); + const histMax = panel.xaxis.max ? panel.xaxis.max : _.max(_.map(this.data, s => s.stats.max)); const ticks = panel.xaxis.buckets || this.panelWidth / 50; bucketSize = tickStep(histMin, histMax, ticks); options.series.bars.barWidth = bucketSize * 0.8; diff --git a/public/app/plugins/panel/graph/specs/graph.test.ts b/public/app/plugins/panel/graph/specs/graph.test.ts index 58a35ea2a5f..dc1c9c99f04 100644 --- a/public/app/plugins/panel/graph/specs/graph.test.ts +++ b/public/app/plugins/panel/graph/specs/graph.test.ts @@ -516,4 +516,68 @@ describe('grafanaGraph', () => { expect(ctx.plotData[0].data[0][1]).toBe(2); }); }); + + describe('when graph is histogram, and xaxis min is set', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.min = 150; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('should not contain values lower than min', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0])) === 200); + expect(Math.max.apply(Math, nonZero.map(t => t[0])) === 300); + }); + }); + + describe('when graph is histogram, and xaxis max is set', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.max = 250; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('should not contain values lower than min', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0])) === 100); + expect(Math.max.apply(Math, nonZero.map(t => t[0])) === 200); + }); + }); + + describe('when graph is histogram, and xaxis min and max are set', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.min = 150; + ctrl.panel.xaxis.max = 250; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('should not contain values lower than min', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0])) === 200); + expect(Math.max.apply(Math, nonZero.map(t => t[0])) === 200); + }); + }); }); From f0d1a9157f79f829d595f9cecdfec494acaf3243 Mon Sep 17 00:00:00 2001 From: Sofia Papagiannaki Date: Fri, 8 Mar 2019 02:30:54 +0200 Subject: [PATCH 2/5] Fix histogram xaxis min/max tests --- public/app/plugins/panel/graph/specs/graph.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/public/app/plugins/panel/graph/specs/graph.test.ts b/public/app/plugins/panel/graph/specs/graph.test.ts index dc1c9c99f04..6ffc0ed7fc3 100644 --- a/public/app/plugins/panel/graph/specs/graph.test.ts +++ b/public/app/plugins/panel/graph/specs/graph.test.ts @@ -533,8 +533,8 @@ describe('grafanaGraph', () => { it('should not contain values lower than min', () => { const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); - expect(Math.min.apply(Math, nonZero.map(t => t[0])) === 200); - expect(Math.max.apply(Math, nonZero.map(t => t[0])) === 300); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(200); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); }); }); @@ -554,8 +554,8 @@ describe('grafanaGraph', () => { it('should not contain values lower than min', () => { const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); - expect(Math.min.apply(Math, nonZero.map(t => t[0])) === 100); - expect(Math.max.apply(Math, nonZero.map(t => t[0])) === 200); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(200); }); }); @@ -576,8 +576,8 @@ describe('grafanaGraph', () => { it('should not contain values lower than min', () => { const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); - expect(Math.min.apply(Math, nonZero.map(t => t[0])) === 200); - expect(Math.max.apply(Math, nonZero.map(t => t[0])) === 200); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(200); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(200); }); }); }); From 96e1804d55750eb1bcbf040089f4b6f0c500b213 Mon Sep 17 00:00:00 2001 From: Sofia Papagiannaki Date: Sat, 9 Mar 2019 12:39:01 +0200 Subject: [PATCH 3/5] Change xaxis min and max form input types to number --- public/app/plugins/panel/graph/axes_editor.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/app/plugins/panel/graph/axes_editor.html b/public/app/plugins/panel/graph/axes_editor.html index 4186111a41c..ced0d8157e9 100644 --- a/public/app/plugins/panel/graph/axes_editor.html +++ b/public/app/plugins/panel/graph/axes_editor.html @@ -70,11 +70,11 @@
- +
- +
From 5ed3139d5abbe12009c1ba4b892e1b08e5759f3c Mon Sep 17 00:00:00 2001 From: Sofia Papagiannaki Date: Sat, 9 Mar 2019 13:35:13 +0200 Subject: [PATCH 4/5] Fix histogram x-axis min/max This commit: *fixes histogram computation when zero x-axis min/max are set (they used to be ignored). *validates the user defined x-axis min/max values and ignores them if they result in invalid bucket sizes. --- public/app/plugins/panel/graph/graph.ts | 12 +- .../plugins/panel/graph/specs/graph.test.ts | 362 +++++++++++++++++- 2 files changed, 361 insertions(+), 13 deletions(-) diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index 98330196ca2..e3eed6fc382 100755 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -337,9 +337,17 @@ class GraphElement { let bucketSize: number; if (this.data.length) { - const histMin = panel.xaxis.min ? panel.xaxis.min : _.min(_.map(this.data, s => s.stats.min)); - const histMax = panel.xaxis.max ? panel.xaxis.max : _.max(_.map(this.data, s => s.stats.max)); + let histMin = _.min(_.map(this.data, s => s.stats.min)); + let histMax = _.max(_.map(this.data, s => s.stats.max)); const ticks = panel.xaxis.buckets || this.panelWidth / 50; + if (panel.xaxis.min != null) { + const isInvalidXaxisMin = tickStep(panel.xaxis.min, histMax, ticks) <= 0; + histMin = isInvalidXaxisMin ? histMin : panel.xaxis.min; + } + if (panel.xaxis.max != null) { + const isInvalidXaxisMax = tickStep(histMin, panel.xaxis.max, ticks) <= 0; + histMax = isInvalidXaxisMax ? histMax : panel.xaxis.max; + } bucketSize = tickStep(histMin, histMax, ticks); options.series.bars.barWidth = bucketSize * 0.8; this.data = convertToHistogramData(this.data, bucketSize, this.ctrl.hiddenSeries, histMin, histMax); diff --git a/public/app/plugins/panel/graph/specs/graph.test.ts b/public/app/plugins/panel/graph/specs/graph.test.ts index 6ffc0ed7fc3..ff81a8ae6eb 100644 --- a/public/app/plugins/panel/graph/specs/graph.test.ts +++ b/public/app/plugins/panel/graph/specs/graph.test.ts @@ -532,9 +532,72 @@ describe('grafanaGraph', () => { }); it('should not contain values lower than min', () => { - const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); - expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(200); - expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(200); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); + }); + }); + + describe('when graph is histogram, and xaxis min is zero', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.min = 0; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[-100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('should not contain values lower than zero', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); + }); + }); + + describe('when graph is histogram, and xaxis min is null', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.min = null; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[-100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('xaxis min should not affect the histogram', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(-100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); + }); + }); + + describe('when graph is histogram, and xaxis min is undefined', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.min = undefined; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[-100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('xaxis min should not affect the histogram', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(-100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); }); }); @@ -552,10 +615,73 @@ describe('grafanaGraph', () => { }); }); - it('should not contain values lower than min', () => { - const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); - expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(100); - expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(200); + it('should not contain values greater than max', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(200); + }); + }); + + describe('when graph is histogram, and xaxis max is zero', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.max = 0; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[-100, 1], [100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('should not contain values greater than zero', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(-100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(-100); + }); + }); + + describe('when graph is histogram, and xaxis max is null', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.max = null; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[-100, 1], [100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('xaxis max should not affect the histogram', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(-100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); + }); + }); + + describe('when graph is histogram, and xaxis max is undefined', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.max = undefined; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[-100, 1], [100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('xaxis max should not should node affect the histogram', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(-100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); }); }); @@ -574,10 +700,224 @@ describe('grafanaGraph', () => { }); }); - it('should not contain values lower than min', () => { - const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); - expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(200); - expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(200); + it('should not contain values lower than min and greater than max', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(200); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(200); + }); + }); + + describe('when graph is histogram, and xaxis min and max are zero', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.min = 0; + ctrl.panel.xaxis.max = 0; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[-100, 1], [100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('xaxis max should be ignored otherwise the bucketSize is zero', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); + }); + }); + + describe('when graph is histogram, and xaxis min and max are null', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.min = null; + ctrl.panel.xaxis.max = null; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('xaxis min and max should not affect the histogram', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); + }); + }); + + describe('when graph is histogram, and xaxis min and max are undefined', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.min = undefined; + ctrl.panel.xaxis.max = undefined; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('xaxis min and max should not affect the histogram', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); + }); + }); + + describe('when graph is histogram, and xaxis min is greater than xaxis max', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.min = 150; + ctrl.panel.xaxis.max = 100; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('xaxis max should be ignored otherwise the bucketSize is negative', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(200); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); + }); + }); + + // aaa + describe('when graph is histogram, and xaxis min is greater than the maximum value', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.min = 301; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('xaxis min should be ignored otherwise the bucketSize is negative', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); + }); + }); + + describe('when graph is histogram, and xaxis min is equal to the maximum value', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.min = 300; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('xaxis min should be ignored otherwise the bucketSize is zero', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); + }); + }); + + describe('when graph is histogram, and xaxis min is lower than the minimum value', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.min = 99; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('xaxis min should not affect the histogram', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); + }); + }); + + describe('when graph is histogram, and xaxis max is equal to the minimum value', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.max = 100; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('should calculate correct histogram', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(100); + }); + }); + + describe('when graph is histogram, and xaxis max is a lower than the minimum value', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.max = 99; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('should calculate empty histogram', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(nonZero.length).toBe(0); + }); + }); + + describe('when graph is histogram, and xaxis max is greater than the maximum value', () => { + beforeEach(() => { + setupCtx(() => { + ctrl.panel.xaxis.mode = 'histogram'; + ctrl.panel.xaxis.max = 301; + ctrl.panel.stack = false; + ctrl.hiddenSeries = {}; + ctx.data[0] = new TimeSeries({ + datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]], + alias: 'series1', + }); + }); + }); + + it('should calculate correct histogram', () => { + const nonZero = ctx.plotData[0].data.filter(t => t[1] > 0); + expect(Math.min.apply(Math, nonZero.map(t => t[0]))).toBe(100); + expect(Math.max.apply(Math, nonZero.map(t => t[0]))).toBe(300); }); }); }); From 4cf698af102bdd483a4288dd8dc9edee63a988bb Mon Sep 17 00:00:00 2001 From: Sofia Papagiannaki Date: Sat, 9 Mar 2019 13:38:57 +0200 Subject: [PATCH 5/5] Minor fix in values to histogram conversion Filter out values outside the min and max boundaries because they are assigned to uninitialized buckets (outside min and max bounds). --- public/app/plugins/panel/graph/histogram.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/app/plugins/panel/graph/histogram.ts b/public/app/plugins/panel/graph/histogram.ts index b09226d15e7..b5c478198c0 100644 --- a/public/app/plugins/panel/graph/histogram.ts +++ b/public/app/plugins/panel/graph/histogram.ts @@ -43,6 +43,10 @@ export function convertValuesToHistogram(values: number[], bucketSize: number, m } for (let i = 0; i < values.length; i++) { + // filter out values outside the min and max boundaries + if (values[i] < min || values[i] > max) { + continue; + } const bound = getBucketBound(values[i], bucketSize); histogram[bound] = histogram[bound] + 1; }