| 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 part of service; | 5 part of service; |
| 6 | 6 |
| 7 /// A [ServiceObject] is an object known to the VM service and is tied | 7 /// A [ServiceObject] is an object known to the VM service and is tied |
| 8 /// to an owning [Isolate]. | 8 /// to an owning [Isolate]. |
| 9 abstract class ServiceObject extends Observable { | 9 abstract class ServiceObject extends Observable { |
| 10 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { | 10 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 var type = _stripRef(map['type']); | 69 var type = _stripRef(map['type']); |
| 70 var obj = null; | 70 var obj = null; |
| 71 assert(type != 'VM'); | 71 assert(type != 'VM'); |
| 72 switch (type) { | 72 switch (type) { |
| 73 case 'Class': | 73 case 'Class': |
| 74 obj = new Class._empty(owner); | 74 obj = new Class._empty(owner); |
| 75 break; | 75 break; |
| 76 case 'Code': | 76 case 'Code': |
| 77 obj = new Code._empty(owner); | 77 obj = new Code._empty(owner); |
| 78 break; | 78 break; |
| 79 case 'Counter': |
| 80 obj = new ServiceMetric._empty(owner); |
| 81 break; |
| 79 case 'Error': | 82 case 'Error': |
| 80 obj = new DartError._empty(owner); | 83 obj = new DartError._empty(owner); |
| 81 break; | 84 break; |
| 82 case 'Function': | 85 case 'Function': |
| 83 obj = new ServiceFunction._empty(owner); | 86 obj = new ServiceFunction._empty(owner); |
| 84 break; | 87 break; |
| 88 case 'Gauge': |
| 89 obj = new ServiceMetric._empty(owner); |
| 90 break; |
| 85 case 'Isolate': | 91 case 'Isolate': |
| 86 obj = new Isolate._empty(owner.vm); | 92 obj = new Isolate._empty(owner.vm); |
| 87 break; | 93 break; |
| 88 case 'Library': | 94 case 'Library': |
| 89 obj = new Library._empty(owner); | 95 obj = new Library._empty(owner); |
| 90 break; | 96 break; |
| 91 case 'ServiceError': | 97 case 'ServiceError': |
| 92 obj = new ServiceError._empty(owner); | 98 obj = new ServiceError._empty(owner); |
| 93 break; | 99 break; |
| 94 case 'ServiceEvent': | 100 case 'ServiceEvent': |
| (...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 return new Future.value(objectClass); | 700 return new Future.value(objectClass); |
| 695 } | 701 } |
| 696 | 702 |
| 697 ServiceObject getFromMap(ObservableMap map) { | 703 ServiceObject getFromMap(ObservableMap map) { |
| 698 if (map == null) { | 704 if (map == null) { |
| 699 return null; | 705 return null; |
| 700 } | 706 } |
| 701 String id = map['id']; | 707 String id = map['id']; |
| 702 var obj = _cache[id]; | 708 var obj = _cache[id]; |
| 703 if (obj != null) { | 709 if (obj != null) { |
| 710 // Consider calling update when map is not a reference. |
| 704 return obj; | 711 return obj; |
| 705 } | 712 } |
| 706 // Build the object from the map directly. | 713 // Build the object from the map directly. |
| 707 obj = new ServiceObject._fromMap(this, map); | 714 obj = new ServiceObject._fromMap(this, map); |
| 708 if (obj != null && obj.canCache) { | 715 if (obj != null && obj.canCache) { |
| 709 _cache[id] = obj; | 716 _cache[id] = obj; |
| 710 } | 717 } |
| 711 return obj; | 718 return obj; |
| 712 } | 719 } |
| 713 | 720 |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1006 return get("debug/resume").then((result) { | 1013 return get("debug/resume").then((result) { |
| 1007 if (result is DartError) { | 1014 if (result is DartError) { |
| 1008 // TODO(turnidge): Handle this more gracefully. | 1015 // TODO(turnidge): Handle this more gracefully. |
| 1009 Logger.root.severe(result.message); | 1016 Logger.root.severe(result.message); |
| 1010 } | 1017 } |
| 1011 return isolate.reload(); | 1018 return isolate.reload(); |
| 1012 }); | 1019 }); |
| 1013 } | 1020 } |
| 1014 | 1021 |
| 1015 Future stepInto() { | 1022 Future stepInto() { |
| 1016 print('isolate.stepInto'); | |
| 1017 return get("debug/resume?step=into").then((result) { | 1023 return get("debug/resume?step=into").then((result) { |
| 1018 if (result is DartError) { | 1024 if (result is DartError) { |
| 1019 // TODO(turnidge): Handle this more gracefully. | 1025 // TODO(turnidge): Handle this more gracefully. |
| 1020 Logger.root.severe(result.message); | 1026 Logger.root.severe(result.message); |
| 1021 } | 1027 } |
| 1022 return isolate.reload(); | 1028 return isolate.reload(); |
| 1023 }); | 1029 }); |
| 1024 } | 1030 } |
| 1025 | 1031 |
| 1026 Future stepOver() { | 1032 Future stepOver() { |
| 1027 return get("debug/resume?step=over").then((result) { | 1033 return get("debug/resume?step=over").then((result) { |
| 1028 if (result is DartError) { | 1034 if (result is DartError) { |
| 1029 // TODO(turnidge): Handle this more gracefully. | 1035 // TODO(turnidge): Handle this more gracefully. |
| 1030 Logger.root.severe(result.message); | 1036 Logger.root.severe(result.message); |
| 1031 } | 1037 } |
| 1032 return isolate.reload(); | 1038 return isolate.reload(); |
| 1033 }); | 1039 }); |
| 1034 } | 1040 } |
| 1035 | 1041 |
| 1036 Future stepOut() { | 1042 Future stepOut() { |
| 1037 return get("debug/resume?step=out").then((result) { | 1043 return get("debug/resume?step=out").then((result) { |
| 1038 if (result is DartError) { | 1044 if (result is DartError) { |
| 1039 // TODO(turnidge): Handle this more gracefully. | 1045 // TODO(turnidge): Handle this more gracefully. |
| 1040 Logger.root.severe(result.message); | 1046 Logger.root.severe(result.message); |
| 1041 } | 1047 } |
| 1042 return isolate.reload(); | 1048 return isolate.reload(); |
| 1043 }); | 1049 }); |
| 1044 } | 1050 } |
| 1045 | 1051 |
| 1052 final ObservableMap<String, ServiceMetric> dartMetrics = |
| 1053 new ObservableMap<String, ServiceMetric>(); |
| 1054 |
| 1055 final ObservableMap<String, ServiceMetric> vmMetrics = |
| 1056 new ObservableMap<String, ServiceMetric>(); |
| 1057 |
| 1058 Future<ObservableMap<String, ServiceMetric>> _refreshMetrics( |
| 1059 String id, |
| 1060 ObservableMap<String, ServiceMetric> metricsMap) { |
| 1061 return get(id).then((result) { |
| 1062 if (result is DartError) { |
| 1063 // TODO(turnidge): Handle this more gracefully. |
| 1064 Logger.root.severe(result.message); |
| 1065 return null; |
| 1066 } |
| 1067 // Clear metrics map. |
| 1068 metricsMap.clear(); |
| 1069 // Repopulate metrics map. |
| 1070 var members = result['members']; |
| 1071 for (var metric in members) { |
| 1072 metricsMap[metric.id] = metric; |
| 1073 } |
| 1074 return metricsMap; |
| 1075 }); |
| 1076 } |
| 1077 |
| 1078 Future<ObservableMap<String, ServiceMetric>> refreshDartMetrics() { |
| 1079 return _refreshMetrics('metrics', dartMetrics); |
| 1080 } |
| 1081 |
| 1082 Future<ObservableMap<String, ServiceMetric>> refreshVMMetrics() { |
| 1083 return _refreshMetrics('metrics/vm', vmMetrics); |
| 1084 } |
| 1085 |
| 1086 Future refreshMetrics() { |
| 1087 return refreshDartMetrics().then((_) => refreshVMMetrics()); |
| 1088 } |
| 1089 |
| 1046 String toString() => "Isolate($_id)"; | 1090 String toString() => "Isolate($_id)"; |
| 1047 } | 1091 } |
| 1048 | 1092 |
| 1049 /// A [ServiceObject] which implements [ObservableMap]. | 1093 /// A [ServiceObject] which implements [ObservableMap]. |
| 1050 class ServiceMap extends ServiceObject implements ObservableMap { | 1094 class ServiceMap extends ServiceObject implements ObservableMap { |
| 1051 final ObservableMap _map = new ObservableMap(); | 1095 final ObservableMap _map = new ObservableMap(); |
| 1052 static String objectIdRingPrefix = 'objects/'; | 1096 static String objectIdRingPrefix = 'objects/'; |
| 1053 | 1097 |
| 1054 bool get canCache { | 1098 bool get canCache { |
| 1055 return (_serviceType == 'Class' || | 1099 return (_serviceType == 'Class' || |
| (...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1534 if (!_isTrivialToken(token)) { | 1578 if (!_isTrivialToken(token)) { |
| 1535 return false; | 1579 return false; |
| 1536 } | 1580 } |
| 1537 } | 1581 } |
| 1538 } | 1582 } |
| 1539 return true; | 1583 return true; |
| 1540 } | 1584 } |
| 1541 | 1585 |
| 1542 ScriptLine(this.script, this.line, this.text) { | 1586 ScriptLine(this.script, this.line, this.text) { |
| 1543 possibleBpt = !_isTrivialLine(text); | 1587 possibleBpt = !_isTrivialLine(text); |
| 1544 | 1588 |
| 1545 // TODO(turnidge): This is not so efficient. Consider improving. | 1589 // TODO(turnidge): This is not so efficient. Consider improving. |
| 1546 for (var bpt in this.script.isolate.breakpoints['breakpoints']) { | 1590 for (var bpt in this.script.isolate.breakpoints['breakpoints']) { |
| 1547 var bptScript = bpt['location']['script']; | 1591 var bptScript = bpt['location']['script']; |
| 1548 var bptTokenPos = bpt['location']['tokenPos']; | 1592 var bptTokenPos = bpt['location']['tokenPos']; |
| 1549 if (bptScript == this.script && | 1593 if (bptScript == this.script && |
| 1550 bptScript.tokenToLine(bptTokenPos) == line) { | 1594 bptScript.tokenToLine(bptTokenPos) == line) { |
| 1551 this.bpt = bpt; | 1595 this.bpt = bpt; |
| 1552 } | 1596 } |
| 1553 } | 1597 } |
| 1554 } | 1598 } |
| (...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2212 localAddress = map['localAddress']; | 2256 localAddress = map['localAddress']; |
| 2213 localPort = map['localPort']; | 2257 localPort = map['localPort']; |
| 2214 remoteAddress = map['remoteAddress']; | 2258 remoteAddress = map['remoteAddress']; |
| 2215 remotePort = map['remotePort']; | 2259 remotePort = map['remotePort']; |
| 2216 | 2260 |
| 2217 fd = map['fd']; | 2261 fd = map['fd']; |
| 2218 socketOwner = map['owner']; | 2262 socketOwner = map['owner']; |
| 2219 } | 2263 } |
| 2220 } | 2264 } |
| 2221 | 2265 |
| 2266 class MetricSample { |
| 2267 final double value; |
| 2268 final DateTime time; |
| 2269 MetricSample(this.value) : time = new DateTime.now(); |
| 2270 } |
| 2271 |
| 2272 class ServiceMetric extends ServiceObject { |
| 2273 ServiceMetric._empty(ServiceObjectOwner owner) : super._empty(owner) { |
| 2274 } |
| 2275 |
| 2276 bool get canCache => true; |
| 2277 bool get immutable => false; |
| 2278 |
| 2279 @observable bool recording = false; |
| 2280 MetricPoller poller; |
| 2281 |
| 2282 final ObservableList<MetricSample> samples = |
| 2283 new ObservableList<MetricSample>(); |
| 2284 int _sampleBufferSize = 100; |
| 2285 int get sampleBufferSize => _sampleBufferSize; |
| 2286 set sampleBufferSize(int size) { |
| 2287 _sampleBufferSize = size; |
| 2288 _removeOld(); |
| 2289 } |
| 2290 |
| 2291 void addSample(MetricSample sample) { |
| 2292 samples.add(sample); |
| 2293 _removeOld(); |
| 2294 } |
| 2295 |
| 2296 void _removeOld() { |
| 2297 // TODO(johnmccutchan): If this becomes hot, consider using a circular |
| 2298 // buffer. |
| 2299 if (samples.length > _sampleBufferSize) { |
| 2300 int count = samples.length - _sampleBufferSize; |
| 2301 samples.removeRange(0, count); |
| 2302 } |
| 2303 } |
| 2304 |
| 2305 @observable String description; |
| 2306 @observable double value = 0.0; |
| 2307 // Only a guage has a non-null min and max. |
| 2308 @observable double min; |
| 2309 @observable double max; |
| 2310 |
| 2311 bool get isGauge => (min != null) && (max != null); |
| 2312 |
| 2313 void _update(ObservableMap map, bool mapIsRef) { |
| 2314 name = map['name']; |
| 2315 description = map['description']; |
| 2316 vmName = map['name']; |
| 2317 value = map['value']; |
| 2318 min = map['min']; |
| 2319 max = map['max']; |
| 2320 } |
| 2321 |
| 2322 String toString() => "ServiceMetric($_id)"; |
| 2323 } |
| 2324 |
| 2325 class MetricPoller { |
| 2326 // Metrics to be polled. |
| 2327 final List<ServiceMetric> metrics = new List<ServiceMetric>(); |
| 2328 final Duration pollPeriod; |
| 2329 Timer _pollTimer; |
| 2330 |
| 2331 MetricPoller(int milliseconds) : |
| 2332 pollPeriod = new Duration(milliseconds: milliseconds) { |
| 2333 start(); |
| 2334 } |
| 2335 |
| 2336 void start() { |
| 2337 _pollTimer = new Timer.periodic(pollPeriod, _onPoll); |
| 2338 } |
| 2339 |
| 2340 void cancel() { |
| 2341 if (_pollTimer != null) { |
| 2342 _pollTimer.cancel(); |
| 2343 } |
| 2344 _pollTimer = null; |
| 2345 } |
| 2346 |
| 2347 void _onPoll(_) { |
| 2348 // Reload metrics and add a sample to each. |
| 2349 for (var metric in metrics) { |
| 2350 metric.reload().then((m) { |
| 2351 m.addSample(new MetricSample(m.value)); |
| 2352 }); |
| 2353 } |
| 2354 } |
| 2355 } |
| 2356 |
| 2222 // Convert any ServiceMaps representing a null instance into an actual null. | 2357 // Convert any ServiceMaps representing a null instance into an actual null. |
| 2223 _convertNull(obj) { | 2358 _convertNull(obj) { |
| 2224 if (obj is ServiceMap && | 2359 if (obj is ServiceMap && |
| 2225 obj.serviceType == 'Null') { | 2360 obj.serviceType == 'Null') { |
| 2226 return null; | 2361 return null; |
| 2227 } | 2362 } |
| 2228 return obj; | 2363 return obj; |
| 2229 } | 2364 } |
| 2230 | 2365 |
| 2231 // Returns true if [map] is a service map. i.e. it has the following keys: | 2366 // Returns true if [map] is a service map. i.e. it has the following keys: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2268 var v = list[i]; | 2403 var v = list[i]; |
| 2269 if ((v is ObservableMap) && _isServiceMap(v)) { | 2404 if ((v is ObservableMap) && _isServiceMap(v)) { |
| 2270 list[i] = owner.getFromMap(v); | 2405 list[i] = owner.getFromMap(v); |
| 2271 } else if (v is ObservableList) { | 2406 } else if (v is ObservableList) { |
| 2272 _upgradeObservableList(v, owner); | 2407 _upgradeObservableList(v, owner); |
| 2273 } else if (v is ObservableMap) { | 2408 } else if (v is ObservableMap) { |
| 2274 _upgradeObservableMap(v, owner); | 2409 _upgradeObservableMap(v, owner); |
| 2275 } | 2410 } |
| 2276 } | 2411 } |
| 2277 } | 2412 } |
| OLD | NEW |