| // Copyright 2013 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 'dart:convert'; | |
| import 'dart:io'; | |
| import 'package:args/args.dart'; | |
| import 'package:metrics_center/metrics_center.dart'; | |
| import 'package:path/path.dart' as p; | |
| Future<ProcessResult> runGit( | |
| List<String> args, { | |
| String? processWorkingDir, | |
| }) async { | |
| return Process.run( | |
| 'git', | |
| args, | |
| workingDirectory: processWorkingDir, | |
| runInShell: true, | |
| ); | |
| } | |
| Future<List<String>> getGitLog() async { | |
| final String gitRoot = p.absolute('../..'); | |
| // Somehow gitDir.currentBranch() doesn't work in Cirrus with "fatal: 'HEAD' - | |
| // not a valid ref". Therefore, we use "git log" to get the revision manually. | |
| final ProcessResult logResult = await runGit( | |
| <String>['log', '--pretty=format:%H %ct', '-n', '1'], | |
| processWorkingDir: gitRoot, | |
| ); | |
| if (logResult.exitCode != 0) { | |
| throw 'Unexpected exit code ${logResult.exitCode}'; | |
| } | |
| return logResult.stdout.toString().trim().split(' '); | |
| } | |
| class PointsAndDate { | |
| PointsAndDate(this.points, this.date); | |
| final List<FlutterEngineMetricPoint> points; | |
| final String date; | |
| } | |
| Future<PointsAndDate> parse(String jsonFileName) async { | |
| final List<String> gitLog = await getGitLog(); | |
| final String gitRevision = gitLog[0]; | |
| final String gitCommitDate = gitLog[1]; | |
| final List<MetricPoint> rawPoints = await GoogleBenchmarkParser.parse( | |
| jsonFileName, | |
| ); | |
| final List<FlutterEngineMetricPoint> points = <FlutterEngineMetricPoint>[]; | |
| for (final MetricPoint rawPoint in rawPoints) { | |
| points.add(FlutterEngineMetricPoint( | |
| rawPoint.tags[kNameKey]!, | |
| rawPoint.value!, | |
| gitRevision, | |
| moreTags: rawPoint.tags, | |
| )); | |
| } | |
| return PointsAndDate(points, gitCommitDate); | |
| } | |
| Future<FlutterDestination> connectFlutterDestination() async { | |
| const String kTokenPath = 'TOKEN_PATH'; | |
| const String kGcpProject = 'GCP_PROJECT'; | |
| final Map<String, String> env = Platform.environment; | |
| final bool isTesting = env['IS_TESTING'] == 'true'; | |
| if (env.containsKey(kTokenPath) && env.containsKey(kGcpProject)) { | |
| return FlutterDestination.makeFromAccessToken( | |
| File(env[kTokenPath]!).readAsStringSync(), | |
| env[kGcpProject]!, | |
| isTesting: isTesting, | |
| ); | |
| } | |
| return FlutterDestination.makeFromCredentialsJson( | |
| jsonDecode(Platform.environment['BENCHMARK_GCP_CREDENTIALS']!) | |
| as Map<String, dynamic>, | |
| isTesting: isTesting, | |
| ); | |
| } | |
| ArgParser _serupOptions() { | |
| final ArgParser parser = ArgParser(); | |
| parser.addOption( | |
| 'json', | |
| mandatory: true, | |
| help: 'Path to the benchmarks json file.', | |
| ); | |
| parser.addFlag( | |
| 'no-upload', | |
| help: 'Upload the parsed benchmarks.', | |
| ); | |
| return parser; | |
| } | |
| Future<void> main(List<String> args) async { | |
| final ArgParser parser = _serupOptions(); | |
| final ArgResults options = parser.parse(args); | |
| final String json = options['json'] as String; | |
| final PointsAndDate pointsAndDate = await parse(json); | |
| final bool noUpload = options['no-upload'] as bool; | |
| if (noUpload) { | |
| return; | |
| } | |
| // The data will be sent to the Datastore of the GCP project specified through | |
| // environment variable BENCHMARK_GCP_CREDENTIALS, or TOKEN_PATH/GCP_PROJECT. | |
| // The engine Cirrus job has currently configured the GCP project to | |
| // flutter-cirrus for test. We'll eventually migrate to flutter-infra project | |
| // once the test is done. | |
| final FlutterDestination destination = await connectFlutterDestination(); | |
| await destination.update( | |
| pointsAndDate.points, | |
| DateTime.fromMillisecondsSinceEpoch( | |
| int.parse(pointsAndDate.date) * 1000, | |
| isUtc: true, | |
| ), | |
| 'flutter_engine_benchmark', | |
| ); | |
| } |