1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: AGPL-3.0
5 import importlib.resources
7 from arvados._internal.report_template import ReportTemplate
9 class DygraphsChart(ReportTemplate):
10 """Crunchstat report using dygraphs for charting.
13 CSS = 'https://cdnjs.cloudflare.com/ajax/libs/dygraph/2.0.0/dygraph.min.css'
14 JSLIB = 'https://cdnjs.cloudflare.com/ajax/libs/dygraph/2.0.0/dygraph.min.js'
15 JSASSETS = ['synchronizer.js','dygraphs.js']
17 def __init__(self, label, summarizers, beforechart, afterchart):
18 super().__init__(label)
19 self.summarizers = summarizers
20 self.beforechart = beforechart
21 self.afterchart = afterchart
24 self.cards.extend(self.beforechart)
27 <div id="chart"></div>
29 self.cards.extend(self.afterchart)
35 <script type="text/javascript" src="{jslib}"></script>
36 <script type="text/javascript">
37 var chartdata = {chartdata};\n{jsassets}
40 chartdata=json.dumps(self.sections()),
42 importlib.resources.read_text('crunchstat_summary', jsa, encoding='utf-8')
43 for jsa in self.JSASSETS
50 'label': s.long_label(),
52 self.chartdata(s.label, s.tasks, stat)
53 for stat in (('cpu', ['user+sys__rate', 'user__rate', 'sys__rate']),
55 ('net:eth0', ['tx+rx__rate','rx__rate','tx__rate']),
56 ('net:keep0', ['tx+rx__rate','rx__rate','tx__rate']),
57 ('statfs', ['used', 'total']),
61 for s in self.summarizers]
63 def chartdata(self, label, tasks, stats):
64 '''For Crunch2, label is the name of container request,
65 tasks is the top level container and
66 stats is index by a tuple of (category, metric).
69 'data': self._collate_data(tasks, stats),
72 'connectSeparatedPoints': True,
73 'labels': ['elapsed'] + stats[1],
75 'title': '{}: {}'.format(label, stats[0]) if label else stats[0],
79 def _collate_data(self, tasks, stats):
82 # uuid is category for crunch2
83 for uuid, task in tasks.items():
84 # All stats in a category are assumed to have the same time base and same number of samples
86 series_names = stats[1]
88 series = task.series[(category,sn0)]
89 for i in range(len(series)):
91 vals = [task.series[(category,stat)][i][1] for stat in series_names[1:]]
92 data.append([pt[0].total_seconds()] + nulls + [pt[1]] + vals)
97 return '\n'.join((super().style(),
98 '<link rel="stylesheet" href="{}">\n'.format(self.CSS)))