1<!DOCTYPE html>
2<!--
3Copyright 2016 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7<html>
8<head>
9  <link type="text/css" rel="stylesheet" href="/dashboard/static/base.css">
10  <title>Bisect Statistics</title>
11  <style>
12    #content {
13      margin-left: 20px;
14      overflow: hidden;
15    }
16
17    #total-chart, #platform-chart {
18      height: 300px;
19      width: 900px;
20      float: left;
21    }
22
23    .chart-wrapper {
24      overflow: hidden;
25    }
26  </style>
27
28  <link rel="import" href="/components/polymer/polymer.html">
29  <link rel="import" href="/dashboard/elements/nav-bar.html">
30  <link rel="import" href="/dashboard/elements/quick-log.html">
31</head>
32<body>
33  <nav-bar></nav-bar>
34  <h1>Bisect Statistics</h1>
35
36  <div id="content">
37    <h2>Bisect Run Summary</h2>
38    <div class="chart-wrapper">
39      <div id="total-chart"></div>
40      <div id="total-legend"></div>
41    </div>
42    <br />
43    <h2>Bisect Run By Platform</h2>
44    <div class="chart-wrapper">
45      <div id="platform-chart"></div>
46      <div id="platform-legend"></div>
47    </div>
48
49    <h2>Infra Failures</h2>
50    <quick-log id="bisect-infra-failure-log"
51               xsrfToken="{{xsrf_token | safe}}"
52               logLabel="Logs"
53               logNamespace="bisect_failures"
54               logName="infra"
55               loadOnReady="true"
56               expandOnReady="true"
57               style="width:900px; height: 600px; display:block;"></quick-log>
58  </div>
59
60  <script src="/jquery/jquery-2.1.4.min.js"></script>
61  <script src="/flot/jquery.flot.min.js"></script>
62  <script src="/flot/jquery.flot.time.min.js"></script>
63  <script src="/flot/jquery.flot.stack.min.js"></script>
64
65  <script>
66    'use strict';
67
68    var ONE_WEEK_MILLISECONDS = 1000 * 60 * 60 * 24 * 7;
69    var GRAPH_WIDTH_PX = 900;
70    var GAP_SIZE_PX = 5;
71
72    // Data object for bisect results by platform.
73    // Expected to have object mapping in the form:
74    // {
75    //   'failed': {
76    //        bot_name: [[week_timestamp, count], [week_timestamp, count]],
77    //   },
78    //     'completed': {
79    //       bot_name: [[week_timestamp, count], [week_timestamp, count]],
80    //   }
81    // }
82    var SERIES_DATA = {{series_data | safe}};
83
84    // Data object for total bisect results in the form:
85    // {
86    //   'failed': [[week_timestamp, count], [week_timestamp, count]],
87    //   'completed': [[week_timestamp, count], [week_timestamp, count]]
88    // }
89    var TOTAL_SERIES_DATA = {{total_series_data | safe}};
90
91    /**
92     * Calculates bar width to make room for gap between each bar.
93     * @param {number} numPoints Number of points on in the chart.
94     * @return {number} Bar width to use in the Flot options.
95     */
96    function getBarWidth(numPoints) {
97      if (numPoints < 1)
98        return 1;
99      var gapPercent = GAP_SIZE_PX / (GRAPH_WIDTH_PX / numPoints);
100      if (gapPercent > 0.25) {
101        return ONE_WEEK_MILLISECONDS * 0.75;
102      } else {
103        return ONE_WEEK_MILLISECONDS - (ONE_WEEK_MILLISECONDS * gapPercent);
104      }
105    }
106
107    /**
108     * Loads chart for bisect total failed and success runs.
109     */
110    function addChartForBisectSummary() {
111      var numPoints = Math.max(TOTAL_SERIES_DATA['completed'].length,
112                              TOTAL_SERIES_DATA['failed'].length);
113      var barWidth = getBarWidth(numPoints);
114      var data = [
115        {
116          label: 'Successes',
117          data: TOTAL_SERIES_DATA['completed'],
118          color: '#0a0',
119        },
120        {
121          label: 'Fails',
122            data: TOTAL_SERIES_DATA['failed'],
123            color: '#DD4B39',
124        },
125      ];
126      var options = {
127        series: {
128          stack: true,
129          lines: {show: false, steps: false},
130          bars: {
131            show: true,
132            barWidth: barWidth,
133            fill: 1,
134          },
135        },
136        yaxis: {tickDecimals: 0},
137        xaxis: {
138          mode: 'time',
139          timeformat: '%y/%m/%d',
140        },
141        legend: {container: $('#total-legend')},
142      };
143
144      $.plot('#total-chart', data, options);
145    }
146
147    /**
148     * Loads chart for bisect runs by platform.
149     */
150    function addChartForBisectRunByPlatform() {
151      var data = [];
152      var series_names = Object.keys(SERIES_DATA['completed']);
153      series_names.sort();
154
155      // Determine bar width.
156      var numPoints = 0;
157      var barWidth = 1;
158      for (var i = 0; i < series_names.length; i++) {
159        var name = series_names[i];
160        numPoints = Math.max(SERIES_DATA['completed'][name].length,
161                            numPoints);
162        if (name in SERIES_DATA['failed']) {
163          numPoints = Math.max(SERIES_DATA['failed'][name].length,
164                              numPoints);
165        }
166      }
167      if (numPoints > 0) {
168        barWidth = getBarWidth(numPoints);
169        barWidth = barWidth / series_names.length;
170      }
171
172      // Add series data.
173      for (var i = 0; i < series_names.length; i++) {
174        var series = SERIES_DATA['completed'][series_names[i]];
175        for (var j = 0; j < series.length; j++) {
176          series[j][0] = series[j][0] + i * barWidth;
177        }
178        data.push({
179            label: series_names[i],
180            data: series,
181        });
182
183        series = SERIES_DATA['failed'][series_names[i]];
184        for (var j = 0; j < series.length; j++) {
185          series[j][0] = series[j][0] + i * barWidth;
186        }
187        data.push({
188            color: '#DD4B39',
189            data: series,
190        });
191      }
192
193      var options = {
194        series: {
195          stack: 0,
196          lines: {show: false, steps: false },
197          bars: {
198            show: true,
199            barWidth: barWidth,
200            fill: 1,
201          },
202        },
203        yaxis: {tickDecimals: 0},
204        xaxis: {
205          mode: 'time',
206          timeformat: '%y/%m/%d',
207        },
208        legend: {container: $('#platform-legend')},
209        colors: [
210          '#4d90fe',
211          '#37731c',
212          '#654ea6',
213          '#e38e39',
214          '#a34d77',
215          '#630000'
216        ]
217      };
218      $.plot('#platform-chart', data, options);
219    }
220
221    addChartForBisectSummary();
222    addChartForBisectRunByPlatform();
223  </script>
224</body>
225</html>
226