Procházet zdrojové kódy

Merge pull request #12123 from alexanderzobnin/fix-11792

graph: fix legend decimals precision calculation
Marcus Efraimsson před 7 roky
rodič
revize
296a841685

+ 25 - 0
public/app/core/specs/ticks.jest.ts

@@ -0,0 +1,25 @@
+import * as ticks from '../utils/ticks';
+
+describe('ticks', () => {
+  describe('getFlotTickDecimals()', () => {
+    let ctx: any = {};
+
+    beforeEach(() => {
+      ctx.axis = {};
+    });
+
+    it('should calculate decimals precision based on graph height', () => {
+      let dec = ticks.getFlotTickDecimals(0, 10, ctx.axis, 200);
+      expect(dec.tickDecimals).toBe(1);
+      expect(dec.scaledDecimals).toBe(1);
+
+      dec = ticks.getFlotTickDecimals(0, 100, ctx.axis, 200);
+      expect(dec.tickDecimals).toBe(0);
+      expect(dec.scaledDecimals).toBe(-1);
+
+      dec = ticks.getFlotTickDecimals(0, 1, ctx.axis, 200);
+      expect(dec.tickDecimals).toBe(2);
+      expect(dec.scaledDecimals).toBe(3);
+    });
+  });
+});

+ 52 - 0
public/app/core/specs/time_series.jest.ts

@@ -1,4 +1,5 @@
 import TimeSeries from 'app/core/time_series2';
 import TimeSeries from 'app/core/time_series2';
+import { updateLegendValues } from 'app/core/time_series2';
 
 
 describe('TimeSeries', function() {
 describe('TimeSeries', function() {
   var points, series;
   var points, series;
@@ -311,4 +312,55 @@ describe('TimeSeries', function() {
       expect(series.formatValue(-Infinity)).toBe('');
       expect(series.formatValue(-Infinity)).toBe('');
     });
     });
   });
   });
+
+  describe('legend decimals', function() {
+    let series, panel;
+    let height = 200;
+    beforeEach(function() {
+      testData = {
+        alias: 'test',
+        datapoints: [[1, 2], [0, 3], [10, 4], [8, 5]],
+      };
+      series = new TimeSeries(testData);
+      series.getFlotPairs();
+      panel = {
+        decimals: null,
+        yaxes: [
+          {
+            decimals: null,
+          },
+        ],
+      };
+    });
+
+    it('should set decimals based on Y axis (expect calculated decimals = 1)', function() {
+      let data = [series];
+      // Expect ticks with this data will have decimals = 1
+      updateLegendValues(data, panel, height);
+      expect(data[0].decimals).toBe(2);
+    });
+
+    it('should set decimals based on Y axis to 0 if calculated decimals = 0)', function() {
+      testData.datapoints = [[10, 2], [0, 3], [100, 4], [80, 5]];
+      series = new TimeSeries(testData);
+      series.getFlotPairs();
+      let data = [series];
+      updateLegendValues(data, panel, height);
+      expect(data[0].decimals).toBe(0);
+    });
+
+    it('should set decimals to Y axis decimals + 1', function() {
+      panel.yaxes[0].decimals = 2;
+      let data = [series];
+      updateLegendValues(data, panel, height);
+      expect(data[0].decimals).toBe(3);
+    });
+
+    it('should set decimals to legend decimals value if it was set explicitly', function() {
+      panel.decimals = 3;
+      let data = [series];
+      updateLegendValues(data, panel, height);
+      expect(data[0].decimals).toBe(3);
+    });
+  });
 });
 });

+ 9 - 5
public/app/core/time_series2.ts

@@ -23,23 +23,27 @@ function translateFillOption(fill) {
  * Calculate decimals for legend and update values for each series.
  * Calculate decimals for legend and update values for each series.
  * @param data series data
  * @param data series data
  * @param panel
  * @param panel
+ * @param height
  */
  */
-export function updateLegendValues(data: TimeSeries[], panel) {
+export function updateLegendValues(data: TimeSeries[], panel, height) {
   for (let i = 0; i < data.length; i++) {
   for (let i = 0; i < data.length; i++) {
     let series = data[i];
     let series = data[i];
-    let yaxes = panel.yaxes;
+    const yaxes = panel.yaxes;
     const seriesYAxis = series.yaxis || 1;
     const seriesYAxis = series.yaxis || 1;
-    let axis = yaxes[seriesYAxis - 1];
-    let { tickDecimals, scaledDecimals } = getFlotTickDecimals(data, axis);
-    let formater = kbn.valueFormats[panel.yaxes[seriesYAxis - 1].format];
+    const axis = yaxes[seriesYAxis - 1];
+    let formater = kbn.valueFormats[axis.format];
 
 
     // decimal override
     // decimal override
     if (_.isNumber(panel.decimals)) {
     if (_.isNumber(panel.decimals)) {
       series.updateLegendValues(formater, panel.decimals, null);
       series.updateLegendValues(formater, panel.decimals, null);
+    } else if (_.isNumber(axis.decimals)) {
+      series.updateLegendValues(formater, axis.decimals + 1, null);
     } else {
     } else {
       // auto decimals
       // auto decimals
       // legend and tooltip gets one more decimal precision
       // legend and tooltip gets one more decimal precision
       // than graph legend ticks
       // than graph legend ticks
+      const { datamin, datamax } = getDataMinMax(data);
+      let { tickDecimals, scaledDecimals } = getFlotTickDecimals(datamin, datamax, axis, height);
       tickDecimals = (tickDecimals || -1) + 1;
       tickDecimals = (tickDecimals || -1) + 1;
       series.updateLegendValues(formater, tickDecimals, scaledDecimals + 2);
       series.updateLegendValues(formater, tickDecimals, scaledDecimals + 2);
     }
     }

+ 6 - 12
public/app/core/utils/ticks.ts

@@ -1,5 +1,3 @@
-import { getDataMinMax } from 'app/core/time_series2';
-
 /**
 /**
  * Calculate tick step.
  * Calculate tick step.
  * Implementation from d3-array (ticks.js)
  * Implementation from d3-array (ticks.js)
@@ -121,12 +119,10 @@ export function getFlotRange(panelMin, panelMax, datamin, datamax) {
  * Calculate tick decimals.
  * Calculate tick decimals.
  * Implementation from Flot.
  * Implementation from Flot.
  */
  */
-export function getFlotTickDecimals(data, axis) {
-  let { datamin, datamax } = getDataMinMax(data);
-  let { min, max } = getFlotRange(axis.min, axis.max, datamin, datamax);
-  let noTicks = 3;
-  let tickDecimals, maxDec;
-  let delta = (max - min) / noTicks;
+export function getFlotTickDecimals(datamin, datamax, axis, height) {
+  const { min, max } = getFlotRange(axis.min, axis.max, datamin, datamax);
+  const noTicks = 0.3 * Math.sqrt(height);
+  const delta = (max - min) / noTicks;
   let dec = -Math.floor(Math.log(delta) / Math.LN10);
   let dec = -Math.floor(Math.log(delta) / Math.LN10);
 
 
   let magn = Math.pow(10, -dec);
   let magn = Math.pow(10, -dec);
@@ -139,19 +135,17 @@ export function getFlotTickDecimals(data, axis) {
   } else if (norm < 3) {
   } else if (norm < 3) {
     size = 2;
     size = 2;
     // special case for 2.5, requires an extra decimal
     // special case for 2.5, requires an extra decimal
-    if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) {
+    if (norm > 2.25) {
       size = 2.5;
       size = 2.5;
-      ++dec;
     }
     }
   } else if (norm < 7.5) {
   } else if (norm < 7.5) {
     size = 5;
     size = 5;
   } else {
   } else {
     size = 10;
     size = 10;
   }
   }
-
   size *= magn;
   size *= magn;
 
 
-  tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);
+  const tickDecimals = Math.max(0, -Math.floor(Math.log(delta) / Math.LN10) + 1);
   // grafana addition
   // grafana addition
   const scaledDecimals = tickDecimals - Math.floor(Math.log(size) / Math.LN10);
   const scaledDecimals = tickDecimals - Math.floor(Math.log(size) / Math.LN10);
   return { tickDecimals, scaledDecimals };
   return { tickDecimals, scaledDecimals };

+ 2 - 1
public/app/plugins/panel/graph/graph.ts

@@ -64,7 +64,8 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) {
         }
         }
         annotations = ctrl.annotations || [];
         annotations = ctrl.annotations || [];
         buildFlotPairs(data);
         buildFlotPairs(data);
-        updateLegendValues(data, panel);
+        const graphHeight = elem.height();
+        updateLegendValues(data, panel, graphHeight);
 
 
         ctrl.events.emit('render-legend');
         ctrl.events.emit('render-legend');
       });
       });