21121: Fixed dygraph ticker
[arvados.git] / tools / crunchstat-summary / crunchstat_summary / dygraphs.js
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 window.onload = function() {
6     var charts = {};
7     var fmt = {
8         iso: function(y) {
9             var s='';
10             if (y > 1000000000000000) { y=y/1000000000000000; s='P'; }
11             if (y > 1000000000000) { y=y/1000000000000; s='T'; }
12             if (y > 1000000000) { y=y/1000000000; s='G'; }
13             else if (y > 1000000) { y=y/1000000; s='M'; }
14             else if (y > 1000) { y=y/1000; s='K'; }
15             return y.toFixed(2).replace(/\.0+$/, '')+s;
16         },
17         time: function(s) {
18             var ret = ''
19             if (s >= 86400) ret += Math.floor(s/86400) + 'd'
20             if (s >= 3600) ret += Math.floor(s/3600)%24 + 'h'
21             if (s >= 60) ret += Math.floor(s/60)%60 + 'm'
22             ret += Math.floor(s)%60 + 's'
23             // finally, strip trailing zeroes: 1d0m0s -> 1d
24             return ret.replace(/(\D)(0\D)*$/, '$1')
25         },
26         date: function(s, opts, sth, dg, idk, excludeHour) {
27             var date = new Date(s);
28             var options = {month: 'numeric', day: 'numeric'};
29             if (!excludeHour) {
30                 options.hour = 'numeric';
31                 options.minute = 'numeric';
32                 options.hour12 = false;
33             }
34             var r = new Intl.DateTimeFormat(undefined, options).format(date);
35             return r;
36         },
37     }
38     var ticker = {
39         time: function(min, max, pixels, opts, dg) {
40             var max_ticks = Math.floor(pixels / (opts('axisLabelWidth')+opts('pixelsPerLabel')/2))
41             var natural = [/*1, 5, 10, 30,*/ 60,
42                            120, 300, 600, 1800, 3600,
43                            7200, 14400, 43200, 86400]
44             var interval = natural.shift()*1000
45             while (max>min && (max-min)/interval > max_ticks) {
46                 interval = (natural.shift()*1000) || (interval * 2)
47             }
48             var ticks = []
49             var excludeHour = false;
50             var date = new Date(min);
51             // need to take the seconds since midnight and then round off to the nearest interval.
52             var millisecondsSinceMidnight = (date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds()) * 1000;
53             if (interval >= 86400000) {
54                 excludeHour = true;
55             } else {
56                 var roundedOff = Math.ceil(millisecondsSinceMidnight/interval)*interval;
57                 min = (min - millisecondsSinceMidnight) + roundedOff;
58             }
59             //for (var i=Math.ceil(min/interval)*interval; i<=max; i+=interval) {
60             for (var i=min; i<=max; i+=interval) {
61                 ticks.push({v: i, label: opts('axisLabelFormatter')(i, opts, "", false, false, excludeHour)})
62             }
63             return ticks
64         },
65     }
66     chartdata.forEach(function(section, section_idx) {
67         var chartDiv = document.getElementById("chart");
68         section.charts.forEach(function(chart, chart_idx) {
69             // Skip chart if every series has zero data points
70             if (0 == chart.data.reduce(function(len, series) {
71                 return len + series.length;
72             }, 0)) {
73                 return;
74             }
75             var id = 'chart-'+section_idx+'-'+chart_idx;
76             var div = document.createElement('div');
77             div.setAttribute('id', id);
78             div.setAttribute('style', 'width: 100%; height: 250px');
79             chartDiv.appendChild(div);
80             chart.options.valueFormatter = function(y) {
81             }
82             chart.options.axes = {
83                 x: {
84                     axisLabelFormatter: fmt.date,
85                     valueFormatter: fmt.date,
86                     ticker: ticker.time,
87                     axisLabelWidth: 60,
88                     pixelsPerLabel: 20,
89                 },
90                 y: {
91                     axisLabelFormatter: fmt.iso,
92                     valueFormatter: fmt.iso,
93                 },
94             }
95             var div2 = document.createElement('div');
96             div2.setAttribute('style', 'width: 150px; height: 250px');
97             chart.options.labelsDiv = div2;
98             chart.options.labelsSeparateLines = true;
99
100             var div3 = document.createElement('div');
101             div3.setAttribute('style', 'display: flex; padding-bottom: 16px');
102             div3.appendChild(div);
103             div3.appendChild(div2);
104             chartDiv.appendChild(div3);
105
106             charts[id] = new Dygraph(div, chart.data, chart.options);
107         });
108     });
109
110     var sync = Dygraph.synchronize(Object.values(charts), {range: false});
111
112     if (typeof window.debug === 'undefined')
113         window.debug = {};
114     window.debug.charts = charts;
115 };