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