OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 /** | 5 /** |
6 * A representation of the contents of an instrumentation log. | 6 * A representation of the contents of an instrumentation log. |
7 */ | 7 */ |
8 library analysis_server.tool.instrumentation.log.log; | 8 library analysis_server.tool.instrumentation.log.log; |
9 | 9 |
10 import 'dart:convert'; | 10 import 'dart:convert'; |
11 import 'dart:math' as math; | 11 import 'dart:math' as math; |
12 | 12 |
13 import 'package:analyzer/instrumentation/instrumentation.dart'; | 13 import 'package:analyzer/instrumentation/instrumentation.dart'; |
| 14 import 'package:path/path.dart' as path; |
14 | 15 |
15 /** | 16 /** |
16 * A boolean-valued function of one argument. | 17 * A boolean-valued function of one argument. |
17 */ | 18 */ |
18 typedef bool Predicate<T>(T value); | 19 typedef bool Predicate<T>(T value); |
19 | 20 |
20 /** | 21 /** |
21 * A description of a group of log entries. | 22 * A description of a group of log entries. |
22 */ | 23 */ |
23 class EntryGroup { | 24 class EntryGroup { |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 * with which they are paired. | 188 * with which they are paired. |
188 */ | 189 */ |
189 Map<LogEntry, LogEntry> _pairedEntries = <LogEntry, LogEntry>{}; | 190 Map<LogEntry, LogEntry> _pairedEntries = <LogEntry, LogEntry>{}; |
190 | 191 |
191 /** | 192 /** |
192 * A table mapping the id's of requests to the entry representing the request. | 193 * A table mapping the id's of requests to the entry representing the request. |
193 */ | 194 */ |
194 Map<String, RequestEntry> _requestMap = <String, RequestEntry>{}; | 195 Map<String, RequestEntry> _requestMap = <String, RequestEntry>{}; |
195 | 196 |
196 /** | 197 /** |
| 198 * A table mapping the id's of plugin requests to the entry representing the |
| 199 * request. |
| 200 */ |
| 201 Map<String, PluginRequestEntry> _pluginRequestMap = |
| 202 <String, PluginRequestEntry>{}; |
| 203 |
| 204 /** |
197 * A table mapping the id's of responses to the entry representing the | 205 * A table mapping the id's of responses to the entry representing the |
198 * response. | 206 * response. |
199 */ | 207 */ |
200 Map<String, ResponseEntry> _responseMap = <String, ResponseEntry>{}; | 208 Map<String, ResponseEntry> _responseMap = <String, ResponseEntry>{}; |
201 | 209 |
202 /** | 210 /** |
| 211 * A table mapping the id's of plugin responses to the entry representing the |
| 212 * response. |
| 213 */ |
| 214 Map<String, PluginResponseEntry> _pluginResponseMap = |
| 215 <String, PluginResponseEntry>{}; |
| 216 |
| 217 /** |
203 * A table mapping the ids of completion events to the events with those ids. | 218 * A table mapping the ids of completion events to the events with those ids. |
204 */ | 219 */ |
205 Map<String, List<NotificationEntry>> _completionMap = | 220 Map<String, List<NotificationEntry>> _completionMap = |
206 <String, List<NotificationEntry>>{}; | 221 <String, List<NotificationEntry>>{}; |
207 | 222 |
208 /** | 223 /** |
209 * The ranges of entries that are between analysis start and analysis end | 224 * The ranges of entries that are between analysis start and analysis end |
210 * notifications. | 225 * notifications. |
211 */ | 226 */ |
212 List<EntryRange> analysisRanges; | 227 List<EntryRange> analysisRanges; |
(...skipping 19 matching lines...) Expand all Loading... |
232 List<LogEntry> entriesInGroup(EntryGroup group) => | 247 List<LogEntry> entriesInGroup(EntryGroup group) => |
233 entryGroups.putIfAbsent(group, () => group.computeMembers(logEntries)); | 248 entryGroups.putIfAbsent(group, () => group.computeMembers(logEntries)); |
234 | 249 |
235 /** | 250 /** |
236 * Return the entry that is paired with the given [entry], or `null` if there | 251 * Return the entry that is paired with the given [entry], or `null` if there |
237 * is no entry paired with it. | 252 * is no entry paired with it. |
238 */ | 253 */ |
239 LogEntry pairedEntry(LogEntry entry) => _pairedEntries[entry]; | 254 LogEntry pairedEntry(LogEntry entry) => _pairedEntries[entry]; |
240 | 255 |
241 /** | 256 /** |
| 257 * Return the response that corresponds to the given plugin request. |
| 258 */ |
| 259 PluginRequestEntry pluginRequestFor(PluginResponseEntry entry) => |
| 260 _pluginRequestMap[entry.id]; |
| 261 |
| 262 /** |
| 263 * Return the response that corresponds to the given request. |
| 264 */ |
| 265 PluginResponseEntry pluginResponseFor(PluginRequestEntry entry) => |
| 266 _pluginResponseMap[entry.id]; |
| 267 |
| 268 /** |
242 * Return the response that corresponds to the given request. | 269 * Return the response that corresponds to the given request. |
243 */ | 270 */ |
244 RequestEntry requestFor(ResponseEntry entry) => _requestMap[entry.id]; | 271 RequestEntry requestFor(ResponseEntry entry) => _requestMap[entry.id]; |
245 | 272 |
246 /** | 273 /** |
247 * Return the response that corresponds to the given request. | 274 * Return the response that corresponds to the given request. |
248 */ | 275 */ |
249 ResponseEntry responseFor(RequestEntry entry) => _responseMap[entry.id]; | 276 ResponseEntry responseFor(RequestEntry entry) => _responseMap[entry.id]; |
250 | 277 |
251 /** | 278 /** |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 } | 426 } |
400 } | 427 } |
401 } else if (entry.event == 'completion.results') { | 428 } else if (entry.event == 'completion.results') { |
402 String id = entry.param('id'); | 429 String id = entry.param('id'); |
403 if (id != null) { | 430 if (id != null) { |
404 _completionMap | 431 _completionMap |
405 .putIfAbsent(id, () => new List<NotificationEntry>()) | 432 .putIfAbsent(id, () => new List<NotificationEntry>()) |
406 .add(entry); | 433 .add(entry); |
407 } | 434 } |
408 } | 435 } |
| 436 } else if (entry is PluginRequestEntry) { |
| 437 _pluginRequestMap[entry.id] = entry; |
| 438 } else if (entry is PluginResponseEntry) { |
| 439 _pluginResponseMap[entry.id] = entry; |
| 440 PluginRequestEntry request = _pluginRequestMap[entry.id]; |
| 441 _pairedEntries[entry] = request; |
| 442 _pairedEntries[request] = entry; |
409 } | 443 } |
410 } | 444 } |
411 } | 445 } |
412 if (analysisStartEntry != null) { | 446 if (analysisStartEntry != null) { |
413 analysisStartEntry | 447 analysisStartEntry |
414 .recordProblem('Analysis started without being terminated.'); | 448 .recordProblem('Analysis started without being terminated.'); |
415 } | 449 } |
416 if (pubStartEntry != null) { | 450 if (pubStartEntry != null) { |
417 pubStartEntry | 451 pubStartEntry |
418 .recordProblem('Pub started without previous being terminated.'); | 452 .recordProblem('Pub started without previous being terminated.'); |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 index, timeStamp, entryKind, components.sublist(2)); | 633 index, timeStamp, entryKind, components.sublist(2)); |
600 } else if (entryKind == InstrumentationService.TAG_FILE_READ) { | 634 } else if (entryKind == InstrumentationService.TAG_FILE_READ) { |
601 // Fall through | 635 // Fall through |
602 } else if (entryKind == InstrumentationService.TAG_LOG_ENTRY) { | 636 } else if (entryKind == InstrumentationService.TAG_LOG_ENTRY) { |
603 // Fall through | 637 // Fall through |
604 } else if (entryKind == InstrumentationService.TAG_NOTIFICATION) { | 638 } else if (entryKind == InstrumentationService.TAG_NOTIFICATION) { |
605 Map requestData = JSON.decode(components[2]); | 639 Map requestData = JSON.decode(components[2]); |
606 return new NotificationEntry(index, timeStamp, requestData); | 640 return new NotificationEntry(index, timeStamp, requestData); |
607 } else if (entryKind == InstrumentationService.TAG_PERFORMANCE) { | 641 } else if (entryKind == InstrumentationService.TAG_PERFORMANCE) { |
608 // Fall through | 642 // Fall through |
| 643 } else if (entryKind == InstrumentationService.TAG_PLUGIN_ERROR) { |
| 644 return new PluginErrorEntry( |
| 645 index, timeStamp, entryKind, components[2], components.sublist(3)); |
| 646 } else if (entryKind == InstrumentationService.TAG_PLUGIN_EXCEPTION) { |
| 647 return new PluginExceptionEntry( |
| 648 index, timeStamp, entryKind, components[2], components.sublist(3)); |
| 649 } else if (entryKind == InstrumentationService.TAG_PLUGIN_NOTIFICATION) { |
| 650 Map requestData = JSON.decode(components[3]); |
| 651 return new PluginNotificationEntry( |
| 652 index, timeStamp, components[2], requestData); |
| 653 } else if (entryKind == InstrumentationService.TAG_PLUGIN_REQUEST) { |
| 654 Map requestData = JSON.decode(components[3]); |
| 655 return new PluginRequestEntry( |
| 656 index, timeStamp, components[2], requestData); |
| 657 } else if (entryKind == InstrumentationService.TAG_PLUGIN_RESPONSE) { |
| 658 Map responseData = JSON.decode(components[3]); |
| 659 return new PluginResponseEntry( |
| 660 index, timeStamp, components[2], responseData); |
| 661 } else if (entryKind == InstrumentationService.TAG_PLUGIN_TIMEOUT) { |
| 662 return new PluginErrorEntry( |
| 663 index, timeStamp, entryKind, components[2], components.sublist(3)); |
609 } else if (entryKind == InstrumentationService.TAG_REQUEST) { | 664 } else if (entryKind == InstrumentationService.TAG_REQUEST) { |
610 Map requestData = JSON.decode(components[2]); | 665 Map requestData = JSON.decode(components[2]); |
611 return new RequestEntry(index, timeStamp, requestData); | 666 return new RequestEntry(index, timeStamp, requestData); |
612 } else if (entryKind == InstrumentationService.TAG_RESPONSE) { | 667 } else if (entryKind == InstrumentationService.TAG_RESPONSE) { |
613 Map responseData = JSON.decode(components[2]); | 668 Map responseData = JSON.decode(components[2]); |
614 return new ResponseEntry(index, timeStamp, responseData); | 669 return new ResponseEntry(index, timeStamp, responseData); |
615 } else if (entryKind == InstrumentationService.TAG_SUBPROCESS_START) { | 670 } else if (entryKind == InstrumentationService.TAG_SUBPROCESS_START) { |
616 // Fall through | 671 // Fall through |
617 } else if (entryKind == InstrumentationService.TAG_SUBPROCESS_RESULT) { | 672 } else if (entryKind == InstrumentationService.TAG_SUBPROCESS_RESULT) { |
618 // Fall through | 673 // Fall through |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
771 dynamic param(String parameterName) { | 826 dynamic param(String parameterName) { |
772 var parameters = data['params']; | 827 var parameters = data['params']; |
773 if (parameters is Map) { | 828 if (parameters is Map) { |
774 return parameters[parameterName]; | 829 return parameters[parameterName]; |
775 } | 830 } |
776 return null; | 831 return null; |
777 } | 832 } |
778 } | 833 } |
779 | 834 |
780 /** | 835 /** |
| 836 * A log entry representing a communication between the server and a plugin. |
| 837 */ |
| 838 abstract class PluginEntry extends JsonBasedEntry with PluginEntryMixin { |
| 839 /** |
| 840 * The id of the plugin being communicated with. |
| 841 */ |
| 842 final String pluginId; |
| 843 |
| 844 /** |
| 845 * Initialize a newly created entry to have the given [timeStamp] and |
| 846 * [notificationData] and to be associated with the plugin with the given |
| 847 * [pluginId]. |
| 848 */ |
| 849 PluginEntry(int index, int timeStamp, this.pluginId, Map notificationData) |
| 850 : super(index, timeStamp, notificationData); |
| 851 } |
| 852 |
| 853 /** |
| 854 * A log entry representing a communication between the server and a plugin. |
| 855 */ |
| 856 abstract class PluginEntryMixin { |
| 857 /** |
| 858 * The id of the plugin being communicated with. |
| 859 */ |
| 860 String get pluginId; |
| 861 |
| 862 /** |
| 863 * Return a shortened version of the plugin id. |
| 864 */ |
| 865 String get shortPluginId { |
| 866 int index = pluginId.lastIndexOf(path.separator); |
| 867 if (index > 0) { |
| 868 return pluginId.substring(index + 1); |
| 869 } |
| 870 return pluginId; |
| 871 } |
| 872 } |
| 873 |
| 874 /** |
| 875 * A log entry representing an PluginErr entry. |
| 876 */ |
| 877 class PluginErrorEntry extends GenericEntry with PluginEntryMixin { |
| 878 /** |
| 879 * The id of the plugin that generated the error. |
| 880 */ |
| 881 final String pluginId; |
| 882 |
| 883 /** |
| 884 * Initialize a newly created log entry. |
| 885 */ |
| 886 PluginErrorEntry(int index, int timeStamp, String entryKind, this.pluginId, |
| 887 List<String> components) |
| 888 : super(index, timeStamp, entryKind, components); |
| 889 } |
| 890 |
| 891 /** |
| 892 * A log entry representing an PluginEx entry. |
| 893 */ |
| 894 class PluginExceptionEntry extends GenericEntry with PluginEntryMixin { |
| 895 /** |
| 896 * The id of the plugin that generated the exception. |
| 897 */ |
| 898 final String pluginId; |
| 899 |
| 900 /** |
| 901 * Initialize a newly created log entry. |
| 902 */ |
| 903 PluginExceptionEntry(int index, int timeStamp, String entryKind, |
| 904 this.pluginId, List<String> components) |
| 905 : super(index, timeStamp, entryKind, components); |
| 906 } |
| 907 |
| 908 /** |
| 909 * A log entry representing a notification that was sent from a plugin to the |
| 910 * server. |
| 911 */ |
| 912 class PluginNotificationEntry extends PluginEntry { |
| 913 /** |
| 914 * Initialize a newly created notification to have the given [timeStamp] and |
| 915 * [notificationData]. |
| 916 */ |
| 917 PluginNotificationEntry( |
| 918 int index, int timeStamp, String pluginId, Map notificationData) |
| 919 : super(index, timeStamp, pluginId, notificationData); |
| 920 |
| 921 /** |
| 922 * Return the event field of the notification. |
| 923 */ |
| 924 String get event => data['event']; |
| 925 |
| 926 @override |
| 927 String get kind => 'PluginNoti'; |
| 928 |
| 929 /** |
| 930 * Return the value of the parameter with the given [parameterName], or `null` |
| 931 * if there is no such parameter. |
| 932 */ |
| 933 dynamic param(String parameterName) { |
| 934 var parameters = data['params']; |
| 935 if (parameters is Map) { |
| 936 return parameters[parameterName]; |
| 937 } |
| 938 return null; |
| 939 } |
| 940 } |
| 941 |
| 942 /** |
| 943 * A log entry representing a request that was sent from the server to a plugin. |
| 944 */ |
| 945 class PluginRequestEntry extends PluginEntry { |
| 946 /** |
| 947 * Initialize a newly created response to have the given [timeStamp] and |
| 948 * [requestData]. |
| 949 */ |
| 950 PluginRequestEntry(int index, int timeStamp, String pluginId, Map requestData) |
| 951 : super(index, timeStamp, pluginId, requestData); |
| 952 |
| 953 /** |
| 954 * Return the id field of the request. |
| 955 */ |
| 956 String get id => data['id']; |
| 957 |
| 958 @override |
| 959 String get kind => 'PluginReq'; |
| 960 |
| 961 /** |
| 962 * Return the method field of the request. |
| 963 */ |
| 964 String get method => data['method']; |
| 965 |
| 966 /** |
| 967 * Return the value of the parameter with the given [parameterName], or `null` |
| 968 * if there is no such parameter. |
| 969 */ |
| 970 dynamic param(String parameterName) { |
| 971 var parameters = data['params']; |
| 972 if (parameters is Map) { |
| 973 return parameters[parameterName]; |
| 974 } |
| 975 return null; |
| 976 } |
| 977 } |
| 978 |
| 979 /** |
| 980 * A log entry representing a response that was sent from a plugin to the |
| 981 * server. |
| 982 */ |
| 983 class PluginResponseEntry extends PluginEntry { |
| 984 /** |
| 985 * Initialize a newly created response to have the given [timeStamp] and |
| 986 * [responseData]. |
| 987 */ |
| 988 PluginResponseEntry( |
| 989 int index, int timeStamp, String pluginId, Map responseData) |
| 990 : super(index, timeStamp, pluginId, responseData); |
| 991 |
| 992 /** |
| 993 * Return the id field of the response. |
| 994 */ |
| 995 String get id => data['id']; |
| 996 |
| 997 @override |
| 998 String get kind => 'PluginRes'; |
| 999 |
| 1000 /** |
| 1001 * Return the value of the result with the given [resultName], or `null` if |
| 1002 * there is no such result. |
| 1003 */ |
| 1004 dynamic result(String resultName) { |
| 1005 var results = data['result']; |
| 1006 if (results is Map) { |
| 1007 return results[resultName]; |
| 1008 } |
| 1009 return null; |
| 1010 } |
| 1011 } |
| 1012 |
| 1013 /** |
781 * A log entry representing a request that was sent from the client to the | 1014 * A log entry representing a request that was sent from the client to the |
782 * server. | 1015 * server. |
783 */ | 1016 */ |
784 class RequestEntry extends JsonBasedEntry { | 1017 class RequestEntry extends JsonBasedEntry { |
785 /** | 1018 /** |
786 * Initialize a newly created response to have the given [timeStamp] and | 1019 * Initialize a newly created response to have the given [timeStamp] and |
787 * [requestData]. | 1020 * [requestData]. |
788 */ | 1021 */ |
789 RequestEntry(int index, int timeStamp, Map requestData) | 1022 RequestEntry(int index, int timeStamp, Map requestData) |
790 : super(index, timeStamp, requestData); | 1023 : super(index, timeStamp, requestData); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
930 int slash = context.lastIndexOf('/'); | 1163 int slash = context.lastIndexOf('/'); |
931 if (slash < 0) { | 1164 if (slash < 0) { |
932 slash = context.lastIndexOf('\\'); | 1165 slash = context.lastIndexOf('\\'); |
933 } | 1166 } |
934 if (slash >= 0) { | 1167 if (slash >= 0) { |
935 String prefix = context.substring(0, slash); | 1168 String prefix = context.substring(0, slash); |
936 _target = _target.replaceAll(prefix, '...'); | 1169 _target = _target.replaceAll(prefix, '...'); |
937 } | 1170 } |
938 } | 1171 } |
939 } | 1172 } |
OLD | NEW |