Просмотр исходного кода

Smart decimal precision when using scaled unit format, Closes #877

Torkel Ödegaard 11 лет назад
Родитель
Сommit
cc31a12b8c

+ 44 - 209
src/app/components/kbn.js

@@ -7,7 +7,7 @@ function($, _, moment) {
   'use strict';
 
   var kbn = {};
-  kbn.formatFunctions = {};
+  kbn.valueFormats = {};
 
   kbn.round_interval = function(interval) {
     switch (true) {
@@ -310,192 +310,24 @@ function($, _, moment) {
     ].join(';') + '"></div>';
   };
 
-  kbn.byteFormat = function(size, decimals) {
-    var ext, steps = 0;
-
-    if(_.isUndefined(decimals)) {
-      decimals = 2;
-    } else if (decimals === 0) {
-      decimals = undefined;
-    }
-
-    while (Math.abs(size) >= 1024) {
-      steps++;
-      size /= 1024;
-    }
-
-    switch (steps) {
-    case 0:
-      ext = " B";
-      break;
-    case 1:
-      ext = " KiB";
-      break;
-    case 2:
-      ext = " MiB";
-      break;
-    case 3:
-      ext = " GiB";
-      break;
-    case 4:
-      ext = " TiB";
-      break;
-    case 5:
-      ext = " PiB";
-      break;
-    case 6:
-      ext = " EiB";
-      break;
-    case 7:
-      ext = " ZiB";
-      break;
-    case 8:
-      ext = " YiB";
-      break;
-    }
-
-    return (size.toFixed(decimals) + ext);
+  kbn.valueFormats.percent = function(size, decimals) {
+    return kbn.toFixed(size, decimals) + '%';
   };
 
-  kbn.bitFormat = function(size, decimals) {
-    var ext, steps = 0;
-
-    if(_.isUndefined(decimals)) {
-      decimals = 2;
-    } else if (decimals === 0) {
-      decimals = undefined;
-    }
-
-    while (Math.abs(size) >= 1024) {
-      steps++;
-      size /= 1024;
-    }
-
-    switch (steps) {
-    case 0:
-      ext = " b";
-      break;
-    case 1:
-      ext = " Kib";
-      break;
-    case 2:
-      ext = " Mib";
-      break;
-    case 3:
-      ext = " Gib";
-      break;
-    case 4:
-      ext = " Tib";
-      break;
-    case 5:
-      ext = " Pib";
-      break;
-    case 6:
-      ext = " Eib";
-      break;
-    case 7:
-      ext = " Zib";
-      break;
-    case 8:
-      ext = " Yib";
-      break;
-    }
-
-    return (size.toFixed(decimals) + ext);
-  };
+  kbn.formatFuncCreator = function(factor, extArray) {
+    return function(size, decimals, scaledDecimals) {
+      var steps = 0;
 
-  kbn.bpsFormat = function(size, decimals) {
-    var ext, steps = 0;
-
-    if(_.isUndefined(decimals)) {
-      decimals = 2;
-    } else if (decimals === 0) {
-      decimals = undefined;
-    }
-
-    while (Math.abs(size) >= 1000) {
-      steps++;
-      size /= 1000;
-    }
-
-    switch (steps) {
-    case 0:
-      ext = " bps";
-      break;
-    case 1:
-      ext = " Kbps";
-      break;
-    case 2:
-      ext = " Mbps";
-      break;
-    case 3:
-      ext = " Gbps";
-      break;
-    case 4:
-      ext = " Tbps";
-      break;
-    case 5:
-      ext = " Pbps";
-      break;
-    case 6:
-      ext = " Ebps";
-      break;
-    case 7:
-      ext = " Zbps";
-      break;
-    case 8:
-      ext = " Ybps";
-      break;
-    }
-
-    return (size.toFixed(decimals) + ext);
-  };
+      while (Math.abs(size) >= factor) {
+        steps++;
+        size /= factor;
+      }
+      if (steps > 0) {
+        decimals = scaledDecimals + (3 * steps);
+      }
 
-  kbn.shortFormat = function(size, decimals) {
-    var ext, steps = 0;
-
-    if(_.isUndefined(decimals)) {
-      decimals = 2;
-    } else if (decimals === 0) {
-      decimals = undefined;
-    }
-
-    while (Math.abs(size) >= 1000) {
-      steps++;
-      size /= 1000;
-    }
-
-    switch (steps) {
-    case 0:
-      ext = "";
-      break;
-    case 1:
-      ext = " K";
-      break;
-    case 2:
-      ext = " Mil";
-      break;
-    case 3:
-      ext = " Bil";
-      break;
-    case 4:
-      ext = " Tri";
-      break;
-    case 5:
-      ext = " Quadr";
-      break;
-    case 6:
-      ext = " Quint";
-      break;
-    case 7:
-      ext = " Sext";
-      break;
-    case 8:
-      ext = " Sept";
-      break;
-    }
-
-    return (size.toFixed(decimals) + ext);
+      return kbn.toFixed(size, decimals) + extArray[steps];
+    };
   };
 
   kbn.toFixed = function(value, decimals) {
@@ -520,84 +352,87 @@ function($, _, moment) {
     return formatted;
   };
 
-  kbn.formatFunctions.ms = function(size, decimals) {
+  kbn.valueFormats.bits = kbn.formatFuncCreator(1024, [' b', ' Kib', ' Mib', ' Gib', ' Tib', ' Pib', ' Eib', ' Zib', ' Yib']);
+  kbn.valueFormats.bytes = kbn.formatFuncCreator(1024, [' B', ' KiB', ' MiB', ' GiB', ' TiB', ' PiB', ' EiB', ' ZiB', ' YiB']);
+  kbn.valueFormats.bps = kbn.formatFuncCreator(1000, [' bps', ' Kbps', ' Mbps', ' Gbps', ' Tbps', ' Pbps', ' Ebps', ' Zbps', ' Ybps']);
+  kbn.valueFormats.short = kbn.formatFuncCreator(1000, ['', ' K', ' Mil', ' Bil', ' Tri', ' Qaudr', ' Quint', ' Sext', ' Sept']);
+  kbn.valueFormats.none = kbn.toFixed;
+
+  kbn.valueFormats.ms = function(size, decimals, scaledDecimals) {
     if (Math.abs(size) < 1000) {
       return kbn.toFixed(size, decimals) + " ms";
     }
     // Less than 1 min
     else if (Math.abs(size) < 60000) {
-      return kbn.toFixed(size / 1000, decimals) + " s";
+      return kbn.toFixed(size / 1000, scaledDecimals + 3) + " s";
     }
     // Less than 1 hour, devide in minutes
     else if (Math.abs(size) < 3600000) {
-      return (size / 60000).toFixed(decimals) + " min";
+      return kbn.toFixed(size / 60000, scaledDecimals + 5) + " min";
     }
     // Less than one day, devide in hours
     else if (Math.abs(size) < 86400000) {
-      return (size / 3600000).toFixed(decimals) + " hour";
+      return kbn.toFixed(size / 3600000, scaledDecimals + 7) + " hour";
     }
     // Less than one year, devide in days
     else if (Math.abs(size) < 31536000000) {
-      return (size / 86400000).toFixed(decimals) + " day";
+      return kbn.toFixed(size / 86400000, scaledDecimals + 8) + " day";
     }
 
-    return (size / 31536000000).toFixed(decimals) + " year";
+    return kbn.toFixed(size / 31536000000, scaledDecimals + 10) + " year";
   };
 
-  kbn.sFormat = function(size, decimals) {
+  kbn.valueFormats.s = function(size, decimals, scaledDecimals) {
     if (Math.abs(size) < 600) {
-      return size.toFixed(decimals) + " s";
+      return kbn.toFixed(size, decimals) + " s";
     }
     // Less than 1 hour, devide in minutes
     else if (Math.abs(size) < 3600) {
-      return (size / 60).toFixed(decimals) + " min";
+      return kbn.toFixed(size / 60, scaledDecimals + 1) + " min";
     }
     // Less than one day, devide in hours
     else if (Math.abs(size) < 86400) {
-      return (size / 3600).toFixed(decimals) + " hour";
+      return kbn.toFixed(size / 3600, scaledDecimals + 4) + " hour";
     }
     // Less than one week, devide in days
     else if (Math.abs(size) < 604800) {
-      return (size / 86400).toFixed(decimals) + " day";
+      return kbn.toFixed(size / 86400, scaledDecimals + 5) + " day";
     }
     // Less than one year, devide in week
     else if (Math.abs(size) < 31536000) {
-      return (size / 604800).toFixed(decimals) + " week";
+      return kbn.toFixed(size / 604800, scaledDecimals + 6) + " week";
     }
 
-    return (size / 3.15569e7).toFixed(decimals) + " year";
+    return kbn.toFixed(size / 3.15569e7, scaledDecimals + 7) + " year";
   };
 
-  kbn.microsFormat = function(size, decimals) {
+  kbn.valueFormats['µs'] = function(size, decimals, scaledDecimals) {
     if (Math.abs(size) < 1000) {
       return kbn.toFixed(size, decimals) + " µs";
     }
     else if (Math.abs(size) < 1000000) {
-      return (size / 1000).toFixed(decimals) + " ms";
+      return kbn.toFixed(size / 1000, scaledDecimals + 3) + " ms";
     }
     else {
-      return (size / 1000000).toFixed(decimals) + " s";
+      return kbn.toFixed(size / 1000000, scaledDecimals + 6) + " s";
     }
   };
 
-  kbn.nanosFormat = function(size, decimals) {
-    if (Math.abs(size) < 1) {
-      return size.toFixed(decimals) + " ns";
-    }
-    else if (Math.abs(size) < 1000) {
-      return size.toFixed(0) + " ns";
+  kbn.valueFormats.ns = function(size, decimals, scaledDecimals) {
+    if (Math.abs(size) < 1000) {
+      return kbn.toFixed(size, decimals) + " ns";
     }
     else if (Math.abs(size) < 1000000) {
-      return (size / 1000).toFixed(decimals) + " µs";
+      return kbn.toFixed(size / 1000, scaledDecimals + 3) + " µs";
     }
     else if (Math.abs(size) < 1000000000) {
-      return (size / 1000000).toFixed(decimals) + " ms";
+      return kbn.toFixed(size / 1000000, scaledDecimals + 6) + " ms";
     }
     else if (Math.abs(size) < 60000000000){
-      return (size / 1000000000).toFixed(decimals) + " s";
+      return kbn.toFixed(size / 1000000000, scaledDecimals + 9) + " s";
     }
     else {
-      return (size / 60000000000).toFixed(decimals) + " m";
+      return kbn.toFixed(size / 60000000000, scaledDecimals + 12) + " m";
     }
   };
 

+ 7 - 7
src/app/components/timeSeries.js

@@ -54,7 +54,7 @@ function (_, kbn) {
     }
   };
 
-  TimeSeries.prototype.getFlotPairs = function (fillStyle, yFormats) {
+  TimeSeries.prototype.getFlotPairs = function (fillStyle) {
     var result = [];
 
     this.color = this.info.color;
@@ -107,12 +107,12 @@ function (_, kbn) {
     return result;
   };
 
-  TimeSeries.prototype.updateLegendValues = function(formater, decimals) {
-    this.info.avg = this.info.avg != null ? formater(this.info.avg, decimals) : null;
-    this.info.current = this.info.current != null ? formater(this.info.current, decimals) : null;
-    this.info.min = this.info.min != null ? formater(this.info.min, decimals) : null;
-    this.info.max = this.info.max != null ? formater(this.info.max, decimals) : null;
-    this.info.total = this.info.total != null ? formater(this.info.total, decimals) : null;
+  TimeSeries.prototype.updateLegendValues = function(formater, decimals, scaledDecimals) {
+    this.info.avg = this.info.avg != null ? formater(this.info.avg, decimals, scaledDecimals) : null;
+    this.info.current = this.info.current != null ? formater(this.info.current, decimals, scaledDecimals) : null;
+    this.info.min = this.info.min != null ? formater(this.info.min, decimals, scaledDecimals) : null;
+    this.info.max = this.info.max != null ? formater(this.info.max, decimals, scaledDecimals) : null;
+    this.info.total = this.info.total != null ? formater(this.info.total, decimals, scaledDecimals) : null;
   };
 
   return TimeSeries;

+ 5 - 5
src/app/directives/grafanaGraph.js

@@ -90,12 +90,12 @@ function (angular, $, kbn, moment, _) {
 
         function updateLegendValues(plot) {
           var yaxis = plot.getYAxes();
-          console.log('drawSeries', yaxis);
 
           for (var i = 0; i < data.length; i++) {
             var series = data[i];
-            var formater = kbn.formatFunctions[scope.panel.y_formats[series.yaxis - 1]];
-            series.updateLegendValues(formater, yaxis[series.yaxis - 1].tickDecimals);
+            var axis = yaxis[series.yaxis - 1];
+            var formater = kbn.valueFormats[scope.panel.y_formats[series.yaxis - 1]];
+            series.updateLegendValues(formater, axis.tickDecimals, axis.scaledDecimals);
           }
 
         }
@@ -327,7 +327,7 @@ function (angular, $, kbn, moment, _) {
 
         function configureAxisMode(axis, format) {
           axis.tickFormatter = function(val, axis) {
-            return kbn.formatFunctions[format](val, axis.tickDecimals);
+            return kbn.valueFormats[format](val, axis.tickDecimals, axis.scaledDecimals);
           };
         }
 
@@ -378,7 +378,7 @@ function (angular, $, kbn, moment, _) {
               value = item.datapoint[1];
             }
 
-            value = kbn.getFormatFunction(format, 2)(value, item.series.yaxis);
+            value = kbn.valueFormats[format](value, item.series.yaxis.tickDecimals);
             timestamp = dashboard.formatDate(item.datapoint[0]);
 
             $tooltip.html(group + value + " @ " + timestamp).place_tt(pos.pageX, pos.pageY);

+ 19 - 64
src/test/specs/kbn-format-specs.js

@@ -3,76 +3,31 @@ define([
 ], function(kbn) {
   'use strict';
 
-  describe('millisecond formating', function() {
+  function describeValueFormat(desc, value, tickSize, tickDecimals, result) {
 
-    it('should translate 4378634603 as 1.67 years', function() {
-      var str = kbn.msFormat(4378634603, 2);
-      expect(str).to.be('50.68 day');
+    describe('value format: ' + desc, function() {
+      it('should translate ' + value + ' as ' + result, function() {
+        var scaledDecimals = tickDecimals - Math.floor(Math.log(tickSize) / Math.LN10);
+        var str = kbn.valueFormats[desc](value, tickDecimals, scaledDecimals);
+        expect(str).to.be(result);
+      });
     });
 
-    it('should translate 3654454 as 1.02 hour', function() {
-      var str = kbn.msFormat(3654454, 2);
-      expect(str).to.be('1.02 hour');
-    });
-
-    it('should not downscale when value is zero', function() {
-      var str = kbn.msFormat(0, 2);
-      expect(str).to.be('0.00 ms');
-    });
-
-
-    it('should translate 365445 as 6.09 min', function() {
-      var str = kbn.msFormat(365445, 2);
-      expect(str).to.be('6.09 min');
-    });
-
-  });
-
-  describe('high negative exponent, issue #696', function() {
-    it('should ignore decimal correction if exponent', function() {
-      var str = kbn.getFormatFunction('')(2.75e-10, { tickDecimals: 12 });
-      expect(str).to.be('2.75e-10');
-    });
-    it('should format 0 correctly', function() {
-      var str = kbn.getFormatFunction('')(0.0, { tickDecimals: 12 });
-      expect(str).to.be('0');
-    });
-  });
+  }
 
-  describe('none format tests', function() {
-    it('should translate 2 as 2.0000 if axis decimals is 4', function() {
-      var str = kbn.getFormatFunction('')(2, { tickDecimals: 4 });
-      expect(str).to.be('2.0000');
-    });
-  });
-
-  describe('nanosecond formatting', function () {
-    it('should translate 25 to 25 ns', function () {
-      var str = kbn.nanosFormat(25, 2);
-      expect(str).to.be("25 ns");
-    });
-
-    it('should translate 2558 to 2.56 µs', function () {
-      var str = kbn.nanosFormat(2558, 2);
-      expect(str).to.be("2.56 µs");
-    });
+  describeValueFormat('ms', 0.0024, 0.0005, 4, '0.0024 ms');
+  describeValueFormat('ms', 100, 1, 0, '100 ms');
+  describeValueFormat('ms', 1250, 10, 0, '1.25 s');
+  describeValueFormat('ms', 1250, 300, 0, '1.3 s');
+  describeValueFormat('ms', 65150, 10000, 0, '1.1 min');
+  describeValueFormat('ms', 6515000, 1500000, 0, '1.8 hour');
+  describeValueFormat('ms', 651500000, 150000000, 0, '8 day');
 
-    it('should translate 2558000 to 2.56 ms', function () {
-      var str = kbn.nanosFormat(2558000, 2);
-      expect(str).to.be("2.56 ms");
-    });
-
-    it('should translate 2019962000 to 2.02 s', function () {
-      var str = kbn.nanosFormat(2049962000, 2);
-      expect(str).to.be("2.05 s");
-    });
+  describeValueFormat('none', 2.75e-10, 0, 10, '3e-10');
+  describeValueFormat('none', 0, 0, 2, '0');
 
-    it('should translate 95199620000 to 1.59 m', function () {
-      var str = kbn.nanosFormat(95199620000, 2);
-      expect(str).to.be("1.59 m");
-    });
-
-  });
+  describeValueFormat('ns', 25, 1, 0, '25 ns');
+  describeValueFormat('ns', 2558, 50, 0, '2.56 µs');
 
   describe('calculateInterval', function() {
     it('1h 100 resultion', function() {

+ 2 - 0
src/vendor/jquery/jquery.flot.js

@@ -1728,6 +1728,8 @@ Licensed under the MIT license.
             axis.delta = delta;
             axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);
             axis.tickSize = opts.tickSize || size;
+            // grafana addition
+            axis.scaledDecimals = axis.tickDecimals - Math.floor(Math.log(axis.tickSize) / Math.LN10);
 
             // Time mode was moved to a plug-in in 0.8, and since so many people use it
             // we'll add an especially friendly reminder to make sure they included it.