From 839b320fef75ea093b1d10c1a0a4cdabd8669d31 Mon Sep 17 00:00:00 2001 From: Thomas Jager Date: Thu, 11 Aug 2016 15:02:45 +0200 Subject: [PATCH] Feature: Flexible Y-Min and Y-Max settings. Y-Min and Y-Max is now string. New usage for both Y-Min and Y-Max (Where X is a real number): >X Y-Max/Y-Max is auto if data is above X else X 200 If all points are within 100 and 200: Y-Min is 100 and Y-Max is 200 If some points are above 200: Y-Min is 100 and Y-Max is auto If some points are below 100: Y-Min is auto and Y-Max is 200 if some points are below 100 and above 200: Y-Min and Y-Max is auto Tests for new settings added --- public/app/plugins/panel/graph/graph.js | 41 ++++++++++++ .../plugins/panel/graph/specs/graph_specs.ts | 63 +++++++++++++++++++ public/app/plugins/panel/graph/tab_axes.html | 4 +- 3 files changed, 106 insertions(+), 2 deletions(-) diff --git a/public/app/plugins/panel/graph/graph.js b/public/app/plugins/panel/graph/graph.js index 0a6a2bc0e456..e8cf4e4dc250 100755 --- a/public/app/plugins/panel/graph/graph.js +++ b/public/app/plugins/panel/graph/graph.js @@ -352,6 +352,45 @@ function (angular, $, moment, _, kbn, GraphTooltip) { }; } + //Override min/max to provide more flexible autoscaling + function autoscaleSpanOverride(yaxis, data, options) { + var m, op, num, precision; + if (yaxis.min != null && data != null) { + m = yaxis.min.match(/([<=>~]*)\W*(\d+(\.\d+)?)/); + if (m != null) { + op = m[1]; + num = m[2]*1; + precision = m[3] == null ? 0 : m[3].length - 1; //Precision based on input + if (op === ">") { + options.min = data.stats.min < num ? num : null; + } else if (op === "<") { + options.min = data.stats.min > num ? num : null; + } else if (op === "~") { + options.min = kbn.roundValue(data.stats.avg - num, precision); + } else if (op === "=") { + options.min = kbn.roundValue(data.stats.current - num, precision); + } + } + } + if (yaxis.max != null && data != null) { + m = yaxis.max.match(/([<=>~]*)\W*(\d+(\.\d+)?)/); + if (m != null) { + op = m[1]; + num = m[2]*1; + precision = m[3] == null ? 0 : m[3].length - 1; //Precision based on input + if (op === ">") { + options.max = data.stats.max < num ? num : null; + } else if (op === "<") { + options.max = data.stats.max > num ? num : null; + } else if (op === "~") { + options.max = kbn.roundValue(data.stats.avg + num, precision); + } else if (op === "=") { + options.max = kbn.roundValue(data.stats.current + num, precision); + } + } + } + } + function configureAxisOptions(data, options) { var defaults = { position: 'left', @@ -362,6 +401,7 @@ function (angular, $, moment, _, kbn, GraphTooltip) { max: panel.percentage && panel.stack ? 100 : panel.yaxes[0].max, }; + autoscaleSpanOverride(panel.yaxes[0], data[0], defaults); options.yaxes.push(defaults); if (_.findWhere(data, {yaxis: 2})) { @@ -372,6 +412,7 @@ function (angular, $, moment, _, kbn, GraphTooltip) { secondY.position = 'right'; secondY.min = panel.yaxes[1].min; secondY.max = panel.percentage && panel.stack ? 100 : panel.yaxes[1].max; + autoscaleSpanOverride(panel.yaxes[1], data[1], secondY); options.yaxes.push(secondY); applyLogScale(options.yaxes[1], data); diff --git a/public/app/plugins/panel/graph/specs/graph_specs.ts b/public/app/plugins/panel/graph/specs/graph_specs.ts index b9c9362e5de4..6cb51cac90c8 100644 --- a/public/app/plugins/panel/graph/specs/graph_specs.ts +++ b/public/app/plugins/panel/graph/specs/graph_specs.ts @@ -271,4 +271,67 @@ describe('grafanaGraph', function() { }); }, 10); + + graphScenario('when using flexible Y-Min and Y-Max settings', function(ctx) { + describe('and Y-Min is <100 and Y-Max is >200 and values within range', function() { + ctx.setup(function(ctrl, data) { + ctrl.panel.yaxes[0].min = '<100'; + ctrl.panel.yaxes[0].max = '>200'; + data[0] = new TimeSeries({ + datapoints: [[120,10],[160,20]], + alias: 'series1', + }); + }); + + it('should set min to 100 and max to 200', function() { + expect(ctx.plotOptions.yaxes[0].min).to.be(100); + expect(ctx.plotOptions.yaxes[0].max).to.be(200); + }); + }); + describe('and Y-Min is <100 and Y-Max is >200 and values outside range', function() { + ctx.setup(function(ctrl, data) { + ctrl.panel.yaxes[0].min = '<100'; + ctrl.panel.yaxes[0].max = '>200'; + data[0] = new TimeSeries({ + datapoints: [[99,10],[201,20]], + alias: 'series1', + }); + }); + + it('should set min to auto and max to auto', function() { + expect(ctx.plotOptions.yaxes[0].min).to.be(null); + expect(ctx.plotOptions.yaxes[0].max).to.be(null); + }); + }); + describe('and Y-Min is =10.5 and Y-Max is =10.5', function() { + ctx.setup(function(ctrl, data) { + ctrl.panel.yaxes[0].min = '=10.5'; + ctrl.panel.yaxes[0].max = '=10.5'; + data[0] = new TimeSeries({ + datapoints: [[100,10],[120,20], [110,30]], + alias: 'series1', + }); + }); + + it('should set min to last value + 10.5 and max to last value + 10.5', function() { + expect(ctx.plotOptions.yaxes[0].min).to.be(99.5); + expect(ctx.plotOptions.yaxes[0].max).to.be(120.5); + }); + }); + describe('and Y-Min is ~10.5 and Y-Max is ~10.5', function() { + ctx.setup(function(ctrl, data) { + ctrl.panel.yaxes[0].min = '~10.5'; + ctrl.panel.yaxes[0].max = '~10.5'; + data[0] = new TimeSeries({ + datapoints: [[102,10],[104,20], [110,30]], //Also checks precision + alias: 'series1', + }); + }); + + it('should set min to average value + 10.5 and max to average value + 10.5', function() { + expect(ctx.plotOptions.yaxes[0].min).to.be(94.8); + expect(ctx.plotOptions.yaxes[0].max).to.be(115.8); + }); + }); + }); }); diff --git a/public/app/plugins/panel/graph/tab_axes.html b/public/app/plugins/panel/graph/tab_axes.html index eeaf27aff78a..5723e666d051 100644 --- a/public/app/plugins/panel/graph/tab_axes.html +++ b/public/app/plugins/panel/graph/tab_axes.html @@ -22,11 +22,11 @@
Right Y
- +
- +