Merge lp:~cjohnston/qa-dashboard/1209161 into lp:qa-dashboard

Proposed by Chris Johnston
Status: Merged
Approved by: Chris Johnston
Approved revision: 582
Merged at revision: 583
Proposed branch: lp:~cjohnston/qa-dashboard/1209161
Merge into: lp:qa-dashboard
Diff against target: 340 lines (+205/-43)
5 files modified
bootspeed/templates/bootspeed/kpi_simple_average.html (+1/-1)
common/static/css/style.css (+10/-0)
eventstat/templates/eventstat/kpi_simple_average.html (+1/-1)
smokeng/dashboard.py (+161/-41)
smokeng/templates/smokeng/kpi_variant_pass_rate.html (+32/-0)
To merge this branch: bzr merge lp:~cjohnston/qa-dashboard/1209161
Reviewer Review Type Date Requested Status
Andy Doan (community) Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+181606@code.launchpad.net

Commit message

Shows smoke kpi per variant per release

Description of the change

Due to the potential massive differences between the different variants, we should display the kpi per variant per release

Also floats kpi 'help' to the right side of the kpi's

To post a comment you must log in.
lp:~cjohnston/qa-dashboard/1209161 updated
582. By Chris Johnston

Add smoke kpi by variant

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:582
http://s-jenkins:8080/job/dashboard-ci/162/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins:8080/job/dashboard-ci/162/rebuild

review: Approve (continuous-integration)
Revision history for this message
Andy Doan (doanac) wrote :

i didn't notice how/why this is needed:

32 +.r {
33 + position: relative!important;
34 + margin: 0!important;
35 + background: transparent!important;
36 + padding: 0!important;
37 +}

Revision history for this message
Andy Doan (doanac) wrote :

dashboard.py is started to get a bit out of control. But I suppose carrying around that baggage might be handy some day

Revision history for this message
Chris Johnston (cjohnston) wrote :

Andy, the css change was required to be able to do the coloring.

Revision history for this message
Andy Doan (doanac) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bootspeed/templates/bootspeed/kpi_simple_average.html'
--- bootspeed/templates/bootspeed/kpi_simple_average.html 2013-07-03 15:12:46 +0000
+++ bootspeed/templates/bootspeed/kpi_simple_average.html 2013-08-22 16:13:38 +0000
@@ -3,7 +3,7 @@
3 <strong>Build:</strong> {{ build_number }}3 <strong>Build:</strong> {{ build_number }}
4 {% endif %}4 {% endif %}
5 {% if help_info %}5 {% if help_info %}
6 <a class="css-tooltip no-border" href="#"><div class="help">?</div><span class="classic">6 <a class="css-tooltip no-border" href="#"><div class="help kpihelp">?</div><span class="classic">
7 {{ help_info }}7 {{ help_info }}
8 </span></a>8 </span></a>
9 {% endif %}9 {% endif %}
1010
=== modified file 'common/static/css/style.css'
--- common/static/css/style.css 2013-08-19 15:25:18 +0000
+++ common/static/css/style.css 2013-08-22 16:13:38 +0000
@@ -764,6 +764,10 @@
764 width: 25px;764 width: 25px;
765}765}
766766
767div.kpihelp {
768 float: right;
769}
770
767.css-tooltip {771.css-tooltip {
768 border-bottom: 1px dotted #000000;772 border-bottom: 1px dotted #000000;
769 color: #000000; outline: none;773 color: #000000; outline: none;
@@ -873,3 +877,9 @@
873 padding-bottom: 10px!important;877 padding-bottom: 10px!important;
874}878}
875879
880.r {
881 position: relative!important;
882 margin: 0!important;
883 background: transparent!important;
884 padding: 0!important;
885}
876886
=== modified file 'eventstat/templates/eventstat/kpi_simple_average.html'
--- eventstat/templates/eventstat/kpi_simple_average.html 2013-07-03 15:12:46 +0000
+++ eventstat/templates/eventstat/kpi_simple_average.html 2013-08-22 16:13:38 +0000
@@ -3,7 +3,7 @@
3 <strong>Build:</strong> {{ build_number }}3 <strong>Build:</strong> {{ build_number }}
4 {% endif %}4 {% endif %}
5 {% if help_info %}5 {% if help_info %}
6 <a class="css-tooltip no-border" href="#"><div class="help">?</div><span class="classic">6 <a class="css-tooltip no-border" href="#"><div class="help kpihelp">?</div><span class="classic">
7 {{ help_info }}7 {{ help_info }}
8 </span></a>8 </span></a>
9 {% endif %}9 {% endif %}
1010
=== modified file 'smokeng/dashboard.py'
--- smokeng/dashboard.py 2013-08-14 02:44:00 +0000
+++ smokeng/dashboard.py 2013-08-22 16:13:38 +0000
@@ -51,10 +51,11 @@
51 def importance(self):51 def importance(self):
52 return self.IMPORTANCE_HIGH52 return self.IMPORTANCE_HIGH
5353
54 def _get_result_bug_count(self, build_number):54 def _get_result_bug_count(self, build_number, variant=None):
55 qs = SmokeResultBug.objects.filter(55 qs = SmokeResultBug.objects.filter(
56 publish=True,56 publish=True,
57 result__image__build_number=build_number,57 result__image__build_number=build_number,
58 result__image__variant=variant,
58 ).values(59 ).values(
59 'result__image__release',60 'result__image__release',
60 'bug__bug_no',61 'bug__bug_no',
@@ -79,8 +80,11 @@
79 def _get_result_data(self):80 def _get_result_data(self):
80 qs = SmokeResult.objects.filter(81 qs = SmokeResult.objects.filter(
81 publish=True,82 publish=True,
83 ).exclude(
84 image__build_number__contains='?',
82 ).values(85 ).values(
83 'image__arch',86 'image__arch',
87 'image__variant',
84 'image__release',88 'image__release',
85 'image__build_number',89 'image__build_number',
86 ).annotate(90 ).annotate(
@@ -98,6 +102,9 @@
98 entry['image__release'],102 entry['image__release'],
99 {},103 {},
100 ).setdefault(104 ).setdefault(
105 entry['image__variant'],
106 {},
107 ).setdefault(
101 entry['image__arch'],108 entry['image__arch'],
102 {},109 {},
103 ).setdefault(110 ).setdefault(
@@ -115,45 +122,51 @@
115 TREND_ENTRIES = 7122 TREND_ENTRIES = 7
116123
117 results = {}124 results = {}
118 for release, arches in entry_tree.items():125 for release, variants in entry_tree.items():
119 #print("release: {}, arches: {}".format(release, arches))126 for variant, arches in variants.items():
120 for arch_name, arch in arches.items():127 for arch_name, arch in arches.items():
121 res_arch = results.setdefault(128 res_arch = results.setdefault(
122 release,129 release,
123 {},130 {},
124 ).setdefault(131 ).setdefault(
125 arch_name,132 variant,
126 {},133 {},
127 )134 ).setdefault(
128 keys = arch.keys()135 arch_name,
129 item_count = min(len(keys), TREND_ENTRIES)136 {},
130 for build in sorted(keys, reverse=True)[:item_count]:137 )
131 res_arch.setdefault(138 keys = arch.keys()
132 'latest_build_number',139
133 build140 item_count = min(len(keys), TREND_ENTRIES)
134 )141 for build in sorted(keys, reverse=True)[:item_count]:
135142 res_arch.setdefault(
136 arch_build = arch[build]143 'latest_build_number',
137 arch_build['pass_rate'] = 0144 build
138 if len(arch_build['pass_rates']) > 0:145 )
139 pr_sum = sum(arch_build['pass_rates'])146 arch_build = arch[build]
140 pr_len = len(arch_build['pass_rates'])147 arch_build['pass_rate'] = 0
141 arch_build['pass_rate'] = pr_sum / pr_len148 if len(arch_build['pass_rates']) > 0:
142149 pr_sum = sum(arch_build['pass_rates'])
143 res_arch.setdefault('pass_rate', arch_build['pass_rate'])150 pr_len = len(arch_build['pass_rates'])
144151 arch_build['pass_rate'] = pr_sum / pr_len
145 if build > res_arch['latest_build_number']:152
146 res_arch['latest_build_number'] = build153 res_arch.setdefault(
147 res_arch['pass_rate'] = arch_build['pass_rate']154 'pass_rate',
148155 arch_build['pass_rate'],
149 res_arch.setdefault('data', []).append(156 )
150 dict(157
151 release=release,158 if build > res_arch['latest_build_number']:
152 arch=arch_name,159 res_arch['latest_build_number'] = build
153 build_number=build,160 res_arch['pass_rate'] = arch_build['pass_rate']
154 pass_rate=arch_build['pass_rate'],161
155 )162 res_arch.setdefault('data', []).append(
156 )163 dict(
164 release=release,
165 arch=arch_name,
166 build_number=build,
167 pass_rate=arch_build['pass_rate'],
168 )
169 )
157170
158 return results171 return results
159172
@@ -326,6 +339,113 @@
326 return retval339 return retval
327340
328341
342class SmokengVariantPassRateKPI(SmokengPassRateKPI):
343 """
344 A simple KPI entry with an average pass-rate for each variant in each
345 release.
346
347 This KPI determines the latest build number for each variant and shows
348 an average of those results for each release.
349
350 To identify missing images a list of architectures used to calculate
351 the pass-rate for each release are listed.
352
353 A count of bugs filed by the QA Team is also included.
354
355 """
356
357 def _get_latest_build_number(self, results, release, variant):
358
359 build_numbers = []
360
361 if release in results and variant in results[release]:
362 for arch, a_data in results[release][variant].items():
363 build_numbers.append(a_data['latest_build_number'])
364
365 if len(build_numbers) == 0:
366 return ""
367
368 # TODO: fix so it's sorted by float(build_number)
369 return sorted(build_numbers, reverse=True)[0]
370
371 def render(self):
372
373 results = self._calculate_pass_rates()
374
375 skipped_releases = ['quantal', 'raring']
376 entries = []
377 for release in sorted(results.keys(), reverse=True):
378 if release in skipped_releases:
379 continue
380 variants = results[release]
381 variant_entries = []
382 for variant in sorted(variants.keys(), reverse=True):
383 found_arches = []
384 arches = results[release][variant]
385 expected_build = self._get_latest_build_number(
386 results,
387 release,
388 variant,
389 )
390
391 bug_counts = self._get_result_bug_count(
392 expected_build,
393 variant,
394 )
395
396 arch_passrates = []
397 has_expected_build = False
398 for arch in sorted(arches.keys()):
399 data = arches[arch]
400 build_no = data['latest_build_number']
401 if build_no == expected_build:
402 arch_passrates.append(data['pass_rate'])
403 found_arches.append(arch)
404 has_expected_build = True
405
406 pass_rate = 0.0
407
408 if len(arch_passrates) > 0:
409 pass_rate = sum(arch_passrates) / len(arch_passrates)
410
411 bug_count = bug_counts.get(release, 0)
412
413 if has_expected_build:
414 build_no = expected_build
415 else:
416 build_no = ''
417
418 variant_kpi = dict(
419 variant=variant,
420 results=dict(
421 build_no=build_no,
422 pass_rate=pass_rate,
423 found_arches=found_arches,
424 bug_count=bug_count,
425 ),
426 )
427 variant_entries.append(variant_kpi)
428 release_kpi = dict(
429 release=release,
430 kpi=variant_entries,
431 )
432 entries.append(release_kpi)
433
434 retval = render_to_string(
435 'smokeng/kpi_variant_pass_rate.html',
436 dict(
437 entries=entries,
438 help_info="""The average pass_rate for each variant is
439 calculated by accounting for each architecture (i.e. "amd64",
440 "i386", "armhf") in the variant. These averages are averaged
441 for each release being tracked. Hover over the pass rate
442 for each release for the number of bugs reported.""",
443 ),
444 )
445
446 return retval
447
448
329class SmokengExtension(Extension):449class SmokengExtension(Extension):
330 URL_PATTERNS = patterns(450 URL_PATTERNS = patterns(
331 '',451 '',
@@ -343,7 +463,7 @@
343463
344 def contribute_to_kpis(self, kpi_mgr):464 def contribute_to_kpis(self, kpi_mgr):
345 return [465 return [
346 SmokengPassRateV3KPI,466 SmokengVariantPassRateKPI,
347 ]467 ]
348468
349 def pull_data(self):469 def pull_data(self):
350470
=== added file 'smokeng/templates/smokeng/kpi_variant_pass_rate.html'
--- smokeng/templates/smokeng/kpi_variant_pass_rate.html 1970-01-01 00:00:00 +0000
+++ smokeng/templates/smokeng/kpi_variant_pass_rate.html 2013-08-22 16:13:38 +0000
@@ -0,0 +1,32 @@
1{% load dashboard_extras %}
2 {% if help_info %}
3 <a class="css-tooltip no-border" href="#"><div class="help kpihelp">?</div><span class="classic">
4 {{ help_info }}
5 </span></a>
6 {% endif %}
7 {% for release in entries %}
8 <strong>{{ release.release|capfirst }}</strong>
9 <table class="kpi">
10 {% for kpi in release.kpi %}
11 <tr>
12 <td><a href="{% url smokeng_overview release.release kpi.variant %}">{{ kpi.variant }}</a></td>
13 <td>
14 {{ kpi.results.build_no }}
15 </td>
16 <td class="num pad-seven {{ kpi.results.pass_rate|pass_rate_color }}">
17 <a class="css-tooltip no-border" href="#">
18 <div class="r" style="color: {% if kpi.results.pass_rate|pass_rate_color == "yellow" %}#000;{% else %}#fff;{% endif %}">
19 {{ kpi.results.pass_rate|decimal_to_percent }}</div>
20 <span class="classic">
21 {{ kpi.results.bug_count }} Bug{% if kpi.results.bug_count > 1 %}s{% endif %}
22 </span>
23 </a>
24 </td>
25 <td class="pad-seven">
26 {% if kpi.results.found_arches %}{% for arch in kpi.results.found_arches %}{{ arch|product_name }}{% if not forloop.last %}, {% endif %}{% endfor %}
27 {% endif %}
28 </td>
29 </tr>
30{% endfor %}
31</table>
32{% endfor %}

Subscribers

People subscribed via source and target branches