-
Notifications
You must be signed in to change notification settings - Fork 1
/
common.dart
116 lines (99 loc) · 4.34 KB
/
common.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import 'dart:convert';
import 'dart:collection';
import 'package:equatable/equatable.dart';
import 'package:crypto/crypto.dart';
/// Common format of a metric data point
class MetricPoint extends Equatable {
MetricPoint(
this.value,
Map<String, dynamic> tags,
this.originId, [
this.sourceTime,
]) : assert(value != null),
assert(tags != null),
assert(originId != null),
this._tags = SplayTreeMap.from(tags);
/// Can store integer values
final double value;
/// Test name, unit, timestamp, configs, git revision, ..., in sorted order
UnmodifiableMapView<String, String> get tags =>
UnmodifiableMapView<String, String>(_tags);
/// Unique identifier for updating existing data point.
///
/// We shouldn't have to worry about hash collisions until we have about
/// 2^128 points.
///
/// This id should stay constant even if the [tags.keys] are reordered.
/// (Because we are using an ordered SplayTreeMap to generate the id.)
String get id => sha256.convert(utf8.encode('$originId: $_tags')).toString();
@override
String toString() {
return 'MetricPoint(value=$value, tags=$_tags, originId=$originId, sourceTime=$sourceTime)';
}
/// Where this point originally comes from. Used for dedup.
///
/// This should stay constant as the point is transferred among multiple
/// sources and destinations.
final String originId;
/// The last modified time of this point in a [MetricSource]. Can be null if
/// this point isn't loaded from a source (e.g., it's constructed in memory).
final DateTime sourceTime;
final SplayTreeMap<String, String> _tags;
@override
List<Object> get props => [value, tags, originId, sourceTime];
}
/// Source must support efficient index on [MetricPoint.sourceTime]
/// so we can query with a time range.
abstract class MetricSource<SourcePoint extends MetricPoint> {
/// Return points updated since timestamp [timestamp] exclusively. (i.e., data
/// with sourceTime = [timestamp] won't be returned.)
///
/// The returned points should be sorted by their srcTimeNanos ascendingly.
///
/// [FlutterCenter] requires that the source's clock is strictly increasing
/// between batches: if [getUpdateAfter] already returned a list of data
/// points with the largest [sourceTime] = x, then the newer points updated
/// after this [getUpdateAfter] call must have strictly greater [sourceTime] >
/// x. Otherwise, [FlutterCenter] may miss those updates.
///
/// See [FlutterSource] for an example of the strict monotonicity on
/// [sourceTime].
Future<List<SourcePoint>> getUpdatesAfter(DateTime timestamp);
/// Unique id of the source. If this source is also a destination, then its
/// corresponding destination (e.g., [FlutterSource] and [FlutterDestination])
/// should have the same id.
String get id;
}
abstract class MetricDestination {
/// Insert new data points or modify old ones with matching id.
///
/// Deletion is done by setting [MetricPoint.value] to [double.nan].
///
/// The destination could also ignore some points and not store them. For the
/// non-ignored points, it should faithfully store the value, tags, raw, and
/// originId fields. Thus, if this destination is also a source (e.g.,
/// [FlutterCenter]), then when [getUpdatesAfter] is called on the source, we
/// should get the points with exactly the same fields that we just updated.
/// This is especially important for the originId field which is used for
/// dedup. Otherwise, there might be an update loop to generate an infinite
/// amount of duplicate points.
Future<void> update(List<MetricPoint> points);
/// Unique id of the destination. If this destination is also a source, then
/// its corresponding source (e.g., [FlutterSource] and [FlutterDestination])
/// should have the same id.
String get id;
}
/// Some common tag keys
const String kGithubRepoKey = 'gitRepo';
const String kGitRevisionKey = 'gitRevision';
const String kOriginIdKey = 'originId';
const String kUnitKey = 'unit';
const String kNameKey = 'name';
const String kSubResultKey = 'subResult';
/// Known source/destination ids
const String kCocoonId = 'cocoon';
const String kSkiaPerfId = 'skiaperf';
const String kFlutterCenterId = 'flutter-center';
/// Known github repo
const String kFlutterFrameworkRepo = 'flutter/flutter';
const String kFlutterEngineRepo = 'flutter/engine';