OLD | NEW |
(Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 part of dart.developer; |
| 6 |
| 7 /// A UserTag can be used to group samples in the Observatory profiler. |
| 8 abstract class UserTag { |
| 9 /// The maximum number of UserTag instances that can be created by a program. |
| 10 static const MAX_USER_TAGS = 64; |
| 11 |
| 12 factory UserTag(String label) => new _FakeUserTag(label); |
| 13 |
| 14 /// Label of [this]. |
| 15 String get label; |
| 16 |
| 17 /// Make [this] the current tag for the isolate. Returns the current tag |
| 18 /// before setting. |
| 19 UserTag makeCurrent(); |
| 20 |
| 21 /// The default [UserTag] with label 'Default'. |
| 22 static UserTag get defaultTag => _FakeUserTag._defaultTag; |
| 23 } |
| 24 |
| 25 // This is a fake implementation of UserTag so that code can compile and run |
| 26 // in dart2js. |
| 27 class _FakeUserTag implements UserTag { |
| 28 static Map _instances = {}; |
| 29 |
| 30 _FakeUserTag.real(this.label); |
| 31 |
| 32 factory _FakeUserTag(String label) { |
| 33 // Canonicalize by name. |
| 34 var existingTag = _instances[label]; |
| 35 if (existingTag != null) { |
| 36 return existingTag; |
| 37 } |
| 38 // Throw an exception if we've reached the maximum number of user tags. |
| 39 if (_instances.length == UserTag.MAX_USER_TAGS) { |
| 40 throw new UnsupportedError( |
| 41 'UserTag instance limit (${UserTag.MAX_USER_TAGS}) reached.'); |
| 42 } |
| 43 // Create a new instance and add it to the instance map. |
| 44 var instance = new _FakeUserTag.real(label); |
| 45 _instances[label] = instance; |
| 46 return instance; |
| 47 } |
| 48 |
| 49 final String label; |
| 50 |
| 51 UserTag makeCurrent() { |
| 52 var old = _currentTag; |
| 53 _currentTag = this; |
| 54 return old; |
| 55 } |
| 56 |
| 57 static final UserTag _defaultTag = new _FakeUserTag('Default'); |
| 58 } |
| 59 |
| 60 var _currentTag = _FakeUserTag._defaultTag; |
| 61 |
| 62 /// Returns the current [UserTag] for the isolate. |
| 63 UserTag getCurrentTag() { |
| 64 return _currentTag; |
| 65 } |
| 66 |
| 67 /// Abstract [Metric] class. Metric names must be unique, are hierarchical, |
| 68 /// and use periods as separators. For example, 'a.b.c'. Uniqueness is only |
| 69 /// enforced when a Metric is registered. The name of a metric cannot contain |
| 70 /// the slash ('/') character. |
| 71 abstract class Metric { |
| 72 /// [name] of this metric. |
| 73 final String name; |
| 74 /// [description] of this metric. |
| 75 final String description; |
| 76 |
| 77 Metric(this.name, this.description) { |
| 78 if ((name == 'vm') || name.contains('/')) { |
| 79 throw new ArgumentError('Invalid Metric name.'); |
| 80 } |
| 81 |
| 82 } |
| 83 |
| 84 Map _toJSON(); |
| 85 } |
| 86 |
| 87 /// A measured value with a min and max. Initial value is min. Value will |
| 88 /// be clamped to the interval [min, max]. |
| 89 class Gauge extends Metric { |
| 90 final double min; |
| 91 final double max; |
| 92 |
| 93 double _value; |
| 94 double get value => _value; |
| 95 set value(double v) { |
| 96 if (v < min) { |
| 97 v = min; |
| 98 } else if (v > max) { |
| 99 v = max; |
| 100 } |
| 101 _value = v; |
| 102 } |
| 103 |
| 104 Gauge(String name, String description, this.min, this.max) |
| 105 : super(name, description) { |
| 106 if (min is! double) { |
| 107 throw new ArgumentError('min must be a double'); |
| 108 } |
| 109 if (max is! double) { |
| 110 throw new ArgumentError('max must be a double'); |
| 111 } |
| 112 if (!(min < max)) { |
| 113 throw new ArgumentError('min must be less than max'); |
| 114 } |
| 115 _value = min; |
| 116 } |
| 117 |
| 118 Map _toJSON() { |
| 119 var map = { |
| 120 'type': 'Gauge', |
| 121 'id': 'metrics/$name', |
| 122 'name': name, |
| 123 'description': description, |
| 124 'value': value, |
| 125 'min': min, |
| 126 'max': max, |
| 127 }; |
| 128 return map; |
| 129 } |
| 130 } |
| 131 |
| 132 |
| 133 /// A changing value. Initial value is 0.0. |
| 134 class Counter extends Metric { |
| 135 Counter(String name, String description) |
| 136 : super(name, description); |
| 137 |
| 138 double _value = 0.0; |
| 139 double get value => _value; |
| 140 set value(double v) { |
| 141 _value = v; |
| 142 } |
| 143 |
| 144 Map _toJSON() { |
| 145 var map = { |
| 146 'type': 'Counter', |
| 147 'id': 'metrics/$name', |
| 148 'name': name, |
| 149 'description': description, |
| 150 'value': value, |
| 151 }; |
| 152 return map; |
| 153 } |
| 154 } |
| 155 |
| 156 class Metrics { |
| 157 static final Map<String, Metric> _metrics = new Map<String, Metric>(); |
| 158 |
| 159 /// Register [Metric]s to make them visible to Observatory. |
| 160 static void register(Metric metric) { |
| 161 if (metric is! Metric) { |
| 162 throw new ArgumentError('metric must be a Metric'); |
| 163 } |
| 164 if (_metrics[metric.name] != null) { |
| 165 throw new ArgumentError('Registered metrics have unique names'); |
| 166 } |
| 167 _metrics[metric.name] = metric; |
| 168 } |
| 169 |
| 170 /// Deregister [Metric]s to make them not visible to Observatory. |
| 171 static void deregister(Metric metric) { |
| 172 if (metric is! Metric) { |
| 173 throw new ArgumentError('metric must be a Metric'); |
| 174 } |
| 175 _metrics.remove(metric.name); |
| 176 } |
| 177 |
| 178 static String _printMetric(String id) { |
| 179 var metric = _metrics[id]; |
| 180 if (metric == null) { |
| 181 return null; |
| 182 } |
| 183 return JSON.encode(metric._toJSON()); |
| 184 } |
| 185 |
| 186 static String _printMetrics() { |
| 187 var metrics = []; |
| 188 for (var metric in _metrics.values) { |
| 189 metrics.add(metric._toJSON()); |
| 190 } |
| 191 var map = { |
| 192 'type': 'MetricList', |
| 193 'metrics': metrics, |
| 194 }; |
| 195 return JSON.encode(map); |
| 196 } |
| 197 } |
OLD | NEW |