Unverified Commit 22a61b94 authored by Lau Ching Jun's avatar Lau Ching Jun Committed by GitHub

Allow passing verbose log from flutter daemon. (#132828)

It would be helpful for debugging if we can choose to also receive remote verbose logs.
parent 865b5b48
...@@ -335,6 +335,7 @@ class DaemonDomain extends Domain { ...@@ -335,6 +335,7 @@ class DaemonDomain extends Domain {
registerHandler('version', version); registerHandler('version', version);
registerHandler('shutdown', shutdown); registerHandler('shutdown', shutdown);
registerHandler('getSupportedPlatforms', getSupportedPlatforms); registerHandler('getSupportedPlatforms', getSupportedPlatforms);
registerHandler('setNotifyVerbose', setNotifyVerbose);
sendEvent( sendEvent(
'daemon.connected', 'daemon.connected',
...@@ -346,7 +347,7 @@ class DaemonDomain extends Domain { ...@@ -346,7 +347,7 @@ class DaemonDomain extends Domain {
_subscription = daemon.notifyingLogger!.onMessage.listen((LogMessage message) { _subscription = daemon.notifyingLogger!.onMessage.listen((LogMessage message) {
if (daemon.logToStdout) { if (daemon.logToStdout) {
if (message.level == 'status') { if (message.level == 'status' || message.level == 'trace') {
// We use `print()` here instead of `stdout.writeln()` in order to // We use `print()` here instead of `stdout.writeln()` in order to
// capture the print output for testing. // capture the print output for testing.
// ignore: avoid_print // ignore: avoid_print
...@@ -461,6 +462,11 @@ class DaemonDomain extends Domain { ...@@ -461,6 +462,11 @@ class DaemonDomain extends Domain {
}; };
} }
} }
/// If notifyVerbose is set, the daemon will forward all verbose logs.
Future<void> setNotifyVerbose(Map<String, Object?> args) async {
daemon.notifyingLogger?.notifyVerbose = _getBoolArg(args, 'verbose') ?? true;
}
} }
typedef RunOrAttach = Future<void> Function({ typedef RunOrAttach = Future<void> Function({
...@@ -1210,7 +1216,7 @@ Object? _toJsonable(Object? obj) { ...@@ -1210,7 +1216,7 @@ Object? _toJsonable(Object? obj) {
} }
class NotifyingLogger extends DelegatingLogger { class NotifyingLogger extends DelegatingLogger {
NotifyingLogger({ required this.verbose, required Logger parent }) : super(parent) { NotifyingLogger({ required this.verbose, required Logger parent, this.notifyVerbose = false }) : super(parent) {
_messageController = StreamController<LogMessage>.broadcast( _messageController = StreamController<LogMessage>.broadcast(
onListen: _onListen, onListen: _onListen,
); );
...@@ -1220,6 +1226,8 @@ class NotifyingLogger extends DelegatingLogger { ...@@ -1220,6 +1226,8 @@ class NotifyingLogger extends DelegatingLogger {
final List<LogMessage> messageBuffer = <LogMessage>[]; final List<LogMessage> messageBuffer = <LogMessage>[];
late StreamController<LogMessage> _messageController; late StreamController<LogMessage> _messageController;
bool notifyVerbose = false;
void _onListen() { void _onListen() {
if (messageBuffer.isNotEmpty) { if (messageBuffer.isNotEmpty) {
messageBuffer.forEach(_messageController.add); messageBuffer.forEach(_messageController.add);
...@@ -1277,6 +1285,10 @@ class NotifyingLogger extends DelegatingLogger { ...@@ -1277,6 +1285,10 @@ class NotifyingLogger extends DelegatingLogger {
@override @override
void printTrace(String message) { void printTrace(String message) {
if (notifyVerbose) {
_sendMessage(LogMessage('trace', message));
return;
}
if (!verbose) { if (!verbose) {
return; return;
} }
......
...@@ -195,6 +195,63 @@ void main() { ...@@ -195,6 +195,63 @@ void main() {
Logger: () => notifyingLogger, Logger: () => notifyingLogger,
}); });
testUsingContext('printTrace should send daemon.logMessage event when notifyVerbose is enabled', () async {
daemon = Daemon(
daemonConnection,
notifyingLogger: notifyingLogger,
);
notifyingLogger.notifyVerbose = false;
globals.printTrace('daemon.logMessage test 1');
notifyingLogger.notifyVerbose = true;
globals.printTrace('daemon.logMessage test 2');
final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere((DaemonMessage message) {
return message.data['event'] == 'daemon.logMessage' && (message.data['params']! as Map<String, Object?>)['level'] == 'trace';
});
expect(response.data['id'], isNull);
expect(response.data['event'], 'daemon.logMessage');
final Map<String, String> logMessage = castStringKeyedMap(response.data['params'])!.cast<String, String>();
expect(logMessage['level'], 'trace');
expect(logMessage['message'], 'daemon.logMessage test 2');
}, overrides: <Type, Generator>{
Logger: () => notifyingLogger,
});
testUsingContext('daemon.setNotifyVerbose command should update the notify verbose status to true', () async {
daemon = Daemon(
daemonConnection,
notifyingLogger: notifyingLogger,
);
expect(notifyingLogger.notifyVerbose, false);
daemonStreams.inputs.add(DaemonMessage(<String, Object?>{
'id': 0,
'method': 'daemon.setNotifyVerbose',
'params': <String, Object?>{
'verbose': true,
},
}));
await daemonStreams.outputs.stream.firstWhere(_notEvent);
expect(notifyingLogger.notifyVerbose, true);
});
testUsingContext('daemon.setNotifyVerbose command should update the notify verbose status to false', () async {
daemon = Daemon(
daemonConnection,
notifyingLogger: notifyingLogger,
);
notifyingLogger.notifyVerbose = false;
daemonStreams.inputs.add(DaemonMessage(<String, Object?>{
'id': 0,
'method': 'daemon.setNotifyVerbose',
'params': <String, Object?>{
'verbose': false,
},
}));
await daemonStreams.outputs.stream.firstWhere(_notEvent);
expect(notifyingLogger.notifyVerbose, false);
});
testUsingContext('daemon.shutdown command should stop daemon', () async { testUsingContext('daemon.shutdown command should stop daemon', () async {
daemon = Daemon( daemon = Daemon(
daemonConnection, daemonConnection,
...@@ -755,6 +812,19 @@ void main() { ...@@ -755,6 +812,19 @@ void main() {
expect(bufferLogger.errorText, isEmpty); expect(bufferLogger.errorText, isEmpty);
}); });
testUsingContext('sends trace messages in notify verbose mode', () async {
final NotifyingLogger logger = NotifyingLogger(verbose: false, parent: bufferLogger, notifyVerbose: true);
final Future<LogMessage> messageResult = logger.onMessage.first;
logger.printTrace('hello');
final LogMessage message = await messageResult;
expect(message.level, 'trace');
expect(message.message, 'hello');
expect(bufferLogger.errorText, isEmpty);
});
testUsingContext('buffers messages sent before a subscription', () async { testUsingContext('buffers messages sent before a subscription', () async {
final NotifyingLogger logger = NotifyingLogger(verbose: false, parent: bufferLogger); final NotifyingLogger logger = NotifyingLogger(verbose: false, parent: bufferLogger);
......
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