Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LogConsoleHandler / feature request #9

Open
MikeMitterer opened this issue Jul 14, 2014 · 2 comments
Open

LogConsoleHandler / feature request #9

MikeMitterer opened this issue Jul 14, 2014 · 2 comments

Comments

@MikeMitterer
Copy link

Hi Chris, can you do me a favor and add a LogConsolHandler:

class LogConsoleHandler implements BaseLoggingHandler {

    LogRecordTransformer transformer;
    String messageFormat;
    String exceptionFormatSuffix;
    String timestampFormat;

    LogConsoleHandler({
                    this.messageFormat: StringTransformer.DEFAULT_MESSAGE_FORMAT,
                    this.exceptionFormatSuffix: StringTransformer.DEFAULT_EXCEPTION_FORMAT,
                    this.timestampFormat: StringTransformer.DEFAULT_DATE_TIME_FORMAT }) {

        transformer = new StringTransformer(
            messageFormat: messageFormat,
            exceptionFormatSuffix: exceptionFormatSuffix,
            timestampFormat: timestampFormat);
    }

    void call(LogRecord logRecord) {
        if(logRecord.level <= Level.FINE) {
            window.console.debug(transformer.transform(logRecord));

        } else if(logRecord.level <= Level.INFO) {
            window.console.info(transformer.transform(logRecord));

        } else {
            window.console.error(transformer.transform(logRecord));
        }
    }
}
@MikeMitterer
Copy link
Author

Hi, I've updated my Logger. As you can see in den SS it gives a really nice output. The only application-specific part is _makeJsonGroup. I could adapt it to a more general solution if you want.
How can I help?

The output you can see in the SS is produced by:
_logger.severe("Got RestError: ${resterror.data.devmessage}",resterror, stacktrace);

As you can see I added:
%r | %r = Short Logger.name - padded with space if width is given

library webapp_base_dart.logging;

import 'dart:html';
import "package:intl/intl.dart";

import 'package:logging/logging.dart';
import 'package:logging_handlers/logging_handlers_shared.dart';

import 'package:webapp_base_dart/communication.dart';

/**
 * Gibt die Logmessages farbig auf der Console aus
 *
 * Format:
 *      %p = Outputs LogRecord.level
 *      %m = Outputs LogRecord.message
 *      %n = Outputs the Logger.name
 *      %r | %<width>r = Short Logger.name - padded with space if width is given
 *      %t = Outputs the timestamp according to the Date Time Format specified
 *      %s = Outputs the logger sequence
 *      %x = Outputs the exception
 *      %e = Outputs the exception message
 */
class LogConsoleHandler implements BaseLoggingHandler {
    /// Default format for a log message that does not contain an exception.
    static const DEFAULT_MESSAGE_FORMAT = "%r: (%t) %m";

    LogRecordTransformer transformer;

    String messageFormat;
    String exceptionFormatSuffix;
    String timestampFormat;

    LogConsoleHandler({ this.messageFormat: DEFAULT_MESSAGE_FORMAT,
                        this.exceptionFormatSuffix: StringTransformer.DEFAULT_EXCEPTION_FORMAT,
                        this.timestampFormat: StringTransformer.DEFAULT_DATE_TIME_FORMAT } ) {

        transformer = new ConsolStringTransformer(messageFormat: messageFormat, timestampFormat: timestampFormat);
    }

    void call(final LogRecord logRecord) {
        if (logRecord.level <= Level.FINE) {
            window.console.debug(transformer.transform(logRecord));

        }
        else if (logRecord.level <= Level.INFO) {
            window.console.info(transformer.transform(logRecord));

        }
        else {
            window.console.error(transformer.transform(logRecord));
        }
        _makeStackTraceGroup("  ○ StackTrace",logRecord);
        _makeJsonGroup(      "  ○ JSON-Object",logRecord);
    }

    // -- private -------------------------------------------------------------

    void _makeJsonGroup(final String groupName, final LogRecord logRecord) {
        if (logRecord.error != null) {
            if (logRecord.error is JsonTO) {
                window.console.groupCollapsed(groupName);
                window.console.log((logRecord.error as JsonTO).toPrettyString());
                window.console.groupEnd();
            }
        }
    }

    void _makeStackTraceGroup(final String groupName, final LogRecord logRecord) {
        if (logRecord.stackTrace != null) {
            window.console.group(groupName);
            window.console.log(logRecord.stackTrace.toString());
            window.console.groupEnd();
        }
    }
}

/// Format a log record according to a string pattern
class ConsolStringTransformer implements LogRecordTransformer {

    /// Outputs [LogRecord.level]
    static const LEVEL = "%p";

    /// Outputs [LogRecord.message]
    static const MESSAGE = "%m";

    /// Outputs the [Logger.name]
    static const NAME = "%n";

    /// Outputs the short version of [Logger.name]
    static const NAME_SHORT = '(?:%\\d{1,2}r|%r)';

    /// Outputs the timestamp according to the Date Time Format specified in
    /// [timestampFormatString]
    static const TIME = "%t";

    /// Outputs the logger sequence
    static const SEQ = "%s";

    /// logger exception
    static const EXCEPTION = "%x";

    /// logger exception message
    static const EXCEPTION_TEXT = "%e";

    /// Default format for a log message that does not contain an exception.
    static const DEFAULT_MESSAGE_FORMAT = "%t\t%n\t[%p]:\t%m";

    /// Default format for a log message the contains an exception
    /// This is appended onto the message format if there is an exception
    static const DEFAULT_EXCEPTION_FORMAT = "\n%e\n%x";

    /// Default date time format for log messages
    static const DEFAULT_DATE_TIME_FORMAT = "HH:mm:ss.SSS";

    /// Contains the standard message format string
    final String messageFormat;

    /// Contains the timestamp format string
    final String timestampFormat;

    /// Contains the date format instance
    DateFormat dateFormat;

    /// Contains the regexp pattern
    static final _regexp = new List<RegExp>.from([new RegExp(LEVEL), new RegExp(MESSAGE), new RegExp(NAME), new RegExp(NAME_SHORT), new RegExp(TIME), new RegExp(SEQ), new RegExp(EXCEPTION), new RegExp(EXCEPTION_TEXT)]);

    ConsolStringTransformer({String this.messageFormat : StringTransformer.DEFAULT_MESSAGE_FORMAT, String this.timestampFormat : StringTransformer.DEFAULT_DATE_TIME_FORMAT}) {
        dateFormat = new DateFormat(this.timestampFormat);
    }

    /**
     * Transform the log record into a string according to the [messageFormat],
     * [exceptionFormatSuffix] and [timestampFormat] pattern.
     */
    String transform(LogRecord logRecord) {
        String formatString = messageFormat;

        int lengthInPattern(final String pattern) {
            final String digits = pattern.replaceAll(new RegExp('[^\\d]'),'');
            return int.parse(digits,onError: (_) => 0);
        }

        _regexp.forEach((final RegExp regexp) {
            switch (regexp.pattern) {

                case LEVEL:
                    formatString = formatString.replaceAll(regexp, logRecord.level.name);
                    break;

                case MESSAGE:
                    formatString = formatString.replaceAll(regexp, logRecord.message);
                    break;

                case NAME:
                    formatString = formatString.replaceAll(regexp, logRecord.loggerName);
                    break;

                case NAME_SHORT:
                    final String shortLoggerName = logRecord.loggerName.replaceAll(new RegExp('^.+\\.'), "");

                    formatString = formatString.replaceAllMapped(regexp, (final Match match) {
                        final int length = lengthInPattern(match.group(0));
                        return shortLoggerName.padRight(length);
                    });
                    break;

                case TIME:
                    if (logRecord.time != null) {
                        try {
                            formatString = formatString.replaceAll(regexp, dateFormat.format(logRecord.time));
                        }
                        on UnimplementedError
                        catch (e) {
                            // at time of writing, dateFormat.format seems to be unimplemented.
                            // so just return the time.toString()
                            formatString = formatString.replaceAll(regexp, logRecord.time.toString());
                        }
                    }

                    break;
                case SEQ:
                    formatString = formatString.replaceAll(regexp, logRecord.sequenceNumber.toString());
                    break;

                case EXCEPTION:case EXCEPTION_TEXT:
                    if (logRecord.error != null) formatString = formatString.replaceAll(regexp, logRecord.error.toString());
                    break;
            }
        });

        return formatString;
    }
}

screenshot-1567

@stevenroose
Copy link

Make a PR.

@chrisbu
Would you be willing to give me write permission to this repo to update to latest logging version and take a look at PRs and issues?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants