Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(222)

Side by Side Diff: runtime/observatory/web/timeline.js

Issue 1972523003: Improve Observatory Timeline UI (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 // Used to delay the initial timeline load until the timeline has finished 5 // See also timeline_message_handler.js.
6 // loading.
7 timeline_loaded = false;
8 timeline_vm_address = undefined;
9 timeline_isolates = undefined;
10
11 function registerForMessages() {
12 window.addEventListener("message", onMessage, false);
13 }
14
15 registerForMessages();
16 6
17 function onModelLoaded() { 7 function onModelLoaded() {
18 viewer.globalMode = true; 8 viewer.globalMode = true;
19 viewer.model = model; 9 viewer.model = model;
20 } 10 }
21 11
22 function clearTimeline() { 12 function clearTimeline() {
23 viewer.model = undefined; 13 viewer.model = undefined;
24 } 14 }
25 15
26 function onImportFail() { 16 function onImportFail() {
27 var overlay = new tr.ui.b.Overlay(); 17 var overlay = new tr.ui.b.Overlay();
28 overlay.textContent = tr.b.normalizeException(err).message; 18 overlay.textContent = tr.b.normalizeException(err).message;
29 overlay.title = 'Import error'; 19 overlay.title = 'Import error';
30 overlay.visible = true; 20 overlay.visible = true;
31 console.log('import failed'); 21 console.log('import failed');
32 } 22 }
33 23
34 function updateTimeline(events) { 24 function updateTimeline(events) {
35 model = new tr.Model(); 25 model = new tr.Model();
36 var importer = new tr.importer.Import(model); 26 var importer = new tr.importer.Import(model);
37 var p = importer.importTracesWithProgressDialog([events]); 27 var p = importer.importTracesWithProgressDialog([events]);
38 p.then(onModelLoaded, onImportFail); 28 p.then(onModelLoaded, onImportFail);
39 } 29 }
40 30
41
42
43 function fetchUri(uri, onLoad, onError) { 31 function fetchUri(uri, onLoad, onError) {
44 var xhr = new XMLHttpRequest(); 32 var xhr = new XMLHttpRequest();
45 xhr.open('GET', uri, true); 33 xhr.open('GET', uri, true);
46 xhr.responseType = 'text'; 34 xhr.responseType = 'text';
47 xhr.addEventListener("load", onLoad); 35 xhr.addEventListener("load", onLoad);
48 xhr.addEventListener("error", onError); 36 xhr.addEventListener("error", onError);
49 xhr.send(); 37 xhr.send();
50 console.log('GET ' + uri); 38 console.log('GET ' + uri);
51 } 39 }
52 40
53
54 var traceObject; 41 var traceObject;
55 var pendingRequests; 42 var pendingRequests;
43 var loadingOverlay;
44
45 function showLoadingOverlay(msg) {
46 if (!loadingOverlay) {
47 loadingOverlay = new tr.ui.b.Overlay();
48 }
49 loadingOverlay.textContent = msg;
50 loadingOverlay.title = 'Loading...';
51 loadingOverlay.visible = true;
52 }
53
54 function hideLoadingOverlay() {
55 if (!loadingOverlay) {
56 return;
57 }
58 loadingOverlay.visible = false;
59 loadingOverlay = undefined;
60 }
56 61
57 function gotReponse() { 62 function gotReponse() {
58 pendingRequests--; 63 pendingRequests--;
59 if (pendingRequests == 0) { 64 if (pendingRequests == 0) {
60 console.log("Got all timeline parts"); 65 console.log("Got all timeline parts");
61 updateTimeline(traceObject); 66 updateTimeline(traceObject);
67 hideLoadingOverlay();
62 } 68 }
63 } 69 }
64 70
65 function fetchTimelineOnLoad(event) { 71 function processTimelineResponse(response) {
66 var xhr = event.target;
67 var response = JSON.parse(xhr.responseText);
68
69 if (response.error) { 72 if (response.error) {
70 // Maybe profiling is disabled. 73 // Maybe profiling is disabled.
71 console.log("ERROR " + response.error.message); 74 console.log("ERROR " + response.error.message);
72 } else { 75 } else {
73 var result = response['result']; 76 var result = response['result'];
74 var newStackFrames = result['stackFrames']; // Map. 77 var newStackFrames = result['stackFrames']; // Map.
75 var newTraceEvents = result['traceEvents']; // List. 78 var newTraceEvents = result['traceEvents']; // List.
76 79
77 // Merge in timeline events. 80 // Merge in timeline events.
78 traceObject.traceEvents = traceObject.traceEvents.concat(newTraceEvents); 81 traceObject.traceEvents = traceObject.traceEvents.concat(newTraceEvents);
79 for (var key in newStackFrames) { 82 for (var key in newStackFrames) {
80 if (newStackFrames.hasOwnProperty(key)) { 83 if (newStackFrames.hasOwnProperty(key)) {
81 traceObject.stackFrames[key] = newStackFrames[key]; 84 traceObject.stackFrames[key] = newStackFrames[key];
82 } 85 }
83 } 86 }
84 } 87 }
85 88
86 gotReponse(); 89 gotReponse();
87 } 90 }
88 91
92 function fetchTimelineOnLoad(event) {
93 var xhr = event.target;
94 var response = JSON.parse(xhr.responseText);
95 processTimelineResponse(response);
96 }
97
89 function fetchTimelineOnError(event) { 98 function fetchTimelineOnError(event) {
90 var xhr = event.target; 99 var xhr = event.target;
91 console.log(xhr.statusText); 100 console.log(xhr.statusText);
92 gotReponse(); 101 gotReponse();
93 } 102 }
94 103
104 function fetchCPUProfile(vmAddress, isolateIds, timeOrigin, timeExtent) {
105 showLoadingOverlay('Fetching CPU profile(s) from Dart VM');
106 var parser = document.createElement('a');
107 parser.href = vmAddress;
108 pendingRequests += isolateIds.length;
109 for (var i = 0; i < isolateIds.length; i++) {
110 var isolateId = isolateIds[i];
111 var requestUri = 'http://' +
112 parser.hostname +
113 ':' +
114 parser.port +
115 '/_getCpuProfileTimeline?tags=VMUser&isolateId=' +
116 isolateId +
117 '&timeOriginMicros=' + timeOrigin +
118 '&timeExtentMicros=' + timeExtent;
119 fetchUri(requestUri, fetchTimelineOnLoad, fetchTimelineOnError);
120 }
121 }
122
95 function fetchTimeline(vmAddress, isolateIds) { 123 function fetchTimeline(vmAddress, isolateIds) {
96 // Reset combined timeline. 124 // Reset combined timeline.
97 traceObject = { 125 traceObject = {
98 'stackFrames': {}, 126 'stackFrames': {},
99 'traceEvents': [] 127 'traceEvents': []
100 }; 128 };
101 pendingRequests = 1 + isolateIds.length; 129 pendingRequests = 1;
102 130
131 showLoadingOverlay('Fetching timeline from Dart VM');
103 var parser = document.createElement('a'); 132 var parser = document.createElement('a');
104 parser.href = vmAddress; 133 parser.href = vmAddress;
105 var requestUri = 'http://' + 134 var requestUri = 'http://' +
106 parser.hostname + 135 parser.hostname +
107 ':' + 136 ':' +
108 parser.port + 137 parser.port +
109 '/_getVMTimeline'; 138 '/_getVMTimeline';
110 fetchUri(requestUri, fetchTimelineOnLoad, fetchTimelineOnError); 139 fetchUri(requestUri, function(event) {
111 140 // Grab the response.
112 for (var i = 0; i < isolateIds.length; i++) { 141 var xhr = event.target;
113 var isolateId = isolateIds[i]; 142 var response = JSON.parse(xhr.responseText);
114 var requestUri = 'http://' + 143 // Extract the time origin and extent.
115 parser.hostname + 144 var timeOrigin = response['result']['timeOriginMicros'];
116 ':' + 145 var timeExtent = response['result']['timeExtentMicros'];
117 parser.port + 146 console.assert(Number.isInteger(timeOrigin), timeOrigin);
118 '/_getCpuProfileTimeline?tags=VMUser&isolateId=' + 147 console.assert(Number.isInteger(timeExtent), timeExtent);
119 isolateId; 148 console.log(timeOrigin);
120 fetchUri(requestUri, fetchTimelineOnLoad, fetchTimelineOnError); 149 console.log(timeExtent);
121 } 150 // fetchCPUProfile.
151 fetchCPUProfile(vmAddress, isolateIds, timeOrigin, timeExtent);
152 // This must happen after 'fetchCPUProfile';
153 processTimelineResponse(response);
154 }, fetchTimelineOnError);
122 } 155 }
123 156
124 function saveTimeline() { 157 function saveTimeline() {
125 if (pendingRequests > 0) { 158 if (pendingRequests > 0) {
126 var overlay = new tr.ui.b.Overlay(); 159 var overlay = new tr.ui.b.Overlay();
127 overlay.textContent = 'Cannot save timeline while fetching one.'; 160 overlay.textContent = 'Cannot save timeline while fetching one.';
128 overlay.title = 'Save error'; 161 overlay.title = 'Save error';
129 overlay.visible = true; 162 overlay.visible = true;
130 console.log('cannot save timeline while fetching one.'); 163 console.log('cannot save timeline while fetching one.');
131 return; 164 return;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 tr.ui.b.Overlay.showError('Error while loading file: ' + event); 226 tr.ui.b.Overlay.showError('Error while loading file: ' + event);
194 }; 227 };
195 reader.onabort = function(event) { 228 reader.onabort = function(event) {
196 tr.ui.b.Overlay.showError('Error while loading file: ' + event); 229 tr.ui.b.Overlay.showError('Error while loading file: ' + event);
197 } 230 }
198 reader.readAsText(file); 231 reader.readAsText(file);
199 }); 232 });
200 inputElement.click(); 233 inputElement.click();
201 } 234 }
202 235
203 function onMessage(event) { 236 window.addEventListener('DOMContentLoaded', function() {
204 var request = JSON.parse(event.data);
205 var method = request['method'];
206 var params = request['params'];
207 switch (method) {
208 case 'refresh':
209 if (!timeline_loaded) {
210 timeline_vm_address = params['vmAddress'];
211 timeline_isolates = params['isolateIds'];
212 console.log('Delaying timeline refresh until loaded.');
213 } else {
214 fetchTimeline(params['vmAddress'], params['isolateIds']);
215 }
216 break;
217 case 'clear':
218 clearTimeline();
219 break;
220 case 'save':
221 saveTimeline();
222 break;
223 case 'load':
224 loadTimeline();
225 break;
226 default:
227 console.log('Unknown method:' + method + '.');
228 }
229 }
230
231 document.addEventListener('DOMContentLoaded', function() {
232 var container = document.createElement('track-view-container'); 237 var container = document.createElement('track-view-container');
233 container.id = 'track_view_container'; 238 container.id = 'track_view_container';
234 viewer = document.createElement('tr-ui-timeline-view'); 239 viewer = document.createElement('tr-ui-timeline-view');
235 viewer.track_view_container = container; 240 viewer.track_view_container = container;
236 viewer.appendChild(container); 241 viewer.appendChild(container);
237 viewer.id = 'trace-viewer'; 242 viewer.id = 'trace-viewer';
238 viewer.globalMode = true; 243 viewer.globalMode = true;
239 document.body.appendChild(viewer); 244 document.body.appendChild(viewer);
240 timeline_loaded = true; 245 timeline_loaded = true;
246 console.log('DOMContentLoaded');
241 if (timeline_vm_address != undefined) { 247 if (timeline_vm_address != undefined) {
242 console.log('Triggering delayed timeline refresh.'); 248 console.log('Triggering delayed timeline refresh.');
243 fetchTimeline(timeline_vm_address, timeline_isolates); 249 fetchTimeline(timeline_vm_address, timeline_isolates);
244 timeline_vm_address = undefined; 250 timeline_vm_address = undefined;
245 timeline_isolates = undefined; 251 timeline_isolates = undefined;
246 } 252 }
247 }); 253 });
248 254
249 console.log('loaded'); 255 console.log('timeline.js loaded');
OLDNEW
« no previous file with comments | « runtime/observatory/web/timeline.html ('k') | runtime/observatory/web/timeline_message_handler.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698