blob: 96231b6886b34eb80be60a4a6d930812f162ba04 [file] [log] [blame]
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. 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:io/ansi.dart';
import 'package:logging/logging.dart';
import 'package:stack_trace/stack_trace.dart';
Function(LogRecord) stdIOLogListener({bool assumeTty, bool verbose}) =>
(record) => overrideAnsiOutput(assumeTty == true || ansiOutputEnabled, () {
_stdIOLogListener(record, verbose: verbose ?? false);
});
StringBuffer colorLog(LogRecord record, {bool verbose}) {
AnsiCode color;
if (record.level < Level.WARNING) {
color = cyan;
} else if (record.level < Level.SEVERE) {
color = yellow;
} else {
color = red;
}
final level = color.wrap('[${record.level}]');
final eraseLine = ansiOutputEnabled && !verbose ? '\x1b[2K\r' : '';
var lines = <Object>[
'$eraseLine$level ${_recordHeader(record, verbose)}${record.message}'
];
if (record.error != null) {
lines.add(record.error);
}
if (record.stackTrace != null && verbose) {
var trace = Trace.from(record.stackTrace).foldFrames((f) {
return f.package == 'build_runner' || f.package == 'build';
}, terse: true);
lines.add(trace);
}
var message = StringBuffer(lines.join('\n'));
// We always add an extra newline at the end of each message, so it
// isn't multiline unless we see > 2 lines.
var multiLine = LineSplitter.split(message.toString()).length > 2;
if (record.level > Level.INFO || !ansiOutputEnabled || multiLine || verbose) {
// Add an extra line to the output so the last line isn't written over.
message.writeln('');
}
return message;
}
void _stdIOLogListener(LogRecord record, {bool verbose}) =>
stdout.write(colorLog(record, verbose: verbose));
/// Filter out the Logger names which aren't coming from specific builders and
/// splits the header for levels >= WARNING.
String _recordHeader(LogRecord record, bool verbose) {
var maybeSplit = record.level >= Level.WARNING ? '\n' : '';
return verbose || record.loggerName.contains(' ')
? '${record.loggerName}:$maybeSplit'
: '';
}