Commit 1b79e179 by Daniel Lee

graph: better generation of y-axis ticks for log-scale

If there are too many ticks generated for the y-axis (which can occur
for log scale 2, with a small y-min and a large max), then the ticks
will be regenerated using larger jumps between the ticks.

This also handles the case when y-min is set to 0. Previously, y-min of
0 was ignored as zero is not a valid value for log scale. Now the tick
generator approximates zero by setting min to 0.1.

Ref #8244

Ref #8516
parent 1efdd92a
......@@ -506,6 +506,8 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
return;
}
const minSetToZero = axis.min === 0;
if (axis.min < Number.MIN_VALUE) {
axis.min = null;
}
......@@ -556,10 +558,17 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
}
if (Number.isFinite(min) && Number.isFinite(max)) {
axis.ticks = [];
var nextTick;
for (nextTick = min; nextTick <= max; nextTick *= axis.logBase) {
axis.ticks.push(nextTick);
if (minSetToZero) {
axis.min = 0.1;
min = 1;
}
axis.ticks = generateTicksForLogScaleYAxis(min, max, axis.logBase);
if (minSetToZero) {
axis.ticks.unshift(0.1);
}
if (axis.ticks[axis.ticks.length - 1] > axis.max) {
axis.max = axis.ticks[axis.ticks.length - 1];
}
axis.tickDecimals = decimalPlaces(min);
} else {
......@@ -567,7 +576,28 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
delete axis.min;
delete axis.max;
}
}
function generateTicksForLogScaleYAxis(min, max, logBase) {
let ticks = [];
var nextTick;
for (nextTick = min; nextTick <= max; nextTick *= logBase) {
ticks.push(nextTick);
}
const maxNumTicks = Math.ceil(ctrl.height/25);
const numTicks = ticks.length;
if (numTicks > maxNumTicks) {
const factor = Math.ceil(numTicks/maxNumTicks) * logBase;
ticks = [];
for (nextTick = min; nextTick <= (max * factor); nextTick *= factor) {
ticks.push(nextTick);
}
}
return ticks;
}
function decimalPlaces(num) {
......
......@@ -176,6 +176,60 @@ describe('grafanaGraph', function() {
});
});
// y-min set 0 is a special case for log scale,
// this approximates it by setting min to 0.1
graphScenario('when logBase is log 10 and y-min is set to 0 and auto min is > 0.1', function(ctx) {
ctx.setup(function(ctrl, data) {
ctrl.panel.yaxes[0].logBase = 10;
ctrl.panel.yaxes[0].min = '0';
data[0] = new TimeSeries({
datapoints: [[2000,1],[4 ,2],[500,3],[3000,4]],
alias: 'seriesAutoscale',
});
data[0].yaxis = 1;
});
it('should set min to 0.1 and add a tick for 0.1 and tickDecimals to be 0', function() {
var axisAutoscale = ctx.plotOptions.yaxes[0];
expect(axisAutoscale.transform(100)).to.be(2);
expect(axisAutoscale.inverseTransform(-3)).to.be(0.001);
expect(axisAutoscale.min).to.be(0.1);
expect(axisAutoscale.max).to.be(10000);
expect(axisAutoscale.ticks.length).to.be(6);
expect(axisAutoscale.ticks[0]).to.be(0.1);
expect(axisAutoscale.ticks[5]).to.be(10000);
expect(axisAutoscale.tickDecimals).to.be(0);
});
});
graphScenario('when logBase is log 2 and y-min is set to 0 and num of ticks exceeds max', function(ctx) {
ctx.setup(function(ctrl, data) {
const heightForApprox5Ticks = 125;
ctrl.height = heightForApprox5Ticks;
ctrl.panel.yaxes[0].logBase = 2;
ctrl.panel.yaxes[0].min = '0';
data[0] = new TimeSeries({
datapoints: [[2000,1],[4 ,2],[500,3],[3000,4], [10000,5], [100000,6]],
alias: 'seriesAutoscale',
});
data[0].yaxis = 1;
});
it('should regenerate ticks so that if fits on the y-axis', function() {
var axisAutoscale = ctx.plotOptions.yaxes[0];
expect(axisAutoscale.min).to.be(0.1);
expect(axisAutoscale.ticks.length).to.be(8);
expect(axisAutoscale.ticks[0]).to.be(0.1);
expect(axisAutoscale.ticks[7]).to.be(262144);
expect(axisAutoscale.max).to.be(262144);
expect(axisAutoscale.tickDecimals).to.be(0);
});
it('should set axis max to be max tick value', function() {
expect(ctx.plotOptions.yaxes[0].max).to.be(262144);
});
});
graphScenario('dashed lines options', function(ctx) {
ctx.setup(function(ctrl) {
ctrl.panel.lines = true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment