Commit 896246ad authored by Devon Carew's avatar Devon Carew

Merge pull request #2079 from devoncarew/more_specific_logging

log for specific adb devices
parents 2b70fda1 488e5dcd
...@@ -307,7 +307,7 @@ class AndroidDevice extends Device { ...@@ -307,7 +307,7 @@ class AndroidDevice extends Device {
TargetPlatform get platform => TargetPlatform.android; TargetPlatform get platform => TargetPlatform.android;
void clearLogs() { void clearLogs() {
runSync(adbCommandForDevice(<String>['logcat', '-c'])); runSync(adbCommandForDevice(<String>['-s', id, 'logcat', '-c']));
} }
DeviceLogReader createLogReader() => new _AdbLogReader(this); DeviceLogReader createLogReader() => new _AdbLogReader(this);
...@@ -322,10 +322,12 @@ class AndroidDevice extends Device { ...@@ -322,10 +322,12 @@ class AndroidDevice extends Device {
])); ]));
} }
// Return the most recent timestamp in the Android log. The format can be // Return the most recent timestamp in the Android log. The format can be
// passed to logcat's -T option. // passed to logcat's -T option.
String lastLogcatTimestamp() { String lastLogcatTimestamp() {
String output = runCheckedSync(adbCommandForDevice(<String>['logcat', '-v', 'time', '-t', '1'])); String output = runCheckedSync(adbCommandForDevice(<String>[
'-s', id, 'logcat', '-v', 'time', '-t', '1'
]));
RegExp timeRegExp = new RegExp(r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}', multiLine: true); RegExp timeRegExp = new RegExp(r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}', multiLine: true);
Match timeMatch = timeRegExp.firstMatch(output); Match timeMatch = timeRegExp.firstMatch(output);
...@@ -350,7 +352,9 @@ class AndroidDevice extends Device { ...@@ -350,7 +352,9 @@ class AndroidDevice extends Device {
String tracePath = null; String tracePath = null;
bool isComplete = false; bool isComplete = false;
while (!isComplete) { while (!isComplete) {
String logs = runCheckedSync(adbCommandForDevice(<String>['logcat', '-d', '-T', beforeStop])); String logs = runCheckedSync(adbCommandForDevice(<String>[
'-s', id, 'logcat', '-d', '-T', beforeStop
]));
Match fileMatch = traceRegExp.firstMatch(logs); Match fileMatch = traceRegExp.firstMatch(logs);
if (fileMatch != null && fileMatch[1] != null) { if (fileMatch != null && fileMatch[1] != null) {
tracePath = fileMatch[1]; tracePath = fileMatch[1];
...@@ -484,16 +488,15 @@ List<AndroidDevice> getAdbDevices() { ...@@ -484,16 +488,15 @@ List<AndroidDevice> getAdbDevices() {
return devices; return devices;
} }
/// A log reader that logs from `adb logcat`. This will have the same output as /// A log reader that logs from `adb logcat`.
/// another copy of [_AdbLogReader], and the two instances will be equivalent.
class _AdbLogReader extends DeviceLogReader { class _AdbLogReader extends DeviceLogReader {
_AdbLogReader(this.device); _AdbLogReader(this.device);
final AndroidDevice device; final AndroidDevice device;
String get name => 'Android'; String get name => device.name;
Future<int> logs({bool clear: false}) async { Future<int> logs({ bool clear: false, bool showPrefix: false }) async {
if (!device.isConnected()) if (!device.isConnected())
return 2; return 2;
...@@ -501,6 +504,8 @@ class _AdbLogReader extends DeviceLogReader { ...@@ -501,6 +504,8 @@ class _AdbLogReader extends DeviceLogReader {
device.clearLogs(); device.clearLogs();
return await runCommandAndStreamOutput(device.adbCommandForDevice(<String>[ return await runCommandAndStreamOutput(device.adbCommandForDevice(<String>[
'-s',
device.id,
'logcat', 'logcat',
'-v', '-v',
'tag', // Only log the tag and the message 'tag', // Only log the tag and the message
...@@ -509,15 +514,16 @@ class _AdbLogReader extends DeviceLogReader { ...@@ -509,15 +514,16 @@ class _AdbLogReader extends DeviceLogReader {
'ActivityManager:W', 'ActivityManager:W',
'System.err:W', 'System.err:W',
'*:F', '*:F',
]), prefix: '[Android] '); ]), prefix: showPrefix ? '[$name] ' : '');
} }
// Intentionally constant; overridden because we've overridden the `operator ==` method below.
int get hashCode => name.hashCode; int get hashCode => name.hashCode;
bool operator ==(dynamic other) { bool operator ==(dynamic other) {
if (identical(this, other)) if (identical(this, other))
return true; return true;
return other is _AdbLogReader; if (other is! _AdbLogReader)
return false;
return other.device.id == device.id;
} }
} }
...@@ -35,15 +35,15 @@ class LogsCommand extends FlutterCommand { ...@@ -35,15 +35,15 @@ class LogsCommand extends FlutterCommand {
bool clear = argResults['clear']; bool clear = argResults['clear'];
Set<DeviceLogReader> readers = new Set<DeviceLogReader>(); List<DeviceLogReader> readers = new List<DeviceLogReader>();
for (Device device in devices) { for (Device device in devices) {
readers.add(device.createLogReader()); readers.add(device.createLogReader());
} }
printStatus('Showing logs for ${readers.join(', ')}:'); printStatus('Showing ${readers.join(', ')} logs:');
List<int> results = await Future.wait(readers.map((DeviceLogReader reader) async { List<int> results = await Future.wait(readers.map((DeviceLogReader reader) async {
int result = await reader.logs(clear: clear); int result = await reader.logs(clear: clear, showPrefix: devices.length > 1);
if (result != 0) if (result != 0)
printError('Error listening to $reader logs.'); printError('Error listening to $reader logs.');
return result; return result;
......
...@@ -189,7 +189,7 @@ abstract class Device { ...@@ -189,7 +189,7 @@ abstract class Device {
abstract class DeviceLogReader { abstract class DeviceLogReader {
String get name; String get name;
Future<int> logs({ bool clear: false }); Future<int> logs({ bool clear: false, bool showPrefix: false });
int get hashCode; int get hashCode;
bool operator ==(dynamic other); bool operator ==(dynamic other);
......
...@@ -232,13 +232,13 @@ class _IOSDeviceLogReader extends DeviceLogReader { ...@@ -232,13 +232,13 @@ class _IOSDeviceLogReader extends DeviceLogReader {
String get name => device.name; String get name => device.name;
// TODO(devoncarew): Support [clear]. // TODO(devoncarew): Support [clear].
Future<int> logs({ bool clear: false }) async { Future<int> logs({ bool clear: false, bool showPrefix: false }) async {
if (!device.isConnected()) if (!device.isConnected())
return 2; return 2;
return await runCommandAndStreamOutput( return await runCommandAndStreamOutput(
<String>[device.loggerPath], <String>[device.loggerPath],
prefix: '[$name] ', prefix: showPrefix ? '[$name] ' : '',
filter: new RegExp(r'Runner') filter: new RegExp(r'Runner')
); );
} }
......
...@@ -410,7 +410,7 @@ class _IOSSimulatorLogReader extends DeviceLogReader { ...@@ -410,7 +410,7 @@ class _IOSSimulatorLogReader extends DeviceLogReader {
String get name => device.name; String get name => device.name;
Future<int> logs({ bool clear: false }) async { Future<int> logs({ bool clear: false, bool showPrefix: false }) async {
if (!device.isConnected()) if (!device.isConnected())
return 2; return 2;
...@@ -432,7 +432,7 @@ class _IOSSimulatorLogReader extends DeviceLogReader { ...@@ -432,7 +432,7 @@ class _IOSSimulatorLogReader extends DeviceLogReader {
Future<int> result = runCommandAndStreamOutput( Future<int> result = runCommandAndStreamOutput(
<String>['tail', '-n', '+0', '-F', device.logFilePath], <String>['tail', '-n', '+0', '-F', device.logFilePath],
prefix: '[$name] ', prefix: showPrefix ? '[$name] ' : '',
mapFunction: (String string) { mapFunction: (String string) {
Match match = mapRegex.matchAsPrefix(string); Match match = mapRegex.matchAsPrefix(string);
if (match != null) { if (match != null) {
...@@ -465,7 +465,7 @@ class _IOSSimulatorLogReader extends DeviceLogReader { ...@@ -465,7 +465,7 @@ class _IOSSimulatorLogReader extends DeviceLogReader {
// ReportCrash[37965]: Saved crash report for FlutterRunner[37941]... // ReportCrash[37965]: Saved crash report for FlutterRunner[37941]...
runCommandAndStreamOutput( runCommandAndStreamOutput(
<String>['tail', '-F', '/private/var/log/system.log'], <String>['tail', '-F', '/private/var/log/system.log'],
prefix: '[$name] ', prefix: showPrefix ? '[$name] ' : '',
filter: new RegExp(r' FlutterRunner\[\d+\] '), filter: new RegExp(r' FlutterRunner\[\d+\] '),
mapFunction: (String string) { mapFunction: (String string) {
Match match = mapRegex.matchAsPrefix(string); Match match = mapRegex.matchAsPrefix(string);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment