Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: flexible Y-Min and Y-Max settings #6051

Merged
merged 5 commits into from Sep 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
71 changes: 71 additions & 0 deletions public/app/plugins/panel/graph/graph.js
Expand Up @@ -339,6 +339,75 @@ function (angular, $, moment, _, kbn, GraphTooltip, thresholdManExports) {
};
}

//Override min/max to provide more flexible autoscaling
function autoscaleSpanOverride(yaxis, data, options) {
var expr;
if (yaxis.min != null && data != null) {
expr = parseThresholdExpr(yaxis.min);
options.min = autoscaleYAxisMin(expr, data.stats);
}
if (yaxis.max != null && data != null) {
expr = parseThresholdExpr(yaxis.max);
options.max = autoscaleYAxisMax(expr, data.stats);
}
}

function parseThresholdExpr(expr) {
var match, operator, value, precision;
match = expr.match(/\s*([<=>~]*)\W*(\d+(\.\d+)?)/);
if (match) {
operator = match[1];
value = parseFloat(match[2]);
//Precision based on input
precision = match[3] ? match[3].length - 1 : 0;
return {
operator: operator,
value: value,
precision: precision
};
} else {
return undefined;
}
}

function autoscaleYAxisMax(expr, dataStats) {
var operator = expr.operator,
value = expr.value,
precision = expr.precision;
if (operator === ">") {
return dataStats.max < value ? value : null;
} else if (operator === "<") {
return dataStats.max > value ? value : null;
} else if (operator === "~") {
return kbn.roundValue(dataStats.avg + value, precision);
} else if (operator === "=") {
return kbn.roundValue(dataStats.current + value, precision);
} else if (!operator && !isNaN(value)) {
return kbn.roundValue(value, precision);
} else {
return null;
}
}

function autoscaleYAxisMin(expr, dataStats) {
var operator = expr.operator,
value = expr.value,
precision = expr.precision;
if (operator === ">") {
return dataStats.min < value ? value : null;
} else if (operator === "<") {
return dataStats.min > value ? value : null;
} else if (operator === "~") {
return kbn.roundValue(dataStats.avg - value, precision);
} else if (operator === "=") {
return kbn.roundValue(dataStats.current - value, precision);
} else if (!operator && !isNaN(value)) {
return kbn.roundValue(value, precision);
} else {
return null;
}
}

function configureAxisOptions(data, options) {
var defaults = {
position: 'left',
Expand All @@ -349,6 +418,7 @@ function (angular, $, moment, _, kbn, GraphTooltip, thresholdManExports) {
max: panel.percentage && panel.stack ? 100 : panel.yaxes[0].max,
};

autoscaleSpanOverride(panel.yaxes[0], data[0], defaults);
options.yaxes.push(defaults);

if (_.find(data, {yaxis: 2})) {
Expand All @@ -359,6 +429,7 @@ function (angular, $, moment, _, kbn, GraphTooltip, thresholdManExports) {
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
95 changes: 95 additions & 0 deletions public/app/plugins/panel/graph/specs/graph_specs.ts
Expand Up @@ -218,4 +218,99 @@ 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);
});
});
});
graphScenario('when using regular Y-Min and Y-Max settings', function(ctx) {
describe('and Y-Min is 100 and Y-Max is 200', 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 0 and Y-Max is 0', function() {
ctx.setup(function(ctrl, data) {
ctrl.panel.yaxes[0].min = '0';
ctrl.panel.yaxes[0].max = '0';
data[0] = new TimeSeries({
datapoints: [[120,10],[160,20]],
alias: 'series1',
});
});

it('should set min to 0 and max to 0', function() {
expect(ctx.plotOptions.yaxes[0].min).to.be(0);
expect(ctx.plotOptions.yaxes[0].max).to.be(0);
});
});
});
});
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