Scale gcs metrics center write with task name (#444)
diff --git a/packages/metrics_center/CHANGELOG.md b/packages/metrics_center/CHANGELOG.md
index 731d2ce..bf0d250 100644
--- a/packages/metrics_center/CHANGELOG.md
+++ b/packages/metrics_center/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 1.0.1
+
+- `update` now requires taskName to scale metric writes
+
# 1.0.0
- Null safety support
diff --git a/packages/metrics_center/lib/src/common.dart b/packages/metrics_center/lib/src/common.dart
index ca6cabd..fc8240d 100644
--- a/packages/metrics_center/lib/src/common.dart
+++ b/packages/metrics_center/lib/src/common.dart
@@ -49,7 +49,8 @@
/// Interface to write [MetricPoint].
abstract class MetricDestination {
/// Insert new data points or modify old ones with matching id.
- Future<void> update(List<MetricPoint> points, DateTime commitTime);
+ Future<void> update(
+ List<MetricPoint> points, DateTime commitTime, String taskName);
}
/// Create `AuthClient` in case we only have an access token without the full
diff --git a/packages/metrics_center/lib/src/flutter.dart b/packages/metrics_center/lib/src/flutter.dart
index cb96afe..acdac08 100644
--- a/packages/metrics_center/lib/src/flutter.dart
+++ b/packages/metrics_center/lib/src/flutter.dart
@@ -52,8 +52,9 @@
}
@override
- Future<void> update(List<MetricPoint> points, DateTime commitTime) async {
- await _skiaPerfDestination.update(points, commitTime);
+ Future<void> update(
+ List<MetricPoint> points, DateTime commitTime, String taskName) async {
+ await _skiaPerfDestination.update(points, commitTime, taskName);
}
final SkiaPerfDestination _skiaPerfDestination;
diff --git a/packages/metrics_center/lib/src/skiaperf.dart b/packages/metrics_center/lib/src/skiaperf.dart
index 999b734..5a9f921 100644
--- a/packages/metrics_center/lib/src/skiaperf.dart
+++ b/packages/metrics_center/lib/src/skiaperf.dart
@@ -312,12 +312,12 @@
/// (git revision).
///
/// Skia perf needs all directory names to be well formatted. The final name
- /// of the json file (currently `values.json`) can be arbitrary, and multiple
- /// json files can be put in that leaf directory. We intend to use multiple
- /// json files in the future to scale up the system if too many writes are
- /// competing for the same json file.
- static Future<String> computeObjectName(
- String githubRepo, String? revision, DateTime commitTime) async {
+ /// of the json file can be arbitrary, and multiple json files can be put
+ /// in that leaf directory. We are using multiple json files divided by test
+ /// names to scale up the system to avoid too many writes competing for
+ /// the same json file.
+ static Future<String> computeObjectName(String githubRepo, String? revision,
+ DateTime commitTime, String taskName) async {
assert(_githubRepoToGcsName[githubRepo] != null);
final String? topComponent = _githubRepoToGcsName[githubRepo];
// [commitTime] is not guranteed to be UTC. Ensure it is so all results
@@ -327,7 +327,7 @@
final String day = commitUtcTime.day.toString().padLeft(2, '0');
final String hour = commitUtcTime.hour.toString().padLeft(2, '0');
final String dateComponents = '${commitUtcTime.year}/$month/$day/$hour';
- return '$topComponent/$dateComponents/$revision/values.json';
+ return '$topComponent/$dateComponents/$revision/${taskName}_values.json';
}
static final Map<String, String> _githubRepoToGcsName = <String, String>{
@@ -392,7 +392,8 @@
}
@override
- Future<void> update(List<MetricPoint> points, DateTime commitTime) async {
+ Future<void> update(
+ List<MetricPoint> points, DateTime commitTime, String taskName) async {
// 1st, create a map based on git repo, git revision, and point id. Git repo
// and git revision are the top level components of the Skia perf GCS object
// name.
@@ -411,14 +412,13 @@
for (final String repo in pointMap.keys) {
for (final String? revision in pointMap[repo]!.keys) {
final String objectName = await SkiaPerfGcsAdaptor.computeObjectName(
- repo, revision, commitTime);
+ repo, revision, commitTime, taskName);
final Map<String, SkiaPerfPoint>? newPoints = pointMap[repo]![revision];
- // If too many bots are writing the metrics of a git revision into this
- // single json file (with name `objectName`), the contention on the lock
- // might be too high. In that case, break the json file into multiple
- // json files according to bot names or task names. Skia perf read all
- // json files in the directory so one can use arbitrary names for those
- // sharded json file names.
+ // Too many bots writing the metrics of a git revision into a single json
+ // file will cause high contention on the lock. We use multiple
+ // json files according to task names. Skia perf read all json files in
+ // the directory so one can use arbitrary names for those sharded json
+ // file names.
_lock!.protectedRun('$objectName.lock', () async {
final List<SkiaPerfPoint> oldPoints =
await _gcs.readPoints(objectName);
diff --git a/packages/metrics_center/pubspec.yaml b/packages/metrics_center/pubspec.yaml
index 3c7947c..a44a100 100644
--- a/packages/metrics_center/pubspec.yaml
+++ b/packages/metrics_center/pubspec.yaml
@@ -1,5 +1,5 @@
name: metrics_center
-version: 1.0.0
+version: 1.0.1
description:
Support multiple performance metrics sources/formats and destinations.
repository: https://github.com/flutter/packages/tree/master/packages/metrics_center
diff --git a/packages/metrics_center/test/flutter_test.dart b/packages/metrics_center/test/flutter_test.dart
index d50794d..be13bd0 100644
--- a/packages/metrics_center/test/flutter_test.dart
+++ b/packages/metrics_center/test/flutter_test.dart
@@ -45,6 +45,6 @@
await FlutterDestination.makeFromCredentialsJson(credentialsJson!,
isTesting: true);
dst.update(<FlutterEngineMetricPoint>[simplePoint],
- DateTime.fromMillisecondsSinceEpoch(123));
+ DateTime.fromMillisecondsSinceEpoch(123), 'test');
}, skip: credentialsJson == null);
}
diff --git a/packages/metrics_center/test/skiaperf_test.dart b/packages/metrics_center/test/skiaperf_test.dart
index 09eeed9..4c49bc4 100644
--- a/packages/metrics_center/test/skiaperf_test.dart
+++ b/packages/metrics_center/test/skiaperf_test.dart
@@ -317,24 +317,28 @@
kFlutterFrameworkRepo,
kFrameworkRevision1,
DateTime.utc(2019, 12, 04, 23),
+ 'test',
),
- equals('flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'),
+ equals(
+ 'flutter-flutter/2019/12/04/23/$kFrameworkRevision1/test_values.json'),
);
expect(
await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterEngineRepo,
kEngineRevision1,
DateTime.utc(2019, 12, 03, 20),
+ 'test',
),
- equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'),
+ equals('flutter-engine/2019/12/03/20/$kEngineRevision1/test_values.json'),
);
expect(
await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterEngineRepo,
kEngineRevision2,
DateTime.utc(2020, 01, 03, 15),
+ 'test',
),
- equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'),
+ equals('flutter-engine/2020/01/03/15/$kEngineRevision2/test_values.json'),
);
});
@@ -343,9 +347,11 @@
final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket);
final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName(
- kFlutterFrameworkRepo,
- kFrameworkRevision1,
- DateTime.fromMillisecondsSinceEpoch(123));
+ kFlutterFrameworkRepo,
+ kFrameworkRevision1,
+ DateTime.fromMillisecondsSinceEpoch(123),
+ 'test',
+ );
final List<SkiaPerfPoint> writePoints = <SkiaPerfPoint>[
SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1),
@@ -384,9 +390,11 @@
final MockBucket testBucket = MockBucket();
final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket);
final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName(
- kFlutterFrameworkRepo,
- kFrameworkRevision1,
- DateTime.fromMillisecondsSinceEpoch(123));
+ kFlutterFrameworkRepo,
+ kFrameworkRevision1,
+ DateTime.fromMillisecondsSinceEpoch(123),
+ 'test',
+ );
when(testBucket.info(testObjectName))
.thenThrow(Exception('No such object'));
expect((await skiaPerfGcs.readPoints(testObjectName)).length, 0);
@@ -416,9 +424,11 @@
final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket!);
final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName(
- kFlutterFrameworkRepo,
- kFrameworkRevision1,
- DateTime.fromMillisecondsSinceEpoch(123));
+ kFlutterFrameworkRepo,
+ kFrameworkRevision1,
+ DateTime.fromMillisecondsSinceEpoch(123),
+ 'test',
+ );
await skiaPerfGcs.writePoints(testObjectName, <SkiaPerfPoint>[
SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1),
@@ -447,9 +457,11 @@
final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket!);
final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName(
- kFlutterEngineRepo,
- engineRevision,
- DateTime.fromMillisecondsSinceEpoch(123));
+ kFlutterEngineRepo,
+ engineRevision,
+ DateTime.fromMillisecondsSinceEpoch(123),
+ 'test',
+ );
await skiaPerfGcs.writePoints(testObjectName, <SkiaPerfPoint>[
SkiaPerfPoint.fromPoint(enginePoint1),
@@ -505,25 +517,30 @@
kFlutterFrameworkRepo,
kFrameworkRevision1,
DateTime.utc(2019, 12, 04, 23),
+ 'test',
),
equals(
- 'flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'),
+ 'flutter-flutter/2019/12/04/23/$kFrameworkRevision1/test_values.json'),
);
expect(
await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterEngineRepo,
kEngineRevision1,
DateTime.utc(2019, 12, 03, 20),
+ 'test',
),
- equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'),
+ equals(
+ 'flutter-engine/2019/12/03/20/$kEngineRevision1/test_values.json'),
);
expect(
await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterEngineRepo,
kEngineRevision2,
DateTime.utc(2020, 01, 03, 15),
+ 'test',
),
- equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'),
+ equals(
+ 'flutter-engine/2020/01/03/15/$kEngineRevision2/test_values.json'),
);
},
skip: testBucket == null,
@@ -533,13 +550,23 @@
final SkiaPerfGcsAdaptor mockGcs = MockSkiaPerfGcsAdaptor();
final GcsLock mockLock = MockGcsLock();
final SkiaPerfDestination dst = SkiaPerfDestination(mockGcs, mockLock);
- await dst.update(<MetricPoint>[cocoonPointRev1Metric1],
- DateTime.fromMillisecondsSinceEpoch(123));
- await dst.update(<MetricPoint>[cocoonPointRev1Metric2],
- DateTime.fromMillisecondsSinceEpoch(123));
- List<SkiaPerfPoint> points = await mockGcs.readPoints(
- await SkiaPerfGcsAdaptor.computeObjectName(kFlutterFrameworkRepo,
- kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123)));
+ await dst.update(
+ <MetricPoint>[cocoonPointRev1Metric1],
+ DateTime.fromMillisecondsSinceEpoch(123),
+ 'test',
+ );
+ await dst.update(
+ <MetricPoint>[cocoonPointRev1Metric2],
+ DateTime.fromMillisecondsSinceEpoch(123),
+ 'test',
+ );
+ List<SkiaPerfPoint> points =
+ await mockGcs.readPoints(await SkiaPerfGcsAdaptor.computeObjectName(
+ kFlutterFrameworkRepo,
+ kFrameworkRevision1,
+ DateTime.fromMillisecondsSinceEpoch(123),
+ 'test',
+ ));
expect(points.length, equals(2));
expectSetMatch(
points.map((SkiaPerfPoint p) => p.testName), <String>[kTaskName]);
@@ -551,19 +578,30 @@
final MetricPoint updated =
MetricPoint(kValue3, cocoonPointRev1Metric1.tags);
- await dst.update(<MetricPoint>[updated, cocoonPointRev2Metric1],
- DateTime.fromMillisecondsSinceEpoch(123));
+ await dst.update(
+ <MetricPoint>[updated, cocoonPointRev2Metric1],
+ DateTime.fromMillisecondsSinceEpoch(123),
+ 'test',
+ );
- points = await mockGcs.readPoints(
- await SkiaPerfGcsAdaptor.computeObjectName(kFlutterFrameworkRepo,
- kFrameworkRevision2, DateTime.fromMillisecondsSinceEpoch(123)));
+ points =
+ await mockGcs.readPoints(await SkiaPerfGcsAdaptor.computeObjectName(
+ kFlutterFrameworkRepo,
+ kFrameworkRevision2,
+ DateTime.fromMillisecondsSinceEpoch(123),
+ 'test',
+ ));
expect(points.length, equals(1));
expect(points[0].gitHash, equals(kFrameworkRevision2));
expect(points[0].value, equals(kValue3));
- points = await mockGcs.readPoints(
- await SkiaPerfGcsAdaptor.computeObjectName(kFlutterFrameworkRepo,
- kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123)));
+ points =
+ await mockGcs.readPoints(await SkiaPerfGcsAdaptor.computeObjectName(
+ kFlutterFrameworkRepo,
+ kFrameworkRevision1,
+ DateTime.fromMillisecondsSinceEpoch(123),
+ 'test',
+ ));
expectSetMatch(
points.map((SkiaPerfPoint p) => p.value), <double>[kValue2, kValue3]);
});
@@ -571,8 +609,11 @@
Future<void> skiaPerfDestinationIntegrationTest() async {
final SkiaPerfDestination destination =
SkiaPerfDestination(SkiaPerfGcsAdaptor(testBucket!), testLock);
- await destination.update(<MetricPoint>[cocoonPointRev1Metric1],
- DateTime.fromMillisecondsSinceEpoch(123));
+ await destination.update(
+ <MetricPoint>[cocoonPointRev1Metric1],
+ DateTime.fromMillisecondsSinceEpoch(123),
+ 'test',
+ );
}
test(