auto-scaling of units on the dashboard; #2745
Costa Tsaousis (ktsaou) committed
Oct 6, 2017 at 01:25 UTC
dfe78d25e9ebed4ca70d96219e71661302c1d54b
2 files changed
+202
-14
web/dashboard.js
+180
-13
@@ -294,6 +294,8 @@ var NETDATA = window.NETDATA || {};
294
// the current profile
295
// we may have many...
296
current: {
297
+ units: 'auto', // can be 'auto' or 'original'
298
+
299
pixels_per_point: isSlowDevice()?5:1, // the minimum pixels per point for all charts
300
// increase this to speed javascript up
301
// each chart library has its own limit too
@@ -1464,6 +1466,119 @@ var NETDATA = window.NETDATA || {};
1466
};
1467
1468
1469
+ // ----------------------------------------------------------------------------------------------------------------
1470
+ // units conversion
1471
+
1472
+ NETDATA.unitsConversion = {
1473
+ units: {
1474
+ 'kilobits/s': {
1475
+ 'bits/s' : 0.001,
1476
+ 'kilobits/s': 1,
1477
+ 'megabits/s': 1000,
1478
+ 'gigabits/s': 1000000
1479
+ },
1480
+ 'kilobytes/s': {
1481
+ 'bytes/s' : 0.001,
1482
+ 'kilobytes/s': 1,
1483
+ 'megabytes/s': 1000,
1484
+ 'gigabytes/s': 1000000
1485
+ },
1486
+ 'MB': {
1487
+ 'B' : 0.000001,
1488
+ 'KB': 0.001,
1489
+ 'MB': 1,
1490
+ 'GB': 1000,
1491
+ 'TB': 1000000
1492
+ },
1493
+ 'GB': {
1494
+ 'B' : 0.000000001,
1495
+ 'KB': 0.000001,
1496
+ 'MB': 0.001,
1497
+ 'GB': 1,
1498
+ 'TB': 1000
1499
+ },
1500
+ 'seconds': {
1501
+ 'milliseconds': 0.001,
1502
+ 'seconds' : 1,
1503
+ 'minutes' : 60,
1504
+ 'hours' : 3600,
1505
+ 'days' : 86400
1506
+ }
1507
+ },
1508
+
1509
+ get: function(min, max, units, desired_units, switch_units_callback) {
1510
+ if(typeof units === 'undefined')
1511
+ units = 'undefined';
1512
+
1513
+ if(typeof desired_units === 'undefined' || desired_units === null)
1514
+ desired_units = 'original';
1515
+
1516
+ if(desired_units !== 'original' && typeof NETDATA.unitsConversion.units[units] !== 'undefined') {
1517
+ // console.log('NETDATA.unitsConversion(' + units.toString() + ', ' + desired_units.toString() + ', function()) decide divider with min = ' + min.toString() + ', max = ' + max.toString());
1518
+
1519
+ min = Math.abs(min);
1520
+ max = Math.abs(max);
1521
+ if (min > max) max = min;
1522
+
1523
+ var divider = 1;
1524
+ var x;
1525
+
1526
+ if (desired_units === 'auto') {
1527
+ var tunits = null;
1528
+ var tdivider = 0;
1529
+
1530
+ for (x in NETDATA.unitsConversion.units[units]) {
1531
+ if (!NETDATA.unitsConversion.units[units].hasOwnProperty(x)) continue;
1532
+
1533
+ var m = NETDATA.unitsConversion.units[units][x];
1534
+
1535
+ if (m <= max && m > tdivider) {
1536
+ tunits = x;
1537
+ tdivider = m;
1538
+ }
1539
+ }
1540
+
1541
+ if (tunits !== null) {
1542
+ switch_units_callback(tunits);
1543
+ divider = tdivider;
1544
+ }
1545
+ }
1546
+ else {
1547
+ var found = 0;
1548
+ for (x in NETDATA.unitsConversion.units[units]) {
1549
+ if (!NETDATA.unitsConversion.units[units].hasOwnProperty(x)) continue;
1550
+
1551
+ if (x === desired_units) {
1552
+ found = 1;
1553
+ switch_units_callback(x);
1554
+ divider = NETDATA.unitsConversion.units[units][x];
1555
+ break;
1556
+ }
1557
+ }
1558
+
1559
+ if(!found)
1560
+ console.log('Units conversion from ' + units.toString() + ' to ' + desired_units.toString() + ' is not supported.');
1561
+ }
1562
+
1563
+ if(divider <= 0 || divider === 1)
1564
+ return function (value) {
1565
+ return value;
1566
+ };
1567
+
1568
+ return function (value) {
1569
+ // console.log('NETDATA.unitsConversion(' + units.toString() + ', ' + desired_units.toString() + ', function()) decide divider with min = ' + min.toString() + ', max = ' + max.toString() + ', divider = ' + divider.toString() + ', value = ' + value.toString());
1570
+ return value / divider;
1571
+ };
1572
+ }
1573
+ else {
1574
+ return function (value) {
1575
+ // console.log('NETDATA.unitsConversion(' + units.toString() + ', ' + desired_units.toString() + ', function()) dummy divider');
1576
+ return value;
1577
+ };
1578
+ }
1579
+ }
1580
+ };
1581
+
1582
// ----------------------------------------------------------------------------------------------------------------
1583
// global selection sync
1584
@@ -1677,6 +1792,9 @@ var NETDATA = window.NETDATA || {};
1792
1793
that.title = NETDATA.dataAttribute(that.element, 'title', null); // the title of the chart
1794
that.units = NETDATA.dataAttribute(that.element, 'units', null); // the units of the chart dimensions
1795
+ that.units_desired = NETDATA.dataAttribute(that.element, 'desired-units', NETDATA.options.current.units); // the units of the chart dimensions
1796
+ that.units_current = that.units;
1797
+
1798
that.append_options = NETDATA.dataAttribute(that.element, 'append-options', null); // additional options to pass to netdata
1799
that.override_options = NETDATA.dataAttribute(that.element, 'override-options', null); // override options to pass to netdata
1800
@@ -2525,6 +2643,30 @@ var NETDATA = window.NETDATA || {};
2643
return ret;
2644
};
2645
2646
+ var __unitsConversionLastUnits = undefined;
2647
+ var __unitsConversionLastUnitsDesired = undefined;
2648
+ var __unitsConversionLastMin = undefined;
2649
+ var __unitsConversionLastMax = undefined;
2650
+ var __unitsConversion = function(value) { return value; };
2651
+ this.unitsConversionSetup = function(min, max) {
2652
+ if(this.units !== __unitsConversionLastUnits
2653
+ || this.units_desired !== __unitsConversionLastUnitsDesired
2654
+ || min !== __unitsConversionLastMin
2655
+ || max !== __unitsConversionLastMax) {
2656
+
2657
+ __unitsConversionLastUnits = this.units;
2658
+ __unitsConversionLastUnitsDesired = this.units_desired;
2659
+ __unitsConversionLastMin = min;
2660
+ __unitsConversionLastMax = max;
2661
+
2662
+ __unitsConversion = NETDATA.unitsConversion.get(min, max, this.units, this.units_desired, function (units) {
2663
+ // console.log('switching units from ' + that.units.toString() + ' to ' + units.toString());
2664
+ that.units_current = units;
2665
+ that.legendSetUnitsString(that.units_current);
2666
+ });
2667
+ }
2668
+ };
2669
+
2670
var __legendFormatValueChartDecimalsLastMin = undefined;
2671
var __legendFormatValueChartDecimalsLastMax = undefined;
2672
var __legendFormatValueChartDecimals = -1;
@@ -2533,6 +2675,12 @@ var NETDATA = window.NETDATA || {};
2675
if(min === __legendFormatValueChartDecimalsLastMin && max === __legendFormatValueChartDecimalsLastMax)
2676
return;
2677
2678
+ this.unitsConversionSetup(min, max);
2679
+ if(__unitsConversion !== null) {
2680
+ min = __unitsConversion(min);
2681
+ max = __unitsConversion(max);
2682
+ }
2683
+
2684
__legendFormatValueChartDecimalsLastMin = min;
2685
__legendFormatValueChartDecimalsLastMax = max;
2686
@@ -2579,6 +2727,8 @@ var NETDATA = window.NETDATA || {};
2727
this.legendFormatValue = function(value) {
2728
if(typeof value !== 'number') return '-';
2729
2730
+ value = __unitsConversion(value);
2731
+
2732
if(__intlNumberFormat !== null)
2733
return __intlNumberFormat.format(value);
2734
@@ -2662,7 +2812,7 @@ var NETDATA = window.NETDATA || {};
2812
}
2813
};
2814
2665
- this.__legendSetUnitsString = function(units) {
2815
+ this.legendSetUnitsString = function(units) {
2816
if(units !== this.tmp.__last_shown_legend_units) {
2817
this.element_legend_childs.title_units.innerText = units;
2818
this.tmp.__last_shown_legend_units = units;
@@ -2695,7 +2845,7 @@ var NETDATA = window.NETDATA || {};
2845
this.__legendSetTimeString(this.legendSetDateLast.time);
2846
2847
if(this.element_legend_childs.title_units !== null)
2698
- this.__legendSetUnitsString(this.units)
2848
+ this.legendSetUnitsString(this.units_current)
2849
};
2850
2851
this.legendShowUndefined = function() {
@@ -2706,7 +2856,7 @@ var NETDATA = window.NETDATA || {};
2856
this.__legendSetTimeString(this.chart.name);
2857
2858
if(this.element_legend_childs.title_units !== null)
2709
- this.__legendSetUnitsString(' ');
2859
+ this.legendSetUnitsString(' ');
2860
2861
if(this.data && this.element_legend_childs.series !== null) {
2862
var labels = this.data.dimension_names;
@@ -3857,8 +4007,10 @@ var NETDATA = window.NETDATA || {};
4007
if(this.title === null)
4008
this.title = chart.title;
4009
3860
- if(this.units === null)
4010
+ if(this.units === null) {
4011
this.units = chart.units;
4012
+ this.units_current = this.units;
4013
+ }
4014
};
4015
4016
// fetch the chart description from the netdata server
@@ -4469,7 +4621,7 @@ var NETDATA = window.NETDATA || {};
4621
var tooltipClassname = NETDATA.dataAttribute(state.element, 'sparkline-tooltipclassname', undefined);
4622
var tooltipFormat = NETDATA.dataAttribute(state.element, 'sparkline-tooltipformat', undefined);
4623
var tooltipPrefix = NETDATA.dataAttribute(state.element, 'sparkline-tooltipprefix', undefined);
4472
- var tooltipSuffix = NETDATA.dataAttribute(state.element, 'sparkline-tooltipsuffix', ' ' + state.units);
4624
+ var tooltipSuffix = NETDATA.dataAttribute(state.element, 'sparkline-tooltipsuffix', ' ' + state.units_current);
4625
var tooltipSkipNull = NETDATA.dataAttributeBoolean(state.element, 'sparkline-tooltipskipnull', true);
4626
var tooltipValueLookups = NETDATA.dataAttribute(state.element, 'sparkline-tooltipvaluelookups', undefined);
4627
var tooltipFormatFieldlist = NETDATA.dataAttribute(state.element, 'sparkline-tooltipformatfieldlist', undefined);
@@ -4538,6 +4690,7 @@ var NETDATA = window.NETDATA || {};
4690
};
4691
4692
$(state.element_chart).sparkline(data.result, state.sparkline_options);
4693
+
4694
return true;
4695
};
4696
@@ -4756,7 +4909,7 @@ var NETDATA = window.NETDATA || {};
4909
xRangePad: NETDATA.dataAttribute(state.element, 'dygraph-xrangepad', 0),
4910
yRangePad: NETDATA.dataAttribute(state.element, 'dygraph-yrangepad', 1),
4911
valueRange: NETDATA.dataAttribute(state.element, 'dygraph-valuerange', [ null, null ]),
4759
- ylabel: state.units,
4912
+ ylabel: state.units_current,
4913
yLabelWidth: NETDATA.dataAttribute(state.element, 'dygraph-ylabelwidth', 12),
4914
4915
// the function to plot the chart
@@ -5590,7 +5743,7 @@ var NETDATA = window.NETDATA || {};
5743
}
5744
},
5745
vAxis: {
5593
- title: state.units,
5746
+ title: state.units_current,
5747
viewWindowMode: 'pretty',
5748
minValue: -0.1,
5749
maxValue: 0.1,
@@ -5672,6 +5825,8 @@ var NETDATA = window.NETDATA || {};
5825
if(min > value) min = value;
5826
if(max < value) max = value;
5827
5828
+ state.legendFormatValueDecimalsFromMinMax(min, max);
5829
+
5830
if(state.tmp.easyPieChartMin === null && min > 0) min = 0;
5831
if(state.tmp.easyPieChartMax === null && max < 0) max = 0;
5832
@@ -5825,10 +5980,6 @@ var NETDATA = window.NETDATA || {};
5980
else
5981
state.tmp.easyPieChartMax = max;
5982
5828
- var pcent = NETDATA.easypiechartPercentFromValueMinMax(state, value, min, max);
5829
-
5830
- chart.data('data-percent', pcent);
5831
-
5983
var size = state.chartWidth();
5984
var stroke = Math.floor(size / 22);
5985
if(stroke < 3) stroke = 2;
@@ -5856,7 +6007,7 @@ var NETDATA = window.NETDATA || {};
6007
var unittop = Math.round(valuetop + (valuefontsize + unitfontsize) + (size / 40));
6008
state.tmp.easyPieChartUnits = document.createElement('span');
6009
state.tmp.easyPieChartUnits.className = 'easyPieChartUnits';
5859
- state.tmp.easyPieChartUnits.innerText = state.units;
6010
+ state.tmp.easyPieChartUnits.innerText = state.units_current;
6011
state.tmp.easyPieChartUnits.style.fontSize = unitfontsize + 'px';
6012
state.tmp.easyPieChartUnits.style.top = unittop.toString() + 'px';
6013
state.element_chart.appendChild(state.tmp.easyPieChartUnits);
@@ -5871,6 +6022,13 @@ var NETDATA = window.NETDATA || {};
6022
barColor = tmp;
6023
}
6024
6025
+ state.legendSetUnitsString = function(units) {
6026
+ state.tmp.easyPieChartUnits.innerText = units;
6027
+ };
6028
+
6029
+ var pcent = NETDATA.easypiechartPercentFromValueMinMax(state, value, min, max);
6030
+ chart.data('data-percent', pcent);
6031
+
6032
chart.easyPieChart({
6033
barColor: barColor,
6034
trackColor: NETDATA.dataAttribute(state.element, 'easypiechart-trackcolor', NETDATA.themes.current.easypiechart_track),
@@ -5955,6 +6113,8 @@ var NETDATA = window.NETDATA || {};
6113
else if(min === max)
6114
max = min + 1;
6115
6116
+ state.legendFormatValueDecimalsFromMinMax(min, max);
6117
+
6118
// gauge.js has an issue if the needle
6119
// is smaller than min or larger than max
6120
// when we set the new values
@@ -6216,7 +6376,7 @@ var NETDATA = window.NETDATA || {};
6376
var unitfontsize = Math.round(titlefontsize * 0.9);
6377
state.tmp.gaugeChartUnits = document.createElement('span');
6378
state.tmp.gaugeChartUnits.className = 'gaugeChartUnits';
6219
- state.tmp.gaugeChartUnits.innerText = state.units;
6379
+ state.tmp.gaugeChartUnits.innerText = state.units_current;
6380
state.tmp.gaugeChartUnits.style.fontSize = unitfontsize + 'px';
6381
state.element_chart.appendChild(state.tmp.gaugeChartUnits);
6382
@@ -6236,6 +6396,13 @@ var NETDATA = window.NETDATA || {};
6396
if(typeof state.tmp.gauge_instance !== 'undefined')
6397
animate = false;
6398
6399
+ state.legendSetUnitsString = function(units) {
6400
+ state.tmp.gaugeChartUnits.innerText = units;
6401
+ state.tmp.___gaugeOld__.valueLabel = null;
6402
+ state.tmp.___gaugeOld__.minLabel = null;
6403
+ state.tmp.___gaugeOld__.maxLabel = null;
6404
+ };
6405
+
6406
state.tmp.gauge_instance = new Gauge(state.tmp.gauge_canvas).setOptions(options); // create sexy gauge!
6407
6408
state.tmp.___gaugeOld__ = {
web/index.html
+22
-1
@@ -2718,6 +2718,11 @@
2718
2719
self.bootstrapToggle(netdataTheme === 'slate'?'on':'off');
2720
};
2721
+ var units_sync_option = function(option) {
2722
+ var self = $('#' + option);
2723
+
2724
+ self.bootstrapToggle(NETDATA.options.current.units === 'auto'?'on':'off');
2725
+ };
2726
2727
sync_option('eliminate_zero_dimensions');
2728
sync_option('destroy_on_hide');
@@ -2731,6 +2736,7 @@
2736
sync_option('pan_and_zoom_data_padding');
2737
sync_option('show_help');
2738
theme_sync_option('netdata_theme_control');
2739
+ units_sync_option('units_conversion');
2740
2741
if(NETDATA.getOption('parallel_refresher') === false) {
2742
$('#concurrent_refreshes_row').hide();
@@ -2757,6 +2763,12 @@
2763
});
2764
$('#smooth_plot').change(function() { NETDATA.setOption('smooth_plot', $(this).prop('checked')); });
2765
$('#pan_and_zoom_data_padding').change(function() { NETDATA.setOption('pan_and_zoom_data_padding', $(this).prop('checked')); });
2766
+
2767
+ $('#units_conversion').change(function() {
2768
+ NETDATA.setOption('units', $(this).prop('checked')?'auto':'original');
2769
+ netdataReload();
2770
+ });
2771
+
2772
$('#show_help').change(function() {
2773
urlOptions.help = $(this).prop('checked');
2774
urlOptions.hashUpdate();
@@ -3381,6 +3393,15 @@
3393
</small>
3394
</td>
3395
</tr>
3396
+ <tr class="option-row">
3397
+ <td class="option-control"><input id="units_conversion" type="checkbox" checked data-toggle="toggle" data-on="Scale Units" data-off="Original" data-width="110px"></td>
3398
+ <td class="option-info"><strong>Enable auto-conversion of units?</strong><br/>
3399
+ <small>When set to <b>Scale Units</b> the values shown will be scaled to the maximum unit (ie. kilobits will be scaled to megabits or even gigabits). When set to <b>Original</b> all the values will be rendered using the original units maintained by the server.
3400
+ <br/>
3401
+ <b>Switching this will reload the dashboard</b>.
3402
+ </small>
3403
+ </td>
3404
+ </tr>
3405
<tr class="option-row">
3406
<td class="option-control"><input id="pan_and_zoom_data_padding" type="checkbox" checked data-toggle="toggle" data-on="Pad" data-off="Don't Pad" data-width="110px"></td>
3407
<td class="option-info"><strong>Enable data padding when panning and zooming?</strong><br/>
@@ -3533,4 +3554,4 @@
3554
</div>
3555
</body>
3556
</html>
3536
-<script type="text/javascript" src="dashboard.js?v20171003-20"></script>
3557
+<script type="text/javascript" src="dashboard.js?v20171005-1"></script>