Skip to content

Commit

Permalink
Feature: Flexible Y-Min and Y-Max settings.
Browse files Browse the repository at this point in the history
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
  <X Y-Max/Y-Min is auto if data is below X else X
  =X Y-Max/Y-Min is scaled to current value +/- X
  ~X Y-Max/Y-Min is caled to average value +/- X

Example: Y-Min: <100 Y-Max: >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
  • Loading branch information
thoj committed Aug 12, 2016
1 parent 2fa9742 commit 839b320
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 2 deletions.
41 changes: 41 additions & 0 deletions public/app/plugins/panel/graph/graph.js
Expand Up @@ -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',
Expand All @@ -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})) {
Expand All @@ -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);
Expand Down
63 changes: 63 additions & 0 deletions public/app/plugins/panel/graph/specs/graph_specs.ts
Expand Up @@ -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);
});
});
});
});
4 changes: 2 additions & 2 deletions public/app/plugins/panel/graph/tab_axes.html
Expand Up @@ -22,11 +22,11 @@ <h5 class="section-heading" ng-show="$index === 1">Right Y</h5>
<div class="gf-form-inline">
<div class="gf-form max-width-10">
<label class="gf-form-label width-5">Y-Min</label>
<input type="number" class="gf-form-input" placeholder="auto" empty-to-null ng-model="yaxis.min" ng-change="ctrl.render()" ng-model-onblur>
<input type="text" class="gf-form-input" placeholder="auto" empty-to-null ng-model="yaxis.min" ng-change="ctrl.render()" ng-model-onblur>
</div>
<div class="gf-form max-width-10">
<label class="gf-form-label width-5">Y-Max</label>
<input type="number" class="gf-form-input" placeholder="auto" empty-to-null ng-model="yaxis.max" ng-change="ctrl.render()" ng-model-onblur>
<input type="text" class="gf-form-input" placeholder="auto" empty-to-null ng-model="yaxis.max" ng-change="ctrl.render()" ng-model-onblur>
</div>
</div>

Expand Down

0 comments on commit 839b320

Please sign in to comment.