logger icon indicating copy to clipboard operation
logger copied to clipboard

Looks ugly in Android Studio

Open subzero911 opened this issue 4 years ago • 15 comments

VS Code: image

AS: image

subzero911 avatar Sep 16 '20 09:09 subzero911

Both consoles use bash.

I also tried to customize PrettyPrinter as mentioned in docs: image It led to the following error: image

subzero911 avatar Sep 16 '20 11:09 subzero911

Is there an option to get rid of those line frames and leave a text only? SimplePrinter does not show references.

subzero911 avatar Sep 16 '20 12:09 subzero911

It parses wrong, showing strange symbols:

image

subzero911 avatar Sep 16 '20 12:09 subzero911

You can pass 'colors: false' to the prettyprint constitutor. Or you can use simpleprinter to get rid of the fanciness altogether. Please refer to the readme how.

On Wed, Sep 16, 2020, 14:31 Sergey Molchanovsky [email protected] wrote:

It sometimes parses wrong, showing strange symbols:

[image: image] https://user-images.githubusercontent.com/12999702/93337071-4d2b7100-f831-11ea-9b3d-f4de58e26237.png

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/leisim/logger/issues/61#issuecomment-693373503, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAACTJB2GT6WM4HDEMDSSULSGCVYTANCNFSM4ROQLM2Q .

haarts avatar Sep 16 '20 12:09 haarts

But SimplePrinter does not show these references. image

subzero911 avatar Sep 16 '20 12:09 subzero911

The problem is that I use VS Code, and I want colorful output. But my colleague uses AS and he needs colors: false. He also dislikes fanciness. And we both need class references.

subzero911 avatar Sep 16 '20 12:09 subzero911

I tested it several times and can confirm that this line lineLength: io.stdout.terminalColumns produces random errors like this: image

colors: io.stdout.supportsAnsiEscapes this line is not offending though it is false both in VS Code and AS.

subzero911 avatar Sep 16 '20 14:09 subzero911

Please add a parameter noBorders: to PrettyPrinter. Or sourceReferences: to SimplePrinter().

subzero911 avatar Sep 16 '20 18:09 subzero911

Both consoles use bash.

I also tried to customize PrettyPrinter as mentioned in docs: image It led to the following error: image

This is expected behaviour in an IDE console. These consoles do not support colors or emojis.

haarts avatar Sep 28 '20 07:09 haarts

Is there an option to get rid of those line frames and leave a text only? SimplePrinter does not show references.

I'm not sure what you mean by 'references'. References to what?

haarts avatar Sep 28 '20 08:09 haarts

I'm not sure what you mean by 'references'. References to what?

I mean stack trace. References to the code lines where logger.d was called. Basically I need SimplePrinter with stack trace in the same line.

subzero911 avatar Sep 28 '20 08:09 subzero911

I unsuccessfully tried to implement it, the source is too tangled and full of "magic". image

Not exactly what I wanted image I need only these "package:health" strings as links

subzero911 avatar Oct 01 '20 19:10 subzero911

It would have been great if it was possible to use the prettyPrinter, but without the borders. For instance by passing a flag of some sort: printer: PrettyPrinter(methodCount: 1, borders: false)). This is because the borders gets messed up both in Android Studio (if using an emulator device) and in the console output in a browser. Icons, colors and stacktrace works perfect, though.

Anyone knows if that is possible now?

kesteinbakk avatar Apr 29 '21 10:04 kesteinbakk

Use this log printer to ignore the borders.

import 'dart:convert';

import 'package:logger/logger.dart';

class CustomLogPrinter extends LogPrinter {
  static const topLeftCorner = '┌';
  static const bottomLeftCorner = '└';
  static const middleCorner = '├';
  static const verticalLine = '│';
  static const doubleDivider = '─';
  static const singleDivider = '┄';

  static final levelColors = {
	Level.verbose: AnsiColor.fg(AnsiColor.grey(0.5)),
	Level.debug: AnsiColor.none(),
	Level.info: AnsiColor.fg(12),
	Level.warning: AnsiColor.fg(208),
	Level.error: AnsiColor.fg(196),
	Level.wtf: AnsiColor.fg(199),
  };

  static final levelEmojis = {
	Level.verbose: '',
	Level.debug: '🐛 ',
	Level.info: '💡 ',
	Level.warning: '⚠️ ',
	Level.error: '⛔ ',
	Level.wtf: '👾 ',
  };

  /// Matches a stacktrace line as generated on Android/iOS devices.
  /// For example:
  /// #1      Logger.log (package:logger/src/logger.dart:115:29)
  static final _deviceStackTraceRegex =
	  RegExp(r'#[0-9]+[\s]+(.+) \(([^\s]+)\)');

  /// Matches a stacktrace line as generated by Flutter web.
  /// For example:
  /// packages/logger/src/printers/pretty_printer.dart 91:37
  static final _webStackTraceRegex =
	  RegExp(r'^((packages|dart-sdk)\/[^\s]+\/)');

  /// Matches a stacktrace line as generated by browser Dart.
  /// For example:
  /// dart:sdk_internal
  /// package:logger/src/logger.dart
  static final _browserStackTraceRegex =
	  RegExp(r'^(?:package:)?(dart:[^\s]+|[^\s]+)');

  static DateTime? _startTime;

  /// The index which to begin the stack trace at
  ///
  /// This can be useful if, for instance, Logger is wrapped in another class and
  /// you wish to remove these wrapped calls from stack trace
  final int stackTraceBeginIndex;
  final int methodCount;
  final int errorMethodCount;
  final int lineLength;
  final bool colors;
  final bool printEmojis;
  final bool printTime;
  final bool showBorder;

  String _topBorder = '';
  String _middleBorder = '';
  String _bottomBorder = '';

  CustomLogPrinter({
	this.stackTraceBeginIndex = 0,
	this.methodCount = 2,
	this.errorMethodCount = 8,
	this.lineLength = 120,
	this.colors = true,
	this.printEmojis = true,
	this.printTime = false,
	this.showBorder = true,
  }) {
	_startTime ??= DateTime.now();

	var doubleDividerLine = StringBuffer();
	var singleDividerLine = StringBuffer();
	for (var i = 0; i < lineLength - 1; i++) {
	  doubleDividerLine.write(doubleDivider);
	  singleDividerLine.write(singleDivider);
	}

	_topBorder = '$topLeftCorner$doubleDividerLine';
	_middleBorder = '$middleCorner$singleDividerLine';
	_bottomBorder = '$bottomLeftCorner$doubleDividerLine';
  }

  @override
  List<String> log(LogEvent event) {
	var messageStr = stringifyMessage(event.message);

	String? stackTraceStr;
	if (event.stackTrace == null) {
	  if (methodCount > 0) {
		stackTraceStr = formatStackTrace(StackTrace.current, methodCount);
	  }
	} else if (errorMethodCount > 0) {
	  stackTraceStr = formatStackTrace(event.stackTrace, errorMethodCount);
	}

	var errorStr = event.error?.toString();

	String? timeStr;
	if (printTime) {
	  timeStr = getTime();
	}

	return _formatAndPrint(
	  event.level,
	  messageStr,
	  timeStr,
	  errorStr,
	  stackTraceStr,
	);
  }

  String? formatStackTrace(StackTrace? stackTrace, int methodCount) {
	var lines = stackTrace.toString().split('\n');
	if (stackTraceBeginIndex > 0 && stackTraceBeginIndex < lines.length - 1) {
	  lines = lines.sublist(stackTraceBeginIndex);
	}
	var formatted = <String>[];
	var count = 0;
	for (var line in lines) {
	  if (_discardDeviceStacktraceLine(line) ||
		  _discardWebStacktraceLine(line) ||
		  _discardBrowserStacktraceLine(line) ||
		  line.isEmpty) {
		continue;
	  }
	  formatted.add('#$count   ${line.replaceFirst(RegExp(r'#\d+\s+'), '')}');
	  if (++count == methodCount) {
		break;
	  }
	}

	if (formatted.isEmpty) {
	  return null;
	} else {
	  return formatted.join('\n');
	}
  }

  bool _discardDeviceStacktraceLine(String line) {
	var match = _deviceStackTraceRegex.matchAsPrefix(line);
	if (match == null) {
	  return false;
	}
	return match.group(2)!.startsWith('package:logger');
  }

  bool _discardWebStacktraceLine(String line) {
	var match = _webStackTraceRegex.matchAsPrefix(line);
	if (match == null) {
	  return false;
	}
	return match.group(1)!.startsWith('packages/logger') ||
		match.group(1)!.startsWith('dart-sdk/lib');
  }

  bool _discardBrowserStacktraceLine(String line) {
	var match = _browserStackTraceRegex.matchAsPrefix(line);
	if (match == null) {
	  return false;
	}
	return match.group(1)!.startsWith('package:logger') ||
		match.group(1)!.startsWith('dart:');
  }

  String getTime() {
	String _threeDigits(int n) {
	  if (n >= 100) return '$n';
	  if (n >= 10) return '0$n';
	  return '00$n';
	}

	String _twoDigits(int n) {
	  if (n >= 10) return '$n';
	  return '0$n';
	}

	var now = DateTime.now();
	var h = _twoDigits(now.hour);
	var min = _twoDigits(now.minute);
	var sec = _twoDigits(now.second);
	var ms = _threeDigits(now.millisecond);
	var timeSinceStart = now.difference(_startTime!).toString();
	return '$h:$min:$sec.$ms (+$timeSinceStart)';
  }

  String stringifyMessage(dynamic message) {
	if (message is Map || message is Iterable) {
	  var encoder = JsonEncoder.withIndent('  ');
	  return encoder.convert(message);
	} else {
	  return message.toString();
	}
  }

  AnsiColor _getLevelColor(Level level) {
	if (colors) {
	  return levelColors[level]!;
	} else {
	  return AnsiColor.none();
	}
  }

  AnsiColor _getErrorColor(Level level) {
	if (colors) {
	  if (level == Level.wtf) {
		return levelColors[Level.wtf]!.toBg();
	  } else {
		return levelColors[Level.error]!.toBg();
	  }
	} else {
	  return AnsiColor.none();
	}
  }

  String _getEmoji(Level level) {
	if (printEmojis) {
	  return levelEmojis[level]!;
	} else {
	  return '';
	}
  }

  List<String> _formatAndPrint(
	Level level,
	String message,
	String? time,
	String? error,
	String? stacktrace,
  ) {
	// This code is non trivial and a type annotation here helps understanding.
	// ignore: omit_local_variable_types
	List<String> buffer = [];
	var color = _getLevelColor(level);
	if (showBorder) {
	  buffer.add(color(_topBorder));
	}

	if (error != null) {
	  var errorColor = _getErrorColor(level);
	  for (var line in error.split('\n')) {
		if (showBorder) {
		  buffer.add(
			color('$verticalLine ') +
				errorColor.resetForeground +
				errorColor(line) +
				errorColor.resetBackground,
		  );
		} else {
		  buffer.add(
			errorColor.resetForeground +
				errorColor(line) +
				errorColor.resetBackground,
		  );
		}
	  }
	  if (showBorder) {
		buffer.add(color(_middleBorder));
	  }
	}

	if (stacktrace != null) {
	  for (var line in stacktrace.split('\n')) {
		if (showBorder) {
		  buffer.add('$color$verticalLine $line');
		}
	  }
	  if (showBorder) {
		buffer.add(color(_middleBorder));
	  }
	}

	if (time != null) {
	  if (showBorder) {
		buffer..add(color('$verticalLine $time'))..add(color(_middleBorder));
	  }
	}

	var emoji = _getEmoji(level);
	for (var line in message.split('\n')) {
	  if (showBorder) {
		buffer.add(color('$verticalLine $emoji$line'));
	  } else {
		buffer.add(color('$emoji$line'));
	  }
	}
	if (showBorder) {
	  buffer.add(color(_bottomBorder));
	}

	return buffer;
  }
}

sagarnayak avatar Jun 09 '21 05:06 sagarnayak

any updates?

pol9kov avatar Feb 10 '23 21:02 pol9kov