koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 1 | import os |
| 2 | import sys |
| 3 | |
| 4 | from wally import charts |
| 5 | from wally.statistic import med_dev |
| 6 | from wally.utils import parse_creds |
| 7 | from wally.suits.io.results_loader import filter_data |
| 8 | from wally.meta_info import total_lab_info, collect_lab_data |
| 9 | |
| 10 | |
| 11 | # from collections import OrderedDict |
| 12 | # from wally.suits.io import formatter |
| 13 | # def pgbench_chart_data(results): |
| 14 | # """ |
| 15 | # Format pgbench results for chart |
| 16 | # """ |
| 17 | # data = {} |
| 18 | # charts_url = [] |
| 19 | |
| 20 | # formatted_res = formatters.format_pgbench_stat(results) |
| 21 | # for key, value in formatted_res.items(): |
| 22 | # num_cl, num_tr = key.split(' ') |
| 23 | # data.setdefault(num_cl, {}).setdefault(build, {}) |
| 24 | # data[keys[z]][build][ |
| 25 | # ' '.join(keys)] = value |
| 26 | |
| 27 | # for name, value in data.items(): |
| 28 | # title = name |
| 29 | # legend = [] |
| 30 | # dataset = [] |
| 31 | |
| 32 | # scale_x = [] |
| 33 | |
| 34 | # for build_id, build_results in value.items(): |
| 35 | # vals = [] |
| 36 | # OD = OrderedDict |
| 37 | # ordered_build_results = OD(sorted(build_results.items(), |
| 38 | # key=lambda t: t[0])) |
| 39 | # scale_x = ordered_build_results.keys() |
| 40 | # for key in scale_x: |
| 41 | # res = build_results.get(key) |
| 42 | # if res: |
| 43 | # vals.append(res) |
| 44 | # if vals: |
| 45 | # dataset.append(vals) |
| 46 | # legend.append(build_id) |
| 47 | |
| 48 | # if dataset: |
| 49 | # charts_url.append(str(charts.render_vertical_bar |
| 50 | # (title, legend, dataset, scale_x=scale_x))) |
| 51 | # return charts_url |
| 52 | |
| 53 | # def build_lines_chart(results, z=0): |
| 54 | # data = {} |
| 55 | # charts_url = [] |
| 56 | |
| 57 | # for build, res in results: |
| 58 | # formatted_res = formatters.get_formatter(build)(res) |
| 59 | # for key, value in formatted_res.items(): |
| 60 | # keys = key.split(' ') |
| 61 | # data.setdefault(key[z], {}) |
| 62 | # data[key[z]].setdefault(build, {})[keys[1]] = value |
| 63 | |
| 64 | # for name, value in data.items(): |
| 65 | # title = name |
| 66 | # legend = [] |
| 67 | # dataset = [] |
| 68 | # scale_x = [] |
| 69 | # for build_id, build_results in value.items(): |
| 70 | # legend.append(build_id) |
| 71 | |
| 72 | # OD = OrderedDict |
| 73 | # ordered_build_results = OD(sorted(build_results.items(), |
| 74 | # key=lambda t: ssize_to_b(t[0]))) |
| 75 | |
| 76 | # if not scale_x: |
| 77 | # scale_x = ordered_build_results.keys() |
| 78 | # dataset.append(zip(*ordered_build_results.values())[0]) |
| 79 | |
| 80 | # chart = charts.render_lines(title, legend, dataset, scale_x) |
| 81 | # charts_url.append(str(chart)) |
| 82 | |
| 83 | # return charts_url |
| 84 | |
| 85 | # def build_vertical_bar(results, z=0): |
| 86 | # data = {} |
| 87 | # charts_url = [] |
| 88 | # for build, res in results: |
| 89 | # formatted_res = formatter.get_formatter(build)(res) |
| 90 | # for key, value in formatted_res.items(): |
| 91 | # keys = key.split(' ') |
| 92 | # data.setdefault(keys[z], {}).setdefault(build, {}) |
| 93 | # data[keys[z]][build][ |
| 94 | # ' '.join(keys)] = value |
| 95 | |
| 96 | # for name, value in data.items(): |
| 97 | # title = name |
| 98 | # legend = [] |
| 99 | # dataset = [] |
| 100 | |
| 101 | # scale_x = [] |
| 102 | |
| 103 | # for build_id, build_results in value.items(): |
| 104 | # vals = [] |
| 105 | # OD = OrderedDict |
| 106 | # ordered_build_results = OD(sorted(build_results.items(), |
| 107 | # key=lambda t: t[0])) |
| 108 | # scale_x = ordered_build_results.keys() |
| 109 | # for key in scale_x: |
| 110 | # res = build_results.get(key) |
| 111 | # if res: |
| 112 | # vals.append(res) |
| 113 | # if vals: |
| 114 | # dataset.append(vals) |
| 115 | # legend.append(build_id) |
| 116 | |
| 117 | # if dataset: |
| 118 | # charts_url.append(str(charts.render_vertical_bar |
| 119 | # (title, legend, dataset, scale_x=scale_x))) |
| 120 | # return charts_url |
| 121 | |
| 122 | |
| 123 | def render_html(charts_urls, dest, lab_description, info): |
| 124 | templ = open("report.html", 'r').read() |
| 125 | body = "<a href='#lab_desc'>Lab description</a>" \ |
| 126 | "<ol>{0}</ol>" \ |
| 127 | "<div>{1}</div>" \ |
| 128 | '<a name="lab_desc"></a>' \ |
| 129 | "<div><ul>{2}</ul></div>" |
| 130 | table = "<table><tr><td>{0}</td><td>{1}</td></tr>" \ |
| 131 | "<tr><td>{2}</td><td>{3}</td></tr></table>" |
| 132 | ul = [] |
| 133 | ol = [] |
| 134 | li = '<li>{0} : {1}</li>' |
| 135 | |
| 136 | for elem in info: |
| 137 | ol.append(li.format(elem.keys(), elem.values())) |
| 138 | |
| 139 | for key in lab_description: |
| 140 | value = lab_description[key] |
| 141 | ul.append("<li>{0} : {1}</li>".format(key, value)) |
| 142 | |
| 143 | charts_urls = ['<img src="{0}">'.format(url) for url in charts_urls] |
| 144 | |
| 145 | body = body.format('\n'.join(ol), |
| 146 | table.format(*charts_urls), |
| 147 | '\n'.join(ul)) |
| 148 | |
| 149 | open(dest, 'w').write(templ % {'body': body}) |
| 150 | |
| 151 | |
| 152 | def io_chart(title, concurence, latv, iops_or_bw, iops_or_bw_dev, |
| 153 | legend, fname): |
| 154 | bar_data, bar_dev = iops_or_bw, iops_or_bw_dev |
| 155 | legend = [legend] |
| 156 | |
| 157 | iops_or_bw_per_vm = [] |
| 158 | for i in range(len(concurence)): |
| 159 | iops_or_bw_per_vm.append(iops_or_bw[i] / concurence[i]) |
| 160 | |
| 161 | bar_dev_bottom = [] |
| 162 | bar_dev_top = [] |
| 163 | for i in range(len(bar_data)): |
| 164 | bar_dev_top.append(bar_data[i] + bar_dev[i]) |
| 165 | bar_dev_bottom.append(bar_data[i] - bar_dev[i]) |
| 166 | |
| 167 | latv = [lat / 1000 for lat in latv] |
| 168 | ch = charts.render_vertical_bar(title, legend, [bar_data], [bar_dev_top], |
| 169 | [bar_dev_bottom], file_name=fname, |
| 170 | scale_x=concurence, |
| 171 | lines=[ |
| 172 | (latv, "msec", "rr", "lat"), |
| 173 | (iops_or_bw_per_vm, None, None, |
| 174 | "bw_per_vm") |
| 175 | ]) |
| 176 | return str(ch) |
| 177 | |
| 178 | |
| 179 | def make_io_report(results, path, lab_url=None, creds=None): |
| 180 | if lab_url is not None: |
| 181 | username, password, tenant_name = parse_creds(creds) |
| 182 | creds = {'username': username, |
| 183 | 'password': password, |
| 184 | "tenant_name": tenant_name} |
| 185 | data = collect_lab_data(lab_url, creds) |
| 186 | lab_info = total_lab_info(data) |
| 187 | else: |
| 188 | lab_info = "" |
| 189 | |
| 190 | for suite_type, test_suite_data in results: |
| 191 | if suite_type != 'io' or test_suite_data is None: |
| 192 | continue |
| 193 | |
| 194 | io_test_suite_res = test_suite_data['res'] |
| 195 | |
| 196 | charts_url = [] |
| 197 | info = [] |
| 198 | |
| 199 | name_filters = [ |
| 200 | ('hdd_test_rrd4k', ('concurence', 'lat', 'iops'), 'rand_read_4k'), |
| 201 | ('hdd_test_swd1m', ('concurence', 'lat', 'bw'), 'seq_write_1m'), |
| 202 | ('hdd_test_srd1m', ('concurence', 'lat', 'bw'), 'seq_read_1m'), |
| 203 | ('hdd_test_rws4k', ('concurence', 'lat', 'bw'), 'rand_write_1m') |
| 204 | ] |
| 205 | |
| 206 | for name_filter, fields, fname in name_filters: |
| 207 | th_filter = filter_data(name_filter, fields) |
| 208 | |
| 209 | data = sorted(th_filter(io_test_suite_res.values())) |
| 210 | if len(data) == 0: |
| 211 | continue |
| 212 | |
| 213 | concurence, latv, iops_or_bw_v = zip(*data) |
| 214 | iops_or_bw_v, iops_or_bw_dev_v = zip(*map(med_dev, iops_or_bw_v)) |
| 215 | latv, _ = zip(*map(med_dev, latv)) |
| 216 | |
| 217 | url = io_chart(name_filter, concurence, latv, iops_or_bw_v, |
| 218 | iops_or_bw_dev_v, |
| 219 | fields[2], fname) |
| 220 | info.append(dict(zip(fields, (concurence, latv, iops_or_bw_v)))) |
| 221 | charts_url.append(url) |
| 222 | |
| 223 | if len(charts_url) != 0: |
| 224 | render_html(charts_url, path, lab_info, info) |
| 225 | |
| 226 | |
| 227 | def main(args): |
| 228 | make_io_report(results=[('a', 'b')], |
| 229 | path=os.path.dirname(args[0]), |
| 230 | lab_url='http://172.16.52.112:8000', |
| 231 | creds='admin:admin@admin') |
| 232 | return 0 |
| 233 | |
| 234 | |
| 235 | if __name__ == '__main__': |
| 236 | exit(main(sys.argv)) |