[metrics_center] Remove github dependency (#323)

This commit is contained in:
Casey Hillers
2021-04-13 16:24:03 -07:00
committed by GitHub
parent 2307dda0c3
commit ed4ec6fa83
9 changed files with 68 additions and 126 deletions

View File

@ -1,13 +1,22 @@
# 0.1.0
- `update` now requires DateTime when commit was merged
- Removed `github` dependency
# 0.0.9 # 0.0.9
- Remove legacy datastore and destination. - Remove legacy datastore and destination.
# 0.0.8 # 0.0.8
- Allow tests to override LegacyFlutterDestination GCP project id. - Allow tests to override LegacyFlutterDestination GCP project id.
# 0.0.7 # 0.0.7
- Expose constants that were missing since 0.0.4+1. - Expose constants that were missing since 0.0.4+1.
# 0.0.6 # 0.0.6
- Allow `datastoreFromCredentialsJson` to specify project id. - Allow `datastoreFromCredentialsJson` to specify project id.
# 0.0.5 # 0.0.5

View File

@ -50,7 +50,7 @@ class MetricPoint extends Equatable {
/// Interface to write [MetricPoint]. /// Interface to write [MetricPoint].
abstract class MetricDestination { abstract class MetricDestination {
/// Insert new data points or modify old ones with matching id. /// Insert new data points or modify old ones with matching id.
Future<void> update(List<MetricPoint> points); Future<void> update(List<MetricPoint> points, DateTime commitTime);
} }
/// Create `AuthClient` in case we only have an access token without the full /// Create `AuthClient` in case we only have an access token without the full

View File

@ -52,8 +52,8 @@ class FlutterDestination extends MetricDestination {
} }
@override @override
Future<void> update(List<MetricPoint> points) async { Future<void> update(List<MetricPoint> points, DateTime commitTime) async {
await _skiaPerfDestination.update(points); await _skiaPerfDestination.update(points, commitTime);
} }
final SkiaPerfDestination _skiaPerfDestination; final SkiaPerfDestination _skiaPerfDestination;

View File

@ -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<DateTime> 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<String, DateTime> _commitDateTimeCache = <String, DateTime>{};
}

View File

@ -12,7 +12,6 @@ import 'package:googleapis_auth/auth_io.dart';
import 'common.dart'; import 'common.dart';
import 'constants.dart'; import 'constants.dart';
import 'gcs_lock.dart'; import 'gcs_lock.dart';
import 'github_helper.dart';
/// A [MetricPoint] modeled after the format that Skia Perf expects. /// A [MetricPoint] modeled after the format that Skia Perf expects.
/// ///
@ -317,16 +316,17 @@ class SkiaPerfGcsAdaptor {
/// json files can be put in that leaf directory. We intend to use 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 /// json files in the future to scale up the system if too many writes are
/// competing for the same json file. /// competing for the same json file.
static Future<String> computeObjectName(String githubRepo, String revision, static Future<String> computeObjectName(
{GithubHelper githubHelper}) async { String githubRepo, String revision, DateTime commitTime) async {
assert(_githubRepoToGcsName[githubRepo] != null); assert(_githubRepoToGcsName[githubRepo] != null);
final String topComponent = _githubRepoToGcsName[githubRepo]; final String topComponent = _githubRepoToGcsName[githubRepo];
final DateTime t = await (githubHelper ?? GithubHelper()) // [commitTime] is not guranteed to be UTC. Ensure it is so all results
.getCommitDateTime(githubRepo, revision); // pushed to GCS are the same timezone.
final String month = t.month.toString().padLeft(2, '0'); final DateTime commitUtcTime = commitTime.toUtc();
final String day = t.day.toString().padLeft(2, '0'); final String month = commitUtcTime.month.toString().padLeft(2, '0');
final String hour = t.hour.toString().padLeft(2, '0'); final String day = commitUtcTime.day.toString().padLeft(2, '0');
final String dateComponents = '${t.year}/$month/$day/$hour'; 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/values.json';
} }
@ -392,7 +392,7 @@ class SkiaPerfDestination extends MetricDestination {
} }
@override @override
Future<void> update(List<MetricPoint> points) async { Future<void> update(List<MetricPoint> points, DateTime commitTime) async {
// 1st, create a map based on git repo, git revision, and point id. Git repo // 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 // and git revision are the top level components of the Skia perf GCS object
// name. // name.
@ -410,8 +410,8 @@ class SkiaPerfDestination extends MetricDestination {
// 2nd, read existing points from the gcs object and update with new ones. // 2nd, read existing points from the gcs object and update with new ones.
for (final String repo in pointMap.keys) { for (final String repo in pointMap.keys) {
for (final String revision in pointMap[repo].keys) { for (final String revision in pointMap[repo].keys) {
final String objectName = final String objectName = await SkiaPerfGcsAdaptor.computeObjectName(
await SkiaPerfGcsAdaptor.computeObjectName(repo, revision); repo, revision, commitTime);
final Map<String, SkiaPerfPoint> newPoints = pointMap[repo][revision]; final Map<String, SkiaPerfPoint> newPoints = pointMap[repo][revision];
// If too many bots are writing the metrics of a git revision into this // 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 // single json file (with name `objectName`), the contention on the lock

View File

@ -1,5 +1,5 @@
name: metrics_center name: metrics_center
version: 0.0.9 version: 0.1.0
description: description:
Support multiple performance metrics sources/formats and destinations. Support multiple performance metrics sources/formats and destinations.
homepage: homepage:
@ -9,11 +9,9 @@ environment:
sdk: '>=2.10.0 <3.0.0' sdk: '>=2.10.0 <3.0.0'
dependencies: dependencies:
args: ^1.6.0
crypto: ^2.1.5 crypto: ^2.1.5
equatable: ^1.2.5 equatable: ^1.2.5
gcloud: ^0.7.3 gcloud: ^0.7.3
github: ^7.0.4
googleapis: ^0.56.1 googleapis: ^0.56.1
googleapis_auth: ^0.2.12 googleapis_auth: ^0.2.12
http: ^0.12.2 http: ^0.12.2

View File

@ -44,6 +44,7 @@ void main() {
final FlutterDestination dst = final FlutterDestination dst =
await FlutterDestination.makeFromCredentialsJson(credentialsJson, await FlutterDestination.makeFromCredentialsJson(credentialsJson,
isTesting: true); isTesting: true);
dst.update(<FlutterEngineMetricPoint>[simplePoint]); dst.update(<FlutterEngineMetricPoint>[simplePoint],
DateTime.fromMillisecondsSinceEpoch(123));
}, skip: credentialsJson == null); }, skip: credentialsJson == null);
} }

View File

@ -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)));
});
}

View File

@ -13,7 +13,6 @@ import 'package:metrics_center/metrics_center.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:metrics_center/src/constants.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 'package:metrics_center/src/gcs_lock.dart';
import 'common.dart'; import 'common.dart';
@ -23,8 +22,6 @@ class MockBucket extends Mock implements Bucket {}
class MockObjectInfo extends Mock implements ObjectInfo {} class MockObjectInfo extends Mock implements ObjectInfo {}
class MockGithubHelper extends Mock implements GithubHelper {}
class MockGcsLock implements GcsLock { class MockGcsLock implements GcsLock {
@override @override
Future<void> protectedRun( Future<void> protectedRun(
@ -317,35 +314,27 @@ Future<void> main() async {
}); });
test('SkiaPerfGcsAdaptor computes name correctly', () async { test('SkiaPerfGcsAdaptor computes name correctly', () async {
final MockGithubHelper mockHelper = MockGithubHelper();
when(mockHelper.getCommitDateTime(
kFlutterFrameworkRepo, kFrameworkRevision1))
.thenAnswer((_) => Future<DateTime>.value(DateTime(2019, 12, 4, 23)));
expect( expect(
await SkiaPerfGcsAdaptor.computeObjectName( await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterFrameworkRepo, kFlutterFrameworkRepo,
kFrameworkRevision1, kFrameworkRevision1,
githubHelper: mockHelper, DateTime.utc(2019, 12, 04, 23),
), ),
equals('flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'), equals('flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'),
); );
when(mockHelper.getCommitDateTime(kFlutterEngineRepo, kEngineRevision1))
.thenAnswer((_) => Future<DateTime>.value(DateTime(2019, 12, 3, 20)));
expect( expect(
await SkiaPerfGcsAdaptor.computeObjectName( await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterEngineRepo, kFlutterEngineRepo,
kEngineRevision1, kEngineRevision1,
githubHelper: mockHelper, DateTime.utc(2019, 12, 03, 20),
), ),
equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'), equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'),
); );
when(mockHelper.getCommitDateTime(kFlutterEngineRepo, kEngineRevision2))
.thenAnswer((_) => Future<DateTime>.value(DateTime(2020, 1, 3, 15)));
expect( expect(
await SkiaPerfGcsAdaptor.computeObjectName( await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterEngineRepo, kFlutterEngineRepo,
kEngineRevision2, kEngineRevision2,
githubHelper: mockHelper, DateTime.utc(2020, 01, 03, 15),
), ),
equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'), equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'),
); );
@ -356,7 +345,9 @@ Future<void> main() async {
final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket); final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket);
final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName( final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterFrameworkRepo, kFrameworkRevision1); kFlutterFrameworkRepo,
kFrameworkRevision1,
DateTime.fromMillisecondsSinceEpoch(123));
final List<SkiaPerfPoint> writePoints = <SkiaPerfPoint>[ final List<SkiaPerfPoint> writePoints = <SkiaPerfPoint>[
SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1), SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1),
@ -393,7 +384,9 @@ Future<void> main() async {
final MockBucket testBucket = MockBucket(); final MockBucket testBucket = MockBucket();
final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket); final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket);
final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName( final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterFrameworkRepo, kFrameworkRevision1); kFlutterFrameworkRepo,
kFrameworkRevision1,
DateTime.fromMillisecondsSinceEpoch(123));
when(testBucket.info(testObjectName)) when(testBucket.info(testObjectName))
.thenThrow(Exception('No such object')); .thenThrow(Exception('No such object'));
expect((await skiaPerfGcs.readPoints(testObjectName)).length, 0); expect((await skiaPerfGcs.readPoints(testObjectName)).length, 0);
@ -423,7 +416,9 @@ Future<void> main() async {
final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket); final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket);
final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName( final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterFrameworkRepo, kFrameworkRevision1); kFlutterFrameworkRepo,
kFrameworkRevision1,
DateTime.fromMillisecondsSinceEpoch(123));
await skiaPerfGcs.writePoints(testObjectName, <SkiaPerfPoint>[ await skiaPerfGcs.writePoints(testObjectName, <SkiaPerfPoint>[
SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1), SkiaPerfPoint.fromPoint(cocoonPointRev1Metric1),
@ -452,7 +447,9 @@ Future<void> main() async {
final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket); final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket);
final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName( final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterEngineRepo, engineRevision); kFlutterEngineRepo,
engineRevision,
DateTime.fromMillisecondsSinceEpoch(123));
await skiaPerfGcs.writePoints(testObjectName, <SkiaPerfPoint>[ await skiaPerfGcs.writePoints(testObjectName, <SkiaPerfPoint>[
SkiaPerfPoint.fromPoint(enginePoint1), SkiaPerfPoint.fromPoint(enginePoint1),
@ -505,18 +502,27 @@ Future<void> main() async {
() async { () async {
expect( expect(
await SkiaPerfGcsAdaptor.computeObjectName( await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterFrameworkRepo, kFrameworkRevision1), kFlutterFrameworkRepo,
kFrameworkRevision1,
DateTime.utc(2019, 12, 04, 23),
),
equals( equals(
'flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'), 'flutter-flutter/2019/12/04/23/$kFrameworkRevision1/values.json'),
); );
expect( expect(
await SkiaPerfGcsAdaptor.computeObjectName( await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterEngineRepo, kEngineRevision1), kFlutterEngineRepo,
kEngineRevision1,
DateTime.utc(2019, 12, 03, 20),
),
equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'), equals('flutter-engine/2019/12/03/20/$kEngineRevision1/values.json'),
); );
expect( expect(
await SkiaPerfGcsAdaptor.computeObjectName( await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterEngineRepo, kEngineRevision2), kFlutterEngineRepo,
kEngineRevision2,
DateTime.utc(2020, 01, 03, 15),
),
equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'), equals('flutter-engine/2020/01/03/15/$kEngineRevision2/values.json'),
); );
}, },
@ -527,11 +533,13 @@ Future<void> main() async {
final SkiaPerfGcsAdaptor mockGcs = MockSkiaPerfGcsAdaptor(); final SkiaPerfGcsAdaptor mockGcs = MockSkiaPerfGcsAdaptor();
final GcsLock mockLock = MockGcsLock(); final GcsLock mockLock = MockGcsLock();
final SkiaPerfDestination dst = SkiaPerfDestination(mockGcs, mockLock); final SkiaPerfDestination dst = SkiaPerfDestination(mockGcs, mockLock);
await dst.update(<MetricPoint>[cocoonPointRev1Metric1]); await dst.update(<MetricPoint>[cocoonPointRev1Metric1],
await dst.update(<MetricPoint>[cocoonPointRev1Metric2]); DateTime.fromMillisecondsSinceEpoch(123));
await dst.update(<MetricPoint>[cocoonPointRev1Metric2],
DateTime.fromMillisecondsSinceEpoch(123));
List<SkiaPerfPoint> points = await mockGcs.readPoints( List<SkiaPerfPoint> points = await mockGcs.readPoints(
await SkiaPerfGcsAdaptor.computeObjectName( await SkiaPerfGcsAdaptor.computeObjectName(kFlutterFrameworkRepo,
kFlutterFrameworkRepo, kFrameworkRevision1)); kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123)));
expect(points.length, equals(2)); expect(points.length, equals(2));
expectSetMatch( expectSetMatch(
points.map((SkiaPerfPoint p) => p.testName), <String>[kTaskName]); points.map((SkiaPerfPoint p) => p.testName), <String>[kTaskName]);
@ -543,18 +551,19 @@ Future<void> main() async {
final MetricPoint updated = final MetricPoint updated =
MetricPoint(kValue3, cocoonPointRev1Metric1.tags); MetricPoint(kValue3, cocoonPointRev1Metric1.tags);
await dst.update(<MetricPoint>[updated, cocoonPointRev2Metric1]); await dst.update(<MetricPoint>[updated, cocoonPointRev2Metric1],
DateTime.fromMillisecondsSinceEpoch(123));
points = await mockGcs.readPoints( points = await mockGcs.readPoints(
await SkiaPerfGcsAdaptor.computeObjectName( await SkiaPerfGcsAdaptor.computeObjectName(kFlutterFrameworkRepo,
kFlutterFrameworkRepo, kFrameworkRevision2)); kFrameworkRevision2, DateTime.fromMillisecondsSinceEpoch(123)));
expect(points.length, equals(1)); expect(points.length, equals(1));
expect(points[0].gitHash, equals(kFrameworkRevision2)); expect(points[0].gitHash, equals(kFrameworkRevision2));
expect(points[0].value, equals(kValue3)); expect(points[0].value, equals(kValue3));
points = await mockGcs.readPoints( points = await mockGcs.readPoints(
await SkiaPerfGcsAdaptor.computeObjectName( await SkiaPerfGcsAdaptor.computeObjectName(kFlutterFrameworkRepo,
kFlutterFrameworkRepo, kFrameworkRevision1)); kFrameworkRevision1, DateTime.fromMillisecondsSinceEpoch(123)));
expectSetMatch( expectSetMatch(
points.map((SkiaPerfPoint p) => p.value), <double>[kValue2, kValue3]); points.map((SkiaPerfPoint p) => p.value), <double>[kValue2, kValue3]);
}); });
@ -562,7 +571,8 @@ Future<void> main() async {
Future<void> skiaPerfDestinationIntegrationTest() async { Future<void> skiaPerfDestinationIntegrationTest() async {
final SkiaPerfDestination destination = final SkiaPerfDestination destination =
SkiaPerfDestination(SkiaPerfGcsAdaptor(testBucket), testLock); SkiaPerfDestination(SkiaPerfGcsAdaptor(testBucket), testLock);
await destination.update(<MetricPoint>[cocoonPointRev1Metric1]); await destination.update(<MetricPoint>[cocoonPointRev1Metric1],
DateTime.fromMillisecondsSinceEpoch(123));
} }
test( test(