[ARVADOS] created: a143375dc725aa517c091c6826bf37b4caa69161

Git user git at public.curoverse.com
Tue Jul 18 22:40:46 EDT 2017


        at  a143375dc725aa517c091c6826bf37b4caa69161 (commit)


commit a143375dc725aa517c091c6826bf37b4caa69161
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Jul 18 22:38:18 2017 -0400

    11842: Use CDNJS for dygraphs js and css.
    
    Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom at curoverse.com>

diff --git a/tools/crunchstat-summary/crunchstat_summary/dygraphs.py b/tools/crunchstat-summary/crunchstat_summary/dygraphs.py
index 58429f4..e72832e 100644
--- a/tools/crunchstat-summary/crunchstat_summary/dygraphs.py
+++ b/tools/crunchstat-summary/crunchstat_summary/dygraphs.py
@@ -6,8 +6,8 @@ import crunchstat_summary.webchart
 
 
 class DygraphsChart(crunchstat_summary.webchart.WebChart):
-    CSS = 'http://dygraphs.com/2.0.0/dygraph.css'
-    JSLIB = 'http://dygraphs.com/2.0.0/dygraph.min.js'
+    CSS = 'https://cdnjs.cloudflare.com/ajax/libs/dygraph/2.0.0/dygraph.min.css'
+    JSLIB = 'https://cdnjs.cloudflare.com/ajax/libs/dygraph/2.0.0/dygraph.min.js'
     JSASSET = 'dygraphs.js'
 
     def headHTML(self):

commit 85d5f916501c05e1bb980690f2d2712a3413e975
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Jul 18 13:54:39 2017 -0400

    11842: Generate charts with dygraphs.
    
    Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom at curoverse.com>

diff --git a/tools/crunchstat-summary/MANIFEST.in b/tools/crunchstat-summary/MANIFEST.in
index 32a9e7d..f87ccca 100644
--- a/tools/crunchstat-summary/MANIFEST.in
+++ b/tools/crunchstat-summary/MANIFEST.in
@@ -3,4 +3,5 @@
 # SPDX-License-Identifier: AGPL-3.0
 
 include agpl-3.0.txt
+include crunchstat_summary/dygraphs.js
 include crunchstat_summary/chartjs.js
diff --git a/tools/crunchstat-summary/crunchstat_summary/dygraphs.js b/tools/crunchstat-summary/crunchstat_summary/dygraphs.js
new file mode 100644
index 0000000..6a6225d
--- /dev/null
+++ b/tools/crunchstat-summary/crunchstat_summary/dygraphs.js
@@ -0,0 +1,63 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+window.onload = function() {
+    var charts = {};
+    var fmt = {
+        iso: function(y) {
+            var s='';
+            if (y > 1000000000) { y=y/1000000000; s='G'; }
+            else if (y > 1000000) { y=y/1000000; s='M'; }
+            else if (y > 1000) { y=y/1000; s='K'; }
+            return y.toFixed(2).replace(/\.0+$/, '')+s;
+        },
+        time: function(s) {
+            var u='s';
+            if (s < 60) return s;
+            var u = 'm'+(s%60)+'s';
+            var m = Math.floor(s/60);
+            if (m < 60) return ''+m+u;
+            u = 'h'+(m%60)+u;
+            var h = Math.floor(m/60);
+            if (h < 24) return ''+h+u;
+            u = 'd'+(h%24)+s;
+            return ''+Math.floor(h/24)+u;
+        },
+    }
+    chartdata.forEach(function(section, section_idx) {
+        var h1 = document.createElement('h1');
+        h1.appendChild(document.createTextNode(section.label));
+        document.body.appendChild(h1);
+        section.charts.forEach(function(chart, chart_idx) {
+            // Skip chart if every series has zero data points
+            if (0 == chart.data.reduce(function(len, series) {
+                return len + series.length;
+            }, 0)) {
+                return;
+            }
+            var id = 'chart-'+section_idx+'-'+chart_idx;
+            var div = document.createElement('div');
+            div.setAttribute('id', id);
+            div.setAttribute('style', 'width: 100%; height: 150px');
+            document.body.appendChild(div);
+            chart.options.valueFormatter = function(y) {
+            }
+            chart.options.axes = {
+                x: {
+                    axisLabelFormatter: fmt.time,
+                    valueFormatter: fmt.time,
+                },
+                y: {
+                    axisLabelFormatter: fmt.iso,
+                    valueFormatter: fmt.iso,
+                },
+            }
+            charts[id] = new Dygraph(div, chart.data, chart.options);
+        });
+    });
+
+    if (typeof window.debug === 'undefined')
+        window.debug = {};
+    window.debug.charts = charts;
+};
diff --git a/tools/crunchstat-summary/crunchstat_summary/dygraphs.py b/tools/crunchstat-summary/crunchstat_summary/dygraphs.py
new file mode 100644
index 0000000..58429f4
--- /dev/null
+++ b/tools/crunchstat-summary/crunchstat_summary/dygraphs.py
@@ -0,0 +1,33 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
+import crunchstat_summary.webchart
+
+
+class DygraphsChart(crunchstat_summary.webchart.WebChart):
+    CSS = 'http://dygraphs.com/2.0.0/dygraph.css'
+    JSLIB = 'http://dygraphs.com/2.0.0/dygraph.min.js'
+    JSASSET = 'dygraphs.js'
+
+    def headHTML(self):
+        return '<link rel="stylesheet" href="{}">\n'.format(self.CSS)
+
+    def chartdata(self, label, tasks, stat):
+        return {
+            'data': self._collate_data(tasks, stat),
+            'options': {
+                'connectSeparatedPoints': True,
+                'labels': ['elapsed']+[uuid for uuid, _ in tasks.iteritems()],
+                'title': '{}: {} {}'.format(label, stat[0], stat[1]),
+            },
+        }
+
+    def _collate_data(self, tasks, stat):
+        data = []
+        nulls = []
+        for uuid, task in tasks.iteritems():
+            for pt in task.series[stat]:
+                data.append([pt[0].total_seconds()] + nulls + [pt[1]])
+            nulls.append(None)
+        return sorted(data)
diff --git a/tools/crunchstat-summary/crunchstat_summary/summarizer.py b/tools/crunchstat-summary/crunchstat_summary/summarizer.py
index 62ccd50..d51c6e3 100644
--- a/tools/crunchstat-summary/crunchstat_summary/summarizer.py
+++ b/tools/crunchstat-summary/crunchstat_summary/summarizer.py
@@ -6,7 +6,7 @@ from __future__ import print_function
 
 import arvados
 import collections
-import crunchstat_summary.chartjs
+import crunchstat_summary.dygraphs
 import crunchstat_summary.reader
 import datetime
 import functools
@@ -31,7 +31,7 @@ AVAILABLE_RAM_RATIO = 0.95
 datetime.datetime.strptime('1999-12-31_23:59:59', '%Y-%m-%d_%H:%M:%S')
 
 
-WEBCHART_CLASS = crunchstat_summary.chartjs.ChartJS
+WEBCHART_CLASS = crunchstat_summary.dygraphs.DygraphsChart
 
 
 class Task(object):

commit 10138c15c015c3c0c3546e5083642cf2145dfe82
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Jul 18 13:20:45 2017 -0400

    11842: Split generic webchart code from ChartJS to WebChart.
    
    Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom at curoverse.com>

diff --git a/tools/crunchstat-summary/crunchstat_summary/chartjs.js b/tools/crunchstat-summary/crunchstat_summary/chartjs.js
index 1a84aab..a369f26 100644
--- a/tools/crunchstat-summary/crunchstat_summary/chartjs.js
+++ b/tools/crunchstat-summary/crunchstat_summary/chartjs.js
@@ -4,7 +4,7 @@
 
 window.onload = function() {
     var charts = {};
-    sections.forEach(function(section, section_idx) {
+    chartdata.forEach(function(section, section_idx) {
         var h1 = document.createElement('h1');
         h1.appendChild(document.createTextNode(section.label));
         document.body.appendChild(h1);
diff --git a/tools/crunchstat-summary/crunchstat_summary/chartjs.py b/tools/crunchstat-summary/crunchstat_summary/chartjs.py
index bd8af8c..d047144 100644
--- a/tools/crunchstat-summary/crunchstat_summary/chartjs.py
+++ b/tools/crunchstat-summary/crunchstat_summary/chartjs.py
@@ -2,43 +2,31 @@
 #
 # SPDX-License-Identifier: AGPL-3.0
 
-from __future__ import print_function
-
-import cgi
-import json
 import math
-import pkg_resources
-
-from crunchstat_summary import logger
+import crunchstat_summary.webchart
 
 
-class ChartJS(object):
+class ChartJS(crunchstat_summary.webchart.WebChart):
     JSLIB = 'https://cdnjs.cloudflare.com/ajax/libs/canvasjs/1.7.0/canvasjs.min.js'
+    JSASSET = 'chartjs.js'
 
-    def __init__(self, label, summarizers):
-        self.label = label
-        self.summarizers = summarizers
-
-    def html(self):
-        return '''<!doctype html><html><head>
-        <title>{} stats</title>
-        <script type="text/javascript" src="{}"></script>
-        <script type="text/javascript">{}</script>
-        </head><body></body></html>
-        '''.format(cgi.escape(self.label), self.JSLIB, self.js())
-
-    def js(self):
-        return 'var sections = {};\n{}'.format(
-            json.dumps(self.sections()),
-            pkg_resources.resource_string('crunchstat_summary', 'chartjs.js'))
-
-    def sections(self):
-        return [
-            {
-                'label': s.long_label(),
-                'charts': self.charts(s.label, s.tasks),
-            }
-            for s in self.summarizers]
+    def chartdata(self, label, tasks, stat):
+        return {
+            'axisY': self._axisY(tasks=tasks, stat=stat),
+            'data': [
+                {
+                    'type': 'line',
+                    'markerType': 'none',
+                    'dataPoints': self._datapoints(
+                        label=uuid, task=task, series=task.series[stat]),
+                }
+                for uuid, task in tasks.iteritems()
+            ],
+            'title': {
+                'text': '{}: {} {}'.format(label, stat[0], stat[1]),
+            },
+            'zoomEnabled': True,
+        }
 
     def _axisY(self, tasks, stat):
         ymax = 1
@@ -55,29 +43,6 @@ class ChartJS(object):
             'valueFormatString': "''",
         }
 
-    def charts(self, label, tasks):
-        return [
-            {
-                'axisY': self._axisY(tasks=tasks, stat=stat),
-                'data': [
-                    {
-                        'type': 'line',
-                        'markerType': 'none',
-                        'dataPoints': self._datapoints(
-                            label=uuid, task=task, series=task.series[stat]),
-                    }
-                    for uuid, task in tasks.iteritems()
-                ],
-                'title': {
-                    'text': '{}: {} {}'.format(label, stat[0], stat[1]),
-                },
-                'zoomEnabled': True,
-            }
-            for stat in (('cpu', 'user+sys__rate'),
-                         ('mem', 'rss'),
-                         ('net:eth0', 'tx+rx__rate'),
-                         ('net:keep0', 'tx+rx__rate'))]
-
     def _datapoints(self, label, task, series):
         points = [
             {'x': pt[0].total_seconds(), 'y': pt[1]}
diff --git a/tools/crunchstat-summary/crunchstat_summary/summarizer.py b/tools/crunchstat-summary/crunchstat_summary/summarizer.py
index 9b8410e..62ccd50 100644
--- a/tools/crunchstat-summary/crunchstat_summary/summarizer.py
+++ b/tools/crunchstat-summary/crunchstat_summary/summarizer.py
@@ -31,6 +31,9 @@ AVAILABLE_RAM_RATIO = 0.95
 datetime.datetime.strptime('1999-12-31_23:59:59', '%Y-%m-%d_%H:%M:%S')
 
 
+WEBCHART_CLASS = crunchstat_summary.chartjs.ChartJS
+
+
 class Task(object):
     def __init__(self):
         self.starttime = None
@@ -217,7 +220,7 @@ class Summarizer(object):
             self._recommend_gen())) + "\n"
 
     def html_report(self):
-        return crunchstat_summary.chartjs.ChartJS(self.label, [self]).html()
+        return WEBCHART_CLASS(self.label, [self]).html()
 
     def _text_report_gen(self):
         yield "\t".join(['category', 'metric', 'task_max', 'task_max_rate', 'job_total'])
@@ -446,5 +449,4 @@ class PipelineSummarizer(object):
         return txt
 
     def html_report(self):
-        return crunchstat_summary.chartjs.ChartJS(
-            self.label, self.summarizers.itervalues()).html()
+        return WEBCHART_CLASS(self.label, self.summarizers.itervalues()).html()
diff --git a/tools/crunchstat-summary/crunchstat_summary/webchart.py b/tools/crunchstat-summary/crunchstat_summary/webchart.py
new file mode 100644
index 0000000..790b08d
--- /dev/null
+++ b/tools/crunchstat-summary/crunchstat_summary/webchart.py
@@ -0,0 +1,61 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
+import cgi
+import json
+import pkg_resources
+
+
+class WebChart(object):
+    """Base class for a web chart.
+
+    Subclasses must assign JSLIB and JSASSET, and override the
+    chartdata() method.
+    """
+    JSLIB = None
+    JSASSET = None
+
+    def __init__(self, label, summarizers):
+        self.label = label
+        self.summarizers = summarizers
+
+    def html(self):
+        return '''<!doctype html><html><head>
+        <title>{} stats</title>
+        <script type="text/javascript" src="{}"></script>
+        <script type="text/javascript">{}</script>
+        {}
+        </head><body></body></html>
+        '''.format(cgi.escape(self.label),
+                   self.JSLIB, self.js(), self.headHTML())
+
+    def js(self):
+        return 'var chartdata = {};\n{}'.format(
+            json.dumps(self.sections()),
+            pkg_resources.resource_string('crunchstat_summary', self.JSASSET))
+
+    def sections(self):
+        return [
+            {
+                'label': s.long_label(),
+                'charts': [
+                    self.chartdata(s.label, s.tasks, stat)
+                    for stat in (('cpu', 'user+sys__rate'),
+                                 ('mem', 'rss'),
+                                 ('net:eth0', 'tx+rx__rate'),
+                                 ('net:keep0', 'tx+rx__rate'))],
+            }
+            for s in self.summarizers]
+
+    def chartdata(self, label, tasks, stat):
+        """Return chart data for the given tasks.
+
+        The returned value will be available on the client side as an
+        element of the "chartdata" array.
+        """
+        raise NotImplementedError()
+
+    def headHTML(self):
+        """Return extra HTML text to include in HEAD."""
+        return ''

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list