mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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
This commit is contained in:
parent
1efdd92ae8
commit
1b79e17970
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user