simc / logger

Small, easy to use and extensible logger which prints beautiful logs.
https://pub.dev/packages/logger
MIT License
1.07k stars 129 forks source link

Looks ugly in Android Studio #61

Open subzero911 opened 3 years ago

subzero911 commented 3 years ago

VS Code: image

AS: image

subzero911 commented 3 years ago

Both consoles use bash.

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

subzero911 commented 3 years ago

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

subzero911 commented 3 years ago

It parses wrong, showing strange symbols:

image

haarts commented 3 years ago

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 notifications@github.com 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 .

subzero911 commented 3 years ago

But SimplePrinter does not show these references. image

subzero911 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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

haarts commented 3 years ago

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 commented 3 years ago

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?

subzero911 commented 3 years ago

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 commented 3 years ago

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

kesteinbakk commented 3 years ago

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?

sagarnayak commented 3 years ago

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;
  }
}
pol9kov commented 1 year ago

any updates?