[LNT] r343467 - Install missing files.
Martin Liska via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 1 05:38:11 PDT 2018
Author: marxin
Date: Mon Oct 1 05:38:11 2018
New Revision: 343467
URL: http://llvm.org/viewvc/llvm-project?rev=343467&view=rev
Log:
Install missing files.
Added:
lnt/trunk/lnt/server/reporting/latestrunsreport.py
lnt/trunk/lnt/server/reporting/report.py
lnt/trunk/lnt/server/ui/templates/reporting/latest_runs_report.html
lnt/trunk/lnt/server/ui/templates/reportutils.html
lnt/trunk/lnt/server/ui/templates/v4_latest_runs_report.html
Added: lnt/trunk/lnt/server/reporting/latestrunsreport.py
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/reporting/latestrunsreport.py?rev=343467&view=auto
==============================================================================
--- lnt/trunk/lnt/server/reporting/latestrunsreport.py (added)
+++ lnt/trunk/lnt/server/reporting/latestrunsreport.py Mon Oct 1 05:38:11 2018
@@ -0,0 +1,114 @@
+from collections import namedtuple
+from lnt.server.reporting.analysis import REGRESSED, UNCHANGED_FAIL
+from lnt.server.reporting.report import RunResult, RunResults, report_css_styles
+from lnt.util import multidict
+import lnt.server.reporting.analysis
+import lnt.server.ui.app
+import sqlalchemy.sql
+import urllib
+
+class LatestRunsReport(object):
+ def __init__(self, ts, run_count):
+ self.ts = ts
+ self.run_count = run_count
+ self.hash_of_binary_field = self.ts.Sample.get_hash_of_binary_field()
+ self.fields = list(ts.Sample.get_metric_fields())
+
+ # Computed values.
+ self.result_table = None
+
+ def build(self, session):
+ ts = self.ts
+
+ machines = session.query(ts.Machine).all()
+
+ self.result_table = []
+ for field in self.fields:
+ field_results = []
+ for machine in machines:
+ machine_results = []
+ machine_runs = list(reversed(session.query(ts.Run)
+ .filter(ts.Run.machine_id == machine.id)
+ .order_by(ts.Run.start_time.desc())
+ .limit(self.run_count)
+ .all()))
+
+ if len(machine_runs) < 2:
+ continue
+
+ machine_runs_ids = [r.id for r in machine_runs]
+
+ # take all tests from latest run and do a comparison
+ oldest_run = machine_runs[0]
+
+ run_tests = session.query(ts.Test) \
+ .join(ts.Sample) \
+ .join(ts.Run) \
+ .filter(ts.Sample.run_id == oldest_run.id) \
+ .filter(ts.Sample.test_id == ts.Test.id) \
+ .all()
+
+ # Create a run info object.
+ sri = lnt.server.reporting.analysis.RunInfo(session, ts, machine_runs_ids)
+
+ # Build the result table of tests with interesting results.
+ def compute_visible_results_priority(visible_results):
+ # We just use an ad hoc priority that favors showing tests with
+ # failures and large changes. We do this by computing the priority
+ # as tuple of whether or not there are any failures, and then sum
+ # of the mean percentage changes.
+ test, results = visible_results
+ had_failures = False
+ sum_abs_deltas = 0.
+ for result in results:
+ test_status = result.cr.get_test_status()
+
+ if (test_status == REGRESSED or test_status == UNCHANGED_FAIL):
+ had_failures = True
+ elif result.cr.pct_delta is not None:
+ sum_abs_deltas += abs(result.cr.pct_delta)
+ return (field.name, -int(had_failures), -sum_abs_deltas, test.name)
+
+ for test in run_tests:
+ cr = sri.get_comparison_result(
+ [machine_runs[-1]], [oldest_run], test.id, field,
+ self.hash_of_binary_field)
+
+ # If the result is not "interesting", ignore it.
+ if not cr.is_result_interesting():
+ continue
+
+ # For all previous runs, analyze comparison results
+ test_results = RunResults()
+
+ for run in reversed(machine_runs):
+ cr = sri.get_comparison_result(
+ [run], [oldest_run], test.id, field,
+ self.hash_of_binary_field)
+ test_results.append(RunResult(cr))
+
+ test_results.complete()
+
+ machine_results.append((test, test_results))
+
+ machine_results.sort(key=compute_visible_results_priority)
+
+ # If there are visible results for this test, append it to the
+ # view.
+ if machine_results:
+ field_results.append((machine, len(machine_runs), machine_results))
+
+ field_results.sort(key=lambda x: x[0].name)
+ self.result_table.append((field, field_results))
+
+ def render(self, ts_url, only_html_body=True):
+ # Strip any trailing slash on the testsuite URL.
+ if ts_url.endswith('/'):
+ ts_url = ts_url[:-1]
+
+ env = lnt.server.ui.app.create_jinja_environment()
+ template = env.get_template('reporting/latest_runs_report.html')
+
+ return template.render(
+ report=self, styles=report_css_styles, analysis=lnt.server.reporting.analysis,
+ ts_url=ts_url, only_html_body=only_html_body)
Added: lnt/trunk/lnt/server/reporting/report.py
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/reporting/report.py?rev=343467&view=auto
==============================================================================
--- lnt/trunk/lnt/server/reporting/report.py (added)
+++ lnt/trunk/lnt/server/reporting/report.py Mon Oct 1 05:38:11 2018
@@ -0,0 +1,131 @@
+"""
+Common functions and classes that are used by reports.
+"""
+
+import colorsys
+
+from collections import namedtuple
+
+OrderAndHistory = namedtuple('OrderAndHistory', ['max_order', 'recent_orders'])
+
+def pairs(list):
+ return zip(list[:-1], list[1:])
+
+# The hash color palette avoids green and red as these colours are already used
+# in quite a few places to indicate "good" or "bad".
+_hash_color_palette = (
+ colorsys.hsv_to_rgb(h=45. / 360, s=0.3, v=0.9999), # warm yellow
+ colorsys.hsv_to_rgb(h=210. / 360, s=0.3, v=0.9999), # blue cyan
+ colorsys.hsv_to_rgb(h=300. / 360, s=0.3, v=0.9999), # mid magenta
+ colorsys.hsv_to_rgb(h=150. / 360, s=0.3, v=0.9999), # green cyan
+ colorsys.hsv_to_rgb(h=225. / 360, s=0.3, v=0.9999), # cool blue
+ colorsys.hsv_to_rgb(h=180. / 360, s=0.3, v=0.9999), # mid cyan
+)
+
+def _clamp(v, minVal, maxVal):
+ return min(max(v, minVal), maxVal)
+
+
+def _toColorString(col):
+ r, g, b = [_clamp(int(v * 255), 0, 255)
+ for v in col]
+ return "#%02x%02x%02x" % (r, g, b)
+
+
+def _get_rgb_colors_for_hashes(hash_strings):
+ hash2color = {}
+ unique_hash_counter = 0
+ for hash_string in hash_strings:
+ if hash_string is not None:
+ if hash_string in hash2color:
+ continue
+ hash2color[hash_string] = _hash_color_palette[unique_hash_counter]
+ unique_hash_counter += 1
+ if unique_hash_counter >= len(_hash_color_palette):
+ break
+ result = []
+ for hash_string in hash_strings:
+ if hash_string is None:
+ result.append(None)
+ else:
+ # If not one of the first N hashes, return rgb value 0,0,0 which is
+ # white.
+ rgb = hash2color.get(hash_string, (0.999, 0.999, 0.999))
+ result.append(_toColorString(rgb))
+ return result
+
+# Helper classes to make the sparkline chart construction easier in the jinja
+# template.
+class RunResult:
+ def __init__(self, comparisonResult):
+ self.cr = comparisonResult
+ self.hash = self.cr.cur_hash
+ self.samples = self.cr.samples
+ if self.samples is None:
+ self.samples = []
+
+class RunResults:
+ """
+ RunResults contains pre-processed data to easily construct the HTML for
+ a single row in the results table, showing how one test on one board
+ evolved over a number of runs.
+ """
+ def __init__(self):
+ self.results = []
+ self._complete = False
+ self.min_sample = None
+ self.max_sample = None
+
+ def __getitem__(self, i):
+ return self.results[i]
+
+ def __len__(self):
+ return len(self.results)
+
+ def append(self, day_result):
+ assert not self._complete
+ self.results.append(day_result)
+
+ def complete(self):
+ """
+ complete() needs to be called after all appends to this object, but
+ before the data is used the jinja template.
+ """
+ self._complete = True
+ all_samples = []
+ for dr in self.results:
+ if dr is None:
+ continue
+ if dr.cr.samples is not None and not dr.cr.failed:
+ all_samples.extend(dr.cr.samples)
+ if len(all_samples) > 0:
+ self.min_sample = min(all_samples)
+ self.max_sample = max(all_samples)
+ hashes = []
+ for dr in self.results:
+ if dr is None:
+ hashes.append(None)
+ else:
+ hashes.append(dr.hash)
+ rgb_colors = _get_rgb_colors_for_hashes(hashes)
+ for i, dr in enumerate(self.results):
+ if dr is not None:
+ dr.hash_rgb_color = rgb_colors[i]
+
+# Compute static CSS styles for elements. We use the style directly on
+# elements instead of via a stylesheet to support major email clients
+# (like Gmail) which can't deal with embedded style sheets.
+# These are derived from the static style.css file we use elsewhere.
+
+report_css_styles = {
+ "body": ("color:#000000; background-color:#ffffff; "
+ "font-family: Helvetica, sans-serif; font-size:9pt"),
+ "table": ("font-size:9pt; border-spacing: 0px; "
+ "border: 1px solid black"),
+ "th": (
+ "background-color:#eee; color:#666666; font-weight: bold; "
+ "cursor: default; text-align:center; font-weight: bold; "
+ "font-family: Verdana; padding:5px; padding-left:8px"),
+ "td": "padding:5px; padding-left:8px",
+ "right": "text-align: right;"
+ }
Added: lnt/trunk/lnt/server/ui/templates/reporting/latest_runs_report.html
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/templates/reporting/latest_runs_report.html?rev=343467&view=auto
==============================================================================
--- lnt/trunk/lnt/server/ui/templates/reporting/latest_runs_report.html (added)
+++ lnt/trunk/lnt/server/ui/templates/reporting/latest_runs_report.html Mon Oct 1 05:38:11 2018
@@ -0,0 +1,67 @@
+{% import "utils.html" as utils %}
+{% import "local.html" as local %}
+{% import "reportutils.html" as reportutils %}
+{% if not only_html_body %}
+<html>
+<head>
+ <title>Latest ({{ report.run_count }}) Runs Report</title>
+</head>
+<body style="{{ styles['body'] }}">
+{% endif %}
+
+<h2 style="text-align:center">Latest ({{ report.run_count }}) Runs Report</h2>
+
+{{ utils.regex_filter_box(input_id='machine-filter',
+ selector='.searchable-machine',
+ placeholder="Machine name regex...",
+ selector_part_to_search=".machine-name")
+}}
+{{ utils.regex_filter_box(input_id='test-filter',
+ selector='.searchable',
+ placeholder="Test name regex...",
+ selector_part_to_search=".test-name")
+}}
+
+{% for field, field_results in report.result_table %}
+ {%- if field_results -%}
+ {{ utils.render_popup_begin(field.display_name, field.display_name, false, element = 'h3') }}
+ {% for machine, machine_runs, machine_results in field_results %}
+ <div class="searchable-machine">
+ <h5 class="machine-name">{{machine.name}}</h5>
+ <table border="1" style="{{ styles.table }};">
+ <thead>
+ <tr>
+ <th style="{{ styles.th }}">Test Name</th>
+ {% for i in range(machine_runs)|reverse %}
+ <th style="{{ styles.th }}">Run #{{i + 1}}</th>
+ {% endfor %}
+ <th style="{{ styles.th }}">Sparkline</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for test, test_results in machine_results %}
+ <tr class="searchable">
+ <td class="test-name" style="{{ styles.td }}"><a href="{{
+ ts_url}}/graph?plot.0={{machine.id}}.{{test.id}}.{{
+ report.ts.get_field_index(field)}}">{{test.name}}</a></td>
+ {{ reportutils.get_initial_cell_value(test_results[-1], field, analysis, styles) }}
+ {% for result in test_results[:-1]|reverse %}
+ {{ reportutils.get_cell_value(result, analysis, styles) }}
+ {% endfor %}
+ <td>{{ reportutils.spark_plot(test_results) }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </div>
+ {% endfor %}
+ {{ utils.render_popup_end() }}
+ {% else %}
+ <h3>No significant {{ field.display_name }} changes found.</h3>
+ {%- endif -%}
+{% endfor %}
+
+{% if not only_html_body %}
+</body>
+</html>
+{% endif %}
Added: lnt/trunk/lnt/server/ui/templates/reportutils.html
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/templates/reportutils.html?rev=343467&view=auto
==============================================================================
--- lnt/trunk/lnt/server/ui/templates/reportutils.html (added)
+++ lnt/trunk/lnt/server/ui/templates/reportutils.html Mon Oct 1 05:38:11 2018
@@ -0,0 +1,100 @@
+{% macro get_initial_cell_value(result, field, analysis, styles) %}
+{%- set cr = result.cr -%}
+{%- set test_status = cr.get_test_status() -%}
+{%- if (test_status == analysis.REGRESSED or
+ test_status == analysis.UNCHANGED_FAIL) %}
+ <td style="{{ styles.td }}; background-color:#e98080">FAIL</td>
+{%- else %}
+ <td style="{{ styles.td }}; {{ styles.right }}; background-color:#d2d2d2"> {#- -#}
+ {{ cr.current|print_value(field.unit, field.unit_abbrev) }}
+ </td>
+{%- endif -%}
+{% endmacro %}
+
+{% macro get_cell_value(result, analysis, styles) %}
+{%- set cr = result.cr -%}
+{%- set test_status = cr.get_test_status() -%}
+{%- set value_status = cr.get_value_status() -%}
+{%- if (test_status == analysis.REGRESSED or
+ test_status == analysis.UNCHANGED_FAIL) %}
+ <td style="{{ styles.td }}; background-color:#e98080">FAIL</td>
+{%- elif test_status == analysis.IMPROVED %}
+ <td style="{{ styles.td }}; background-color:#8fdf5f">PASS</td>
+{%- else -%}
+{%- if (value_status == analysis.REGRESSED or
+ value_status == analysis.IMPROVED) %}
+ {{ cr.pct_delta|aspctcell(reverse=cr.bigger_is_better, style = styles.right)|safe }}
+{%- else %}
+ <td style="{{ styles.td }}">-</td>
+{%- endif -%}
+{%- endif -%}
+{% endmacro %}
+
+{% macro spark_plot(results) %}
+{%- set x_border_size = 5 %}
+{%- set x_border_size = 5 %}
+{%- set y_border_size = 2 %}
+{%- set height = 18 %}
+{%- set full_height = height + 2*y_border_size %}
+{%- set x_day_spacing = 10 %}
+{%- set sample_fuzzing = 0.5 %}
+{%- set nr_days = results|length %}
+{%- set width = x_day_spacing * nr_days + 2*x_border_size %}
+{%- if results.max_sample != results.min_sample %}
+ {%- set scaling_factor = (1.0*height)
+ / (results.max_sample-results.min_sample) -%}
+{%- else %}
+ {%- set scaling_factor = 1.0 -%}
+{%- endif %}
+{%- macro spark_y_coord(day_nr, value) -%}
+ {{ (value-results.min_sample) * scaling_factor + y_border_size }}
+{%- endmacro -%}
+{%- macro spark_x_coord(day_nr) -%}
+ {{ (nr_days - day_nr) * x_day_spacing + x_border_size }}
+{%- endmacro -%}
+{%- macro spark_hash_background(day_nr, dr) -%}
+ {%- if dr.cr.cur_hash is not none -%}
+ {%- set style = "fill: "+dr.hash_rgb_color+";" -%}
+ {%- else -%}
+ {%- set style = "fill: none;" -%}
+ {%- endif -%}
+ <rect x="{{(nr_days-day_nr-0.5) * x_day_spacing + x_border_size}}" y="0"
+ width="{{x_day_spacing}}" height="{{full_height}}" style="{{style}}"/>
+{%- endmacro -%}
+ <span>
+ <svg width="{{width}}" height="{{full_height}}">
+ <rect width="{{width}}" height="{{full_height}}" fill="#f7f7f7"/>
+{#- Make y-axis go upwards instead of downwards: #}
+ <g transform="translate(0, {{full_height}}) scale(1, -1) ">
+{%- for dr in results -%}
+ {%- if dr is not none and not dr.cr.failed -%}
+ {%- set day_nr = loop.index %}
+ {%- set nr_samples_for_day = dr.samples|length %}
+ {{ spark_hash_background(day_nr, dr) }}
+ {%- for sample in dr.samples -%}
+ {# fuzz the x-coordinate slightly so that multiple samples with the same
+ value can be noticed #}
+ {%- set sample_fuzz = (-sample_fuzzing*1.25) +
+ (2.0*sample_fuzzing/nr_samples_for_day) * loop.index %}
+ <circle cx="{{ spark_x_coord(day_nr)|float + sample_fuzz }}" {# -#}
+ cy="{{ spark_y_coord(day_nr, sample) }}" r="1"
+ stroke-width="1" stroke="black" fill="black" />
+ {%- endfor -%}
+ {%- endif -%}
+{%- endfor %}
+ <polyline points="
+ {%- for dr in results -%}
+ {%- if dr is not none -%}
+ {%- set cr = dr.cr -%}
+ {%- set day_nr = loop.index -%}
+ {%- if not cr.failed and cr.current is not none %}
+ {{ spark_x_coord(day_nr) }} {{ spark_y_coord(day_nr, cr.current) }}
+ {%- endif -%}
+ {%- endif -%}
+ {%- endfor -%}
+ " fill="none" stroke="red" stroke-width="1"/>
+ </g>
+ </svg>
+ </span>
+{%- endmacro %}
+
Added: lnt/trunk/lnt/server/ui/templates/v4_latest_runs_report.html
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/templates/v4_latest_runs_report.html?rev=343467&view=auto
==============================================================================
--- lnt/trunk/lnt/server/ui/templates/v4_latest_runs_report.html (added)
+++ lnt/trunk/lnt/server/ui/templates/v4_latest_runs_report.html Mon Oct 1 05:38:11 2018
@@ -0,0 +1,10 @@
+{% set db = request.get_db() %}
+
+{% extends "layout.html" %}
+{% set components = [(ts.name, v4_url_for(".v4_recent_activity"))] %}
+{% block title %}Latest Runs Report{% endblock %}
+{% block body %}
+
+{{ report.render(v4_url_for('.v4_overview'))|safe }}
+
+{% endblock %}
More information about the llvm-commits
mailing list