[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