| OLD | NEW |
| 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 analysis_server.src.get_handler; | 5 library analysis_server.src.get_handler; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 import 'dart:io'; | 9 import 'dart:io'; |
| 10 import 'dart:math'; | 10 import 'dart:math'; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 * Contents of overlay files. | 138 * Contents of overlay files. |
| 139 */ | 139 */ |
| 140 final Map<int, String> _overlayContents = <int, String>{}; | 140 final Map<int, String> _overlayContents = <int, String>{}; |
| 141 | 141 |
| 142 /** | 142 /** |
| 143 * Initialize a newly created handler for GET requests. | 143 * Initialize a newly created handler for GET requests. |
| 144 */ | 144 */ |
| 145 GetHandler(this._server, this._printBuffer); | 145 GetHandler(this._server, this._printBuffer); |
| 146 | 146 |
| 147 /** | 147 /** |
| 148 * Return the active [CompletionDomainHandler] |
| 149 * or `null` if either analysis server is not running |
| 150 * or there is no completion domain handler. |
| 151 */ |
| 152 CompletionDomainHandler get _completionDomainHandler { |
| 153 AnalysisServer analysisServer = _server.analysisServer; |
| 154 if (analysisServer == null) { |
| 155 return null; |
| 156 } |
| 157 return analysisServer.handlers.firstWhere( |
| 158 (h) => h is CompletionDomainHandler, |
| 159 orElse: () => null); |
| 160 } |
| 161 |
| 162 /** |
| 148 * Handle a GET request received by the HTTP server. | 163 * Handle a GET request received by the HTTP server. |
| 149 */ | 164 */ |
| 150 void handleGetRequest(HttpRequest request) { | 165 void handleGetRequest(HttpRequest request) { |
| 151 String path = request.uri.path; | 166 String path = request.uri.path; |
| 152 if (path == STATUS_PATH) { | 167 if (path == STATUS_PATH) { |
| 153 _returnServerStatus(request); | 168 _returnServerStatus(request); |
| 154 } else if (path == '/status2') { | 169 } else if (path == '/status2') { |
| 155 _returnServerStatus2(request); | 170 _returnServerStatus2(request); |
| 156 } else if (path == AST_PATH) { | 171 } else if (path == AST_PATH) { |
| 157 _returnAst(request); | 172 _returnAst(request); |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 response.write('<p>$count files found</p>'); | 581 response.write('<p>$count files found</p>'); |
| 567 response.write('</body>'); | 582 response.write('</body>'); |
| 568 response.write('</html>'); | 583 response.write('</html>'); |
| 569 response.close(); | 584 response.close(); |
| 570 } | 585 } |
| 571 | 586 |
| 572 /** | 587 /** |
| 573 * Return a response displaying code completion information. | 588 * Return a response displaying code completion information. |
| 574 */ | 589 */ |
| 575 void _returnCompletionInfo(HttpRequest request) { | 590 void _returnCompletionInfo(HttpRequest request) { |
| 576 var refresh = request.requestedUri.queryParameters['refresh']; | 591 String value = request.requestedUri.queryParameters['index']; |
| 577 var maxCount = request.requestedUri.queryParameters['maxCount']; | 592 int index = value != null ? int.parse(value, onError: (_) => 0) : 0; |
| 578 HttpResponse response = request.response; | 593 _writeResponse(request, (StringBuffer buffer) { |
| 579 response.statusCode = HttpStatus.OK; | 594 _writePage(buffer, 'Code Completion - Status', [], (StringBuffer buffer) { |
| 580 response.headers.contentType = _htmlContent; | 595 _writeCompletionPerformanceDetail(buffer, index); |
| 581 response.write('<html>'); | 596 _writeCompletionPerformanceList(buffer); |
| 582 response.write('<head>'); | 597 }); |
| 583 response.write('<title>Dart Analysis Server - Completion Stats</title>'); | 598 }); |
| 584 response.write('<style>'); | |
| 585 response.write('td.right {text-align: right;}'); | |
| 586 response.write('</style>'); | |
| 587 if (refresh is String) { | |
| 588 int seconds = int.parse(refresh, onError: (_) => 5); | |
| 589 response.write('<meta http-equiv="refresh" content="$seconds">'); | |
| 590 } | |
| 591 response.write('</head>'); | |
| 592 response.write('<body>'); | |
| 593 _writeCompletionInfo(response, maxCount); | |
| 594 response.write('<p> </p>'); | |
| 595 response.write('<p>Try '); | |
| 596 response.write('<a href="?refresh=5">?refresh=5</a>'); | |
| 597 response.write(' to refresh every 5 seconds</p>'); | |
| 598 response.write('<p>and '); | |
| 599 response.write('<a href="?maxCount=50">?maxCount=50</a>'); | |
| 600 response.write(' to keep the last 50 performance measurements</p>'); | |
| 601 response.write('</body>'); | |
| 602 response.write('</html>'); | |
| 603 response.close(); | |
| 604 } | 599 } |
| 605 | 600 |
| 606 /** | 601 /** |
| 607 * Return a response containing information about a single source file in the | 602 * Return a response containing information about a single source file in the |
| 608 * cache. | 603 * cache. |
| 609 */ | 604 */ |
| 610 void _returnContextInfo(HttpRequest request) { | 605 void _returnContextInfo(HttpRequest request) { |
| 611 AnalysisServer analysisServer = _server.analysisServer; | 606 AnalysisServer analysisServer = _server.analysisServer; |
| 612 if (analysisServer == null) { | 607 if (analysisServer == null) { |
| 613 return _returnFailure(request, 'Analysis server not running'); | 608 return _returnFailure(request, 'Analysis server not running'); |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1081 buffer.write('</p>'); | 1076 buffer.write('</p>'); |
| 1082 }, (StringBuffer buffer) { | 1077 }, (StringBuffer buffer) { |
| 1083 _writeSubscriptionMap( | 1078 _writeSubscriptionMap( |
| 1084 buffer, | 1079 buffer, |
| 1085 AnalysisService.VALUES, | 1080 AnalysisService.VALUES, |
| 1086 analysisServer.analysisServices); | 1081 analysisServer.analysisServices); |
| 1087 }); | 1082 }); |
| 1088 } | 1083 } |
| 1089 | 1084 |
| 1090 /** | 1085 /** |
| 1091 * Append code completion information. | 1086 * Write performance information about a specific completion request |
| 1087 * to the given [buffer] object. |
| 1092 */ | 1088 */ |
| 1093 void _writeCompletionInfo(HttpResponse response, maxCount) { | 1089 void _writeCompletionPerformanceDetail(StringBuffer buffer, int index) { |
| 1094 response.write('<h1>Code Completion</h1>'); | 1090 CompletionDomainHandler handler = _completionDomainHandler; |
| 1095 AnalysisServer analysisServer = _server.analysisServer; | 1091 CompletionPerformance performance; |
| 1096 if (analysisServer == null) { | 1092 if (handler != null) { |
| 1097 response.write('<p>Not running</p>'); | 1093 List<CompletionPerformance> list = handler.performanceList; |
| 1094 if (list != null && list.isNotEmpty) { |
| 1095 performance = list[max(0, min(list.length - 1, index))]; |
| 1096 } |
| 1097 } |
| 1098 if (performance == null) { |
| 1099 buffer.write('<h3>Completion Performance Detail</h3>'); |
| 1100 buffer.write('<p>No completions yet</p>'); |
| 1098 return; | 1101 return; |
| 1099 } | 1102 } |
| 1100 CompletionDomainHandler handler = analysisServer.handlers.firstWhere( | 1103 buffer.write( |
| 1101 (h) => h is CompletionDomainHandler, | 1104 '<h3>Completion Performance Detail - ${performance.startTimeAndMs}</h3>'
); |
| 1102 orElse: () => null); | 1105 buffer.write('<table>'); |
| 1103 if (handler == null) { | 1106 _writeRow2(buffer, ['Elapsed', '', 'Operation'], header: true); |
| 1104 response.write('<p>No code completion</p>'); | |
| 1105 return; | |
| 1106 } | |
| 1107 if (maxCount is String) { | |
| 1108 int count = int.parse(maxCount, onError: (_) => 0); | |
| 1109 handler.performanceListMaxLength = count; | |
| 1110 } | |
| 1111 CompletionPerformance performance = handler.performance; | |
| 1112 if (performance == null) { | |
| 1113 response.write('<p>No performance stats yet</p>'); | |
| 1114 return; | |
| 1115 } | |
| 1116 response.write('<h2>Last Completion Performance</h2>'); | |
| 1117 response.write('<table>'); | |
| 1118 _writeRow(response, ['Elapsed', '', 'Operation'], header: true); | |
| 1119 performance.operations.forEach((OperationPerformance op) { | 1107 performance.operations.forEach((OperationPerformance op) { |
| 1120 String elapsed = op.elapsed != null ? op.elapsed.toString() : '???'; | 1108 String elapsed = op.elapsed != null ? op.elapsed.toString() : '???'; |
| 1121 _writeRow(response, [elapsed, ' ', op.name]); | 1109 _writeRow2(buffer, [elapsed, ' ', op.name]); |
| 1122 }); | 1110 }); |
| 1123 if (handler.priorityChangedPerformance == null) { | 1111 if (handler.priorityChangedPerformance == null) { |
| 1124 response.write('<p>No priorityChanged caching</p>'); | 1112 buffer.write('<p>No priorityChanged caching</p>'); |
| 1125 } else { | 1113 } else { |
| 1126 int len = handler.priorityChangedPerformance.operations.length; | 1114 int len = handler.priorityChangedPerformance.operations.length; |
| 1127 if (len > 0) { | 1115 if (len > 0) { |
| 1128 var op = handler.priorityChangedPerformance.operations[len - 1]; | 1116 var op = handler.priorityChangedPerformance.operations[len - 1]; |
| 1129 if (op != null) { | 1117 if (op != null) { |
| 1130 _writeRow(response, [' ', ' ', ' ']); | 1118 _writeRow2(buffer, [' ', ' ', ' ']); |
| 1131 String elapsed = op.elapsed != null ? op.elapsed.toString() : '???'; | 1119 String elapsed = op.elapsed != null ? op.elapsed.toString() : '???'; |
| 1132 _writeRow(response, [elapsed, ' ', op.name]); | 1120 _writeRow2(buffer, [elapsed, ' ', op.name]); |
| 1133 } | 1121 } |
| 1134 } | 1122 } |
| 1135 } | 1123 } |
| 1136 response.write('</table>'); | 1124 buffer.write('</table>'); |
| 1137 if (handler.performanceList.length > 0) { | |
| 1138 response.write('<h2>Last Completion Summary</h2>'); | |
| 1139 response.write('<table>'); | |
| 1140 _writeRow( | |
| 1141 response, | |
| 1142 [ | |
| 1143 'Start Time', | |
| 1144 '', | |
| 1145 'First (ms)', | |
| 1146 '', | |
| 1147 'Complete (ms)', | |
| 1148 '', | |
| 1149 '# Notifications', | |
| 1150 '', | |
| 1151 '# Suggestions', | |
| 1152 '', | |
| 1153 'Snippet'], | |
| 1154 header: true); | |
| 1155 handler.performanceList.forEach((CompletionPerformance performance) { | |
| 1156 _writeRow( | |
| 1157 response, | |
| 1158 [ | |
| 1159 performance.start, | |
| 1160 ' ', | |
| 1161 performance.firstNotificationInMilliseconds, | |
| 1162 ' ', | |
| 1163 performance.elapsedInMilliseconds, | |
| 1164 ' ', | |
| 1165 performance.notificationCount, | |
| 1166 ' ', | |
| 1167 performance.suggestionCount, | |
| 1168 ' ', | |
| 1169 performance.snippet]); | |
| 1170 }); | |
| 1171 response.write('</table>'); | |
| 1172 } | |
| 1173 } | 1125 } |
| 1174 | 1126 |
| 1175 /** | 1127 /** |
| 1128 * Write a table showing summary information for the last several |
| 1129 * completion requests to the given [buffer] object. |
| 1130 */ |
| 1131 void _writeCompletionPerformanceList(StringBuffer buffer) { |
| 1132 CompletionDomainHandler handler = _completionDomainHandler; |
| 1133 buffer.write('<h3>Completion Performance</h3>'); |
| 1134 if (handler == null) { |
| 1135 return; |
| 1136 } |
| 1137 buffer.write('<table>'); |
| 1138 _writeRow2( |
| 1139 buffer, |
| 1140 [ |
| 1141 'Start Time', |
| 1142 '', |
| 1143 'First (ms)', |
| 1144 '', |
| 1145 'Complete (ms)', |
| 1146 '', |
| 1147 '# Notifications', |
| 1148 '', |
| 1149 '# Suggestions', |
| 1150 '', |
| 1151 'Snippet'], |
| 1152 header: true); |
| 1153 int index = 0; |
| 1154 for (CompletionPerformance performance in handler.performanceList) { |
| 1155 String link = _makeLink(COMPLETION_PATH, { |
| 1156 'index': '$index' |
| 1157 }, '${performance.startTimeAndMs}'); |
| 1158 _writeRow2( |
| 1159 buffer, |
| 1160 [ |
| 1161 link, |
| 1162 ' ', |
| 1163 performance.firstNotificationInMilliseconds, |
| 1164 ' ', |
| 1165 performance.elapsedInMilliseconds, |
| 1166 ' ', |
| 1167 performance.notificationCount, |
| 1168 ' ', |
| 1169 performance.suggestionCount, |
| 1170 ' ', |
| 1171 HTML_ESCAPE.convert(performance.snippet)]); |
| 1172 ++index; |
| 1173 } |
| 1174 ; |
| 1175 buffer.write('</table>'); |
| 1176 buffer.write(''' |
| 1177 <p><strong>First (ms)</strong> - the number of milliseconds |
| 1178 from when completion received the request until the first notification |
| 1179 with completion results was queued for sending back to the client. |
| 1180 <p><strong>Complete (ms)</strong> - the number of milliseconds |
| 1181 from when completion received the request until the final notification |
| 1182 with completion results was queued for sending back to the client. |
| 1183 <p><strong># Notifications</strong> - the total number of notifications |
| 1184 sent to the client with completion results for this request. |
| 1185 <p><strong># Suggestions</strong> - the number of suggestions |
| 1186 sent to the client in the first notification, followed by a comma, |
| 1187 followed by the number of suggestions send to the client |
| 1188 in the last notification. If there is only one notification, |
| 1189 then there will be only one number in this column.'''); |
| 1190 } |
| 1191 |
| 1192 /** |
| 1176 * Generate a table showing the cache values corresponding to the given | 1193 * Generate a table showing the cache values corresponding to the given |
| 1177 * [descriptors], using [getState] to get the cache state corresponding to | 1194 * [descriptors], using [getState] to get the cache state corresponding to |
| 1178 * each descriptor, and [getValue] to get the cached value corresponding to | 1195 * each descriptor, and [getValue] to get the cached value corresponding to |
| 1179 * each descriptor. Append the resulting HTML to the given [buffer]. The | 1196 * each descriptor. Append the resulting HTML to the given [buffer]. The |
| 1180 * [linkParameters] will be used if the value is too large to be displayed on | 1197 * [linkParameters] will be used if the value is too large to be displayed on |
| 1181 * the current page and needs to be linked to a separate page. | 1198 * the current page and needs to be linked to a separate page. |
| 1182 */ | 1199 */ |
| 1183 void _writeDescriptorTable(StringBuffer buffer, | 1200 void _writeDescriptorTable(StringBuffer buffer, |
| 1184 List<DataDescriptor> descriptors, CacheState getState(DataDescriptor), dyn
amic | 1201 List<DataDescriptor> descriptors, CacheState getState(DataDescriptor), dyn
amic |
| 1185 getValue(DataDescriptor), Map<String, String> linkParameters) { | 1202 getValue(DataDescriptor), Map<String, String> linkParameters) { |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1611 } else if (value is Element) { | 1628 } else if (value is Element) { |
| 1612 String link = | 1629 String link = |
| 1613 _makeLink(ELEMENT_PATH, linkParameters, value.runtimeType.toString()); | 1630 _makeLink(ELEMENT_PATH, linkParameters, value.runtimeType.toString()); |
| 1614 buffer.write('<i>$link</i>'); | 1631 buffer.write('<i>$link</i>'); |
| 1615 } else { | 1632 } else { |
| 1616 buffer.write(HTML_ESCAPE.convert(value.toString())); | 1633 buffer.write(HTML_ESCAPE.convert(value.toString())); |
| 1617 buffer.write(' <i>(${value.runtimeType.toString()})</i>'); | 1634 buffer.write(' <i>(${value.runtimeType.toString()})</i>'); |
| 1618 } | 1635 } |
| 1619 } | 1636 } |
| 1620 } | 1637 } |
| OLD | NEW |