1<!DOCTYPE html> 2<!-- 3Copyright (c) 2013 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 8<link rel="import" href="/tracing/base/base.html"> 9<link rel="import" href="/tracing/base/iteration_helpers.html"> 10<link rel="import" href="/tracing/base/statistics.html"> 11<link rel="import" href="/tracing/model/event_set.html"> 12<link rel="import" href="/tracing/ui/analysis/analysis_link.html"> 13<link rel="import" href="/tracing/ui/analysis/multi_event_summary.html"> 14<link rel="import" href="/tracing/ui/base/table.html"> 15<link rel="import" href="/tracing/value/ui/scalar_span.html"> 16<link rel="import" href="/tracing/value/unit.html"> 17 18</script> 19<polymer-element name='tr-ui-a-multi-event-summary-table'> 20 <template> 21 <style> 22 :host { 23 display: flex; 24 } 25 #table { 26 flex: 1 1 auto; 27 align-self: stretch; 28 } 29 </style> 30 <tr-ui-b-table id="table"> 31 </tr-ui-b-table> 32 </div> 33 </template> 34 <script> 35 'use strict'; 36 37 Polymer({ 38 ready: function() { 39 this.showTotals_ = false; 40 this.eventsHaveDuration_ = true; 41 this.eventsHaveSubRows_ = true; 42 this.eventsByTitle_ = undefined; 43 }, 44 45 updateTableColumns_: function(rows, maxValues) { 46 var hasCpuData = false; 47 var hasAlerts = false; 48 rows.forEach(function(row) { 49 if (row.cpuDuration !== undefined) 50 hasCpuData = true; 51 if (row.cpuSelfTime !== undefined) 52 hasCpuData = true; 53 if (row.numAlerts) 54 hasAlerts = true; 55 }); 56 57 var ownerDocument = this.ownerDocument; 58 59 var columns = []; 60 61 columns.push({ 62 title: 'Name', 63 value: function(row) { 64 if (row.title === 'Totals') 65 return 'Totals'; 66 67 var linkEl = document.createElement('tr-ui-a-analysis-link'); 68 linkEl.setSelectionAndContent(function() { 69 return new tr.model.EventSet(row.events); 70 }, row.title); 71 return linkEl; 72 }, 73 width: '350px', 74 cmp: function(rowA, rowB) { 75 return rowA.title.localeCompare(rowB.title); 76 } 77 }); 78 if (this.eventsHaveDuration_) { 79 columns.push({ 80 title: 'Wall Duration', 81 value: function(row) { 82 return tr.v.ui.createScalarSpan(row.duration, { 83 unit: tr.v.Unit.byName.timeDurationInMs, 84 total: row.totalsRow ? undefined : maxValues.duration, 85 ownerDocument: ownerDocument, 86 rightAlign: true 87 }); 88 }, 89 width: '<upated further down>', 90 cmp: function(rowA, rowB) { 91 return rowA.duration - rowB.duration; 92 } 93 }); 94 } 95 96 if (this.eventsHaveDuration_ && hasCpuData) { 97 columns.push({ 98 title: 'CPU Duration', 99 value: function(row) { 100 return tr.v.ui.createScalarSpan(row.cpuDuration, { 101 unit: tr.v.Unit.byName.timeDurationInMs, 102 total: row.totalsRow ? undefined : maxValues.cpuDuration, 103 ownerDocument: ownerDocument, 104 rightAlign: true 105 }); 106 }, 107 width: '<upated further down>', 108 cmp: function(rowA, rowB) { 109 return rowA.cpuDuration - rowB.cpuDuration; 110 } 111 }); 112 } 113 114 if (this.eventsHaveSubRows_ && this.eventsHaveDuration_) { 115 columns.push({ 116 title: 'Self time', 117 value: function(row) { 118 return tr.v.ui.createScalarSpan(row.selfTime, { 119 unit: tr.v.Unit.byName.timeDurationInMs, 120 total: row.totalsRow ? undefined : maxValues.selfTime, 121 ownerDocument: ownerDocument, 122 rightAlign: true 123 }); 124 }, 125 width: '<upated further down>', 126 cmp: function(rowA, rowB) { 127 return rowA.selfTime - rowB.selfTime; 128 } 129 }); 130 } 131 132 if (this.eventsHaveSubRows_ && this.eventsHaveDuration_ && hasCpuData) { 133 columns.push({ 134 title: 'CPU Self Time', 135 value: function(row) { 136 return tr.v.ui.createScalarSpan(row.cpuSelfTime, { 137 unit: tr.v.Unit.byName.timeDurationInMs, 138 total: row.totalsRow ? undefined : maxValues.cpuSelfTime, 139 ownerDocument: ownerDocument, 140 rightAlign: true 141 }); 142 }, 143 width: '<upated further down>', 144 cmp: function(rowA, rowB) { 145 return rowA.cpuSelfTime - rowB.cpuSelfTime; 146 } 147 }); 148 } 149 columns.push({ 150 title: 'Occurrences', 151 value: function(row) { 152 return row.numEvents; 153 }, 154 width: '<upated further down>', 155 cmp: function(rowA, rowB) { 156 return rowA.numEvents - rowB.numEvents; 157 } 158 }); 159 160 var alertsColumnIndex; 161 if (hasAlerts) { 162 columns.push({ 163 title: 'Num Alerts', 164 value: function(row) { 165 return row.numAlerts; 166 }, 167 width: '<upated further down>', 168 cmp: function(rowA, rowB) { 169 return rowA.numAlerts - rowB.numAlerts; 170 } 171 }); 172 alertsColumnIndex = columns.length - 1; 173 } 174 var colWidthPercentage; 175 if (columns.length == 1) 176 colWidthPercentage = '100%'; 177 else 178 colWidthPercentage = (100 / (columns.length - 1)).toFixed(3) + '%'; 179 180 for (var i = 1; i < columns.length; i++) 181 columns[i].width = colWidthPercentage; 182 183 this.$.table.tableColumns = columns; 184 185 if (hasAlerts) { 186 this.$.table.sortColumnIndex = alertsColumnIndex; 187 this.$.table.sortDescending = true; 188 } 189 }, 190 191 configure: function(config) { 192 if (config.eventsByTitle === undefined) 193 throw new Error('Required: eventsByTitle'); 194 195 if (config.showTotals !== undefined) 196 this.showTotals_ = config.showTotals; 197 else 198 this.showTotals_ = true; 199 200 if (config.eventsHaveDuration !== undefined) 201 this.eventsHaveDuration_ = config.eventsHaveDuration; 202 else 203 this.eventsHaveDuration_ = true; 204 205 if (config.eventsHaveSubRows !== undefined) 206 this.eventsHaveSubRows_ = config.eventsHaveSubRows; 207 else 208 this.eventsHaveSubRows_ = true; 209 210 this.eventsByTitle_ = config.eventsByTitle; 211 this.updateContents_(); 212 }, 213 214 get showTotals() { 215 return this.showTotals_; 216 }, 217 218 set showTotals(showTotals) { 219 this.showTotals_ = showTotals; 220 this.updateContents_(); 221 }, 222 223 get eventsHaveDuration() { 224 return this.eventsHaveDuration_; 225 }, 226 227 set eventsHaveDuration(eventsHaveDuration) { 228 this.eventsHaveDuration_ = eventsHaveDuration; 229 this.updateContents_(); 230 }, 231 232 get eventsHaveSubRows() { 233 return this.eventsHaveSubRows_; 234 }, 235 236 set eventsHaveSubRows(eventsHaveSubRows) { 237 this.eventsHaveSubRows_ = eventsHaveSubRows; 238 this.updateContents_(); 239 }, 240 241 get eventsByTitle() { 242 return this.eventsByTitle_; 243 }, 244 245 set eventsByTitle(eventsByTitle) { 246 this.eventsByTitle_ = eventsByTitle; 247 this.updateContents_(); 248 }, 249 250 get selectionBounds() { 251 return this.selectionBounds_; 252 }, 253 254 set selectionBounds(selectionBounds) { 255 this.selectionBounds_ = selectionBounds; 256 this.updateContents_(); 257 }, 258 259 updateContents_: function() { 260 var eventsByTitle; 261 if (this.eventsByTitle_ !== undefined) 262 eventsByTitle = this.eventsByTitle_; 263 else 264 eventsByTitle = []; 265 266 var allEvents = []; 267 var rows = []; 268 tr.b.iterItems( 269 eventsByTitle, 270 function(title, eventsOfSingleTitle) { 271 allEvents.push.apply(allEvents, eventsOfSingleTitle); 272 var row = new tr.ui.analysis.MultiEventSummary( 273 title, eventsOfSingleTitle); 274 rows.push(row); 275 }); 276 277 this.updateTableColumns_(rows); 278 this.$.table.tableRows = rows; 279 280 var maxValues = { 281 duration: undefined, 282 selfTime: undefined, 283 cpuSelfTime: undefined, 284 cpuDuration: undefined 285 }; 286 287 if (this.eventsHaveDuration) { 288 for (var column in maxValues) { 289 maxValues[column] = tr.b.Statistics.max(rows, function(event) { 290 return event[column]; 291 }); 292 } 293 } 294 295 var footerRows = []; 296 297 if (this.showTotals_) { 298 var multiEventSummary = new tr.ui.analysis.MultiEventSummary( 299 'Totals', allEvents); 300 footerRows.push(multiEventSummary); 301 } 302 303 304 this.updateTableColumns_(rows, maxValues); 305 this.$.table.tableRows = rows; 306 307 // TODO(selection bounds). 308 309 // TODO(sorting) 310 311 this.$.table.footerRows = footerRows; 312 this.$.table.rebuild(); 313 } 314 }); 315 </script> 316</polymer-element> 317