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

Graph: Adds logarithmic scale option (log base 10), Closes #452

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

+ 1 - 0
CHANGELOG.md

@@ -7,6 +7,7 @@
 - [Issue #171](https://github.com/grafana/grafana/issues/171).   Panel: Different time periods, panels can override dashboard relative time and/or add a time shift
 - [Issue #1488](https://github.com/grafana/grafana/issues/1488). Dashboard: Clone dashboard / Save as
 - [Issue #1458](https://github.com/grafana/grafana/issues/1458). User: persisted user option for dark or light theme  (no longer an option on a dashboard)
+- [Issue #452](https://github.com/grafana/grafana/issues/452).   Graph: Adds logarithmic scale option (log base 10)
 
 **Enhancements**
 - [Issue #1366](https://github.com/grafana/grafana/issues/1366). Graph & Singlestat: Support for additional units, Fahrenheit (°F) and Celsius (°C), Humidity (%H), kW, watt-hour (Wh), kilowatt-hour (kWh), velocities (m/s, km/h, mpg, knot)

+ 12 - 0
src/app/panels/graph/axisEditor.html

@@ -30,6 +30,12 @@
 					empty-to-null ng-model="panel.grid.leftMin"
 					ng-change="render()" ng-model-onblur>
 				</li>
+				<li class="tight-form-item">
+					Scale type
+				</li>
+				<li>
+					<select class="input-small tight-form-input" style="width: 113px" ng-model="panel.grid.leftScale" ng-options="v as k for (k, v) in scaleTypes" ng-change="render()"></select>
+				</li>
 				<li class="tight-form-item">
 					Label
 				</li>
@@ -69,6 +75,12 @@
 					empty-to-null ng-model="panel.grid.rightMin"
 					ng-change="render()" ng-model-onblur>
 				</li>
+				<li class="tight-form-item">
+					Scale type
+				</li>
+				<li>
+					<select class="input-small tight-form-input" style="width: 113px" ng-model="panel.grid.rightScale" ng-options="v as k for (k, v) in scaleTypes" ng-change="render()"></select>
+				</li>
 				<li class="tight-form-item">
 					Label
 				</li>

+ 88 - 42
src/app/panels/graph/graph.js

@@ -27,6 +27,7 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
         var dashboard = scope.dashboard;
         var data, annotations;
         var sortedSeries;
+        var graphHeight;
         var legendSideLastValue = null;
         scope.crosshairEmiter = false;
 
@@ -64,19 +65,19 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
 
         function setElementHeight() {
           try {
-            var height = scope.height || scope.panel.height || scope.row.height;
-            if (_.isString(height)) {
-              height = parseInt(height.replace('px', ''), 10);
+            graphHeight = scope.height || scope.panel.height || scope.row.height;
+            if (_.isString(graphHeight)) {
+              graphHeight = parseInt(graphHeight.replace('px', ''), 10);
             }
 
-            height -= 5; // padding
-            height -= scope.panel.title ? 24 : 9; // subtract panel title bar
+            graphHeight -= 5; // padding
+            graphHeight -= scope.panel.title ? 24 : 9; // subtract panel title bar
 
             if (scope.panel.legend.show && !scope.panel.legend.rightSide) {
-              height = height - 26; // subtract one line legend
+              graphHeight = graphHeight - 26; // subtract one line legend
             }
 
-            elem.css('height', height + 'px');
+            elem.css('height', graphHeight + 'px');
 
             return true;
           } catch(e) { // IE throws errors sometimes
@@ -349,6 +350,8 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
             position: 'left',
             show: scope.panel['y-axis'],
             min: scope.panel.grid.leftMin,
+            index: 1,
+            scale: scope.panel.grid.leftScale,
             max: scope.panel.percentage && scope.panel.stack ? 100 : scope.panel.grid.leftMax,
           };
 
@@ -356,16 +359,59 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
 
           if (_.findWhere(data, {yaxis: 2})) {
             var secondY = _.clone(defaults);
+            secondY.index = 2,
+            secondY.scale = scope.panel.grid.rightScale;
             secondY.position = 'right';
             secondY.min = scope.panel.grid.rightMin;
             secondY.max = scope.panel.percentage && scope.panel.stack ? 100 : scope.panel.grid.rightMax;
             options.yaxes.push(secondY);
+
+            applyLogScale(options.yaxes[1], data);
             configureAxisMode(options.yaxes[1], scope.panel.y_formats[1]);
           }
 
+          applyLogScale(options.yaxes[0], data);
           configureAxisMode(options.yaxes[0], scope.panel.y_formats[0]);
         }
 
+        function applyLogScale(axis, data) {
+          if (axis.scale !== 2) {
+            return;
+          }
+
+          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;
+                }
+              }
+            }
+
+            if (max === null) {
+              max = 10000000000;
+            }
+          }
+
+          axis.ticks = [0, 1];
+          var tick = 1;
+
+          while (true) {
+            tick = tick*10;
+            axis.ticks.push(tick);
+            if (tick > max) {
+              break;
+            }
+          }
+
+          axis.transform = function(v) { return Math.log(v+0.1); };
+          axis.inverseTransform  = function (v) { return Math.pow(10,v); };
+        }
+
         function configureAxisMode(axis, format) {
           axis.tickFormatter = function(val, axis) {
             return kbn.valueFormats[format](val, axis.tickDecimals, axis.scaledDecimals);
@@ -411,44 +457,44 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
           url += scope.panel['y-axis'] ? '' : '&hideYAxis=true';
 
           switch(scope.panel.y_formats[0]) {
-          case 'bytes':
-            url += '&yUnitSystem=binary';
-            break;
-          case 'bits':
-            url += '&yUnitSystem=binary';
-            break;
-          case 'bps':
-            url += '&yUnitSystem=si';
-            break;
-          case 'Bps':
-            url += '&yUnitSystem=si';
-            break;
-          case 'short':
-            url += '&yUnitSystem=si';
-            break;
-          case 'joule':
-            url += '&yUnitSystem=si';
-            break;
-          case 'watt':
-            url += '&yUnitSystem=si';
-            break;
-          case 'ev':
-            url += '&yUnitSystem=si';
-            break;
-          case 'none':
-            url += '&yUnitSystem=none';
-            break;
+            case 'bytes':
+              url += '&yUnitSystem=binary';
+              break;
+            case 'bits':
+              url += '&yUnitSystem=binary';
+              break;
+            case 'bps':
+              url += '&yUnitSystem=si';
+              break;
+            case 'Bps':
+              url += '&yUnitSystem=si';
+              break;
+            case 'short':
+              url += '&yUnitSystem=si';
+              break;
+            case 'joule':
+              url += '&yUnitSystem=si';
+              break;
+            case 'watt':
+              url += '&yUnitSystem=si';
+              break;
+            case 'ev':
+              url += '&yUnitSystem=si';
+              break;
+            case 'none':
+              url += '&yUnitSystem=none';
+              break;
           }
 
           switch(scope.panel.nullPointMode) {
-          case 'connected':
-            url += '&lineMode=connected';
-            break;
-          case 'null':
-            break; // graphite default lineMode
-          case 'null as zero':
-            url += "&drawNullAsZero=true";
-            break;
+            case 'connected':
+              url += '&lineMode=connected';
+              break;
+            case 'null':
+              break; // graphite default lineMode
+            case 'null as zero':
+              url += "&drawNullAsZero=true";
+              break;
           }
 
           url += scope.panel.steppedLine ? '&lineMode=staircase' : '';

+ 1 - 1
src/app/panels/graph/graph.tooltip.js

@@ -99,7 +99,7 @@ function ($) {
       var group, value, timestamp, hoverInfo, i, series, seriesHtml;
 
       if(dashboard.sharedCrosshair){
-        scope.appEvent('setCrosshair',  { pos: pos, scope: scope });
+        scope.appEvent('setCrosshair', { pos: pos, scope: scope });
       }
 
       if (seriesList.length === 0) {

+ 4 - 0
src/app/panels/graph/module.js

@@ -53,10 +53,12 @@ function (angular, app, $, _, kbn, moment, TimeSeries, PanelMeta) {
       y_formats    : ['short', 'short'],
       // grid options
       grid          : {
+        leftScale: 1,
         leftMax: null,
         rightMax: null,
         leftMin: null,
         rightMin: null,
+        rightScale: 1,
         threshold1: null,
         threshold2: null,
         threshold1Color: 'rgba(216, 200, 27, 0.27)',
@@ -114,6 +116,8 @@ function (angular, app, $, _, kbn, moment, TimeSeries, PanelMeta) {
     _.defaults($scope.panel.grid, _d.grid);
     _.defaults($scope.panel.legend, _d.legend);
 
+    $scope.scaleTypes = {'linear': 1, 'log (base 10)': 2};
+
     $scope.hiddenSeries = {};
     $scope.seriesList = [];
     $scope.unitFormats = kbn.getUnitFormats();