Skip to content

Commit

Permalink
feat: Change concurrent log to sequential log (#679)
Browse files Browse the repository at this point in the history
* feat: Change concurrent log to sequential log

* test: Add analyze -c 2 case

* fix: logger error label

---------

Co-authored-by: Lukas Klingsbo <[email protected]>
  • Loading branch information
koji-1009 and spydon authored Mar 27, 2024
1 parent 69b7fae commit 15b1518
Show file tree
Hide file tree
Showing 4 changed files with 250 additions and 31 deletions.
32 changes: 14 additions & 18 deletions packages/melos/lib/src/commands/analyze.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,20 @@ mixin _AnalyzeMixin on _Melos {
fatalWarnings: fatalWarnings,
concurrency: concurrency,
).join(' ');
final prefixLogs = concurrency != 1 && packages.length != 1;
final useGroupBuffer = concurrency != 1 && packages.length != 1;

logger.command('melos analyze', withDollarSign: true);

logger
.child(targetStyle(analyzeArgsString))
.child('$runningLabel (in ${packages.length} packages)')
.newLine();
if (prefixLogs) {
logger.horizontalLine();
}

final packageResults = Map.fromEntries(
packages.map((package) => MapEntry(package.name, Completer<int?>())),
);

await pool.forEach<Package, void>(packages, (package) async {
if (!prefixLogs) {
logger
..horizontalLine()
..log(AnsiStyles.bgBlack.bold.italic('${package.name}:'));
}
final group = useGroupBuffer ? package.name : null;
logger
..horizontalLine(group: group)
..log(AnsiStyles.bgBlack.bold.italic('${package.name}:'), group: group);

final packageExitCode = await _analyzeForPackage(
workspace,
Expand All @@ -67,20 +59,22 @@ mixin _AnalyzeMixin on _Melos {
fatalInfos: fatalInfos,
fatalWarnings: fatalWarnings,
),
group: group,
);

packageResults[package.name]?.complete(packageExitCode);

if (packageExitCode > 0) {
failures[package.name] = packageExitCode;
} else if (!prefixLogs) {
} else {
logger.log(
AnsiStyles.bgBlack.bold.italic('${package.name}: ') +
AnsiStyles.bgBlack(successLabel),
group: group,
);
}
}).drain<void>();

logger.flushGroupBufferIfNeed();

logger
..horizontalLine()
..newLine()
Expand Down Expand Up @@ -149,8 +143,9 @@ mixin _AnalyzeMixin on _Melos {
Future<int> _analyzeForPackage(
MelosWorkspace workspace,
Package package,
List<String> analyzeArgs,
) async {
List<String> analyzeArgs, {
String? group,
}) async {
final environment = {
EnvironmentVariableKey.melosRootPath: config.path,
if (workspace.sdkPath != null)
Expand All @@ -164,6 +159,7 @@ mixin _AnalyzeMixin on _Melos {
logger: logger,
environment: environment,
workingDirectory: package.path,
group: group,
);
}

Expand Down
18 changes: 14 additions & 4 deletions packages/melos/lib/src/common/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ Future<int> startCommand(
bool onlyOutputOnError = false,
bool includeParentEnvironment = true,
required MelosLogger logger,
String? group,
}) async {
final processedCommand = command
// Remove empty arguments.
Expand Down Expand Up @@ -521,7 +522,10 @@ Future<int> startCommand(
(event) {
processStdout.addAll(event);
if (!onlyOutputOnError) {
logger.write(utf8.decode(event, allowMalformed: true));
logger.logWithoutNewLine(
utf8.decode(event, allowMalformed: true),
group: group,
);
}
},
onDone: processStdoutCompleter.complete,
Expand All @@ -530,7 +534,7 @@ Future<int> startCommand(
(event) {
processStderr.addAll(event);
if (!onlyOutputOnError) {
logger.stderr(utf8.decode(event, allowMalformed: true));
logger.error(utf8.decode(event, allowMalformed: true), group: group);
}
},
onDone: processStderrCompleter.complete,
Expand All @@ -543,8 +547,14 @@ Future<int> startCommand(
_runningPids.remove(process.pid);

if (onlyOutputOnError && exitCode > 0) {
logger.stdout(utf8.decode(processStdout, allowMalformed: true));
logger.stderr(utf8.decode(processStderr, allowMalformed: true));
logger.log(
utf8.decode(processStdout, allowMalformed: true),
group: group,
);
logger.error(
utf8.decode(processStderr, allowMalformed: true),
group: group,
);
}

return exitCode;
Expand Down
147 changes: 138 additions & 9 deletions packages/melos/lib/src/logging.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,23 @@ class MelosLogger with _DelegateLogger {
final String _indentation;
final String _childIndentation;

void log(String message) => stdout(message);
void log(String message, {String? group}) {
if (group != null) {
_stdoutGroup(message, group);
return;
}

stdout(message);
}

void logWithoutNewLine(String message, {String? group}) {
if (group != null) {
_writeGroup(message, group);
return;
}

write(message);
}

void command(String command, {bool withDollarSign = false}) {
if (withDollarSign) {
Expand All @@ -59,50 +75,111 @@ class MelosLogger with _DelegateLogger {
}
}

void success(String message, {bool dryRun = false}) {
void success(String message, {String? group, bool dryRun = false}) {
if (group != null) {
if (dryRun) {
_stdoutGroup(successMessageColor(message), group);
} else {
_stdoutGroup(successMessageColor(successStyle(message)), group);
}

return;
}

if (dryRun) {
stdout(successMessageColor(message));
} else {
stdout(successMessageColor(successStyle(message)));
}
}

void warning(String message, {bool label = true, bool dryRun = false}) {
void warning(
String message, {
String? group,
bool label = true,
bool dryRun = false,
}) {
final labelColor =
dryRun ? dryRunWarningLabelColor : dryRunWarningMessageColor;
final messageColor =
dryRun ? dryRunWarningMessageColor : warningMessageColor;

if (group != null) {
if (label) {
_stdoutGroup('$warningLabel${labelColor(':')} $message', group);
} else {
_stdoutGroup(messageColor(message), group);
}

return;
}

if (label) {
stdout('$warningLabel${labelColor(':')} $message');
} else {
stdout(messageColor(message));
}
}

void error(String message, {bool label = true}) {
void error(String message, {String? group, bool label = true}) {
if (group != null) {
if (label) {
_stderrGroup('$errorLabel${errorLabelColor(':')} $message', group);
} else {
_stderrGroup(errorMessageColor(message), group);
}

return;
}

if (label) {
stderr('$errorLabel${errorLabelColor(':')} $message');
} else {
stderr(errorMessageColor(message));
}
}

void hint(String message, {bool label = true}) {
void hint(String message, {String? group, bool label = true}) {
if (group != null) {
if (label) {
_stdoutGroup('$hintLabel${hintLabelColor(':')} $message', group);
} else {
_stdoutGroup(hintMessageColor(message), group);
}

return;
}

if (label) {
stdout(hintMessageColor('$hintLabel: $message'));
} else {
stdout(hintMessageColor(message));
}
}

void newLine() => _logger.write('\n');
void newLine({String? group}) {
if (group != null) {
_stdoutGroup('', group);
return;
}

_logger.stdout('');
}

void horizontalLine() => _logger.stdout('-' * terminalWidth);
void horizontalLine({String? group}) {
if (group != null) {
_stdoutGroup('-' * terminalWidth, group);
return;
}

_logger.stdout('-' * terminalWidth);
}

MelosLogger child(
String message, {
String prefix = '└> ',
bool stderr = false,
String? group,
}) {
final childIndentation = ' ' * AnsiStyles.strip(prefix).length;
final logger = MelosLogger(
Expand All @@ -116,9 +193,9 @@ class MelosLogger with _DelegateLogger {
for (final line in lines) {
final prefixedLine = '${isFirstLine ? prefix : childIndentation}$line';
if (stderr) {
logger.stderr(prefixedLine);
logger.error(prefixedLine, group: group, label: false);
} else {
logger.stdout(prefixedLine);
logger.log(prefixedLine, group: group);
}
isFirstLine = false;
}
Expand All @@ -141,6 +218,58 @@ class MelosLogger with _DelegateLogger {

@override
void trace(String message) => _logger.trace('$_indentation$message');

final _groupBuffer = <String, List<_GroupBufferMessage>>{};

void _stdoutGroup(String message, String group) {
final previous = _groupBuffer[group] ?? const [];
_groupBuffer[group] = [...previous, _GroupBufferStdoutMessage(message)];
}

void _stderrGroup(String message, String group) {
final previous = _groupBuffer[group] ?? const [];
_groupBuffer[group] = [...previous, _GroupBufferStderrMessage(message)];
}

void _writeGroup(String message, String group) {
final previous = _groupBuffer[group] ?? const [];
_groupBuffer[group] = [...previous, _GroupBufferWriteMessage(message)];
}

void flushGroupBufferIfNeed() {
for (final entry in _groupBuffer.entries) {
for (final value in entry.value) {
switch (value) {
case _GroupBufferStdoutMessage(:final message):
stdout(message);
case _GroupBufferStderrMessage(:final message):
stderr(message);
case _GroupBufferWriteMessage(:final message):
write(message);
}
}
}

_groupBuffer.clear();
}
}

sealed class _GroupBufferMessage {
const _GroupBufferMessage(this.message);

final String message;
}

class _GroupBufferStdoutMessage extends _GroupBufferMessage {
const _GroupBufferStdoutMessage(super.message);
}

class _GroupBufferStderrMessage extends _GroupBufferMessage {
const _GroupBufferStderrMessage(super.message);
}

class _GroupBufferWriteMessage extends _GroupBufferMessage {
const _GroupBufferWriteMessage(super.message);
}

mixin _DelegateLogger implements Logger {
Expand Down
Loading

0 comments on commit 15b1518

Please sign in to comment.