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/model/event_set.html"> 10<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html"> 11<link rel="import" href="/tracing/ui/analysis/generic_object_view.html"> 12<link rel="import" href="/tracing/ui/analysis/stack_frame.html"> 13<link rel="import" href="/tracing/ui/base/table.html"> 14<link rel="import" href="/tracing/ui/base/ui.html"> 15<link rel="import" href="/tracing/value/ui/scalar_span.html"> 16<link rel="import" href="/tracing/value/unit.html"> 17 18<polymer-element name="tr-ui-a-single-event-sub-view" 19 extends="tr-ui-a-sub-view"> 20 <template> 21 <style> 22 :host { 23 display: flex; 24 flex-direction: column; 25 } 26 #table { 27 flex: 1 1 auto; 28 align-self: stretch; 29 } 30 </style> 31 <tr-ui-b-table id="table"> 32 </tr-ui-b-table> 33 </template> 34 <script> 35 'use strict'; 36 37 Polymer({ 38 ready: function() { 39 this.currentSelection_ = undefined; 40 this.$.table.tableColumns = [ 41 { 42 title: 'Label', 43 value: function(row) { return row.name; }, 44 width: '150px' 45 }, 46 { 47 title: 'Value', 48 width: '100%', 49 value: function(row) { return row.value; } 50 } 51 ]; 52 this.$.table.showHeader = false; 53 }, 54 55 get selection() { 56 return this.currentSelection_; 57 }, 58 59 set selection(selection) { 60 if (selection.length !== 1) 61 throw new Error('Only supports single slices'); 62 this.setSelectionWithoutErrorChecks(selection); 63 }, 64 65 setSelectionWithoutErrorChecks: function(selection) { 66 this.currentSelection_ = selection; 67 this.updateContents_(); 68 }, 69 70 getEventRows_: function(event) { 71 var rows = []; 72 73 if (event.error) 74 rows.push({ name: 'Error', value: event.error }); 75 76 if (event.title) 77 rows.push({ name: 'Title', value: event.title }); 78 79 if (event.category) 80 rows.push({ name: 'Category', value: event.category }); 81 82 if (event.model !== undefined) { 83 var ufc = event.model.getUserFriendlyCategoryFromEvent(event); 84 if (ufc !== undefined) 85 rows.push({ name: 'User Friendly Category', value: ufc }); 86 } 87 88 if (event.name) 89 rows.push({ name: 'Name', value: event.name }); 90 91 rows.push({ 92 name: 'Start', 93 value: tr.v.ui.createScalarSpan(event.start, { 94 unit: tr.v.Unit.byName.timeStampInMs 95 }) 96 }); 97 98 if (event.duration) { 99 rows.push({ 100 name: 'Wall Duration', 101 value: tr.v.ui.createScalarSpan(event.duration, { 102 unit: tr.v.Unit.byName.timeDurationInMs 103 }) 104 }); 105 } 106 107 if (event.cpuDuration) { 108 rows.push({ 109 name: 'CPU Duration', 110 value: tr.v.ui.createScalarSpan(event.cpuDuration, { 111 unit: tr.v.Unit.byName.timeDurationInMs 112 }) 113 }); 114 } 115 116 if (event.subSlices !== undefined && event.subSlices.length !== 0) { 117 if (event.selfTime) { 118 rows.push({ 119 name: 'Self Time', 120 value: tr.v.ui.createScalarSpan(event.selfTime, { 121 unit: tr.v.Unit.byName.timeDurationInMs 122 }) 123 }); 124 } 125 126 if (event.cpuSelfTime) { 127 var cpuSelfTimeEl = tr.v.ui.createScalarSpan(event.cpuSelfTime, { 128 unit: tr.v.Unit.byName.timeDurationInMs 129 }); 130 if (event.cpuSelfTime > event.selfTime) { 131 cpuSelfTimeEl.warning = 132 ' Note that CPU Self Time is larger than Self Time. ' + 133 'This is a known limitation of this system, which occurs ' + 134 'due to several subslices, rounding issues, and imprecise ' + 135 'time at which we get cpu- and real-time.'; 136 } 137 rows.push({ name: 'CPU Self Time', value: cpuSelfTimeEl }); 138 } 139 } 140 141 if (event.durationInUserTime) { 142 rows.push({ 143 name: 'Duration (U)', 144 value: tr.v.ui.createScalarSpan(event.durationInUserTime, { 145 unit: tr.v.Unit.byName.timeDurationInMs 146 }) 147 }); 148 } 149 150 function createStackFrameEl(sf) { 151 var sfEl = document.createElement('tr-ui-a-stack-frame'); 152 sfEl.stackFrame = sf; 153 return sfEl; 154 } 155 if (event.startStackFrame && event.endStackFrame) { 156 if (event.startStackFrame === event.endStackFrame) { 157 rows.push({name: 'Start+End Stack Trace', 158 value: createStackFrameEl(event.startStackFrame)}); 159 160 } else { 161 rows.push({ name: 'Start Stack Trace', 162 value: createStackFrameEl(event.startStackFrame)}); 163 rows.push({ name: 'End Stack Trace', 164 value: createStackFrameEl(event.endStackFrame)}); 165 } 166 } else if (event.startStackFrame) { 167 rows.push({ name: 'Start Stack Trace', 168 value: createStackFrameEl(event.startStackFrame)}); 169 170 } else if (event.endStackFrame) { 171 rows.push({ name: 'End Stack Trace', 172 value: createStackFrameEl(event.endStackFrame)}); 173 } 174 175 if (event.info) { 176 var descriptionEl = tr.ui.b.createDiv({ 177 textContent: event.info.description, 178 maxWidth: '300px' 179 }); 180 rows.push({ 181 name: 'Description', 182 value: descriptionEl 183 }); 184 185 186 if (event.info.docLinks) { 187 event.info.docLinks.forEach(function(linkObject) { 188 var linkEl = document.createElement('a'); 189 linkEl.target = '_blank'; 190 linkEl.href = linkObject.href; 191 linkEl.textContent = linkObject.textContent; 192 rows.push({ 193 name: linkObject.label, 194 value: linkEl 195 }); 196 }); 197 } 198 } 199 200 if (event.associatedAlerts.length) { 201 var alertSubRows = []; 202 event.associatedAlerts.forEach(function(alert) { 203 var linkEl = document.createElement('tr-ui-a-analysis-link'); 204 linkEl.setSelectionAndContent(function() { 205 return new tr.model.EventSet(alert); 206 }, alert.info.description); 207 alertSubRows.push({ 208 name: alert.title, 209 value: linkEl 210 }); 211 }); 212 213 rows.push({ 214 name: 'Alerts', value: '', 215 isExpanded: true, subRows: alertSubRows 216 }); 217 } 218 return rows; 219 }, 220 221 addArgsToRows_: function(rows, args) { 222 var n = 0; 223 for (var argName in args) { 224 n += 1; 225 } 226 if (n > 0) { 227 var subRows = []; 228 for (var argName in args) { 229 var argView = 230 document.createElement('tr-ui-a-generic-object-view'); 231 argView.object = args[argName]; 232 subRows.push({ name: argName, 233 value: argView}); 234 } 235 rows.push({ 236 name: 'Args', value: '', 237 isExpanded: true, subRows: subRows 238 }); 239 } 240 return rows; 241 }, 242 243 updateContents_: function() { 244 if (this.currentSelection_ === undefined) { 245 this.$.table.rows = []; 246 this.$.table.rebuild(); 247 return; 248 } 249 250 var event = this.currentSelection_[0]; 251 252 var rows = this.getEventRows_(event); 253 if (event.argsStripped) 254 rows.push({ name: 'Args', value: 'Stripped' }); 255 else 256 this.addArgsToRows_(rows, event.args); 257 258 var event = new tr.b.Event('customize-rows'); 259 event.rows = rows; 260 this.dispatchEvent(event); 261 262 this.$.table.tableRows = rows; 263 this.$.table.rebuild(); 264 } 265 }); 266 </script> 267</polymer-element> 268