From 6b0dc8e6e0351f8a075dea0a32f4472fc1b857f7 Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Mon, 5 Apr 2021 14:38:36 -0700 Subject: [PATCH 01/10] Update metrics_center github version --- packages/metrics_center/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/metrics_center/pubspec.yaml b/packages/metrics_center/pubspec.yaml index 68284e076815..376faf6c7ab8 100644 --- a/packages/metrics_center/pubspec.yaml +++ b/packages/metrics_center/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: crypto: ^2.1.5 equatable: ^1.2.5 gcloud: ^0.7.3 - github: ^7.0.4 + github: ^8.1.0 googleapis: ^0.56.1 googleapis_auth: ^0.2.12 http: ^0.12.2 From 30dced1f0bf9992add894b0bc9af6dbb0bf7b987 Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Mon, 5 Apr 2021 15:19:56 -0700 Subject: [PATCH 02/10] remove github dependency --- packages/metrics_center/lib/src/common.dart | 2 +- packages/metrics_center/lib/src/flutter.dart | 4 +- .../metrics_center/lib/src/github_helper.dart | 35 --------------- packages/metrics_center/lib/src/skiaperf.dart | 18 +++----- packages/metrics_center/pubspec.yaml | 2 - .../metrics_center/test/flutter_test.dart | 2 +- .../test/github_helper_test.dart | 41 ----------------- .../metrics_center/test/skiaperf_test.dart | 45 +++++++------------ 8 files changed, 28 insertions(+), 121 deletions(-) delete mode 100644 packages/metrics_center/lib/src/github_helper.dart delete mode 100644 packages/metrics_center/test/github_helper_test.dart diff --git a/packages/metrics_center/lib/src/common.dart b/packages/metrics_center/lib/src/common.dart index e4864e2d6429..ee17c40a2a42 100644 --- a/packages/metrics_center/lib/src/common.dart +++ b/packages/metrics_center/lib/src/common.dart @@ -50,7 +50,7 @@ class MetricPoint extends Equatable { /// Interface to write [MetricPoint]. abstract class MetricDestination { /// Insert new data points or modify old ones with matching id. - Future update(List points); + Future update(List points, DateTime commitTime); } /// 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 af2a8ad02bd0..89e35ae48f47 100644 --- a/packages/metrics_center/lib/src/flutter.dart +++ b/packages/metrics_center/lib/src/flutter.dart @@ -52,8 +52,8 @@ class FlutterDestination extends MetricDestination { } @override - Future update(List points) async { - await _skiaPerfDestination.update(points); + Future update(List points, DateTime commitTime) async { + await _skiaPerfDestination.update(points, commitTime); } final SkiaPerfDestination _skiaPerfDestination; diff --git a/packages/metrics_center/lib/src/github_helper.dart b/packages/metrics_center/lib/src/github_helper.dart deleted file mode 100644 index 9e33b487f3de..000000000000 --- a/packages/metrics_center/lib/src/github_helper.dart +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:github/github.dart'; - -/// Singleton class to query some Github info with an in-memory cache. -class GithubHelper { - /// Return the singleton helper. - factory GithubHelper() { - return _singleton; - } - - GithubHelper._internal(); - - /// The result is cached in memory so querying the same thing again in the - /// same process is fast. - /// - /// Our unit test requires that calling this method 1000 times for the same - /// `githubRepo` and `sha` should be done in 1 second. - Future getCommitDateTime(String githubRepo, String sha) async { - final String key = '$githubRepo/commit/$sha'; - if (_commitDateTimeCache[key] == null) { - final RepositoryCommit commit = await _github.repositories - .getCommit(RepositorySlug.full(githubRepo), sha); - _commitDateTimeCache[key] = commit.commit.committer.date; - } - return _commitDateTimeCache[key]; - } - - static final GithubHelper _singleton = GithubHelper._internal(); - - final GitHub _github = GitHub(auth: findAuthenticationFromEnvironment()); - final Map _commitDateTimeCache = {}; -} diff --git a/packages/metrics_center/lib/src/skiaperf.dart b/packages/metrics_center/lib/src/skiaperf.dart index b145857a3df5..509c3fa35da2 100644 --- a/packages/metrics_center/lib/src/skiaperf.dart +++ b/packages/metrics_center/lib/src/skiaperf.dart @@ -12,7 +12,6 @@ import 'package:googleapis_auth/auth_io.dart'; import 'common.dart'; import 'constants.dart'; import 'gcs_lock.dart'; -import 'github_helper.dart'; /// A [MetricPoint] modeled after the format that Skia Perf expects. /// @@ -317,16 +316,13 @@ class SkiaPerfGcsAdaptor { /// 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 computeObjectName(String githubRepo, String revision, - {GithubHelper githubHelper}) async { + static Future computeObjectName(String githubRepo, String revision, DateTime commitTime) async { assert(_githubRepoToGcsName[githubRepo] != null); final String topComponent = _githubRepoToGcsName[githubRepo]; - final DateTime t = await (githubHelper ?? GithubHelper()) - .getCommitDateTime(githubRepo, revision); - final String month = t.month.toString().padLeft(2, '0'); - final String day = t.day.toString().padLeft(2, '0'); - final String hour = t.hour.toString().padLeft(2, '0'); - final String dateComponents = '${t.year}/$month/$day/$hour'; + final String month = commitTime.month.toString().padLeft(2, '0'); + final String day = commitTime.day.toString().padLeft(2, '0'); + final String hour = commitTime.hour.toString().padLeft(2, '0'); + final String dateComponents = '${commitTime.year}/$month/$day/$hour'; return '$topComponent/$dateComponents/$revision/values.json'; } @@ -392,7 +388,7 @@ class SkiaPerfDestination extends MetricDestination { } @override - Future update(List points) async { + Future update(List points, DateTime commitTime) 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,7 +407,7 @@ class SkiaPerfDestination extends MetricDestination { for (final String repo in pointMap.keys) { for (final String revision in pointMap[repo].keys) { final String objectName = - await SkiaPerfGcsAdaptor.computeObjectName(repo, revision); + await SkiaPerfGcsAdaptor.computeObjectName(repo, revision, commitTime); final Map 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 diff --git a/packages/metrics_center/pubspec.yaml b/packages/metrics_center/pubspec.yaml index 376faf6c7ab8..ecb60a157f60 100644 --- a/packages/metrics_center/pubspec.yaml +++ b/packages/metrics_center/pubspec.yaml @@ -9,11 +9,9 @@ environment: sdk: '>=2.10.0 <3.0.0' dependencies: - args: ^1.6.0 crypto: ^2.1.5 equatable: ^1.2.5 gcloud: ^0.7.3 - github: ^8.1.0 googleapis: ^0.56.1 googleapis_auth: ^0.2.12 http: ^0.12.2 diff --git a/packages/metrics_center/test/flutter_test.dart b/packages/metrics_center/test/flutter_test.dart index 398516b8241b..5eb8a61fd222 100644 --- a/packages/metrics_center/test/flutter_test.dart +++ b/packages/metrics_center/test/flutter_test.dart @@ -44,6 +44,6 @@ void main() { final FlutterDestination dst = await FlutterDestination.makeFromCredentialsJson(credentialsJson, isTesting: true); - dst.update([simplePoint]); + dst.update([simplePoint], DateTime.fromMillisecondsSinceEpoch(123)); }, skip: credentialsJson == null); } diff --git a/packages/metrics_center/test/github_helper_test.dart b/packages/metrics_center/test/github_helper_test.dart deleted file mode 100644 index 3d53248b7d33..000000000000 --- a/packages/metrics_center/test/github_helper_test.dart +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@Timeout(Duration(seconds: 3600)) - -import 'package:metrics_center/src/github_helper.dart'; - -import 'common.dart'; - -void main() { - test('GithubHelper gets correct commit date time', () async { - final GithubHelper helper = GithubHelper(); - expect( - await helper.getCommitDateTime( - 'flutter/flutter', - 'ad20d368ffa09559754e4b2b5c12951341ca3b2d', - ), - equals(DateTime.parse('2019-12-06 03:33:01.000Z')), - ); - }); - - test('GithubHelper is a singleton', () { - final GithubHelper helper1 = GithubHelper(); - final GithubHelper helper2 = GithubHelper(); - expect(helper1, equals(helper2)); - }); - - test('GithubHelper can query the same commit 1000 times within 1 second', - () async { - final DateTime start = DateTime.now(); - for (int i = 0; i < 1000; i += 1) { - await GithubHelper().getCommitDateTime( - 'flutter/flutter', - 'ad20d368ffa09559754e4b2b5c12951341ca3b2d', - ); - } - final Duration duration = DateTime.now().difference(start); - expect(duration, lessThan(const Duration(seconds: 1))); - }); -} diff --git a/packages/metrics_center/test/skiaperf_test.dart b/packages/metrics_center/test/skiaperf_test.dart index 41d873709efe..04b3d69fad35 100644 --- a/packages/metrics_center/test/skiaperf_test.dart +++ b/packages/metrics_center/test/skiaperf_test.dart @@ -13,7 +13,6 @@ import 'package:metrics_center/metrics_center.dart'; import 'package:mockito/mockito.dart'; import 'package:metrics_center/src/constants.dart'; -import 'package:metrics_center/src/github_helper.dart'; import 'package:metrics_center/src/gcs_lock.dart'; import 'common.dart'; @@ -23,8 +22,6 @@ class MockBucket extends Mock implements Bucket {} class MockObjectInfo extends Mock implements ObjectInfo {} -class MockGithubHelper extends Mock implements GithubHelper {} - class MockGcsLock implements GcsLock { @override Future protectedRun( @@ -317,35 +314,27 @@ Future main() async { }); test('SkiaPerfGcsAdaptor computes name correctly', () async { - final MockGithubHelper mockHelper = MockGithubHelper(); - when(mockHelper.getCommitDateTime( - kFlutterFrameworkRepo, kFrameworkRevision1)) - .thenAnswer((_) => Future.value(DateTime(2019, 12, 4, 23))); expect( await SkiaPerfGcsAdaptor.computeObjectName( kFlutterFrameworkRepo, kFrameworkRevision1, - githubHelper: mockHelper, + DateTime.fromMillisecondsSinceEpoch(1575529660000), ), equals('flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'), ); - when(mockHelper.getCommitDateTime(kFlutterEngineRepo, kEngineRevision1)) - .thenAnswer((_) => Future.value(DateTime(2019, 12, 3, 20))); expect( await SkiaPerfGcsAdaptor.computeObjectName( kFlutterEngineRepo, kEngineRevision1, - githubHelper: mockHelper, + DateTime.fromMillisecondsSinceEpoch(1575432460000), ), equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'), ); - when(mockHelper.getCommitDateTime(kFlutterEngineRepo, kEngineRevision2)) - .thenAnswer((_) => Future.value(DateTime(2020, 1, 3, 15))); expect( await SkiaPerfGcsAdaptor.computeObjectName( kFlutterEngineRepo, kEngineRevision2, - githubHelper: mockHelper, + DateTime.fromMillisecondsSinceEpoch(1578092860000), ), equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'), ); @@ -356,7 +345,7 @@ Future main() async { final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket); final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterFrameworkRepo, kFrameworkRevision1); + kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123)); final List writePoints = [ SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1), @@ -393,7 +382,7 @@ Future main() async { final MockBucket testBucket = MockBucket(); final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket); final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterFrameworkRepo, kFrameworkRevision1); + kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123)); when(testBucket.info(testObjectName)) .thenThrow(Exception('No such object')); expect((await skiaPerfGcs.readPoints(testObjectName)).length, 0); @@ -423,7 +412,7 @@ Future main() async { final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket); final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterFrameworkRepo, kFrameworkRevision1); + kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123)); await skiaPerfGcs.writePoints(testObjectName, [ SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1), @@ -452,7 +441,7 @@ Future main() async { final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket); final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterEngineRepo, engineRevision); + kFlutterEngineRepo, engineRevision, DateTime.fromMillisecondsSinceEpoch(123)); await skiaPerfGcs.writePoints(testObjectName, [ SkiaPerfPoint.fromPoint(enginePoint1), @@ -505,18 +494,18 @@ Future main() async { () async { expect( await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterFrameworkRepo, kFrameworkRevision1), + kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(1575529660000),), equals( 'flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'), ); expect( await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterEngineRepo, kEngineRevision1), + kFlutterEngineRepo, kEngineRevision1, DateTime.fromMillisecondsSinceEpoch(1575432460000),), equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'), ); expect( await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterEngineRepo, kEngineRevision2), + kFlutterEngineRepo, kEngineRevision2, DateTime.fromMillisecondsSinceEpoch(1578092860000),), equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'), ); }, @@ -527,11 +516,11 @@ Future main() async { final SkiaPerfGcsAdaptor mockGcs = MockSkiaPerfGcsAdaptor(); final GcsLock mockLock = MockGcsLock(); final SkiaPerfDestination dst = SkiaPerfDestination(mockGcs, mockLock); - await dst.update([cocoonPointRev1Metric1]); - await dst.update([cocoonPointRev1Metric2]); + await dst.update([cocoonPointRev1Metric1], DateTime.fromMillisecondsSinceEpoch(123)); + await dst.update([cocoonPointRev1Metric2], DateTime.fromMillisecondsSinceEpoch(123)); List points = await mockGcs.readPoints( await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterFrameworkRepo, kFrameworkRevision1)); + kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123))); expect(points.length, equals(2)); expectSetMatch( points.map((SkiaPerfPoint p) => p.testName), [kTaskName]); @@ -543,18 +532,18 @@ Future main() async { final MetricPoint updated = MetricPoint(kValue3, cocoonPointRev1Metric1.tags); - await dst.update([updated, cocoonPointRev2Metric1]); + await dst.update([updated, cocoonPointRev2Metric1], DateTime.fromMillisecondsSinceEpoch(123)); points = await mockGcs.readPoints( await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterFrameworkRepo, kFrameworkRevision2)); + kFlutterFrameworkRepo, kFrameworkRevision2, DateTime.fromMillisecondsSinceEpoch(123))); 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)); + kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123))); expectSetMatch( points.map((SkiaPerfPoint p) => p.value), [kValue2, kValue3]); }); @@ -562,7 +551,7 @@ Future main() async { Future skiaPerfDestinationIntegrationTest() async { final SkiaPerfDestination destination = SkiaPerfDestination(SkiaPerfGcsAdaptor(testBucket), testLock); - await destination.update([cocoonPointRev1Metric1]); + await destination.update([cocoonPointRev1Metric1], DateTime.fromMillisecondsSinceEpoch(123)); } test( From 37213a462a27507ea4d4b15a5490d43bb57edd7b Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Mon, 5 Apr 2021 15:20:08 -0700 Subject: [PATCH 03/10] changelog + lints --- packages/metrics_center/CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/metrics_center/CHANGELOG.md b/packages/metrics_center/CHANGELOG.md index 63cf5593f912..4e629f28afca 100644 --- a/packages/metrics_center/CHANGELOG.md +++ b/packages/metrics_center/CHANGELOG.md @@ -1,13 +1,22 @@ +# 0.1.0 + +- `update` now requires DateTime when commit was merged +- Removed `github` dependency + # 0.0.9 + - Remove legacy datastore and destination. # 0.0.8 + - Allow tests to override LegacyFlutterDestination GCP project id. # 0.0.7 + - Expose constants that were missing since 0.0.4+1. # 0.0.6 + - Allow `datastoreFromCredentialsJson` to specify project id. # 0.0.5 From adcee5b65817086c428022fbd9ed7eb941f45e31 Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Mon, 5 Apr 2021 15:20:30 -0700 Subject: [PATCH 04/10] flutterfmt --- packages/metrics_center/lib/src/common.dart | 9 +- packages/metrics_center/lib/src/flutter.dart | 13 +- packages/metrics_center/lib/src/gcs_lock.dart | 6 +- .../lib/src/google_benchmark.dart | 20 +-- packages/metrics_center/lib/src/skiaperf.dart | 60 +++----- .../metrics_center/test/flutter_test.dart | 4 +- .../metrics_center/test/gcs_lock_test.dart | 14 +- .../test/google_benchmark_test.dart | 3 +- .../metrics_center/test/skiaperf_test.dart | 133 +++++++----------- packages/metrics_center/test/utility.dart | 3 +- 10 files changed, 97 insertions(+), 168 deletions(-) diff --git a/packages/metrics_center/lib/src/common.dart b/packages/metrics_center/lib/src/common.dart index ee17c40a2a42..3ed0f7ec1a7b 100644 --- a/packages/metrics_center/lib/src/common.dart +++ b/packages/metrics_center/lib/src/common.dart @@ -24,8 +24,7 @@ class MetricPoint extends Equatable { final double value; /// Test name, unit, timestamp, configs, git revision, ..., in sorted order. - UnmodifiableMapView get tags => - UnmodifiableMapView(_tags); + UnmodifiableMapView get tags => UnmodifiableMapView(_tags); /// Unique identifier for updating existing data point. /// @@ -57,9 +56,7 @@ abstract class MetricDestination { /// credentials json. It's currently the case for Chrmoium LUCI bots. AuthClient authClientFromAccessToken(String token, List scopes) { final DateTime anHourLater = DateTime.now().add(const Duration(hours: 1)); - final AccessToken accessToken = - AccessToken('Bearer', token, anHourLater.toUtc()); - final AccessCredentials accessCredentials = - AccessCredentials(accessToken, null, scopes); + final AccessToken accessToken = AccessToken('Bearer', token, anHourLater.toUtc()); + final AccessCredentials accessCredentials = AccessCredentials(accessToken, null, scopes); return authenticatedClient(Client(), accessCredentials); } diff --git a/packages/metrics_center/lib/src/flutter.dart b/packages/metrics_center/lib/src/flutter.dart index 89e35ae48f47..1d4bd59fc7da 100644 --- a/packages/metrics_center/lib/src/flutter.dart +++ b/packages/metrics_center/lib/src/flutter.dart @@ -32,22 +32,17 @@ class FlutterDestination extends MetricDestination { FlutterDestination._(this._skiaPerfDestination); /// Creates a [FlutterDestination] from service account JSON. - static Future makeFromCredentialsJson( - Map json, - {bool isTesting = false}) async { + static Future makeFromCredentialsJson(Map json, {bool isTesting = false}) async { final SkiaPerfDestination skiaPerfDestination = - await SkiaPerfDestination.makeFromGcpCredentials(json, - isTesting: isTesting); + await SkiaPerfDestination.makeFromGcpCredentials(json, isTesting: isTesting); return FlutterDestination._(skiaPerfDestination); } /// Creates a [FlutterDestination] from an OAuth access token. - static Future makeFromAccessToken( - String accessToken, String projectId, + static Future makeFromAccessToken(String accessToken, String projectId, {bool isTesting = false}) async { final SkiaPerfDestination skiaPerfDestination = - await SkiaPerfDestination.makeFromAccessToken(accessToken, projectId, - isTesting: isTesting); + await SkiaPerfDestination.makeFromAccessToken(accessToken, projectId, isTesting: isTesting); return FlutterDestination._(skiaPerfDestination); } diff --git a/packages/metrics_center/lib/src/gcs_lock.dart b/packages/metrics_center/lib/src/gcs_lock.dart index 47d0d231ec65..b830a29cbdb1 100644 --- a/packages/metrics_center/lib/src/gcs_lock.dart +++ b/packages/metrics_center/lib/src/gcs_lock.dart @@ -30,8 +30,7 @@ class GcsLock { /// If the lock file is stuck (e.g., `_unlock` is interrupted unexpectedly), /// one may need to manually delete the lock file from GCS to unblock any /// [protectedRun] that may depend on it. - Future protectedRun( - String lockFileName, Future Function() f) async { + Future protectedRun(String lockFileName, Future Function() f) async { await _lock(lockFileName); try { await f(); @@ -53,8 +52,7 @@ class GcsLock { bool locked = false; while (!locked) { try { - await _api.objects.insert(object, _bucketName, - ifGenerationMatch: '0', uploadMedia: content); + await _api.objects.insert(object, _bucketName, ifGenerationMatch: '0', uploadMedia: content); locked = true; } on DetailedApiRequestError catch (e) { if (e.status == 412) { diff --git a/packages/metrics_center/lib/src/google_benchmark.dart b/packages/metrics_center/lib/src/google_benchmark.dart index ab4ae221dc2c..9560aec14be2 100644 --- a/packages/metrics_center/lib/src/google_benchmark.dart +++ b/packages/metrics_center/lib/src/google_benchmark.dart @@ -21,12 +21,9 @@ const List _kNonNumericalValueSubResults = [ class GoogleBenchmarkParser { /// Given a Google benchmark json output, parse its content into a list of [MetricPoint]. static Future> parse(String jsonFileName) async { - final Map jsonResult = - jsonDecode(File(jsonFileName).readAsStringSync()) - as Map; + final Map jsonResult = jsonDecode(File(jsonFileName).readAsStringSync()) as Map; - final Map rawContext = - jsonResult['context'] as Map; + final Map rawContext = jsonResult['context'] as Map; final Map context = rawContext.map( (String k, dynamic v) => MapEntry(k, v.toString()), ); @@ -44,29 +41,24 @@ void _parseAnItem( Map context, ) { final String name = item[kNameKey] as String; - final Map timeUnitMap = { - kUnitKey: item[_kTimeUnitKey] as String - }; + final Map timeUnitMap = {kUnitKey: item[_kTimeUnitKey] as String}; for (final String subResult in item.keys) { if (!_kNonNumericalValueSubResults.contains(subResult)) { num rawValue; try { rawValue = item[subResult] as num; } catch (e) { - print( - '$subResult: ${item[subResult]} (${item[subResult].runtimeType}) is not a number'); + print('$subResult: ${item[subResult]} (${item[subResult].runtimeType}) is not a number'); rethrow; } - final double value = - rawValue is int ? rawValue.toDouble() : rawValue as double; + final double value = rawValue is int ? rawValue.toDouble() : rawValue as double; points.add( MetricPoint( value, {kNameKey: name, kSubResultKey: subResult} ..addAll(context) - ..addAll( - subResult.endsWith('time') ? timeUnitMap : {}), + ..addAll(subResult.endsWith('time') ? timeUnitMap : {}), ), ); } diff --git a/packages/metrics_center/lib/src/skiaperf.dart b/packages/metrics_center/lib/src/skiaperf.dart index 509c3fa35da2..3228b58f7399 100644 --- a/packages/metrics_center/lib/src/skiaperf.dart +++ b/packages/metrics_center/lib/src/skiaperf.dart @@ -47,8 +47,8 @@ import 'gcs_lock.dart'; /// } /// ``` class SkiaPerfPoint extends MetricPoint { - SkiaPerfPoint._(this.githubRepo, this.gitHash, this.testName, this.subResult, - double value, this._options, this.jsonUrl) + SkiaPerfPoint._( + this.githubRepo, this.gitHash, this.testName, this.subResult, double value, this._options, this.jsonUrl) : assert(_options[kGithubRepoKey] == null), assert(_options[kGitRevisionKey] == null), assert(_options[kNameKey] == null), @@ -104,8 +104,7 @@ class SkiaPerfPoint extends MetricPoint { ), ); - return SkiaPerfPoint._( - githubRepo, gitHash, name, subResult, p.value, options, null); + return SkiaPerfPoint._(githubRepo, gitHash, name, subResult, p.value, options, null); } /// In the format of '/' such as 'flutter/flutter' or @@ -155,8 +154,7 @@ class SkiaPerfPoint extends MetricPoint { assert(points.isNotEmpty); assert(() { for (final SkiaPerfPoint p in points) { - if (p.githubRepo != points[0].githubRepo || - p.gitHash != points[0].gitHash) { + if (p.githubRepo != points[0].githubRepo || p.gitHash != points[0].gitHash) { return false; } } @@ -175,11 +173,9 @@ class SkiaPerfPoint extends MetricPoint { // options/configurations. If this actually happens in the future, we // probably can use different values of config (currently there's only // one kSkiaPerfDefaultConfig) to resolve the conflict. - assert(results[p.testName][kSkiaPerfDefaultConfig][kSkiaPerfOptionsKey] - .toString() == + assert(results[p.testName][kSkiaPerfDefaultConfig][kSkiaPerfOptionsKey].toString() == subResultJson[kSkiaPerfOptionsKey].toString()); - assert( - results[p.testName][kSkiaPerfDefaultConfig][p.subResult] == null); + assert(results[p.testName][kSkiaPerfDefaultConfig][p.subResult] == null); results[p.testName][kSkiaPerfDefaultConfig][p.subResult] = p.value; } } @@ -212,8 +208,7 @@ class SkiaPerfGcsAdaptor { /// /// The read may retry multiple times if transient network errors with code /// 504 happens. - Future writePoints( - String objectName, List points) async { + Future writePoints(String objectName, List points) async { final String jsonString = jsonEncode(SkiaPerfPoint.toSkiaPerfJson(points)); final List content = utf8.encode(jsonString); @@ -274,9 +269,7 @@ class SkiaPerfGcsAdaptor { final Stream> stream = _gcsBucket.read(objectName); final Stream byteStream = stream.expand((List x) => x); - final Map decodedJson = - jsonDecode(utf8.decode(await byteStream.toList())) - as Map; + final Map decodedJson = jsonDecode(utf8.decode(await byteStream.toList())) as Map; final List points = []; @@ -286,21 +279,17 @@ class SkiaPerfGcsAdaptor { assert(githubRepo != null); final String gitHash = decodedJson[kSkiaPerfGitHashKey] as String; - final Map results = - decodedJson[kSkiaPerfResultsKey] as Map; + final Map results = decodedJson[kSkiaPerfResultsKey] as Map; for (final String name in results.keys) { - final Map subResultMap = - results[name][kSkiaPerfDefaultConfig] as Map; - for (final String subResult - in subResultMap.keys.where((String s) => s != kSkiaPerfOptionsKey)) { + final Map subResultMap = results[name][kSkiaPerfDefaultConfig] as Map; + for (final String subResult in subResultMap.keys.where((String s) => s != kSkiaPerfOptionsKey)) { points.add(SkiaPerfPoint._( githubRepo, gitHash, name, subResult, subResultMap[subResult] as double, - (subResultMap[kSkiaPerfOptionsKey] as Map) - .cast(), + (subResultMap[kSkiaPerfOptionsKey] as Map).cast(), info.downloadLink.toString(), )); } @@ -351,11 +340,10 @@ class SkiaPerfDestination extends MetricDestination { SkiaPerfDestination(this._gcs, this._lock); /// Create from a full credentials json (of a service account). - static Future makeFromGcpCredentials( - Map credentialsJson, + static Future makeFromGcpCredentials(Map credentialsJson, {bool isTesting = false}) async { - final AutoRefreshingAuthClient client = await clientViaServiceAccount( - ServiceAccountCredentials.fromJson(credentialsJson), Storage.SCOPES); + final AutoRefreshingAuthClient client = + await clientViaServiceAccount(ServiceAccountCredentials.fromJson(credentialsJson), Storage.SCOPES); return make( client, credentialsJson[kProjectId] as String, @@ -364,8 +352,7 @@ class SkiaPerfDestination extends MetricDestination { } /// Create from an access token and its project id. - static Future makeFromAccessToken( - String token, String projectId, + static Future makeFromAccessToken(String token, String projectId, {bool isTesting = false}) async { final AuthClient client = authClientFromAccessToken(token, Storage.SCOPES); return make(client, projectId, isTesting: isTesting); @@ -374,15 +361,13 @@ class SkiaPerfDestination extends MetricDestination { /// Create from an [AuthClient] and a GCP project id. /// /// [AuthClient] can be obtained from functions like `clientViaUserConsent`. - static Future make(AuthClient client, String projectId, - {bool isTesting = false}) async { + static Future make(AuthClient client, String projectId, {bool isTesting = false}) async { final Storage storage = Storage(client, projectId); final String bucketName = isTesting ? kTestBucketName : kBucketName; if (!await storage.bucketExists(bucketName)) { throw 'Bucket $bucketName does not exist.'; } - final SkiaPerfGcsAdaptor adaptor = - SkiaPerfGcsAdaptor(storage.bucket(bucketName)); + final SkiaPerfGcsAdaptor adaptor = SkiaPerfGcsAdaptor(storage.bucket(bucketName)); final GcsLock lock = GcsLock(client, bucketName); return SkiaPerfDestination(adaptor, lock); } @@ -394,8 +379,7 @@ class SkiaPerfDestination extends MetricDestination { // name. final Map>> pointMap = >>{}; - for (final SkiaPerfPoint p - in points.map((MetricPoint x) => SkiaPerfPoint.fromPoint(x))) { + for (final SkiaPerfPoint p in points.map((MetricPoint x) => SkiaPerfPoint.fromPoint(x))) { if (p != null) { pointMap[p.githubRepo] ??= >{}; pointMap[p.githubRepo][p.gitHash] ??= {}; @@ -406,8 +390,7 @@ class SkiaPerfDestination extends MetricDestination { // 2nd, read existing points from the gcs object and update with new ones. for (final String repo in pointMap.keys) { for (final String revision in pointMap[repo].keys) { - final String objectName = - await SkiaPerfGcsAdaptor.computeObjectName(repo, revision, commitTime); + final String objectName = await SkiaPerfGcsAdaptor.computeObjectName(repo, revision, commitTime); final Map 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 @@ -416,8 +399,7 @@ class SkiaPerfDestination extends MetricDestination { // json files in the directory so one can use arbitrary names for those // sharded json file names. _lock.protectedRun('$objectName.lock', () async { - final List oldPoints = - await _gcs.readPoints(objectName); + final List oldPoints = await _gcs.readPoints(objectName); for (final SkiaPerfPoint p in oldPoints) { if (newPoints[p.id] == null) { newPoints[p.id] = p; diff --git a/packages/metrics_center/test/flutter_test.dart b/packages/metrics_center/test/flutter_test.dart index 5eb8a61fd222..2b6263bc44e6 100644 --- a/packages/metrics_center/test/flutter_test.dart +++ b/packages/metrics_center/test/flutter_test.dart @@ -41,9 +41,7 @@ void main() { final Map credentialsJson = getTestGcpCredentialsJson(); test('FlutterDestination integration test with update.', () async { - final FlutterDestination dst = - await FlutterDestination.makeFromCredentialsJson(credentialsJson, - isTesting: true); + final FlutterDestination dst = await FlutterDestination.makeFromCredentialsJson(credentialsJson, isTesting: true); dst.update([simplePoint], DateTime.fromMillisecondsSinceEpoch(123)); }, skip: credentialsJson == null); } diff --git a/packages/metrics_center/test/gcs_lock_test.dart b/packages/metrics_center/test/gcs_lock_test.dart index d682d950c2d1..03661ff5cfdc 100644 --- a/packages/metrics_center/test/gcs_lock_test.dart +++ b/packages/metrics_center/test/gcs_lock_test.dart @@ -29,16 +29,14 @@ void main() { test('GcsLock prints warnings for long waits', () { // Capture print to verify error messages. final List prints = []; - final ZoneSpecification spec = - ZoneSpecification(print: (_, __, ___, String msg) => prints.add(msg)); + final ZoneSpecification spec = ZoneSpecification(print: (_, __, ___, String msg) => prints.add(msg)); Zone.current.fork(specification: spec).run(() { fakeAsync((FakeAsync fakeAsync) { final MockClient mockClient = MockClient(); final GcsLock lock = GcsLock(mockClient, 'mockBucket'); when(mockClient.send(any)).thenThrow(DetailedApiRequestError(412, '')); - final Future runFinished = - lock.protectedRun('mock.lock', () async {}); + final Future runFinished = lock.protectedRun('mock.lock', () async {}); fakeAsync.elapse(const Duration(seconds: 10)); when(mockClient.send(any)).thenThrow(AssertionError('Stop!')); runFinished.catchError((dynamic e) { @@ -58,8 +56,8 @@ void main() { }); test('GcsLock integration test: single protectedRun is successful', () async { - final AutoRefreshingAuthClient client = await clientViaServiceAccount( - ServiceAccountCredentials.fromJson(credentialsJson), Storage.SCOPES); + final AutoRefreshingAuthClient client = + await clientViaServiceAccount(ServiceAccountCredentials.fromJson(credentialsJson), Storage.SCOPES); final GcsLock lock = GcsLock(client, kTestBucketName); int testValue = 0; await lock.protectedRun('test.lock', () async { @@ -69,8 +67,8 @@ void main() { }, skip: credentialsJson == null); test('GcsLock integration test: protectedRun is exclusive', () async { - final AutoRefreshingAuthClient client = await clientViaServiceAccount( - ServiceAccountCredentials.fromJson(credentialsJson), Storage.SCOPES); + final AutoRefreshingAuthClient client = + await clientViaServiceAccount(ServiceAccountCredentials.fromJson(credentialsJson), Storage.SCOPES); final GcsLock lock1 = GcsLock(client, kTestBucketName); final GcsLock lock2 = GcsLock(client, kTestBucketName); diff --git a/packages/metrics_center/test/google_benchmark_test.dart b/packages/metrics_center/test/google_benchmark_test.dart index 11883ae331c3..5c7c9bcfc2c9 100644 --- a/packages/metrics_center/test/google_benchmark_test.dart +++ b/packages/metrics_center/test/google_benchmark_test.dart @@ -11,8 +11,7 @@ import 'utility.dart'; void main() { test('GoogleBenchmarkParser parses example json.', () async { - final List points = - await GoogleBenchmarkParser.parse('test/example_google_benchmark.json'); + final List points = await GoogleBenchmarkParser.parse('test/example_google_benchmark.json'); expect(points.length, 6); expectSetMatch( points.map((MetricPoint p) => p.value), diff --git a/packages/metrics_center/test/skiaperf_test.dart b/packages/metrics_center/test/skiaperf_test.dart index 04b3d69fad35..b1000bfaab86 100644 --- a/packages/metrics_center/test/skiaperf_test.dart +++ b/packages/metrics_center/test/skiaperf_test.dart @@ -24,8 +24,7 @@ class MockObjectInfo extends Mock implements ObjectInfo {} class MockGcsLock implements GcsLock { @override - Future protectedRun( - String exclusiveObjectName, Future Function() f) async { + Future protectedRun(String exclusiveObjectName, Future Function() f) async { await f(); } } @@ -37,14 +36,12 @@ class MockSkiaPerfGcsAdaptor implements SkiaPerfGcsAdaptor { } @override - Future writePoints( - String objectName, List points) async { + Future writePoints(String objectName, List points) async { _storage[objectName] = points.toList(); } // Map from the object name to the list of SkiaPoint that mocks the GCS. - final Map> _storage = - >{}; + final Map> _storage = >{}; } Future main() async { @@ -183,14 +180,12 @@ Future main() async { ); expect(() => SkiaPerfPoint.fromPoint(noGithubRepoPoint), throwsA(anything)); - expect( - () => SkiaPerfPoint.fromPoint(noGitRevisionPoint), throwsA(anything)); + expect(() => SkiaPerfPoint.fromPoint(noGitRevisionPoint), throwsA(anything)); expect(() => SkiaPerfPoint.fromPoint(noTestNamePoint), throwsA(anything)); }); test('Correctly convert a metric point from cocoon to SkiaPoint', () { - final SkiaPerfPoint skiaPoint1 = - SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1); + final SkiaPerfPoint skiaPoint1 = SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1); expect(skiaPoint1, isNotNull); expect(skiaPoint1.testName, equals(kTaskName)); expect(skiaPoint1.subResult, equals(kMetric1)); @@ -201,15 +196,11 @@ Future main() async { test('Cocoon points correctly encode into Skia perf json format', () { final SkiaPerfPoint p1 = SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1); final SkiaPerfPoint p2 = SkiaPerfPoint.fromPoint(cocoonPointRev1Metric2); - final SkiaPerfPoint p3 = - SkiaPerfPoint.fromPoint(cocoonPointBetaRev1Metric1); + final SkiaPerfPoint p3 = SkiaPerfPoint.fromPoint(cocoonPointBetaRev1Metric1); const JsonEncoder encoder = JsonEncoder.withIndent(' '); - expect( - encoder - .convert(SkiaPerfPoint.toSkiaPerfJson([p1, p2, p3])), - equals(''' + expect(encoder.convert(SkiaPerfPoint.toSkiaPerfJson([p1, p2, p3])), equals(''' { "gitHash": "9011cece2595447eea5dd91adaa241c1c9ef9a33", "results": { @@ -304,8 +295,7 @@ Future main() async { 'Throw if two Cocoon metric points with the same name and subResult keys ' 'but different options are converted to Skia perf points', () { final SkiaPerfPoint p1 = SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1); - final SkiaPerfPoint p2 = - SkiaPerfPoint.fromPoint(cocoonPointBetaRev1Metric1BadBranch); + final SkiaPerfPoint p2 = SkiaPerfPoint.fromPoint(cocoonPointBetaRev1Metric1BadBranch); expect( () => SkiaPerfPoint.toSkiaPerfJson([p1, p2]), @@ -350,25 +340,19 @@ Future main() async { final List writePoints = [ SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1), ]; - final String skiaPerfJson = - jsonEncode(SkiaPerfPoint.toSkiaPerfJson(writePoints)); + final String skiaPerfJson = jsonEncode(SkiaPerfPoint.toSkiaPerfJson(writePoints)); await skiaPerfGcs.writePoints(testObjectName, writePoints); verify(testBucket.writeBytes(testObjectName, utf8.encode(skiaPerfJson))); // Emulate the first network request to fail with 504. - when(testBucket.info(testObjectName)) - .thenThrow(DetailedApiRequestError(504, 'Test Failure')); + when(testBucket.info(testObjectName)).thenThrow(DetailedApiRequestError(504, 'Test Failure')); final MockObjectInfo mockObjectInfo = MockObjectInfo(); - when(mockObjectInfo.downloadLink) - .thenReturn(Uri.https('test.com', 'mock.json')); - when(testBucket.info(testObjectName)) - .thenAnswer((_) => Future.value(mockObjectInfo)); - when(testBucket.read(testObjectName)) - .thenAnswer((_) => Stream>.value(utf8.encode(skiaPerfJson))); - - final List readPoints = - await skiaPerfGcs.readPoints(testObjectName); + when(mockObjectInfo.downloadLink).thenReturn(Uri.https('test.com', 'mock.json')); + when(testBucket.info(testObjectName)).thenAnswer((_) => Future.value(mockObjectInfo)); + when(testBucket.read(testObjectName)).thenAnswer((_) => Stream>.value(utf8.encode(skiaPerfJson))); + + final List readPoints = await skiaPerfGcs.readPoints(testObjectName); expect(readPoints.length, equals(1)); expect(readPoints[0].testName, kTaskName); expect(readPoints[0].subResult, kMetric1); @@ -383,8 +367,7 @@ Future main() async { final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket); final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName( kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123)); - when(testBucket.info(testObjectName)) - .thenThrow(Exception('No such object')); + when(testBucket.info(testObjectName)).thenThrow(Exception('No such object')); expect((await skiaPerfGcs.readPoints(testObjectName)).length, 0); }); @@ -393,13 +376,10 @@ Future main() async { GcsLock testLock; final Map credentialsJson = getTestGcpCredentialsJson(); if (credentialsJson != null) { - final ServiceAccountCredentials credentials = - ServiceAccountCredentials.fromJson(credentialsJson); + final ServiceAccountCredentials credentials = ServiceAccountCredentials.fromJson(credentialsJson); - final AutoRefreshingAuthClient client = - await clientViaServiceAccount(credentials, Storage.SCOPES); - final Storage storage = - Storage(client, credentialsJson['project_id'] as String); + final AutoRefreshingAuthClient client = await clientViaServiceAccount(credentials, Storage.SCOPES); + final Storage storage = Storage(client, credentialsJson['project_id'] as String); const String kTestBucketName = 'flutter-skia-perf-test'; @@ -419,19 +399,13 @@ Future main() async { SkiaPerfPoint.fromPoint(cocoonPointRev1Metric2), ]); - final List points = - await skiaPerfGcs.readPoints(testObjectName); + final List points = await skiaPerfGcs.readPoints(testObjectName); expect(points.length, equals(2)); - expectSetMatch( - points.map((SkiaPerfPoint p) => p.testName), [kTaskName]); - expectSetMatch(points.map((SkiaPerfPoint p) => p.subResult), - [kMetric1, kMetric2]); - expectSetMatch( - points.map((SkiaPerfPoint p) => p.value), [kValue1, kValue2]); - expectSetMatch(points.map((SkiaPerfPoint p) => p.githubRepo), - [kFlutterFrameworkRepo]); - expectSetMatch(points.map((SkiaPerfPoint p) => p.gitHash), - [kFrameworkRevision1]); + expectSetMatch(points.map((SkiaPerfPoint p) => p.testName), [kTaskName]); + expectSetMatch(points.map((SkiaPerfPoint p) => p.subResult), [kMetric1, kMetric2]); + expectSetMatch(points.map((SkiaPerfPoint p) => p.value), [kValue1, kValue2]); + expectSetMatch(points.map((SkiaPerfPoint p) => p.githubRepo), [kFlutterFrameworkRepo]); + expectSetMatch(points.map((SkiaPerfPoint p) => p.gitHash), [kFrameworkRevision1]); for (int i = 0; i < 2; i += 1) { expect(points[0].jsonUrl, startsWith('https://')); } @@ -448,8 +422,7 @@ Future main() async { SkiaPerfPoint.fromPoint(enginePoint2), ]); - final List points = - await skiaPerfGcs.readPoints(testObjectName); + final List points = await skiaPerfGcs.readPoints(testObjectName); expect(points.length, equals(2)); expectSetMatch( points.map((SkiaPerfPoint p) => p.testName), @@ -463,8 +436,7 @@ Future main() async { points.map((SkiaPerfPoint p) => p.githubRepo), [kFlutterEngineRepo], ); - expectSetMatch( - points.map((SkiaPerfPoint p) => p.gitHash), [engineRevision]); + expectSetMatch(points.map((SkiaPerfPoint p) => p.gitHash), [engineRevision]); for (int i = 0; i < 2; i += 1) { expect(points[0].jsonUrl, startsWith('https://')); } @@ -494,18 +466,26 @@ Future main() async { () async { expect( await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(1575529660000),), - equals( - 'flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'), + kFlutterFrameworkRepo, + kFrameworkRevision1, + DateTime.fromMillisecondsSinceEpoch(1575529660000), + ), + equals('flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'), ); expect( await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterEngineRepo, kEngineRevision1, DateTime.fromMillisecondsSinceEpoch(1575432460000),), + kFlutterEngineRepo, + kEngineRevision1, + DateTime.fromMillisecondsSinceEpoch(1575432460000), + ), equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'), ); expect( await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterEngineRepo, kEngineRevision2, DateTime.fromMillisecondsSinceEpoch(1578092860000),), + kFlutterEngineRepo, + kEngineRevision2, + DateTime.fromMillisecondsSinceEpoch(1578092860000), + ), equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'), ); }, @@ -518,39 +498,30 @@ Future main() async { final SkiaPerfDestination dst = SkiaPerfDestination(mockGcs, mockLock); await dst.update([cocoonPointRev1Metric1], DateTime.fromMillisecondsSinceEpoch(123)); await dst.update([cocoonPointRev1Metric2], DateTime.fromMillisecondsSinceEpoch(123)); - List points = await mockGcs.readPoints( - await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123))); + List points = await mockGcs.readPoints(await SkiaPerfGcsAdaptor.computeObjectName( + kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123))); expect(points.length, equals(2)); - expectSetMatch( - points.map((SkiaPerfPoint p) => p.testName), [kTaskName]); - expectSetMatch(points.map((SkiaPerfPoint p) => p.subResult), - [kMetric1, kMetric2]); - expectSetMatch( - points.map((SkiaPerfPoint p) => p.value), [kValue1, kValue2]); + expectSetMatch(points.map((SkiaPerfPoint p) => p.testName), [kTaskName]); + expectSetMatch(points.map((SkiaPerfPoint p) => p.subResult), [kMetric1, kMetric2]); + expectSetMatch(points.map((SkiaPerfPoint p) => p.value), [kValue1, kValue2]); - final MetricPoint updated = - MetricPoint(kValue3, cocoonPointRev1Metric1.tags); + final MetricPoint updated = MetricPoint(kValue3, cocoonPointRev1Metric1.tags); await dst.update([updated, cocoonPointRev2Metric1], DateTime.fromMillisecondsSinceEpoch(123)); - points = await mockGcs.readPoints( - await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterFrameworkRepo, kFrameworkRevision2, DateTime.fromMillisecondsSinceEpoch(123))); + points = await mockGcs.readPoints(await SkiaPerfGcsAdaptor.computeObjectName( + kFlutterFrameworkRepo, kFrameworkRevision2, DateTime.fromMillisecondsSinceEpoch(123))); 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))); - expectSetMatch( - points.map((SkiaPerfPoint p) => p.value), [kValue2, kValue3]); + points = await mockGcs.readPoints(await SkiaPerfGcsAdaptor.computeObjectName( + kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123))); + expectSetMatch(points.map((SkiaPerfPoint p) => p.value), [kValue2, kValue3]); }); Future skiaPerfDestinationIntegrationTest() async { - final SkiaPerfDestination destination = - SkiaPerfDestination(SkiaPerfGcsAdaptor(testBucket), testLock); + final SkiaPerfDestination destination = SkiaPerfDestination(SkiaPerfGcsAdaptor(testBucket), testLock); await destination.update([cocoonPointRev1Metric1], DateTime.fromMillisecondsSinceEpoch(123)); } diff --git a/packages/metrics_center/test/utility.dart b/packages/metrics_center/test/utility.dart index 6dacd48b0aff..8fabf18ac74b 100644 --- a/packages/metrics_center/test/utility.dart +++ b/packages/metrics_center/test/utility.dart @@ -18,6 +18,5 @@ Map getTestGcpCredentialsJson() { if (!f.existsSync()) { return null; } - return jsonDecode(File('secret/test_gcp_credentials.json').readAsStringSync()) - as Map; + return jsonDecode(File('secret/test_gcp_credentials.json').readAsStringSync()) as Map; } From 5fbfb8451f8666ebb3095f566d56e2e2972487f1 Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Mon, 5 Apr 2021 15:22:12 -0700 Subject: [PATCH 05/10] version bump --- packages/metrics_center/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/metrics_center/pubspec.yaml b/packages/metrics_center/pubspec.yaml index ecb60a157f60..cc8fac0afc9f 100644 --- a/packages/metrics_center/pubspec.yaml +++ b/packages/metrics_center/pubspec.yaml @@ -1,5 +1,5 @@ name: metrics_center -version: 0.0.9 +version: 0.1.0 description: Support multiple performance metrics sources/formats and destinations. homepage: From 46dd3699a821d97759ec2fc33ade67e717605602 Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Mon, 5 Apr 2021 20:26:44 -0700 Subject: [PATCH 06/10] plugin tools format --- packages/metrics_center/lib/src/common.dart | 9 +- packages/metrics_center/lib/src/flutter.dart | 13 +- packages/metrics_center/lib/src/gcs_lock.dart | 6 +- .../lib/src/google_benchmark.dart | 20 ++- packages/metrics_center/lib/src/skiaperf.dart | 63 +++++--- .../metrics_center/test/flutter_test.dart | 7 +- .../metrics_center/test/gcs_lock_test.dart | 14 +- .../test/google_benchmark_test.dart | 3 +- .../metrics_center/test/skiaperf_test.dart | 146 ++++++++++++------ packages/metrics_center/test/utility.dart | 3 +- 10 files changed, 189 insertions(+), 95 deletions(-) diff --git a/packages/metrics_center/lib/src/common.dart b/packages/metrics_center/lib/src/common.dart index 3ed0f7ec1a7b..ee17c40a2a42 100644 --- a/packages/metrics_center/lib/src/common.dart +++ b/packages/metrics_center/lib/src/common.dart @@ -24,7 +24,8 @@ class MetricPoint extends Equatable { final double value; /// Test name, unit, timestamp, configs, git revision, ..., in sorted order. - UnmodifiableMapView get tags => UnmodifiableMapView(_tags); + UnmodifiableMapView get tags => + UnmodifiableMapView(_tags); /// Unique identifier for updating existing data point. /// @@ -56,7 +57,9 @@ abstract class MetricDestination { /// credentials json. It's currently the case for Chrmoium LUCI bots. AuthClient authClientFromAccessToken(String token, List scopes) { final DateTime anHourLater = DateTime.now().add(const Duration(hours: 1)); - final AccessToken accessToken = AccessToken('Bearer', token, anHourLater.toUtc()); - final AccessCredentials accessCredentials = AccessCredentials(accessToken, null, scopes); + final AccessToken accessToken = + AccessToken('Bearer', token, anHourLater.toUtc()); + final AccessCredentials accessCredentials = + AccessCredentials(accessToken, null, scopes); return authenticatedClient(Client(), accessCredentials); } diff --git a/packages/metrics_center/lib/src/flutter.dart b/packages/metrics_center/lib/src/flutter.dart index 1d4bd59fc7da..89e35ae48f47 100644 --- a/packages/metrics_center/lib/src/flutter.dart +++ b/packages/metrics_center/lib/src/flutter.dart @@ -32,17 +32,22 @@ class FlutterDestination extends MetricDestination { FlutterDestination._(this._skiaPerfDestination); /// Creates a [FlutterDestination] from service account JSON. - static Future makeFromCredentialsJson(Map json, {bool isTesting = false}) async { + static Future makeFromCredentialsJson( + Map json, + {bool isTesting = false}) async { final SkiaPerfDestination skiaPerfDestination = - await SkiaPerfDestination.makeFromGcpCredentials(json, isTesting: isTesting); + await SkiaPerfDestination.makeFromGcpCredentials(json, + isTesting: isTesting); return FlutterDestination._(skiaPerfDestination); } /// Creates a [FlutterDestination] from an OAuth access token. - static Future makeFromAccessToken(String accessToken, String projectId, + static Future makeFromAccessToken( + String accessToken, String projectId, {bool isTesting = false}) async { final SkiaPerfDestination skiaPerfDestination = - await SkiaPerfDestination.makeFromAccessToken(accessToken, projectId, isTesting: isTesting); + await SkiaPerfDestination.makeFromAccessToken(accessToken, projectId, + isTesting: isTesting); return FlutterDestination._(skiaPerfDestination); } diff --git a/packages/metrics_center/lib/src/gcs_lock.dart b/packages/metrics_center/lib/src/gcs_lock.dart index b830a29cbdb1..47d0d231ec65 100644 --- a/packages/metrics_center/lib/src/gcs_lock.dart +++ b/packages/metrics_center/lib/src/gcs_lock.dart @@ -30,7 +30,8 @@ class GcsLock { /// If the lock file is stuck (e.g., `_unlock` is interrupted unexpectedly), /// one may need to manually delete the lock file from GCS to unblock any /// [protectedRun] that may depend on it. - Future protectedRun(String lockFileName, Future Function() f) async { + Future protectedRun( + String lockFileName, Future Function() f) async { await _lock(lockFileName); try { await f(); @@ -52,7 +53,8 @@ class GcsLock { bool locked = false; while (!locked) { try { - await _api.objects.insert(object, _bucketName, ifGenerationMatch: '0', uploadMedia: content); + await _api.objects.insert(object, _bucketName, + ifGenerationMatch: '0', uploadMedia: content); locked = true; } on DetailedApiRequestError catch (e) { if (e.status == 412) { diff --git a/packages/metrics_center/lib/src/google_benchmark.dart b/packages/metrics_center/lib/src/google_benchmark.dart index 9560aec14be2..ab4ae221dc2c 100644 --- a/packages/metrics_center/lib/src/google_benchmark.dart +++ b/packages/metrics_center/lib/src/google_benchmark.dart @@ -21,9 +21,12 @@ const List _kNonNumericalValueSubResults = [ class GoogleBenchmarkParser { /// Given a Google benchmark json output, parse its content into a list of [MetricPoint]. static Future> parse(String jsonFileName) async { - final Map jsonResult = jsonDecode(File(jsonFileName).readAsStringSync()) as Map; + final Map jsonResult = + jsonDecode(File(jsonFileName).readAsStringSync()) + as Map; - final Map rawContext = jsonResult['context'] as Map; + final Map rawContext = + jsonResult['context'] as Map; final Map context = rawContext.map( (String k, dynamic v) => MapEntry(k, v.toString()), ); @@ -41,24 +44,29 @@ void _parseAnItem( Map context, ) { final String name = item[kNameKey] as String; - final Map timeUnitMap = {kUnitKey: item[_kTimeUnitKey] as String}; + final Map timeUnitMap = { + kUnitKey: item[_kTimeUnitKey] as String + }; for (final String subResult in item.keys) { if (!_kNonNumericalValueSubResults.contains(subResult)) { num rawValue; try { rawValue = item[subResult] as num; } catch (e) { - print('$subResult: ${item[subResult]} (${item[subResult].runtimeType}) is not a number'); + print( + '$subResult: ${item[subResult]} (${item[subResult].runtimeType}) is not a number'); rethrow; } - final double value = rawValue is int ? rawValue.toDouble() : rawValue as double; + final double value = + rawValue is int ? rawValue.toDouble() : rawValue as double; points.add( MetricPoint( value, {kNameKey: name, kSubResultKey: subResult} ..addAll(context) - ..addAll(subResult.endsWith('time') ? timeUnitMap : {}), + ..addAll( + subResult.endsWith('time') ? timeUnitMap : {}), ), ); } diff --git a/packages/metrics_center/lib/src/skiaperf.dart b/packages/metrics_center/lib/src/skiaperf.dart index 3228b58f7399..ac6c89cc6da9 100644 --- a/packages/metrics_center/lib/src/skiaperf.dart +++ b/packages/metrics_center/lib/src/skiaperf.dart @@ -47,8 +47,8 @@ import 'gcs_lock.dart'; /// } /// ``` class SkiaPerfPoint extends MetricPoint { - SkiaPerfPoint._( - this.githubRepo, this.gitHash, this.testName, this.subResult, double value, this._options, this.jsonUrl) + SkiaPerfPoint._(this.githubRepo, this.gitHash, this.testName, this.subResult, + double value, this._options, this.jsonUrl) : assert(_options[kGithubRepoKey] == null), assert(_options[kGitRevisionKey] == null), assert(_options[kNameKey] == null), @@ -104,7 +104,8 @@ class SkiaPerfPoint extends MetricPoint { ), ); - return SkiaPerfPoint._(githubRepo, gitHash, name, subResult, p.value, options, null); + return SkiaPerfPoint._( + githubRepo, gitHash, name, subResult, p.value, options, null); } /// In the format of '/' such as 'flutter/flutter' or @@ -154,7 +155,8 @@ class SkiaPerfPoint extends MetricPoint { assert(points.isNotEmpty); assert(() { for (final SkiaPerfPoint p in points) { - if (p.githubRepo != points[0].githubRepo || p.gitHash != points[0].gitHash) { + if (p.githubRepo != points[0].githubRepo || + p.gitHash != points[0].gitHash) { return false; } } @@ -173,9 +175,11 @@ class SkiaPerfPoint extends MetricPoint { // options/configurations. If this actually happens in the future, we // probably can use different values of config (currently there's only // one kSkiaPerfDefaultConfig) to resolve the conflict. - assert(results[p.testName][kSkiaPerfDefaultConfig][kSkiaPerfOptionsKey].toString() == + assert(results[p.testName][kSkiaPerfDefaultConfig][kSkiaPerfOptionsKey] + .toString() == subResultJson[kSkiaPerfOptionsKey].toString()); - assert(results[p.testName][kSkiaPerfDefaultConfig][p.subResult] == null); + assert( + results[p.testName][kSkiaPerfDefaultConfig][p.subResult] == null); results[p.testName][kSkiaPerfDefaultConfig][p.subResult] = p.value; } } @@ -208,7 +212,8 @@ class SkiaPerfGcsAdaptor { /// /// The read may retry multiple times if transient network errors with code /// 504 happens. - Future writePoints(String objectName, List points) async { + Future writePoints( + String objectName, List points) async { final String jsonString = jsonEncode(SkiaPerfPoint.toSkiaPerfJson(points)); final List content = utf8.encode(jsonString); @@ -269,7 +274,9 @@ class SkiaPerfGcsAdaptor { final Stream> stream = _gcsBucket.read(objectName); final Stream byteStream = stream.expand((List x) => x); - final Map decodedJson = jsonDecode(utf8.decode(await byteStream.toList())) as Map; + final Map decodedJson = + jsonDecode(utf8.decode(await byteStream.toList())) + as Map; final List points = []; @@ -279,17 +286,21 @@ class SkiaPerfGcsAdaptor { assert(githubRepo != null); final String gitHash = decodedJson[kSkiaPerfGitHashKey] as String; - final Map results = decodedJson[kSkiaPerfResultsKey] as Map; + final Map results = + decodedJson[kSkiaPerfResultsKey] as Map; for (final String name in results.keys) { - final Map subResultMap = results[name][kSkiaPerfDefaultConfig] as Map; - for (final String subResult in subResultMap.keys.where((String s) => s != kSkiaPerfOptionsKey)) { + final Map subResultMap = + results[name][kSkiaPerfDefaultConfig] as Map; + for (final String subResult + in subResultMap.keys.where((String s) => s != kSkiaPerfOptionsKey)) { points.add(SkiaPerfPoint._( githubRepo, gitHash, name, subResult, subResultMap[subResult] as double, - (subResultMap[kSkiaPerfOptionsKey] as Map).cast(), + (subResultMap[kSkiaPerfOptionsKey] as Map) + .cast(), info.downloadLink.toString(), )); } @@ -305,7 +316,8 @@ class SkiaPerfGcsAdaptor { /// 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 computeObjectName(String githubRepo, String revision, DateTime commitTime) async { + static Future computeObjectName( + String githubRepo, String revision, DateTime commitTime) async { assert(_githubRepoToGcsName[githubRepo] != null); final String topComponent = _githubRepoToGcsName[githubRepo]; final String month = commitTime.month.toString().padLeft(2, '0'); @@ -340,10 +352,11 @@ class SkiaPerfDestination extends MetricDestination { SkiaPerfDestination(this._gcs, this._lock); /// Create from a full credentials json (of a service account). - static Future makeFromGcpCredentials(Map credentialsJson, + static Future makeFromGcpCredentials( + Map credentialsJson, {bool isTesting = false}) async { - final AutoRefreshingAuthClient client = - await clientViaServiceAccount(ServiceAccountCredentials.fromJson(credentialsJson), Storage.SCOPES); + final AutoRefreshingAuthClient client = await clientViaServiceAccount( + ServiceAccountCredentials.fromJson(credentialsJson), Storage.SCOPES); return make( client, credentialsJson[kProjectId] as String, @@ -352,7 +365,8 @@ class SkiaPerfDestination extends MetricDestination { } /// Create from an access token and its project id. - static Future makeFromAccessToken(String token, String projectId, + static Future makeFromAccessToken( + String token, String projectId, {bool isTesting = false}) async { final AuthClient client = authClientFromAccessToken(token, Storage.SCOPES); return make(client, projectId, isTesting: isTesting); @@ -361,13 +375,15 @@ class SkiaPerfDestination extends MetricDestination { /// Create from an [AuthClient] and a GCP project id. /// /// [AuthClient] can be obtained from functions like `clientViaUserConsent`. - static Future make(AuthClient client, String projectId, {bool isTesting = false}) async { + static Future make(AuthClient client, String projectId, + {bool isTesting = false}) async { final Storage storage = Storage(client, projectId); final String bucketName = isTesting ? kTestBucketName : kBucketName; if (!await storage.bucketExists(bucketName)) { throw 'Bucket $bucketName does not exist.'; } - final SkiaPerfGcsAdaptor adaptor = SkiaPerfGcsAdaptor(storage.bucket(bucketName)); + final SkiaPerfGcsAdaptor adaptor = + SkiaPerfGcsAdaptor(storage.bucket(bucketName)); final GcsLock lock = GcsLock(client, bucketName); return SkiaPerfDestination(adaptor, lock); } @@ -379,7 +395,8 @@ class SkiaPerfDestination extends MetricDestination { // name. final Map>> pointMap = >>{}; - for (final SkiaPerfPoint p in points.map((MetricPoint x) => SkiaPerfPoint.fromPoint(x))) { + for (final SkiaPerfPoint p + in points.map((MetricPoint x) => SkiaPerfPoint.fromPoint(x))) { if (p != null) { pointMap[p.githubRepo] ??= >{}; pointMap[p.githubRepo][p.gitHash] ??= {}; @@ -390,7 +407,8 @@ class SkiaPerfDestination extends MetricDestination { // 2nd, read existing points from the gcs object and update with new ones. for (final String repo in pointMap.keys) { for (final String revision in pointMap[repo].keys) { - final String objectName = await SkiaPerfGcsAdaptor.computeObjectName(repo, revision, commitTime); + final String objectName = await SkiaPerfGcsAdaptor.computeObjectName( + repo, revision, commitTime); final Map 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 @@ -399,7 +417,8 @@ class SkiaPerfDestination extends MetricDestination { // json files in the directory so one can use arbitrary names for those // sharded json file names. _lock.protectedRun('$objectName.lock', () async { - final List oldPoints = await _gcs.readPoints(objectName); + final List oldPoints = + await _gcs.readPoints(objectName); for (final SkiaPerfPoint p in oldPoints) { if (newPoints[p.id] == null) { newPoints[p.id] = p; diff --git a/packages/metrics_center/test/flutter_test.dart b/packages/metrics_center/test/flutter_test.dart index 2b6263bc44e6..277e400b86c9 100644 --- a/packages/metrics_center/test/flutter_test.dart +++ b/packages/metrics_center/test/flutter_test.dart @@ -41,7 +41,10 @@ void main() { final Map credentialsJson = getTestGcpCredentialsJson(); test('FlutterDestination integration test with update.', () async { - final FlutterDestination dst = await FlutterDestination.makeFromCredentialsJson(credentialsJson, isTesting: true); - dst.update([simplePoint], DateTime.fromMillisecondsSinceEpoch(123)); + final FlutterDestination dst = + await FlutterDestination.makeFromCredentialsJson(credentialsJson, + isTesting: true); + dst.update([simplePoint], + DateTime.fromMillisecondsSinceEpoch(123)); }, skip: credentialsJson == null); } diff --git a/packages/metrics_center/test/gcs_lock_test.dart b/packages/metrics_center/test/gcs_lock_test.dart index 03661ff5cfdc..d682d950c2d1 100644 --- a/packages/metrics_center/test/gcs_lock_test.dart +++ b/packages/metrics_center/test/gcs_lock_test.dart @@ -29,14 +29,16 @@ void main() { test('GcsLock prints warnings for long waits', () { // Capture print to verify error messages. final List prints = []; - final ZoneSpecification spec = ZoneSpecification(print: (_, __, ___, String msg) => prints.add(msg)); + final ZoneSpecification spec = + ZoneSpecification(print: (_, __, ___, String msg) => prints.add(msg)); Zone.current.fork(specification: spec).run(() { fakeAsync((FakeAsync fakeAsync) { final MockClient mockClient = MockClient(); final GcsLock lock = GcsLock(mockClient, 'mockBucket'); when(mockClient.send(any)).thenThrow(DetailedApiRequestError(412, '')); - final Future runFinished = lock.protectedRun('mock.lock', () async {}); + final Future runFinished = + lock.protectedRun('mock.lock', () async {}); fakeAsync.elapse(const Duration(seconds: 10)); when(mockClient.send(any)).thenThrow(AssertionError('Stop!')); runFinished.catchError((dynamic e) { @@ -56,8 +58,8 @@ void main() { }); test('GcsLock integration test: single protectedRun is successful', () async { - final AutoRefreshingAuthClient client = - await clientViaServiceAccount(ServiceAccountCredentials.fromJson(credentialsJson), Storage.SCOPES); + final AutoRefreshingAuthClient client = await clientViaServiceAccount( + ServiceAccountCredentials.fromJson(credentialsJson), Storage.SCOPES); final GcsLock lock = GcsLock(client, kTestBucketName); int testValue = 0; await lock.protectedRun('test.lock', () async { @@ -67,8 +69,8 @@ void main() { }, skip: credentialsJson == null); test('GcsLock integration test: protectedRun is exclusive', () async { - final AutoRefreshingAuthClient client = - await clientViaServiceAccount(ServiceAccountCredentials.fromJson(credentialsJson), Storage.SCOPES); + final AutoRefreshingAuthClient client = await clientViaServiceAccount( + ServiceAccountCredentials.fromJson(credentialsJson), Storage.SCOPES); final GcsLock lock1 = GcsLock(client, kTestBucketName); final GcsLock lock2 = GcsLock(client, kTestBucketName); diff --git a/packages/metrics_center/test/google_benchmark_test.dart b/packages/metrics_center/test/google_benchmark_test.dart index 5c7c9bcfc2c9..11883ae331c3 100644 --- a/packages/metrics_center/test/google_benchmark_test.dart +++ b/packages/metrics_center/test/google_benchmark_test.dart @@ -11,7 +11,8 @@ import 'utility.dart'; void main() { test('GoogleBenchmarkParser parses example json.', () async { - final List points = await GoogleBenchmarkParser.parse('test/example_google_benchmark.json'); + final List points = + await GoogleBenchmarkParser.parse('test/example_google_benchmark.json'); expect(points.length, 6); expectSetMatch( points.map((MetricPoint p) => p.value), diff --git a/packages/metrics_center/test/skiaperf_test.dart b/packages/metrics_center/test/skiaperf_test.dart index b1000bfaab86..34abacfde5e9 100644 --- a/packages/metrics_center/test/skiaperf_test.dart +++ b/packages/metrics_center/test/skiaperf_test.dart @@ -24,7 +24,8 @@ class MockObjectInfo extends Mock implements ObjectInfo {} class MockGcsLock implements GcsLock { @override - Future protectedRun(String exclusiveObjectName, Future Function() f) async { + Future protectedRun( + String exclusiveObjectName, Future Function() f) async { await f(); } } @@ -36,12 +37,14 @@ class MockSkiaPerfGcsAdaptor implements SkiaPerfGcsAdaptor { } @override - Future writePoints(String objectName, List points) async { + Future writePoints( + String objectName, List points) async { _storage[objectName] = points.toList(); } // Map from the object name to the list of SkiaPoint that mocks the GCS. - final Map> _storage = >{}; + final Map> _storage = + >{}; } Future main() async { @@ -180,12 +183,14 @@ Future main() async { ); expect(() => SkiaPerfPoint.fromPoint(noGithubRepoPoint), throwsA(anything)); - expect(() => SkiaPerfPoint.fromPoint(noGitRevisionPoint), throwsA(anything)); + expect( + () => SkiaPerfPoint.fromPoint(noGitRevisionPoint), throwsA(anything)); expect(() => SkiaPerfPoint.fromPoint(noTestNamePoint), throwsA(anything)); }); test('Correctly convert a metric point from cocoon to SkiaPoint', () { - final SkiaPerfPoint skiaPoint1 = SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1); + final SkiaPerfPoint skiaPoint1 = + SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1); expect(skiaPoint1, isNotNull); expect(skiaPoint1.testName, equals(kTaskName)); expect(skiaPoint1.subResult, equals(kMetric1)); @@ -196,11 +201,15 @@ Future main() async { test('Cocoon points correctly encode into Skia perf json format', () { final SkiaPerfPoint p1 = SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1); final SkiaPerfPoint p2 = SkiaPerfPoint.fromPoint(cocoonPointRev1Metric2); - final SkiaPerfPoint p3 = SkiaPerfPoint.fromPoint(cocoonPointBetaRev1Metric1); + final SkiaPerfPoint p3 = + SkiaPerfPoint.fromPoint(cocoonPointBetaRev1Metric1); const JsonEncoder encoder = JsonEncoder.withIndent(' '); - expect(encoder.convert(SkiaPerfPoint.toSkiaPerfJson([p1, p2, p3])), equals(''' + expect( + encoder + .convert(SkiaPerfPoint.toSkiaPerfJson([p1, p2, p3])), + equals(''' { "gitHash": "9011cece2595447eea5dd91adaa241c1c9ef9a33", "results": { @@ -295,7 +304,8 @@ Future main() async { 'Throw if two Cocoon metric points with the same name and subResult keys ' 'but different options are converted to Skia perf points', () { final SkiaPerfPoint p1 = SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1); - final SkiaPerfPoint p2 = SkiaPerfPoint.fromPoint(cocoonPointBetaRev1Metric1BadBranch); + final SkiaPerfPoint p2 = + SkiaPerfPoint.fromPoint(cocoonPointBetaRev1Metric1BadBranch); expect( () => SkiaPerfPoint.toSkiaPerfJson([p1, p2]), @@ -335,24 +345,32 @@ Future main() async { final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket); final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123)); + kFlutterFrameworkRepo, + kFrameworkRevision1, + DateTime.fromMillisecondsSinceEpoch(123)); final List writePoints = [ SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1), ]; - final String skiaPerfJson = jsonEncode(SkiaPerfPoint.toSkiaPerfJson(writePoints)); + final String skiaPerfJson = + jsonEncode(SkiaPerfPoint.toSkiaPerfJson(writePoints)); await skiaPerfGcs.writePoints(testObjectName, writePoints); verify(testBucket.writeBytes(testObjectName, utf8.encode(skiaPerfJson))); // Emulate the first network request to fail with 504. - when(testBucket.info(testObjectName)).thenThrow(DetailedApiRequestError(504, 'Test Failure')); + when(testBucket.info(testObjectName)) + .thenThrow(DetailedApiRequestError(504, 'Test Failure')); final MockObjectInfo mockObjectInfo = MockObjectInfo(); - when(mockObjectInfo.downloadLink).thenReturn(Uri.https('test.com', 'mock.json')); - when(testBucket.info(testObjectName)).thenAnswer((_) => Future.value(mockObjectInfo)); - when(testBucket.read(testObjectName)).thenAnswer((_) => Stream>.value(utf8.encode(skiaPerfJson))); - - final List readPoints = await skiaPerfGcs.readPoints(testObjectName); + when(mockObjectInfo.downloadLink) + .thenReturn(Uri.https('test.com', 'mock.json')); + when(testBucket.info(testObjectName)) + .thenAnswer((_) => Future.value(mockObjectInfo)); + when(testBucket.read(testObjectName)) + .thenAnswer((_) => Stream>.value(utf8.encode(skiaPerfJson))); + + final List readPoints = + await skiaPerfGcs.readPoints(testObjectName); expect(readPoints.length, equals(1)); expect(readPoints[0].testName, kTaskName); expect(readPoints[0].subResult, kMetric1); @@ -366,8 +384,11 @@ Future main() async { final MockBucket testBucket = MockBucket(); final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket); final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123)); - when(testBucket.info(testObjectName)).thenThrow(Exception('No such object')); + kFlutterFrameworkRepo, + kFrameworkRevision1, + DateTime.fromMillisecondsSinceEpoch(123)); + when(testBucket.info(testObjectName)) + .thenThrow(Exception('No such object')); expect((await skiaPerfGcs.readPoints(testObjectName)).length, 0); }); @@ -376,10 +397,13 @@ Future main() async { GcsLock testLock; final Map credentialsJson = getTestGcpCredentialsJson(); if (credentialsJson != null) { - final ServiceAccountCredentials credentials = ServiceAccountCredentials.fromJson(credentialsJson); + final ServiceAccountCredentials credentials = + ServiceAccountCredentials.fromJson(credentialsJson); - final AutoRefreshingAuthClient client = await clientViaServiceAccount(credentials, Storage.SCOPES); - final Storage storage = Storage(client, credentialsJson['project_id'] as String); + final AutoRefreshingAuthClient client = + await clientViaServiceAccount(credentials, Storage.SCOPES); + final Storage storage = + Storage(client, credentialsJson['project_id'] as String); const String kTestBucketName = 'flutter-skia-perf-test'; @@ -392,20 +416,28 @@ Future main() async { final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket); final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123)); + kFlutterFrameworkRepo, + kFrameworkRevision1, + DateTime.fromMillisecondsSinceEpoch(123)); await skiaPerfGcs.writePoints(testObjectName, [ SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1), SkiaPerfPoint.fromPoint(cocoonPointRev1Metric2), ]); - final List points = await skiaPerfGcs.readPoints(testObjectName); + final List points = + await skiaPerfGcs.readPoints(testObjectName); expect(points.length, equals(2)); - expectSetMatch(points.map((SkiaPerfPoint p) => p.testName), [kTaskName]); - expectSetMatch(points.map((SkiaPerfPoint p) => p.subResult), [kMetric1, kMetric2]); - expectSetMatch(points.map((SkiaPerfPoint p) => p.value), [kValue1, kValue2]); - expectSetMatch(points.map((SkiaPerfPoint p) => p.githubRepo), [kFlutterFrameworkRepo]); - expectSetMatch(points.map((SkiaPerfPoint p) => p.gitHash), [kFrameworkRevision1]); + expectSetMatch( + points.map((SkiaPerfPoint p) => p.testName), [kTaskName]); + expectSetMatch(points.map((SkiaPerfPoint p) => p.subResult), + [kMetric1, kMetric2]); + expectSetMatch( + points.map((SkiaPerfPoint p) => p.value), [kValue1, kValue2]); + expectSetMatch(points.map((SkiaPerfPoint p) => p.githubRepo), + [kFlutterFrameworkRepo]); + expectSetMatch(points.map((SkiaPerfPoint p) => p.gitHash), + [kFrameworkRevision1]); for (int i = 0; i < 2; i += 1) { expect(points[0].jsonUrl, startsWith('https://')); } @@ -415,14 +447,17 @@ Future main() async { final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket); final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterEngineRepo, engineRevision, DateTime.fromMillisecondsSinceEpoch(123)); + kFlutterEngineRepo, + engineRevision, + DateTime.fromMillisecondsSinceEpoch(123)); await skiaPerfGcs.writePoints(testObjectName, [ SkiaPerfPoint.fromPoint(enginePoint1), SkiaPerfPoint.fromPoint(enginePoint2), ]); - final List points = await skiaPerfGcs.readPoints(testObjectName); + final List points = + await skiaPerfGcs.readPoints(testObjectName); expect(points.length, equals(2)); expectSetMatch( points.map((SkiaPerfPoint p) => p.testName), @@ -436,7 +471,8 @@ Future main() async { points.map((SkiaPerfPoint p) => p.githubRepo), [kFlutterEngineRepo], ); - expectSetMatch(points.map((SkiaPerfPoint p) => p.gitHash), [engineRevision]); + expectSetMatch( + points.map((SkiaPerfPoint p) => p.gitHash), [engineRevision]); for (int i = 0; i < 2; i += 1) { expect(points[0].jsonUrl, startsWith('https://')); } @@ -470,7 +506,8 @@ Future main() async { kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(1575529660000), ), - equals('flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'), + equals( + 'flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'), ); expect( await SkiaPerfGcsAdaptor.computeObjectName( @@ -496,33 +533,46 @@ Future main() async { final SkiaPerfGcsAdaptor mockGcs = MockSkiaPerfGcsAdaptor(); final GcsLock mockLock = MockGcsLock(); final SkiaPerfDestination dst = SkiaPerfDestination(mockGcs, mockLock); - await dst.update([cocoonPointRev1Metric1], DateTime.fromMillisecondsSinceEpoch(123)); - await dst.update([cocoonPointRev1Metric2], DateTime.fromMillisecondsSinceEpoch(123)); - List points = await mockGcs.readPoints(await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterFrameworkRepo, kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123))); + await dst.update([cocoonPointRev1Metric1], + DateTime.fromMillisecondsSinceEpoch(123)); + await dst.update([cocoonPointRev1Metric2], + DateTime.fromMillisecondsSinceEpoch(123)); + List points = await mockGcs.readPoints( + await SkiaPerfGcsAdaptor.computeObjectName(kFlutterFrameworkRepo, + kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123))); expect(points.length, equals(2)); - expectSetMatch(points.map((SkiaPerfPoint p) => p.testName), [kTaskName]); - expectSetMatch(points.map((SkiaPerfPoint p) => p.subResult), [kMetric1, kMetric2]); - expectSetMatch(points.map((SkiaPerfPoint p) => p.value), [kValue1, kValue2]); + expectSetMatch( + points.map((SkiaPerfPoint p) => p.testName), [kTaskName]); + expectSetMatch(points.map((SkiaPerfPoint p) => p.subResult), + [kMetric1, kMetric2]); + expectSetMatch( + points.map((SkiaPerfPoint p) => p.value), [kValue1, kValue2]); - final MetricPoint updated = MetricPoint(kValue3, cocoonPointRev1Metric1.tags); + final MetricPoint updated = + MetricPoint(kValue3, cocoonPointRev1Metric1.tags); - await dst.update([updated, cocoonPointRev2Metric1], DateTime.fromMillisecondsSinceEpoch(123)); + await dst.update([updated, cocoonPointRev2Metric1], + DateTime.fromMillisecondsSinceEpoch(123)); - points = await mockGcs.readPoints(await SkiaPerfGcsAdaptor.computeObjectName( - kFlutterFrameworkRepo, kFrameworkRevision2, DateTime.fromMillisecondsSinceEpoch(123))); + points = await mockGcs.readPoints( + await SkiaPerfGcsAdaptor.computeObjectName(kFlutterFrameworkRepo, + kFrameworkRevision2, DateTime.fromMillisecondsSinceEpoch(123))); 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))); - expectSetMatch(points.map((SkiaPerfPoint p) => p.value), [kValue2, kValue3]); + points = await mockGcs.readPoints( + await SkiaPerfGcsAdaptor.computeObjectName(kFlutterFrameworkRepo, + kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123))); + expectSetMatch( + points.map((SkiaPerfPoint p) => p.value), [kValue2, kValue3]); }); Future skiaPerfDestinationIntegrationTest() async { - final SkiaPerfDestination destination = SkiaPerfDestination(SkiaPerfGcsAdaptor(testBucket), testLock); - await destination.update([cocoonPointRev1Metric1], DateTime.fromMillisecondsSinceEpoch(123)); + final SkiaPerfDestination destination = + SkiaPerfDestination(SkiaPerfGcsAdaptor(testBucket), testLock); + await destination.update([cocoonPointRev1Metric1], + DateTime.fromMillisecondsSinceEpoch(123)); } test( diff --git a/packages/metrics_center/test/utility.dart b/packages/metrics_center/test/utility.dart index 8fabf18ac74b..6dacd48b0aff 100644 --- a/packages/metrics_center/test/utility.dart +++ b/packages/metrics_center/test/utility.dart @@ -18,5 +18,6 @@ Map getTestGcpCredentialsJson() { if (!f.existsSync()) { return null; } - return jsonDecode(File('secret/test_gcp_credentials.json').readAsStringSync()) as Map; + return jsonDecode(File('secret/test_gcp_credentials.json').readAsStringSync()) + as Map; } From 5c583eb0eb794ad11713259d98159aa46e4e330e Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Fri, 9 Apr 2021 11:15:40 -0700 Subject: [PATCH 07/10] use utc time of commit timestamp --- packages/metrics_center/lib/src/skiaperf.dart | 7 ++++--- packages/metrics_center/test/skiaperf_test.dart | 12 ++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/metrics_center/lib/src/skiaperf.dart b/packages/metrics_center/lib/src/skiaperf.dart index ac6c89cc6da9..8d4d50bf8b8b 100644 --- a/packages/metrics_center/lib/src/skiaperf.dart +++ b/packages/metrics_center/lib/src/skiaperf.dart @@ -320,9 +320,10 @@ class SkiaPerfGcsAdaptor { String githubRepo, String revision, DateTime commitTime) async { assert(_githubRepoToGcsName[githubRepo] != null); final String topComponent = _githubRepoToGcsName[githubRepo]; - final String month = commitTime.month.toString().padLeft(2, '0'); - final String day = commitTime.day.toString().padLeft(2, '0'); - final String hour = commitTime.hour.toString().padLeft(2, '0'); + final DateTime commitTimeUtc = commitTime.toUtc(); + final String month = commitTimeUtc.month.toString().padLeft(2, '0'); + final String day = commitTimeUtc.day.toString().padLeft(2, '0'); + final String hour = commitTimeUtc.hour.toString().padLeft(2, '0'); final String dateComponents = '${commitTime.year}/$month/$day/$hour'; return '$topComponent/$dateComponents/$revision/values.json'; } diff --git a/packages/metrics_center/test/skiaperf_test.dart b/packages/metrics_center/test/skiaperf_test.dart index 34abacfde5e9..29e9d3c33918 100644 --- a/packages/metrics_center/test/skiaperf_test.dart +++ b/packages/metrics_center/test/skiaperf_test.dart @@ -320,7 +320,7 @@ Future main() async { kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(1575529660000), ), - equals('flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'), + equals('flutter-flutter/2019/12/05/07/$kFrameworkRevision1/values.json'), ); expect( await SkiaPerfGcsAdaptor.computeObjectName( @@ -328,7 +328,7 @@ Future main() async { kEngineRevision1, DateTime.fromMillisecondsSinceEpoch(1575432460000), ), - equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'), + equals('flutter-engine/2019/12/04/04/$kEngineRevision1/values.json'), ); expect( await SkiaPerfGcsAdaptor.computeObjectName( @@ -336,7 +336,7 @@ Future main() async { kEngineRevision2, DateTime.fromMillisecondsSinceEpoch(1578092860000), ), - equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'), + equals('flutter-engine/2020/01/03/23/$kEngineRevision2/values.json'), ); }); @@ -507,7 +507,7 @@ Future main() async { DateTime.fromMillisecondsSinceEpoch(1575529660000), ), equals( - 'flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'), + 'flutter-flutter/2019/12/05/07/$kFrameworkRevision1/values.json'), ); expect( await SkiaPerfGcsAdaptor.computeObjectName( @@ -515,7 +515,7 @@ Future main() async { kEngineRevision1, DateTime.fromMillisecondsSinceEpoch(1575432460000), ), - equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'), + equals('flutter-engine/2019/12/04/04/$kEngineRevision1/values.json'), ); expect( await SkiaPerfGcsAdaptor.computeObjectName( @@ -523,7 +523,7 @@ Future main() async { kEngineRevision2, DateTime.fromMillisecondsSinceEpoch(1578092860000), ), - equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'), + equals('flutter-engine/2020/01/03/23/$kEngineRevision2/values.json'), ); }, skip: testBucket == null, From ef8cdca1486d1c8bd432161596ae2840a8c11616 Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Fri, 9 Apr 2021 14:38:05 -0700 Subject: [PATCH 08/10] remove utc --- packages/metrics_center/lib/src/skiaperf.dart | 7 +++--- .../metrics_center/test/skiaperf_test.dart | 24 +++++++++---------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/packages/metrics_center/lib/src/skiaperf.dart b/packages/metrics_center/lib/src/skiaperf.dart index 8d4d50bf8b8b..ac6c89cc6da9 100644 --- a/packages/metrics_center/lib/src/skiaperf.dart +++ b/packages/metrics_center/lib/src/skiaperf.dart @@ -320,10 +320,9 @@ class SkiaPerfGcsAdaptor { String githubRepo, String revision, DateTime commitTime) async { assert(_githubRepoToGcsName[githubRepo] != null); final String topComponent = _githubRepoToGcsName[githubRepo]; - final DateTime commitTimeUtc = commitTime.toUtc(); - final String month = commitTimeUtc.month.toString().padLeft(2, '0'); - final String day = commitTimeUtc.day.toString().padLeft(2, '0'); - final String hour = commitTimeUtc.hour.toString().padLeft(2, '0'); + final String month = commitTime.month.toString().padLeft(2, '0'); + final String day = commitTime.day.toString().padLeft(2, '0'); + final String hour = commitTime.hour.toString().padLeft(2, '0'); final String dateComponents = '${commitTime.year}/$month/$day/$hour'; return '$topComponent/$dateComponents/$revision/values.json'; } diff --git a/packages/metrics_center/test/skiaperf_test.dart b/packages/metrics_center/test/skiaperf_test.dart index 29e9d3c33918..2e40405bc7dc 100644 --- a/packages/metrics_center/test/skiaperf_test.dart +++ b/packages/metrics_center/test/skiaperf_test.dart @@ -318,25 +318,25 @@ Future main() async { await SkiaPerfGcsAdaptor.computeObjectName( kFlutterFrameworkRepo, kFrameworkRevision1, - DateTime.fromMillisecondsSinceEpoch(1575529660000), + DateTime(2019, 12, 04, 23), ), - equals('flutter-flutter/2019/12/05/07/$kFrameworkRevision1/values.json'), + equals('flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'), ); expect( await SkiaPerfGcsAdaptor.computeObjectName( kFlutterEngineRepo, kEngineRevision1, - DateTime.fromMillisecondsSinceEpoch(1575432460000), + DateTime(2019, 12, 03, 20), ), - equals('flutter-engine/2019/12/04/04/$kEngineRevision1/values.json'), + equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'), ); expect( await SkiaPerfGcsAdaptor.computeObjectName( kFlutterEngineRepo, kEngineRevision2, - DateTime.fromMillisecondsSinceEpoch(1578092860000), + DateTime(2020, 01, 03, 15), ), - equals('flutter-engine/2020/01/03/23/$kEngineRevision2/values.json'), + equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'), ); }); @@ -504,26 +504,26 @@ Future main() async { await SkiaPerfGcsAdaptor.computeObjectName( kFlutterFrameworkRepo, kFrameworkRevision1, - DateTime.fromMillisecondsSinceEpoch(1575529660000), + DateTime(2019, 12, 04, 23), ), equals( - 'flutter-flutter/2019/12/05/07/$kFrameworkRevision1/values.json'), + 'flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'), ); expect( await SkiaPerfGcsAdaptor.computeObjectName( kFlutterEngineRepo, kEngineRevision1, - DateTime.fromMillisecondsSinceEpoch(1575432460000), + DateTime(2019, 12, 03, 20), ), - equals('flutter-engine/2019/12/04/04/$kEngineRevision1/values.json'), + equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'), ); expect( await SkiaPerfGcsAdaptor.computeObjectName( kFlutterEngineRepo, kEngineRevision2, - DateTime.fromMillisecondsSinceEpoch(1578092860000), + DateTime(2020, 01, 03, 15), ), - equals('flutter-engine/2020/01/03/23/$kEngineRevision2/values.json'), + equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'), ); }, skip: testBucket == null, From d9d1745ebc4e9a203349f1aab0f74b75aca81b25 Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Mon, 12 Apr 2021 10:10:50 -0700 Subject: [PATCH 09/10] re-add explicit utc --- packages/metrics_center/lib/src/skiaperf.dart | 11 +++++++---- packages/metrics_center/test/skiaperf_test.dart | 12 ++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/metrics_center/lib/src/skiaperf.dart b/packages/metrics_center/lib/src/skiaperf.dart index ac6c89cc6da9..fe94cf3981b5 100644 --- a/packages/metrics_center/lib/src/skiaperf.dart +++ b/packages/metrics_center/lib/src/skiaperf.dart @@ -320,10 +320,13 @@ class SkiaPerfGcsAdaptor { String githubRepo, String revision, DateTime commitTime) async { assert(_githubRepoToGcsName[githubRepo] != null); final String topComponent = _githubRepoToGcsName[githubRepo]; - final String month = commitTime.month.toString().padLeft(2, '0'); - final String day = commitTime.day.toString().padLeft(2, '0'); - final String hour = commitTime.hour.toString().padLeft(2, '0'); - final String dateComponents = '${commitTime.year}/$month/$day/$hour'; + /// [commitTime] is not guranteed to be UTC. Ensure it is so all results + /// pushed to GCS are the same timezone. + final DateTime commitUtcTime = commitTime.toUtc(); + final String month = commitUtcTime.month.toString().padLeft(2, '0'); + 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'; } diff --git a/packages/metrics_center/test/skiaperf_test.dart b/packages/metrics_center/test/skiaperf_test.dart index 2e40405bc7dc..d8157115d6d4 100644 --- a/packages/metrics_center/test/skiaperf_test.dart +++ b/packages/metrics_center/test/skiaperf_test.dart @@ -318,7 +318,7 @@ Future main() async { await SkiaPerfGcsAdaptor.computeObjectName( kFlutterFrameworkRepo, kFrameworkRevision1, - DateTime(2019, 12, 04, 23), + DateTime.utc(2019, 12, 04, 23), ), equals('flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'), ); @@ -326,7 +326,7 @@ Future main() async { await SkiaPerfGcsAdaptor.computeObjectName( kFlutterEngineRepo, kEngineRevision1, - DateTime(2019, 12, 03, 20), + DateTime.utc(2019, 12, 03, 20), ), equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'), ); @@ -334,7 +334,7 @@ Future main() async { await SkiaPerfGcsAdaptor.computeObjectName( kFlutterEngineRepo, kEngineRevision2, - DateTime(2020, 01, 03, 15), + DateTime.utc(2020, 01, 03, 15), ), equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'), ); @@ -504,7 +504,7 @@ Future main() async { await SkiaPerfGcsAdaptor.computeObjectName( kFlutterFrameworkRepo, kFrameworkRevision1, - DateTime(2019, 12, 04, 23), + DateTime.utc(2019, 12, 04, 23), ), equals( 'flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'), @@ -513,7 +513,7 @@ Future main() async { await SkiaPerfGcsAdaptor.computeObjectName( kFlutterEngineRepo, kEngineRevision1, - DateTime(2019, 12, 03, 20), + DateTime.utc(2019, 12, 03, 20), ), equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'), ); @@ -521,7 +521,7 @@ Future main() async { await SkiaPerfGcsAdaptor.computeObjectName( kFlutterEngineRepo, kEngineRevision2, - DateTime(2020, 01, 03, 15), + DateTime.utc(2020, 01, 03, 15), ), equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'), ); From 46e4c891f8e1b63554f2a7b57d40d4b830f1ea17 Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Mon, 12 Apr 2021 10:32:21 -0700 Subject: [PATCH 10/10] format --- packages/metrics_center/lib/src/skiaperf.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/metrics_center/lib/src/skiaperf.dart b/packages/metrics_center/lib/src/skiaperf.dart index fe94cf3981b5..2a9c4bdba888 100644 --- a/packages/metrics_center/lib/src/skiaperf.dart +++ b/packages/metrics_center/lib/src/skiaperf.dart @@ -320,8 +320,8 @@ class SkiaPerfGcsAdaptor { String githubRepo, String revision, DateTime commitTime) async { assert(_githubRepoToGcsName[githubRepo] != null); final String topComponent = _githubRepoToGcsName[githubRepo]; - /// [commitTime] is not guranteed to be UTC. Ensure it is so all results - /// pushed to GCS are the same timezone. + // [commitTime] is not guranteed to be UTC. Ensure it is so all results + // pushed to GCS are the same timezone. final DateTime commitUtcTime = commitTime.toUtc(); final String month = commitUtcTime.month.toString().padLeft(2, '0'); final String day = commitUtcTime.day.toString().padLeft(2, '0');