[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