Browse Source

Merge branch 'bigbenhur-autologscale'

Closes #5278 and closes #3090
Daniel Lee 8 years ago
parent
commit
84ef6b9d48

+ 6 - 0
public/app/core/time_series2.ts

@@ -100,6 +100,7 @@ export default class TimeSeries {
     this.stats.total = 0;
     this.stats.max = -Number.MAX_VALUE;
     this.stats.min = Number.MAX_VALUE;
+    this.stats.logmin = Number.MAX_VALUE;
     this.stats.avg = null;
     this.stats.current = null;
     this.stats.first = null;
@@ -172,6 +173,11 @@ export default class TimeSeries {
           }
         }
         previousValue = currentValue;
+
+        if (currentValue < this.stats.logmin && currentValue > 0) {
+          this.stats.logmin = currentValue;
+        }
+
       }
 
       if (currentValue !== 0) {

+ 54 - 28
public/app/plugins/panel/graph/graph.ts

@@ -460,7 +460,8 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) {
           show: panel.yaxes[0].show,
           index: 1,
           logBase: panel.yaxes[0].logBase || 1,
-          max: null
+          min: panel.yaxes[0].min ? _.toNumber(panel.yaxes[0].min) : null,
+          max: panel.yaxes[0].max ? _.toNumber(panel.yaxes[0].max) : null,
         };
 
         options.yaxes.push(defaults);
@@ -471,12 +472,13 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) {
           secondY.show = panel.yaxes[1].show;
           secondY.logBase = panel.yaxes[1].logBase || 1;
           secondY.position = 'right';
+          secondY.min = panel.yaxes[1].min ? _.toNumber(panel.yaxes[1].min) : null;
+          secondY.max = panel.yaxes[1].max ? _.toNumber(panel.yaxes[1].max) : null;
           options.yaxes.push(secondY);
 
           applyLogScale(options.yaxes[1], data);
           configureAxisMode(options.yaxes[1], panel.percentage && panel.stack ? "percent" : panel.yaxes[1].format);
         }
-
         applyLogScale(options.yaxes[0], data);
         configureAxisMode(options.yaxes[0], panel.percentage && panel.stack ? "percent" : panel.yaxes[0].format);
       }
@@ -485,43 +487,67 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) {
         if (axis.logBase === 1) {
           return;
         }
+        if (axis.min < Number.MIN_VALUE) {
+          axis.min = null;
+        }
+        if (axis.max < Number.MIN_VALUE) {
+          axis.max = null;
+        }
 
         var series, i;
-        var max = axis.max;
-
-        if (max === null) {
-          for (i = 0; i < data.length; i++) {
-            series = data[i];
-            if (series.yaxis === axis.index) {
-              if (max < series.stats.max) {
-                max = series.stats.max;
-              }
+        var max = axis.max, min = axis.min;
+
+        for (i = 0; i < data.length; i++) {
+          series = data[i];
+          if (series.yaxis === axis.index) {
+            if (!max || max < series.stats.max) {
+              max = series.stats.max;
+            }
+            if (!min || min > series.stats.logmin) {
+              min = series.stats.logmin;
             }
-          }
-          if (max === void 0) {
-            max = Number.MAX_VALUE;
           }
         }
 
-        axis.min = axis.min !== null ? axis.min : 0;
-        axis.ticks = [0, 1];
-        var nextTick = 1;
+        axis.transform = function(v) { return (v < Number.MIN_VALUE) ? null : Math.log(v) / Math.log(axis.logBase); };
+        axis.inverseTransform  = function (v) { return Math.pow(axis.logBase,v); };
 
-        while (true) {
-          nextTick = nextTick * axis.logBase;
-          axis.ticks.push(nextTick);
-          if (nextTick > max) {
-            break;
-          }
+        if (!max && !min) {
+          max = axis.inverseTransform(+2);
+          min = axis.inverseTransform(-2);
+        } else if (!max) {
+          max = min*axis.inverseTransform(+4);
+        } else if (!min) {
+          min = max*axis.inverseTransform(-4);
         }
 
-        if (axis.logBase === 10) {
-          axis.transform = function(v) { return Math.log(v+0.1); };
-          axis.inverseTransform  = function (v) { return Math.pow(10,v); };
+        if (axis.min) {
+          min = axis.inverseTransform(Math.ceil(axis.transform(axis.min)));
+        } else {
+          min = axis.min = axis.inverseTransform(Math.floor(axis.transform(min)));
+        }
+        if (axis.max) {
+          max = axis.inverseTransform(Math.floor(axis.transform(axis.max)));
         } else {
-          axis.transform = function(v) { return Math.log(v+0.1) / Math.log(axis.logBase); };
-          axis.inverseTransform  = function (v) { return Math.pow(axis.logBase,v); };
+          max = axis.max = axis.inverseTransform(Math.ceil(axis.transform(max)));
+        }
+
+        if (!min || min < Number.MIN_VALUE || !max || max < Number.MIN_VALUE) {
+          return;
+        }
+
+        axis.ticks = [];
+        var nextTick;
+        for (nextTick = min; nextTick <= max; nextTick *= axis.logBase) {
+          axis.ticks.push(nextTick);
         }
+        axis.tickDecimals = decimalPlaces(min);
+      }
+
+      function decimalPlaces(num) {
+        if (!num) { return 0; }
+
+        return (num.toString().split('.')[1] || []).length;
       }
 
       function configureAxisMode(axis, format) {

+ 34 - 6
public/app/plugins/panel/graph/specs/graph_specs.ts

@@ -113,15 +113,43 @@ describe('grafanaGraph', function() {
   });
 
   graphScenario('when logBase is log 10', function(ctx) {
-    ctx.setup(function(ctrl) {
+    ctx.setup(function(ctrl, data) {
       ctrl.panel.yaxes[0].logBase = 10;
+      data[0] = new TimeSeries({
+        datapoints: [[2000,1],[0.002,2],[0,3],[-1,4]],
+        alias: 'seriesAutoscale',
+      });
+      data[0].yaxis = 1;
+      ctrl.panel.yaxes[1].logBase = 10;
+      ctrl.panel.yaxes[1].min = '0.05';
+      ctrl.panel.yaxes[1].max = '1500';
+      data[1] = new TimeSeries({
+        datapoints: [[2000,1],[0.002,2],[0,3],[-1,4]],
+        alias: 'seriesFixedscale',
+      });
+      data[1].yaxis = 2;
     });
 
-    it('should apply axis transform and ticks', function() {
-      var axis = ctx.plotOptions.yaxes[0];
-      expect(axis.transform(100)).to.be(Math.log(100+0.1));
-      expect(axis.ticks[0]).to.be(0);
-      expect(axis.ticks[1]).to.be(1);
+    it('should apply axis transform, autoscaling (if necessary) and ticks', 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.001);
+      expect(axisAutoscale.max).to.be(10000);
+      expect(axisAutoscale.ticks.length).to.be(8);
+      expect(axisAutoscale.ticks[0]).to.be(0.001);
+      expect(axisAutoscale.ticks[7]).to.be(10000);
+      expect(axisAutoscale.tickDecimals).to.be(3);
+
+
+      var axisFixedscale = ctx.plotOptions.yaxes[1];
+      expect(axisFixedscale.min).to.be(0.05);
+      expect(axisFixedscale.max).to.be(1500);
+      expect(axisFixedscale.ticks.length).to.be(5);
+      expect(axisFixedscale.ticks[0]).to.be(0.1);
+      expect(axisFixedscale.ticks[4]).to.be(1000);
+      expect(axisFixedscale.tickDecimals).to.be(1);
+
     });
   });