Chromium Code Reviews| Index: runtime/lib/profiler.dart |
| diff --git a/runtime/lib/profiler.dart b/runtime/lib/profiler.dart |
| index 2c60141a492552be8f36be050e44dc0d772f7422..5bcf3a8aec38bc39bd1c9e3172ec1a5b1f476151 100644 |
| --- a/runtime/lib/profiler.dart |
| +++ b/runtime/lib/profiler.dart |
| @@ -2,7 +2,8 @@ |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| -import "dart:_internal"; |
| +import 'dart:_internal'; |
| +import 'dart:convert'; |
| patch class UserTag { |
| /* patch */ factory UserTag(String label) { |
| @@ -22,3 +23,146 @@ patch UserTag getCurrentTag() => _getCurrentTag(); |
| UserTag _getCurrentTag() native "Profiler_getCurrentTag"; |
| UserTag _getDefaultTag() native "UserTag_defaultTag"; |
| + |
| +/// Abstract [Metric] class. Metric names must be unique, are hierarchical, |
| +/// and use periods as separators. For example, 'a.b.c'. Uniqueness is only |
| +/// enforced when a Metric is registered. The name of a metric cannot contain |
| +/// the slash ('/') character. |
| +abstract class Metric { |
| + /// [name] of this metric. |
| + final String name; |
| + /// [description] of this metric. |
| + final String description; |
| + |
| + Metric(this.name, this.description) { |
| + if (name.contains('/')) { |
| + throw new ArgumentError('Invalid Metric name.'); |
| + } |
| + } |
| + |
| + Map _toJSON(); |
| +} |
| + |
| +/// A measured value with a min and max. Initial value is min. Value will |
| +/// be clamped to the interval [min, max]. |
| +class Gauge extends Metric { |
| + final double min; |
| + final double max; |
|
turnidge
2014/07/30 19:15:00
double seems reasonable, but will we ever want mor
Cutch
2014/07/30 21:55:03
I could imagine people wanting integers but they g
|
| + |
| + double _value; |
| + double get value => _value; |
| + set value(double v) { |
| + if (v < min) { |
| + v = min; |
| + } else if (v > max) { |
| + v = max; |
| + } |
| + _value = v; |
| + } |
| + |
| + Gauge(String name, String description, this.min, this.max) |
| + : super(name, description) { |
| + if (min is! double) { |
| + throw new ArgumentError('min must be a double'); |
| + } |
| + if (max is! double) { |
| + throw new ArgumentError('max must be a double'); |
| + } |
| + if (!(min < max)) { |
| + throw new ArgumentError('min must be less than max'); |
| + } |
| + _value = min; |
| + } |
| + |
| + Map _toJSON() { |
| + var map = { |
| + 'type': 'Gauge', |
| + 'id': 'metrics/$name', |
| + 'name': name, |
| + 'description': description, |
| + 'value': value, |
| + 'min': min, |
| + 'max': max, |
| + }; |
| + return map; |
| + } |
| +} |
| + |
| + |
| +/// A changing value. Initial value is 0.0. |
| +class Counter extends Metric { |
|
turnidge
2014/07/30 19:15:00
The name Counter implies monotonic to me, but the
Cutch
2014/07/30 21:55:03
Initially I had this monotonic but decided to rela
|
| + Counter(String name, String description) |
| + : super(name, description); |
| + |
| + double _value = 0.0; |
| + double get value => _value; |
| + set value(double v) { |
| + _value = v; |
| + } |
| + |
| + Map _toJSON() { |
| + var map = { |
| + 'type': 'Counter', |
| + 'id': 'metrics/$name', |
| + 'name': name, |
| + 'description': description, |
| + 'value': value, |
| + }; |
| + return map; |
| + } |
| +} |
| + |
| +/// Register [Metric]s to make them visible to Observatory. |
| +class Metrics { |
| + static final List<Metric> _metrics = new List<Metric>(); |
|
turnidge
2014/07/30 19:15:00
Why not make this a Map? Then you can avoid the l
Cutch
2014/07/30 21:55:03
Done.
|
| + |
| + static bool _nameExists(String name) { |
| + for (var i = 0; i < _metrics.length; i++) { |
| + if (_metrics[i].name == name) { |
| + return true; |
| + } |
| + } |
| + return false; |
| + } |
| + |
| + static void register(Metric metric) { |
| + if (metric is! Metric) { |
| + throw new ArgumentError('metric must be a Metric'); |
| + } |
| + if (_nameExists(metric.name)) { |
| + throw new ArgumentError('Registered metrics have unique names'); |
| + } |
| + _metrics.add(metric); |
| + } |
| + |
| + static void deregister(Metric metric) { |
| + if (metric is! Metric) { |
| + throw new ArgumentError('metric must be a Metric'); |
| + } |
| + _metrics.remove(metric); |
| + } |
| + |
| + static String _printMetric(String id) { |
| + for (var i = 0; i < _metrics.length; i++) { |
| + var m = _metrics[i]; |
| + if (m.name == id) { |
| + return JSON.encode(m._toJSON()); |
| + } |
| + } |
| + return null; |
| + } |
| + |
| + static String _printMetrics() { |
| + var members = []; |
| + for (var i = 0; i < _metrics.length; i++) { |
| + var m = _metrics[i]; |
| + members.add(m._toJSON()); |
| + } |
| + var map = { |
| + 'type': 'MetricList', |
| + 'id': 'metrics', |
| + 'members': members, |
| + }; |
| + return JSON.encode(map); |
| + } |
| +} |