Chromium Code Reviews| Index: runtime/bin/vmservice/observatory/lib/src/service/object.dart |
| diff --git a/runtime/bin/vmservice/observatory/lib/src/service/object.dart b/runtime/bin/vmservice/observatory/lib/src/service/object.dart |
| index 32055de734f4b986228c6f2300ff393a7c887be1..ea40c3c92e515d5453eea4d1e825e34475de643b 100644 |
| --- a/runtime/bin/vmservice/observatory/lib/src/service/object.dart |
| +++ b/runtime/bin/vmservice/observatory/lib/src/service/object.dart |
| @@ -76,12 +76,18 @@ abstract class ServiceObject extends Observable { |
| case 'Code': |
| obj = new Code._empty(owner); |
| break; |
| + case 'Counter': |
| + obj = new Metric._empty(owner); |
| + break; |
| case 'Error': |
| obj = new DartError._empty(owner); |
| break; |
| case 'Function': |
| obj = new ServiceFunction._empty(owner); |
| break; |
| + case 'Gauge': |
| + obj = new Metric._empty(owner); |
| + break; |
| case 'Isolate': |
| obj = new Isolate._empty(owner.vm); |
| break; |
| @@ -697,6 +703,7 @@ class Isolate extends ServiceObjectOwner with Coverage { |
| String id = map['id']; |
| var obj = _cache[id]; |
| if (obj != null) { |
| + // Consider calling update when map is not a reference. |
| return obj; |
| } |
| // Build the object from the map directly. |
| @@ -1009,7 +1016,6 @@ class Isolate extends ServiceObjectOwner with Coverage { |
| } |
| Future stepInto() { |
| - print('isolate.stepInto'); |
| return get("debug/resume?step=into").then((result) { |
| if (result is DartError) { |
| // TODO(turnidge): Handle this more gracefully. |
| @@ -1038,6 +1044,25 @@ class Isolate extends ServiceObjectOwner with Coverage { |
| return isolate.reload(); |
| }); |
| } |
| + |
| + final ObservableMap<String, Metric> metrics = |
| + new ObservableMap<String, Metric>(); |
| + |
| + Future<ObservableMap<String, Metric>> refreshMetrics() { |
| + return get('metrics').then((result) { |
| + if (result is DartError) { |
| + // TODO(turnidge): Handle this more gracefully. |
| + Logger.root.severe(result.message); |
| + } |
| + // Clear metrics map. |
| + metrics.clear(); |
| + // Repopulate metrics map. |
| + var members = result['members']; |
| + for (var metric in members) { |
| + metrics[metric.name] = metric; |
| + } |
| + }); |
| + } |
| } |
| /// A [ServiceObject] which implements [ObservableMap]. |
| @@ -1515,7 +1540,7 @@ class ScriptLine extends Observable { |
| ScriptLine(this.script, this.line, this.text) { |
| possibleBpt = !_isTrivialLine(text); |
| - |
| + |
| // TODO(turnidge): This is not so efficient. Consider improving. |
| for (var bpt in this.script.isolate.breakpoints['breakpoints']) { |
| var bptScript = bpt['location']['script']; |
| @@ -2193,6 +2218,101 @@ class Socket extends ServiceObject { |
| } |
| } |
| +class MetricSample { |
| + final double value; |
| + final DateTime time; |
| + MetricSample(this.value) : time = new DateTime.now(); |
| +} |
| + |
| +class Metric extends ServiceObject { |
| + Metric._empty(ServiceObjectOwner owner) : super._empty(owner) { |
| + } |
| + |
| + bool get canCache => true; |
| + bool get immutable => false; |
| + |
| + @observable bool recording = false; |
| + MetricPoller poller; |
| + |
| + // 8 seconds, 4 seconds, 2 seconds, 1 second, and one hundred milliseconds. |
| + static final List<int> pollPeriods = [8000, 4000, 2000, 1000, 100]; |
|
koda
2014/08/11 16:34:53
Couldn't you traverse the DOM to get this list ins
Cutch
2014/08/27 22:25:40
The service library doesn't import dart:html. Also
|
| + |
| + final ObservableList<MetricSample> samples = |
| + new ObservableList<MetricSample>(); |
| + int _sampleBufferSize = 100; |
| + int get sampleBufferSize => _sampleBufferSize; |
| + set sampleBufferSize(int size) { |
| + _sampleBufferSize = size; |
| + _removeOld(); |
| + } |
| + |
| + void addSample(MetricSample sample) { |
| + samples.add(sample); |
| + _removeOld(); |
| + } |
| + |
| + void _removeOld() { |
| + if (samples.length > _sampleBufferSize) { |
| + int count = samples.length - _sampleBufferSize; |
| + samples.removeRange(0, count); |
|
koda
2014/08/11 16:34:54
I assume ObservableList is backed by an array? If
Cutch
2014/08/27 22:25:40
Done.
|
| + } |
| + } |
| + |
| + @observable String description; |
| + @observable double value = 0.0; |
| + @observable double min; |
| + @observable double max; |
| + |
| + bool get isGauge => (min != null) && (max != null); |
|
koda
2014/08/11 16:34:53
The fact that 'null' is valid and has this particu
Cutch
2014/08/27 22:25:40
Noted.
|
| + |
| + void _update(ObservableMap map, bool mapIsRef) { |
| + name = map['name']; |
| + description = map['description']; |
| + vmName = map['name']; |
| + value = map['value']; |
| + min = map['min']; |
| + max = map['max']; |
| + } |
| +} |
| + |
| +class MetricPoller { |
| + // Metrics to be polled. |
| + final List<Metric> metrics = new List<Metric>(); |
| + final int period; |
|
koda
2014/08/11 16:34:54
Redundant? In any case, avoid untyped times (or at
Cutch
2014/08/27 22:25:40
Redundant. Removed.
|
| + final Duration _pollPeriod; |
| + Timer _pollTimer; |
| + |
| + MetricPoller(int milliseconds) : |
| + period = milliseconds, |
| + _pollPeriod = new Duration(milliseconds: milliseconds) { |
| + start(); |
| + } |
| + |
| + void start() { |
| + _pollTimer = new Timer.periodic(_pollPeriod, _onPoll); |
| + } |
| + |
| + void cancel() { |
| + if (_pollTimer != null) { |
| + _pollTimer.cancel(); |
| + } |
| + _pollTimer = null; |
| + } |
| + |
| + void _onPoll(_) { |
| + if (metrics.length == 0) { |
|
koda
2014/08/11 16:34:53
Redundant.
Cutch
2014/08/27 22:25:40
Done.
|
| + return; |
| + } |
| + // Reload metrics and add a sample to each. |
| + for (var i = 0; i < metrics.length; i++) { |
|
koda
2014/08/11 16:34:53
Use for-in when possible.
Cutch
2014/08/27 22:25:40
Done.
|
| + var metric = metrics[i]; |
| + metric.reload().then((m) { |
| + m.addSample(new MetricSample(m.value)); |
| + }); |
| + } |
| + } |
| +} |
| + |
| // Convert any ServiceMaps representing a null instance into an actual null. |
| _convertNull(obj) { |
| if (obj is ServiceMap && |