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

Side by Side Diff: pkg/analysis_server/lib/src/get_handler.dart

Issue 691853006: display completion performance in new server status page (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 library get.handler; 5 library get.handler;
6 6
7 import 'dart:convert'; 7 import 'dart:convert';
8 import 'dart:io'; 8 import 'dart:io';
9 import 'dart:math'; 9 import 'dart:math';
10 10
11 import 'package:analysis_server/src/analysis_server.dart'; 11 import 'package:analysis_server/src/analysis_server.dart';
12 import 'package:analysis_server/src/domain_completion.dart';
13 import 'package:analysis_server/src/services/completion/completion_manager.dart' ;
12 import 'package:analysis_server/src/socket_server.dart'; 14 import 'package:analysis_server/src/socket_server.dart';
13 import 'package:analyzer/file_system/file_system.dart'; 15 import 'package:analyzer/file_system/file_system.dart';
14 import 'package:analyzer/src/generated/source.dart';
15 import 'package:analyzer/src/generated/engine.dart'; 16 import 'package:analyzer/src/generated/engine.dart';
16 import 'package:analyzer/src/generated/java_engine.dart'; 17 import 'package:analyzer/src/generated/java_engine.dart';
18 import 'package:analyzer/src/generated/source.dart';
19
17 import 'analysis_server.dart'; 20 import 'analysis_server.dart';
18 21
19 /** 22 /**
20 * Instances of the class [GetHandler] handle GET requests. 23 * Instances of the class [GetHandler] handle GET requests.
21 */ 24 */
22 class GetHandler { 25 class GetHandler {
23 /** 26 /**
24 * The path used to request the status of the analysis server as a whole. 27 * The path used to request the status of the analysis server as a whole.
25 */ 28 */
26 static const String STATUS_PATH = '/status'; 29 static const String STATUS_PATH = '/status';
27 30
28 /** 31 /**
32 * The path used to request code completion information.
33 */
34 static const String COMPLETION_PATH = '/completion';
35
36 /**
29 * The path used to request the list of source files in a certain cache 37 * The path used to request the list of source files in a certain cache
30 * state. 38 * state.
31 */ 39 */
32 static const String CACHE_STATE_PATH = '/cache_state'; 40 static const String CACHE_STATE_PATH = '/cache_state';
33 41
34 /** 42 /**
35 * Query parameter used to represent the cache state to search for, when 43 * Query parameter used to represent the cache state to search for, when
36 * accessing [CACHE_STATE_PATH]. 44 * accessing [CACHE_STATE_PATH].
37 */ 45 */
38 static const String STATE_QUERY_PARAM = 'state'; 46 static const String STATE_QUERY_PARAM = 'state';
(...skipping 27 matching lines...) Expand all
66 74
67 /** 75 /**
68 * Handle a GET request received by the HTTP server. 76 * Handle a GET request received by the HTTP server.
69 */ 77 */
70 void handleGetRequest(HttpRequest request) { 78 void handleGetRequest(HttpRequest request) {
71 String path = request.uri.path; 79 String path = request.uri.path;
72 if (path == STATUS_PATH) { 80 if (path == STATUS_PATH) {
73 _returnServerStatus(request); 81 _returnServerStatus(request);
74 } else if (path == CACHE_STATE_PATH) { 82 } else if (path == CACHE_STATE_PATH) {
75 _returnCacheState(request); 83 _returnCacheState(request);
84 } else if (path == COMPLETION_PATH) {
85 _returnCompletionInfo(request);
76 } else { 86 } else {
77 _returnUnknownRequest(request); 87 _returnUnknownRequest(request);
78 } 88 }
79 } 89 }
80 90
81 /** 91 /**
82 * Create a link to [path] with query parameters [params], with inner HTML 92 * Create a link to [path] with query parameters [params], with inner HTML
83 * [innerHtml]. 93 * [innerHtml].
84 */ 94 */
85 String _makeLink(String path, Map<String, String> params, String innerHtml) { 95 String _makeLink(String path, Map<String, String> params, String innerHtml) {
86 Uri uri = new Uri(path: path, queryParameters: params); 96 Uri uri = new Uri(path: path, queryParameters: params);
87 return '<a href="${HTML_ESCAPE.convert(uri.toString())}">$innerHtml</a>'; 97 return '<a href="${HTML_ESCAPE.convert(uri.toString())}">$innerHtml</a>';
88 } 98 }
89 99
90 /** 100 /**
91 * Return a response indicating the set of source files in a certain cache 101 * Return a response indicating the set of source files in a certain cache
92 * state. 102 * state.
93 */ 103 */
94 void _returnCacheState(HttpRequest request) { 104 void _returnCacheState(HttpRequest request) {
95 // Figure out what CacheState is being searched for. 105 // Figure out what CacheState is being searched for.
96 String stateQueryParam = request.uri.queryParameters[STATE_QUERY_PARAM]; 106 String stateQueryParam = request.uri.queryParameters[STATE_QUERY_PARAM];
97 if (stateQueryParam == null) { 107 if (stateQueryParam == null) {
98 return _returnFailure(request, 108 return _returnFailure(
109 request,
99 'Query parameter $STATE_QUERY_PARAM required'); 110 'Query parameter $STATE_QUERY_PARAM required');
100 } 111 }
101 CacheState stateFilter = null; 112 CacheState stateFilter = null;
102 for (CacheState value in CacheState.values) { 113 for (CacheState value in CacheState.values) {
103 if (value.toString() == stateQueryParam) { 114 if (value.toString() == stateQueryParam) {
104 stateFilter = value; 115 stateFilter = value;
105 } 116 }
106 } 117 }
107 if (stateFilter == null) { 118 if (stateFilter == null) {
108 return _returnFailure(request, 119 return _returnFailure(
120 request,
109 'Query parameter $STATE_QUERY_PARAM is invalid'); 121 'Query parameter $STATE_QUERY_PARAM is invalid');
110 } 122 }
111 123
112 // Figure out which context is being searched for. 124 // Figure out which context is being searched for.
113 String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM]; 125 String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM];
114 if (contextFilter == null) { 126 if (contextFilter == null) {
115 return _returnFailure(request, 127 return _returnFailure(
128 request,
116 'Query parameter $CONTEXT_QUERY_PARAM required'); 129 'Query parameter $CONTEXT_QUERY_PARAM required');
117 } 130 }
118 131
119 // Figure out which descriptor is being searched for. 132 // Figure out which descriptor is being searched for.
120 String descriptorFilter = 133 String descriptorFilter =
121 request.uri.queryParameters[DESCRIPTOR_QUERY_PARAM]; 134 request.uri.queryParameters[DESCRIPTOR_QUERY_PARAM];
122 if (descriptorFilter == null) { 135 if (descriptorFilter == null) {
123 return _returnFailure(request, 136 return _returnFailure(
137 request,
124 'Query parameter $DESCRIPTOR_QUERY_PARAM required'); 138 'Query parameter $DESCRIPTOR_QUERY_PARAM required');
125 } 139 }
126 140
127 AnalysisServer analysisServer = _server.analysisServer; 141 AnalysisServer analysisServer = _server.analysisServer;
128 if (analysisServer == null) { 142 if (analysisServer == null) {
129 return _returnFailure(request, 'Analysis server not running'); 143 return _returnFailure(request, 'Analysis server not running');
130 } 144 }
131 HttpResponse response = request.response; 145 HttpResponse response = request.response;
132 response.statusCode = HttpStatus.OK; 146 response.statusCode = HttpStatus.OK;
133 response.headers.add(HttpHeaders.CONTENT_TYPE, "text/html"); 147 response.headers.add(HttpHeaders.CONTENT_TYPE, "text/html");
134 response.write('<html>'); 148 response.write('<html>');
135 response.write('<head>'); 149 response.write('<head>');
136 response.write('<title>Dart Analysis Server - Search result</title>'); 150 response.write('<title>Dart Analysis Server - Search result</title>');
137 response.write('</head>'); 151 response.write('</head>');
138 response.write('<body>'); 152 response.write('<body>');
139 response.write('<h1>'); 153 response.write('<h1>');
140 response.write('Files with state ${HTML_ESCAPE.convert(stateQueryParam)}'); 154 response.write('Files with state ${HTML_ESCAPE.convert(stateQueryParam)}');
141 response.write(' for descriptor ${HTML_ESCAPE.convert(descriptorFilter)}'); 155 response.write(' for descriptor ${HTML_ESCAPE.convert(descriptorFilter)}');
142 response.write(' in context ${HTML_ESCAPE.convert(contextFilter)}'); 156 response.write(' in context ${HTML_ESCAPE.convert(contextFilter)}');
143 response.write('</h1>'); 157 response.write('</h1>');
144 response.write('<ul>'); 158 response.write('<ul>');
145 int count = 0; 159 int count = 0;
146 analysisServer.folderMap.forEach((Folder folder, 160 analysisServer.folderMap.forEach(
147 AnalysisContextImpl context) { 161 (Folder folder, AnalysisContextImpl context) {
148 if (folder.path != contextFilter) { 162 if (folder.path != contextFilter) {
149 return; 163 return;
150 } 164 }
151 context.visitCacheItems((Source source, SourceEntry dartEntry, 165 context.visitCacheItems(
152 DataDescriptor rowDesc, CacheState state) { 166 (Source source, SourceEntry dartEntry, DataDescriptor rowDesc, CacheSt ate state)
167 {
153 if (state != stateFilter || rowDesc.toString() != descriptorFilter) { 168 if (state != stateFilter || rowDesc.toString() != descriptorFilter) {
154 return; 169 return;
155 } 170 }
156 response.write('<li>${HTML_ESCAPE.convert(source.fullName)}</li>'); 171 response.write('<li>${HTML_ESCAPE.convert(source.fullName)}</li>');
157 count++; 172 count++;
158 }); 173 });
159 }); 174 });
160 response.write('</ul>'); 175 response.write('</ul>');
161 response.write('<p>$count files found</p>'); 176 response.write('<p>$count files found</p>');
162 response.write('</body>'); 177 response.write('</body>');
163 response.write('</html>'); 178 response.write('</html>');
164 response.close(); 179 response.close();
165 } 180 }
166 181
167 /** 182 /**
183 * Return a response displaying code completion information.
184 */
185 void _returnCompletionInfo(HttpRequest request) {
186 var refresh = request.requestedUri.queryParameters['refresh'];
187 HttpResponse response = request.response;
188 response.statusCode = HttpStatus.OK;
189 response.headers.add(HttpHeaders.CONTENT_TYPE, "text/html");
190 response.write('<html>');
191 response.write('<head>');
192 response.write('<title>Dart Analysis Server - Completion Stats</title>');
193 response.write('<style>');
194 response.write('td.right {text-align: right;}');
195 response.write('</style>');
196 if (refresh is String) {
197 int seconds = int.parse(refresh, onError: (_) => 5);
198 response.write('<meta http-equiv="refresh" content="$seconds">');
199 }
200 response.write('</head>');
201 response.write('<body>');
202 _writeCompletionInfo(response);
203 response.write('<form>');
204 response.write(
205 '<input type="button" onClick="history.go(0)" value="Refresh">');
206 response.write('</form>');
207 response.write('<p>Append "?refresh=5" to refresh every 5 seconds</p>');
208 response.write('</body>');
209 response.write('</html>');
210 response.close();
211 }
212
213 void _returnFailure(HttpRequest request, String message) {
214 HttpResponse response = request.response;
215 response.statusCode = HttpStatus.OK;
216 response.headers.add(HttpHeaders.CONTENT_TYPE, "text/html");
217 response.write('<html>');
218 response.write('<head>');
219 response.write('<title>Dart Analysis Server - Failure</title>');
220 response.write('</head>');
221 response.write('<body>');
222 response.write(HTML_ESCAPE.convert(message));
223 response.write('</body>');
224 response.write('</html>');
225 response.close();
226 }
227
228 /**
168 * Return a response indicating the status of the analysis server. 229 * Return a response indicating the status of the analysis server.
169 */ 230 */
170 void _returnServerStatus(HttpRequest request) { 231 void _returnServerStatus(HttpRequest request) {
171 HttpResponse response = request.response; 232 HttpResponse response = request.response;
172 response.statusCode = HttpStatus.OK; 233 response.statusCode = HttpStatus.OK;
173 response.headers.add(HttpHeaders.CONTENT_TYPE, "text/html"); 234 response.headers.add(HttpHeaders.CONTENT_TYPE, "text/html");
174 response.write('<html>'); 235 response.write('<html>');
175 response.write('<head>'); 236 response.write('<head>');
176 response.write('<title>Dart Analysis Server - Status</title>'); 237 response.write('<title>Dart Analysis Server - Status</title>');
177 response.write('<style>'); 238 response.write('<style>');
(...skipping 12 matching lines...) Expand all
190 response.write('<p>Running (not analyzing)</p>'); 251 response.write('<p>Running (not analyzing)</p>');
191 } 252 }
192 response.write('<h1>Analysis Contexts</h1>'); 253 response.write('<h1>Analysis Contexts</h1>');
193 response.write('<h2>Summary</h2>'); 254 response.write('<h2>Summary</h2>');
194 response.write('<table>'); 255 response.write('<table>');
195 List headerRowText = ['Context']; 256 List headerRowText = ['Context'];
196 headerRowText.addAll(CacheState.values); 257 headerRowText.addAll(CacheState.values);
197 _writeRow(response, headerRowText, header: true); 258 _writeRow(response, headerRowText, header: true);
198 Map<Folder, AnalysisContext> folderMap = analysisServer.folderMap; 259 Map<Folder, AnalysisContext> folderMap = analysisServer.folderMap;
199 List<Folder> folders = folderMap.keys.toList(); 260 List<Folder> folders = folderMap.keys.toList();
200 folders.sort((Folder first, Folder second) 261 folders.sort(
201 => first.shortName.compareTo(second.shortName)); 262 (Folder first, Folder second) => first.shortName.compareTo(second.shor tName));
202 folders.forEach((Folder folder) { 263 folders.forEach((Folder folder) {
203 AnalysisContextImpl context = folderMap[folder]; 264 AnalysisContextImpl context = folderMap[folder];
204 String key = folder.shortName; 265 String key = folder.shortName;
205 AnalysisContextStatistics statistics = context.statistics; 266 AnalysisContextStatistics statistics = context.statistics;
206 Map<CacheState, int> totals = <CacheState, int>{}; 267 Map<CacheState, int> totals = <CacheState, int>{};
207 for (CacheState state in CacheState.values) { 268 for (CacheState state in CacheState.values) {
208 totals[state] = 0; 269 totals[state] = 0;
209 } 270 }
210 statistics.cacheRows.forEach((AnalysisContextStatistics_CacheRow row) { 271 statistics.cacheRows.forEach((AnalysisContextStatistics_CacheRow row) {
211 for (CacheState state in CacheState.values) { 272 for (CacheState state in CacheState.values) {
212 totals[state] += row.getCount(state); 273 totals[state] += row.getCount(state);
213 } 274 }
214 }); 275 });
215 List rowText = ['<a href="#context_${HTML_ESCAPE.convert(key)}">$key</a> ']; 276 List rowText = [
277 '<a href="#context_${HTML_ESCAPE.convert(key)}">$key</a>'];
216 for (CacheState state in CacheState.values) { 278 for (CacheState state in CacheState.values) {
217 rowText.add(totals[state]); 279 rowText.add(totals[state]);
218 } 280 }
219 _writeRow(response, rowText, classes: [null, "right"]); 281 _writeRow(response, rowText, classes: [null, "right"]);
220 }); 282 });
221 response.write('</table>'); 283 response.write('</table>');
222 folders.forEach((Folder folder) { 284 folders.forEach((Folder folder) {
223 AnalysisContextImpl context = folderMap[folder]; 285 AnalysisContextImpl context = folderMap[folder];
224 String key = folder.shortName; 286 String key = folder.shortName;
225 response.write('<h2><a name="context_${HTML_ESCAPE.convert(key)}">Analys is Context: $key</a></h2>'); 287 response.write(
288 '<h2><a name="context_${HTML_ESCAPE.convert(key)}">Analysis Context: $key</a></h2>');
226 AnalysisContextStatistics statistics = context.statistics; 289 AnalysisContextStatistics statistics = context.statistics;
227 response.write('<table>'); 290 response.write('<table>');
228 _writeRow(response, headerRowText, header: true); 291 _writeRow(response, headerRowText, header: true);
229 statistics.cacheRows.forEach((AnalysisContextStatistics_CacheRow row) { 292 statistics.cacheRows.forEach((AnalysisContextStatistics_CacheRow row) {
230 List rowText = [row.name]; 293 List rowText = [row.name];
231 for (CacheState state in CacheState.values) { 294 for (CacheState state in CacheState.values) {
232 String text = row.getCount(state).toString(); 295 String text = row.getCount(state).toString();
233 Map<String, String> params = <String, String>{ 296 Map<String, String> params = <String, String>{
234 STATE_QUERY_PARAM: state.toString(), 297 STATE_QUERY_PARAM: state.toString(),
235 CONTEXT_QUERY_PARAM: folder.path, 298 CONTEXT_QUERY_PARAM: folder.path,
(...skipping 22 matching lines...) Expand all
258 response.close(); 321 response.close();
259 } 322 }
260 323
261 /** 324 /**
262 * Return an error in response to an unrecognized request received by the HTTP 325 * Return an error in response to an unrecognized request received by the HTTP
263 * server. 326 * server.
264 */ 327 */
265 void _returnUnknownRequest(HttpRequest request) { 328 void _returnUnknownRequest(HttpRequest request) {
266 HttpResponse response = request.response; 329 HttpResponse response = request.response;
267 response.statusCode = HttpStatus.NOT_FOUND; 330 response.statusCode = HttpStatus.NOT_FOUND;
268 response.headers.add(HttpHeaders.CONTENT_TYPE, "text/plain"); 331 response.headers.add(HttpHeaders.CONTENT_TYPE, "text/html");
269 response.write('Not found'); 332 response.write('<html>');
333 response.write('<head>');
334 response.write('<title>Dart Analysis Server - Page Not Found</title>');
335 response.write('</head>');
336 response.write('<body>');
337 response.write('<h1>Page Not Found</h1>');
338 response.write('<p>Try one of these links instead:</p>');
339 response.write('<ul>');
340 response.write('<li><a href="$STATUS_PATH">Server Status</a></li>');
341 response.write('<li><a href="$COMPLETION_PATH">Completion Stats</a></li>');
342 response.write('<ul>');
343 response.write('</body>');
344 response.write('</html>');
270 response.close(); 345 response.close();
271 } 346 }
272 347
273 void _returnFailure(HttpRequest request, String message) { 348 /**
274 HttpResponse response = request.response; 349 * Append code completion information.
275 response.statusCode = HttpStatus.OK; 350 */
276 response.headers.add(HttpHeaders.CONTENT_TYPE, "text/html"); 351 void _writeCompletionInfo(HttpResponse response) {
277 response.write('<html>'); 352 response.write('<h1>Code Completion</h1>');
278 response.write('<head>'); 353 AnalysisServer analysisServer = _server.analysisServer;
279 response.write('<title>Dart Analysis Server - Failure</title>'); 354 if (analysisServer == null) {
280 response.write('</head>'); 355 response.write('<p>Not running</p>');
281 response.write('<body>'); 356 return;
282 response.write(HTML_ESCAPE.convert(message)); 357 }
283 response.write('</body>'); 358 CompletionDomainHandler handler = analysisServer.handlers.firstWhere(
284 response.write('</html>'); 359 (h) => h is CompletionDomainHandler,
285 response.close(); 360 orElse: () => null);
361 if (handler == null) {
362 response.write('<p>No code completion</p>');
363 return;
364 }
365 CompletionPerformance performance = handler.performance;
366 if (performance == null) {
367 response.write('<p>No performance stats yet</p>');
368 return;
369 }
370 response.write('<h2>Performance</h2>');
371 response.write('<table>');
372 _writeRow(response, ['Elapsed', '', 'Operation'], header: true);
373 performance.operations.forEach((OperationPerformance op) {
374 String elapsed = op.elapsed != null ? op.elapsed.toString() : '???';
375 _writeRow(response, [elapsed, '&nbsp;&nbsp;', op.name]);
376 });
377 response.write('</table>');
286 } 378 }
287 379
288 /** 380 /**
289 * Write a single row within a table to the given [response] object. The row 381 * Write a single row within a table to the given [response] object. The row
290 * will have one cell for each of the [columns], and will be a header row if 382 * will have one cell for each of the [columns], and will be a header row if
291 * [header] is `true`. 383 * [header] is `true`.
292 */ 384 */
293 void _writeRow(HttpResponse response, List<Object> columns, 385 void _writeRow(HttpResponse response, List<Object> columns, {bool header:
294 {bool header : false, List<String> classes}) { 386 false, List<String> classes}) {
295 response.write('<tr>'); 387 response.write('<tr>');
296 int count = columns.length; 388 int count = columns.length;
297 int maxClassIndex = classes == null ? 0 : classes.length - 1; 389 int maxClassIndex = classes == null ? 0 : classes.length - 1;
298 for (int i = 0; i < count; i++) { 390 for (int i = 0; i < count; i++) {
299 String classAttribute = ''; 391 String classAttribute = '';
300 if (classes != null) { 392 if (classes != null) {
301 String className = classes[min(i, maxClassIndex)]; 393 String className = classes[min(i, maxClassIndex)];
302 if (className != null) { 394 if (className != null) {
303 classAttribute = ' class="$className"'; 395 classAttribute = ' class="$className"';
304 } 396 }
305 } 397 }
306 if (header) { 398 if (header) {
307 response.write('<th$classAttribute>'); 399 response.write('<th$classAttribute>');
308 } else { 400 } else {
309 response.write('<td$classAttribute>'); 401 response.write('<td$classAttribute>');
310 } 402 }
311 response.write(columns[i]); 403 response.write(columns[i]);
312 if (header) { 404 if (header) {
313 response.write('</th>'); 405 response.write('</th>');
314 } else { 406 } else {
315 response.write('</td>'); 407 response.write('</td>');
316 } 408 }
317 }; 409 }
410 ;
318 response.write('</tr>'); 411 response.write('</tr>');
319 } 412 }
320 } 413 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698