| <!DOCTYPE html> |
| <!-- |
| Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| |
| <link rel="import" href="/tracing/base/base.html"> |
| <link rel="import" href="/tracing/base/iteration_helpers.html"> |
| <link rel="import" href="/tracing/base/unit.html"> |
| <link rel="import" href="/tracing/model/event_set.html"> |
| <link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html"> |
| <link rel="import" href="/tracing/ui/analysis/generic_object_view.html"> |
| <link rel="import" href="/tracing/ui/analysis/stack_frame.html"> |
| <link rel="import" href="/tracing/ui/base/table.html"> |
| <link rel="import" href="/tracing/ui/base/ui.html"> |
| <link rel="import" href="/tracing/value/ui/scalar_span.html"> |
| |
| <dom-module id='tr-ui-a-single-event-sub-view'> |
| <template> |
| <style> |
| :host { |
| display: flex; |
| flex-direction: column; |
| } |
| #table { |
| flex: 1 1 auto; |
| align-self: stretch; |
| } |
| </style> |
| <tr-ui-b-table id="table"> |
| </tr-ui-b-table> |
| </template> |
| </dom-module> |
| <script> |
| 'use strict'; |
| |
| Polymer({ |
| is: 'tr-ui-a-single-event-sub-view', |
| behaviors: [tr.ui.analysis.AnalysisSubView], |
| |
| properties: { |
| isFlow: { |
| type: Boolean, |
| value: false |
| } |
| }, |
| |
| ready: function() { |
| this.currentSelection_ = undefined; |
| this.$.table.tableColumns = [ |
| { |
| title: 'Label', |
| value: function(row) { return row.name; }, |
| width: '150px' |
| }, |
| { |
| title: 'Value', |
| width: '100%', |
| value: function(row) { return row.value; } |
| } |
| ]; |
| this.$.table.showHeader = false; |
| }, |
| |
| get selection() { |
| return this.currentSelection_; |
| }, |
| |
| set selection(selection) { |
| if (selection.length !== 1) |
| throw new Error('Only supports single slices'); |
| this.setSelectionWithoutErrorChecks(selection); |
| }, |
| |
| setSelectionWithoutErrorChecks: function(selection) { |
| this.currentSelection_ = selection; |
| this.updateContents_(); |
| }, |
| |
| getFlowEventRows_: function(event) { |
| // TODO(nduca): Figure out if there is a cleaner way to do this. |
| |
| var rows = this.getEventRowsHelper_(event); |
| // var rows = this.__proto__.__proto__.getEventRows_(event); |
| |
| // Put the ID up top. |
| rows.splice(0, 0, { |
| name: 'ID', |
| value: event.id |
| }); |
| |
| function createLinkTo(slice) { |
| var linkEl = document.createElement('tr-ui-a-analysis-link'); |
| linkEl.setSelectionAndContent(function() { |
| return new tr.model.EventSet(slice); |
| }); |
| Polymer.dom(linkEl).textContent = slice.userFriendlyName; |
| return linkEl; |
| } |
| |
| rows.push({ |
| name: 'From', |
| value: createLinkTo(event.startSlice) |
| }); |
| rows.push({ |
| name: 'To', |
| value: createLinkTo(event.endSlice) |
| }); |
| return rows; |
| }, |
| |
| getEventRowsHelper_: function(event) { |
| var rows = []; |
| |
| if (event.error) |
| rows.push({ name: 'Error', value: event.error }); |
| |
| if (event.title) |
| rows.push({ name: 'Title', value: event.title }); |
| |
| if (event.category) |
| rows.push({ name: 'Category', value: event.category }); |
| |
| if (event.model !== undefined) { |
| var ufc = event.model.getUserFriendlyCategoryFromEvent(event); |
| if (ufc !== undefined) |
| rows.push({ name: 'User Friendly Category', value: ufc }); |
| } |
| |
| if (event.name) |
| rows.push({ name: 'Name', value: event.name }); |
| |
| rows.push({ |
| name: 'Start', |
| value: tr.v.ui.createScalarSpan(event.start, { |
| unit: tr.b.Unit.byName.timeStampInMs |
| }) |
| }); |
| |
| if (event.duration) { |
| rows.push({ |
| name: 'Wall Duration', |
| value: tr.v.ui.createScalarSpan(event.duration, { |
| unit: tr.b.Unit.byName.timeDurationInMs |
| }) |
| }); |
| } |
| |
| if (event.cpuDuration) { |
| rows.push({ |
| name: 'CPU Duration', |
| value: tr.v.ui.createScalarSpan(event.cpuDuration, { |
| unit: tr.b.Unit.byName.timeDurationInMs |
| }) |
| }); |
| } |
| |
| if (event.subSlices !== undefined && event.subSlices.length !== 0) { |
| if (event.selfTime) { |
| rows.push({ |
| name: 'Self Time', |
| value: tr.v.ui.createScalarSpan(event.selfTime, { |
| unit: tr.b.Unit.byName.timeDurationInMs |
| }) |
| }); |
| } |
| |
| if (event.cpuSelfTime) { |
| var cpuSelfTimeEl = tr.v.ui.createScalarSpan(event.cpuSelfTime, { |
| unit: tr.b.Unit.byName.timeDurationInMs |
| }); |
| if (event.cpuSelfTime > event.selfTime) { |
| cpuSelfTimeEl.warning = |
| ' Note that CPU Self Time is larger than Self Time. ' + |
| 'This is a known limitation of this system, which occurs ' + |
| 'due to several subslices, rounding issues, and imprecise ' + |
| 'time at which we get cpu- and real-time.'; |
| } |
| rows.push({ name: 'CPU Self Time', value: cpuSelfTimeEl }); |
| } |
| } |
| |
| if (event.durationInUserTime) { |
| rows.push({ |
| name: 'Duration (U)', |
| value: tr.v.ui.createScalarSpan(event.durationInUserTime, { |
| unit: tr.b.Unit.byName.timeDurationInMs |
| }) |
| }); |
| } |
| |
| function createStackFrameEl(sf) { |
| var sfEl = document.createElement('tr-ui-a-stack-frame'); |
| sfEl.stackFrame = sf; |
| return sfEl; |
| } |
| if (event.startStackFrame && event.endStackFrame) { |
| if (event.startStackFrame === event.endStackFrame) { |
| rows.push({name: 'Start+End Stack Trace', |
| value: createStackFrameEl(event.startStackFrame)}); |
| |
| } else { |
| rows.push({ name: 'Start Stack Trace', |
| value: createStackFrameEl(event.startStackFrame)}); |
| rows.push({ name: 'End Stack Trace', |
| value: createStackFrameEl(event.endStackFrame)}); |
| } |
| } else if (event.startStackFrame) { |
| rows.push({ name: 'Start Stack Trace', |
| value: createStackFrameEl(event.startStackFrame)}); |
| |
| } else if (event.endStackFrame) { |
| rows.push({ name: 'End Stack Trace', |
| value: createStackFrameEl(event.endStackFrame)}); |
| } |
| |
| if (event.info) { |
| var descriptionEl = tr.ui.b.createDiv({ |
| textContent: event.info.description, |
| maxWidth: '300px' |
| }); |
| rows.push({ |
| name: 'Description', |
| value: descriptionEl |
| }); |
| |
| |
| if (event.info.docLinks) { |
| event.info.docLinks.forEach(function(linkObject) { |
| var linkEl = document.createElement('a'); |
| linkEl.target = '_blank'; |
| linkEl.href = linkObject.href; |
| Polymer.dom(linkEl).textContent = Polymer.dom(linkObject).textContent; |
| rows.push({ |
| name: linkObject.label, |
| value: linkEl |
| }); |
| }); |
| } |
| } |
| |
| if (event.associatedAlerts.length) { |
| var alertSubRows = []; |
| event.associatedAlerts.forEach(function(alert) { |
| var linkEl = document.createElement('tr-ui-a-analysis-link'); |
| linkEl.setSelectionAndContent(function() { |
| return new tr.model.EventSet(alert); |
| }, alert.info.description); |
| alertSubRows.push({ |
| name: alert.title, |
| value: linkEl |
| }); |
| }); |
| |
| rows.push({ |
| name: 'Alerts', value: '', |
| isExpanded: true, subRows: alertSubRows |
| }); |
| } |
| return rows; |
| }, |
| |
| getEventRows_: function(event) { |
| |
| if (this.isFlow) |
| return this.getFlowEventRows_(event); |
| |
| return this.getEventRowsHelper_(event); |
| }, |
| |
| addArgsToRows_: function(rows, args) { |
| var n = 0; |
| for (var argName in args) { |
| n += 1; |
| } |
| if (n > 0) { |
| var subRows = []; |
| for (var argName in args) { |
| n += 1; |
| } |
| if (n > 0) { |
| var subRows = []; |
| for (var argName in args) { |
| var argView = |
| document.createElement('tr-ui-a-generic-object-view'); |
| argView.object = args[argName]; |
| subRows.push({name: argName, value: argView}); |
| } |
| rows.push({ |
| name: 'Args', |
| value: '', |
| isExpanded: true, |
| subRows: subRows |
| }); |
| } |
| } |
| }, |
| |
| addContextsToRows_: function(rows, contexts) { |
| if (contexts.length) { |
| var subRows = contexts.map(function(context) { |
| var contextView = |
| document.createElement('tr-ui-a-generic-object-view'); |
| contextView.object = context; |
| return {name: 'Context', value: contextView}; |
| }); |
| rows.push({ |
| name: 'Contexts', |
| value: '', |
| isExpanded: true, |
| subRows: subRows |
| }); |
| } |
| }, |
| |
| updateContents_: function() { |
| if (this.currentSelection_ === undefined) { |
| this.$.table.rows = []; |
| this.$.table.rebuild(); |
| return; |
| } |
| |
| var event = tr.b.getOnlyElement(this.currentSelection_); |
| |
| var rows = this.getEventRows_(event); |
| if (event.argsStripped) |
| rows.push({ name: 'Args', value: 'Stripped' }); |
| else |
| this.addArgsToRows_(rows, event.args); |
| this.addContextsToRows_(rows, event.contexts); |
| |
| var customizeRowsEvent = new tr.b.Event('customize-rows'); |
| customizeRowsEvent.rows = rows; |
| this.dispatchEvent(customizeRowsEvent); |
| |
| this.$.table.tableRows = rows; |
| this.$.table.rebuild(); |
| } |
| }); |
| </script> |