mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
111 lines
3.5 KiB
Dart
111 lines
3.5 KiB
Dart
// Copyright 2015 The Chromium 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:async';
|
|
import 'dart:convert';
|
|
|
|
import '../base/common.dart';
|
|
import '../base/file_system.dart';
|
|
import '../base/utils.dart';
|
|
import '../cache.dart';
|
|
import '../globals.dart';
|
|
import '../runner/flutter_command.dart';
|
|
import '../tracing.dart';
|
|
|
|
class TraceCommand extends FlutterCommand {
|
|
TraceCommand() {
|
|
requiresPubspecYaml();
|
|
argParser.addOption('debug-port',
|
|
help: 'Local port where the observatory is listening. Required.',
|
|
);
|
|
argParser.addFlag('start', negatable: false, help: 'Start tracing. Implied if --stop is also omitted.');
|
|
argParser.addFlag('stop', negatable: false, help: 'Stop tracing. Implied if --start is also omitted.');
|
|
argParser.addOption('duration',
|
|
abbr: 'd',
|
|
help: 'Time to wait after starting (if --start is specified or implied) and before\n'
|
|
'stopping (if --stop is specified or implied).\n'
|
|
'Defaults to ten seconds if --stop is specified or implied, zero otherwise.',
|
|
);
|
|
argParser.addOption('out', help: 'Specify the path of the saved trace file.');
|
|
}
|
|
|
|
@override
|
|
final String name = 'trace';
|
|
|
|
@override
|
|
final String description = 'Start and stop tracing for a running Flutter app.';
|
|
|
|
@override
|
|
final String usageFooter =
|
|
'\`trace\` called without the --start or --stop flags will automatically start tracing,\n'
|
|
'delay a set amount of time (controlled by --duration), and stop tracing. To explicitly\n'
|
|
'control tracing, call trace with --start and later with --stop.\n'
|
|
'The --debug-port argument is required.';
|
|
|
|
@override
|
|
Future<Null> runCommand() async {
|
|
int observatoryPort;
|
|
if (argResults.wasParsed('debug-port')) {
|
|
observatoryPort = int.tryParse(argResults['debug-port']);
|
|
}
|
|
if (observatoryPort == null) {
|
|
throwToolExit('The --debug-port argument must be specified.');
|
|
}
|
|
|
|
bool start = argResults['start'];
|
|
bool stop = argResults['stop'];
|
|
if (!start && !stop) {
|
|
start = true;
|
|
stop = true;
|
|
}
|
|
assert(start || stop);
|
|
|
|
Duration duration;
|
|
if (argResults.wasParsed('duration')) {
|
|
try {
|
|
duration = Duration(seconds: int.parse(argResults['duration']));
|
|
} on FormatException {
|
|
throwToolExit('Invalid duration passed to --duration; it should be a positive number of seconds.');
|
|
}
|
|
} else {
|
|
duration = stop ? const Duration(seconds: 10) : Duration.zero;
|
|
}
|
|
|
|
// TODO(danrubel): this will break if we move to the new observatory URL
|
|
// See https://github.com/flutter/flutter/issues/7038
|
|
final Uri observatoryUri = Uri.parse('http://127.0.0.1:$observatoryPort');
|
|
|
|
Tracing tracing;
|
|
|
|
try {
|
|
tracing = await Tracing.connect(observatoryUri);
|
|
} catch (error) {
|
|
throwToolExit('Error connecting to observatory: $error');
|
|
}
|
|
|
|
Cache.releaseLockEarly();
|
|
|
|
if (start)
|
|
await tracing.startTracing();
|
|
await Future<Null>.delayed(duration);
|
|
if (stop)
|
|
await _stopTracing(tracing);
|
|
}
|
|
|
|
Future<Null> _stopTracing(Tracing tracing) async {
|
|
final Map<String, dynamic> timeline = await tracing.stopTracingAndDownloadTimeline();
|
|
File localFile;
|
|
|
|
if (argResults['out'] != null) {
|
|
localFile = fs.file(argResults['out']);
|
|
} else {
|
|
localFile = getUniqueFile(fs.currentDirectory, 'trace', 'json');
|
|
}
|
|
|
|
await localFile.writeAsString(json.encode(timeline));
|
|
|
|
printStatus('Trace file saved to ${localFile.path}');
|
|
}
|
|
}
|