Improved io charts
diff --git a/chart/__init__.py b/chart/__init__.py
index 4ebfd5e..e69de29 100644
--- a/chart/__init__.py
+++ b/chart/__init__.py
@@ -1 +0,0 @@
-__author__ = 'yportnova'
diff --git a/chart/charts.py b/chart/charts.py
index ec2a86f..b53ac5a 100644
--- a/chart/charts.py
+++ b/chart/charts.py
@@ -6,10 +6,11 @@
from GChartWrapper import Line
from GChartWrapper import constants
-from config import CHARTS_IMG_PATH
+from config import cfg_dict
+CHARTS_IMG_PATH = cfg_dict['charts_img_path']
-COLORS = ["1569C7", "81D8D0", "307D7E", "5CB3FF", "blue", "indigo"]
+COLORS = ["1569C7", "81D8D0", "307D7E", "5CB3FF", "0040FF", "81DAF5"]
constants.MARKERS += 'E' # append E marker to available markers
@@ -19,8 +20,9 @@
t.start()
-def render_vertical_bar(title, legend, dataset, width=700, height=400, scale_x=None,
- scale_y=None):
+def render_vertical_bar(title, legend, dataset, width=700, height=400,
+ scale_x=None, scale_y=None, label_x=None,
+ label_y=None, lines=()):
"""
Renders vertical bar group chart
@@ -29,7 +31,7 @@
:param dataset - list of values for each type (value, deviation)
Example:
[
- [(10,(9,11)), (11, (3,12)), (10,(9,11))], # bar1 values
+ [(10,1), (11, 2), (10,1)], # bar1 values
[(30,(29,33)),(35,(33,36)), (30,(29,33))], # bar2 values
[(20,(19,21)),(20,(13, 24)), (20,(19,21))] # bar 3 values
]
@@ -68,27 +70,49 @@
# deviations.extend(zip(*dev))
deviations.extend(zip(*display_dev))
- bar.dataset(values + deviations, series=len(values))
+ # bar.dataset(values + deviations, series=len(values))
+ bar.dataset(values + deviations + [l[0] for l in lines], series=len(values))
bar.axes.type('xyy')
- bar.axes.label(2, None, 'Kbps')
+ bar.axes.label(2, None, label_x)
if scale_x:
bar.axes.label(0, *scale_x)
- max_value = (max([max(l) for l in values + deviations]))
+ max_value = (max([max(l) for l in values + deviations + [lines[1][0]]]))
bar.axes.range(1, 0, max_value)
bar.axes.style(1, 'N*s*')
bar.axes.style(2, '000000', '13')
- bar.scale(0, max_value)
+ bar.scale(*[0, max_value] * len(values + deviations))
bar.bar('r', '.1', '1')
- for i in range(len(legend)):
+ for i in range(1):
bar.marker('E', '000000', '%s:%s' % ((len(values) + i*2), i),
'', '1:10')
- bar.legend(*legend)
- bar.color(*COLORS[:len(values)])
+ bar.color(*COLORS)
bar.size(width, height)
+ axes_type = "xyy"
+
+ scale = [0, max_value] * len(values + deviations)
+ if lines:
+ line_n = 0
+ for data, label, axe, leg in lines:
+ bar.marker('D', COLORS[len(values) + line_n],
+ (len(values + deviations)) + line_n, 0, 3)
+ max_val_l = max(data)
+ if axe:
+ bar.axes.type(axes_type + axe)
+ bar.axes.range(len(axes_type), 0, max_val_l)
+ bar.axes.style(len(axes_type), 'N*s*')
+ bar.axes.label(len(axes_type) + 1, None, label)
+ bar.axes.style(len(axes_type) + 1, '000000', '13')
+ axes_type += axe
+ line_n += 1
+ legend.append(leg)
+ scale += [0, max_val_l]
+
+ bar.legend(*legend)
+ bar.scale(*scale)
img_name = hashlib.md5(str(bar)).hexdigest() + ".png"
img_path = os.path.join(CHARTS_IMG_PATH, img_name)
if not os.path.exists(img_path):
@@ -111,7 +135,6 @@
line.color(*COLORS[:len(legend)])
line.size(width, height)
-
img_name = hashlib.md5(str(line)).hexdigest() + ".png"
img_path = os.path.join(CHARTS_IMG_PATH, img_name)
if not os.path.exists(img_path):
diff --git a/koder.yaml b/koder.yaml
index 028a975..21dea2e 100644
--- a/koder.yaml
+++ b/koder.yaml
@@ -19,3 +19,5 @@
logging:
extra_logs: 1
+charts_img_path: tmp/charts
+output_dest: results.html
\ No newline at end of file
diff --git a/report.py b/report.py
index aaaaa53..e21665d 100644
--- a/report.py
+++ b/report.py
@@ -1,7 +1,11 @@
import argparse
from collections import OrderedDict
+import itertools
+import math
+import re
from chart import charts
+import formatters
from utils import ssize_to_b
@@ -24,58 +28,95 @@
return parser.parse_args(argv)
-def build_vertical_bar(results):
+def pgbench_chart_data(results):
+ """
+ Format pgbench results for chart
+ """
data = {}
charts_url = []
- for build, results in results.items():
- for key, value in results.results.items():
- keys = key.split(' ')
- if not data.get(keys[2]):
- data[keys[2]] = {}
- if not data[keys[2]].get(build):
- data[keys[2]][build] = {}
- data[keys[2]][build][
- ' '.join([keys[0], sync_async_view[keys[1]]])] = value
+ formatted_res = formatters.format_pgbench_stat(results)
+ for key, value in formatted_res.items():
+ num_cl, num_tr = key.split(' ')
+ data.setdefault(num_cl, {}).setdefault(build, {})
+ data[keys[z]][build][
+ ' '.join(keys)] = value
for name, value in data.items():
- for op_type, operations in OPERATIONS:
- title = "Block size: " + name
- legend = []
- dataset = []
+ title = name
+ legend = []
+ dataset = []
- scale_x = []
+ scale_x = []
- for build_id, build_results in value.items():
- vals = []
+ for build_id, build_results in value.items():
+ vals = []
+ OD = OrderedDict
+ ordered_build_results = OD(sorted(build_results.items(),
+ key=lambda t: t[0]))
+ scale_x = ordered_build_results.keys()
+ for key in scale_x:
+ res = build_results.get(key)
+ if res:
+ vals.append(res)
+ if vals:
+ dataset.append(vals)
+ legend.append(build_id)
- for key in operations:
- res = build_results.get(key)
- if res:
- vals.append(res)
- scale_x.append(key)
- if vals:
- dataset.append(vals)
- legend.append(build_id)
-
- if dataset:
- charts_url.append(str(charts.render_vertical_bar
- (title, legend, dataset, scale_x=scale_x)))
+ if dataset:
+ charts_url.append(str(charts.render_vertical_bar
+ (title, legend, dataset, scale_x=scale_x)))
return charts_url
-def build_lines_chart(results):
+def build_vertical_bar(results, z=0):
+ data = {}
+ charts_url = []
+ for build, res in results:
+ formatted_res = formatters.get_formatter(build)(res)
+ for key, value in formatted_res.items():
+ keys = key.split(' ')
+ data.setdefault(keys[z], {}).setdefault(build, {})
+ data[keys[z]][build][
+ ' '.join(keys)] = value
+
+ for name, value in data.items():
+ title = name
+ legend = []
+ dataset = []
+
+ scale_x = []
+
+ for build_id, build_results in value.items():
+ vals = []
+ OD = OrderedDict
+ ordered_build_results = OD(sorted(build_results.items(),
+ key=lambda t: t[0]))
+ scale_x = ordered_build_results.keys()
+ for key in scale_x:
+ res = build_results.get(key)
+ if res:
+ vals.append(res)
+ if vals:
+ dataset.append(vals)
+ legend.append(build_id)
+
+ if dataset:
+ charts_url.append(str(charts.render_vertical_bar
+ (title, legend, dataset, scale_x=scale_x)))
+ return charts_url
+
+
+def build_lines_chart(results, z=0):
data = {}
charts_url = []
- for build, results in results.items():
- for key, value in results.results.items():
+ for build, res in results:
+ formatted_res = formatters.get_formatter(build)(res)
+ for key, value in formatted_res.items():
keys = key.split(' ')
- if not data.get(' '.join([keys[0], keys[1]])):
- data[' '.join([keys[0], keys[1]])] = {}
- if not data[' '.join([keys[0], keys[1]])].get(build):
- data[' '.join([keys[0], keys[1]])][build] = {}
- data[' '.join([keys[0], keys[1]])][build][keys[2]] = value
+ data.setdefault(key[z], {})
+ data[key[z]].setdefault(build, {})[keys[1]] = value
for name, value in data.items():
title = name
@@ -99,7 +140,7 @@
return charts_url
-def render_html(charts_urls):
+def render_html(charts_urls, dest):
templ = open("report.html", 'r').read()
body = "<div><ol>%s</ol></div>"
li = "<li><img src='%s'></li>"
@@ -107,22 +148,82 @@
for chart in charts_urls:
ol.append(li % chart)
html = templ % {'body': body % '\n'.join(ol)}
- open('results.html', 'w').write(html)
+ open(dest, 'w').write(html)
+def build_io_chart(res):
+ pass
+
+
+def render_html_results(ctx, dest):
+ charts = []
+ import ipdb;ipdb.set_trace()
+ for res in ctx.results:
+ if res[0] == "io":
+ charts.append(build_io_chart(res))
+
+ bars = build_vertical_bar(ctx.results)
+ lines = build_lines_chart(ctx.results)
+
+ render_html(bars + lines, dest)
+
# def report(url, email=None, password=None):
# results = storage.recent_builds()
# bars = build_vertical_bar(results)
# lines = build_lines_chart(results)
#
# render_html(bars + lines)
+#
-#
-# def main(argv):
-# opts = parse_args(argv)
-# report(opts.url)
-# return 0
-#
-#
-# if __name__ == '__main__':
-# exit(main(sys.argv[1:]))
+
+def calc_dev(l):
+ sum_res = sum(l)
+ mean = sum_res/len(l)
+ sum_sq = sum([(r - mean) ** 2 for r in l])
+ if len(l) > 1:
+ return math.sqrt(sum_sq / (len(l) - 1))
+ else:
+ return 0
+
+
+def main():
+ from tests.disk_test_agent import parse_output
+ out = parse_output(
+ open("results/io_scenario_check_th_count.txt").read()).next()
+ results = out['res']
+
+ charts_url = []
+ charts_data = {}
+ for test_name, test_res in results.items():
+ blocksize = test_res['blocksize']
+ op_type = "sync" if test_res['sync'] else "direct"
+ chart_name = "Block size: %s %s" % (blocksize, op_type)
+ lat = sum(test_res['lat']) / len(test_res['lat']) / 1000
+ lat_dev = calc_dev(test_res['lat'])
+ iops = sum(test_res['iops']) / len(test_res['iops'])
+ iops_dev = calc_dev(test_res['iops'])
+ bw = sum(test_res['bw_mean']) / len(test_res['bw_mean'])
+ bw_dev = calc_dev(test_res['bw_mean'])
+ conc = test_res['concurence']
+ vals = ((lat, lat_dev), (iops, iops_dev), (bw, bw_dev))
+ charts_data.setdefault(chart_name, {})[conc] = vals
+
+ for chart_name, chart_data in charts_data.items():
+ legend = ["bw"]
+ ordered_data = OrderedDict(sorted(chart_data.items(),
+ key=lambda t: t[0]))
+
+ lat_d, iops_d, bw_d = zip(*ordered_data.values())
+ bw_sum = [vals[2][0] * conc for conc, vals in ordered_data.items()]
+
+ chart_url = str(charts.render_vertical_bar(
+ chart_name, legend, [bw_d], label_x="KBps",
+ scale_x=ordered_data.keys(),
+ lines=[(zip(*lat_d)[0], 'msec', 'rr', 'lat'), (bw_sum, None, None, 'bw_sum')]))
+ charts_url.append(chart_url)
+ render_html(charts_url, "results.html")
+ return 0
+
+
+if __name__ == '__main__':
+ exit(main())
diff --git a/run_test.py b/run_test.py
index 1dac2e5..3cbdae2 100755
--- a/run_test.py
+++ b/run_test.py
@@ -10,6 +10,8 @@
import collections
from concurrent.futures import ThreadPoolExecutor
+import formatters
+import report
import utils
import ssh_utils
@@ -266,10 +268,14 @@
def report_stage(cfg, ctx):
output_dest = cfg.get('output_dest')
if output_dest is not None:
- with open(output_dest, "w") as fd:
- data = {"sensor_data": ctx.sensor_data,
- "results": ctx.results}
- fd.write(json.dumps(data))
+ if output_dest.endswith(".html"):
+ report.render_html_results(ctx, output_dest)
+ logger.info("Results were stored in %s" % output_dest)
+ else:
+ with open(output_dest, "w") as fd:
+ data = {"sensor_data": ctx.sensor_data,
+ "results": ctx.results}
+ fd.write(json.dumps(data))
else:
print "=" * 20 + " RESULTS " + "=" * 20
pprint.pprint(ctx.results)