1
+ import 'dart:math' ;
2
+
1
3
import 'package:meta/meta.dart' ;
2
4
3
5
import '../../sentry.dart' ;
@@ -26,8 +28,31 @@ abstract class Metric {
26
28
required this .tags,
27
29
});
28
30
31
+ factory Metric .fromType ({
32
+ required final MetricType type,
33
+ required final String key,
34
+ required final num value,
35
+ required final SentryMeasurementUnit unit,
36
+ required final Map <String , String > tags,
37
+ }) {
38
+ switch (type) {
39
+ case MetricType .counter:
40
+ return CounterMetric ._(value: value, key: key, unit: unit, tags: tags);
41
+ case MetricType .gauge:
42
+ return GaugeMetric ._(value: value, key: key, unit: unit, tags: tags);
43
+ case MetricType .set :
44
+ return SetMetric ._(value: value, key: key, unit: unit, tags: tags);
45
+ case MetricType .distribution:
46
+ return DistributionMetric ._(
47
+ value: value, key: key, unit: unit, tags: tags);
48
+ }
49
+ }
50
+
29
51
/// Add a value to the metric.
30
- add (double value);
52
+ add (num value);
53
+
54
+ /// Return the weight of the current metric.
55
+ int getWeight ();
31
56
32
57
/// Serialize the value into a list of Objects to be converted into a String.
33
58
Iterable <Object > _serializeValue ();
@@ -87,6 +112,10 @@ abstract class Metric {
87
112
return ('${type .statsdType }_${key }_${unit .name }_$serializedTags ' );
88
113
}
89
114
115
+ /// Return a key created by [key] , [type] and [unit] .
116
+ /// This key should be used to aggregate the metric locally in a span.
117
+ String getSpanAggregationKey () => '${type .statsdType }:$key @${unit .name }' ;
118
+
90
119
/// Remove forbidden characters from the metric key and tag key.
91
120
String _normalizeKey (String input) =>
92
121
input.replaceAll (forbiddenKeyCharsRegex, '_' );
@@ -100,31 +129,135 @@ abstract class Metric {
100
129
input.replaceAll (forbiddenUnitCharsRegex, '_' );
101
130
}
102
131
103
- @internal
104
-
105
132
/// Metric [MetricType.counter] that tracks a value that can only be incremented.
133
+ @internal
106
134
class CounterMetric extends Metric {
107
- double value;
135
+ num value;
108
136
109
- CounterMetric ({
137
+ CounterMetric ._ ({
110
138
required this .value,
111
139
required super .key,
112
140
required super .unit,
113
141
required super .tags,
114
142
}) : super (type: MetricType .counter);
115
143
116
144
@override
117
- add (double value) => this .value += value;
145
+ add (num value) => this .value += value;
118
146
119
147
@override
120
148
Iterable <Object > _serializeValue () => [value];
149
+
150
+ @override
151
+ int getWeight () => 1 ;
121
152
}
122
153
154
+ /// Metric [MetricType.gauge] that tracks a value that can go up and down.
123
155
@internal
156
+ class GaugeMetric extends Metric {
157
+ num _last;
158
+ num _minimum;
159
+ num _maximum;
160
+ num _sum;
161
+ int _count;
162
+
163
+ GaugeMetric ._({
164
+ required num value,
165
+ required super .key,
166
+ required super .unit,
167
+ required super .tags,
168
+ }) : _last = value,
169
+ _minimum = value,
170
+ _maximum = value,
171
+ _sum = value,
172
+ _count = 1 ,
173
+ super (type: MetricType .gauge);
174
+
175
+ @override
176
+ add (num value) {
177
+ _last = value;
178
+ _minimum = min (_minimum, value);
179
+ _maximum = max (_maximum, value);
180
+ _sum += value;
181
+ _count++ ;
182
+ }
183
+
184
+ @override
185
+ Iterable <Object > _serializeValue () =>
186
+ [_last, _minimum, _maximum, _sum, _count];
187
+
188
+ @override
189
+ int getWeight () => 5 ;
190
+
191
+ @visibleForTesting
192
+ num get last => _last;
193
+ num get minimum => _minimum;
194
+ num get maximum => _maximum;
195
+ num get sum => _sum;
196
+ int get count => _count;
197
+ }
198
+
199
+ /// Metric [MetricType.set] that tracks a set of values on which you can perform
200
+ /// aggregations such as count_unique.
201
+ @internal
202
+ class SetMetric extends Metric {
203
+ final Set <int > _values = {};
204
+
205
+ SetMetric ._(
206
+ {required num value,
207
+ required super .key,
208
+ required super .unit,
209
+ required super .tags})
210
+ : super (type: MetricType .set ) {
211
+ add (value);
212
+ }
213
+
214
+ @override
215
+ add (num value) => _values.add (value.toInt ());
216
+
217
+ @override
218
+ Iterable <Object > _serializeValue () => _values;
219
+
220
+ @override
221
+ int getWeight () => _values.length;
222
+
223
+ @visibleForTesting
224
+ Set <num > get values => _values;
225
+ }
226
+
227
+ /// Metric [MetricType.distribution] that tracks a list of values.
228
+ @internal
229
+ class DistributionMetric extends Metric {
230
+ final List <num > _values = [];
231
+
232
+ DistributionMetric ._(
233
+ {required num value,
234
+ required super .key,
235
+ required super .unit,
236
+ required super .tags})
237
+ : super (type: MetricType .distribution) {
238
+ add (value);
239
+ }
240
+
241
+ @override
242
+ add (num value) => _values.add (value);
243
+
244
+ @override
245
+ Iterable <Object > _serializeValue () => _values;
246
+
247
+ @override
248
+ int getWeight () => _values.length;
249
+
250
+ @visibleForTesting
251
+ List <num > get values => _values;
252
+ }
124
253
125
254
/// The metric type and its associated statsd encoded value.
255
+ @internal
126
256
enum MetricType {
127
- counter ('c' );
257
+ counter ('c' ),
258
+ gauge ('g' ),
259
+ distribution ('d' ),
260
+ set ('s' );
128
261
129
262
final String statsdType;
130
263
0 commit comments