diff --git a/source/net/filebot/Logging.java b/source/net/filebot/Logging.java index f58f5fd0..7b78b08d 100644 --- a/source/net/filebot/Logging.java +++ b/source/net/filebot/Logging.java @@ -20,8 +20,9 @@ import net.filebot.util.SystemProperty; public final class Logging { - private static final SystemProperty anonymizePattern = SystemProperty.of("net.filebot.logging.anonymize", Pattern::compile); private static final SystemProperty debugLevel = SystemProperty.of("net.filebot.logging.debug", Level::parse, Level.WARNING); + private static final SystemProperty anonymizePattern = SystemProperty.of("net.filebot.logging.anonymize", Pattern::compile); + private static final SystemProperty color = SystemProperty.of("net.filebot.logging.color", Boolean::parseBoolean, Color::isSupported); public static final Logger log = createConsoleLogger("net.filebot.console", Level.ALL); public static final Logger debug = createConsoleLogger("net.filebot.debug", debugLevel.get()); @@ -41,7 +42,7 @@ public final class Logging { } public static ConsoleHandler createConsoleHandler(Level level) { - ConsoleHandler handler = new ConsoleHandler(); + ConsoleHandler handler = color.get() ? new AnsiColorConsoleHandler() : new ConsoleHandler(); handler.setLevel(level); handler.setFormatter(new ConsoleFormatter(anonymizePattern.get())); return handler; @@ -65,6 +66,25 @@ public final class Logging { }; } + public static class ConsoleFormatter extends Formatter { + + private final Pattern anonymize; + + public ConsoleFormatter(Pattern anonymize) { + this.anonymize = anonymize; + } + + @Override + public String format(LogRecord record) { + String message = record.getMessage(); + if (anonymize != null && message != null) { + message = anonymize.matcher(message).replaceAll(""); + } + + return message + System.lineSeparator(); + } + } + public static class ConsoleHandler extends Handler { @Override @@ -72,16 +92,20 @@ public final class Logging { // use either System.out or System.err depending on the severity of the error PrintStream out = record.getLevel().intValue() < Level.WARNING.intValue() ? System.out : System.err; - // print messages + // print messages to selected output stream + print(record, out); + + // flush every message immediately + out.flush(); + } + + public void print(LogRecord record, PrintStream out) { out.print(getFormatter().format(record)); Throwable thrown = record.getThrown(); if (thrown != null) { StackTraceUtils.deepSanitize(thrown).printStackTrace(out); } - - // flush every message immediately - out.flush(); } @Override @@ -97,22 +121,66 @@ public final class Logging { } - public static class ConsoleFormatter extends Formatter { - - private final Pattern anonymize; - - public ConsoleFormatter(Pattern anonymize) { - this.anonymize = anonymize; - } + public static class AnsiColorConsoleHandler extends ConsoleHandler { @Override - public String format(LogRecord record) { - String message = record.getMessage(); - if (anonymize != null && message != null) { - message = anonymize.matcher(message).replaceAll(""); + public void print(LogRecord record, PrintStream out) { + Color c = getColor(record.getLevel().intValue()); + + if (c == null) { + super.print(record, out); + } else { + out.print(c.head); + super.print(record, out); + out.print(c.tail); } - return message + System.lineSeparator(); } + + public Color getColor(int level) { + if (level >= Level.SEVERE.intValue()) + return Color.CHERRY_RED; + if (level >= Level.WARNING.intValue()) + return Color.ORANGE_RED; + if (level >= Level.INFO.intValue()) + return null; + if (level >= Level.FINE.intValue()) + return Color.ROYAL_BLUE; + if (level >= Level.FINEST.intValue()) + return Color.LIME_GREEN; + + return null; + } + + } + + public static class Color { + + public static final Color CHERRY_RED = new Color(0xC4); + public static final Color ORANGE_RED = new Color(0xCA); + public static final Color ROYAL_BLUE = new Color(0x28); + public static final Color LIME_GREEN = new Color(0x27); + + public final String head; + public final String tail; + + Color(int color) { + this("38;5;" + color); // see https://en.wikipedia.org/wiki/ANSI_escape_code#Colors + } + + Color(String code) { + this.head = "\u001b[" + code + "m"; + this.tail = "\u001b[0m"; + } + + public String colorize(String message) { + return head + message + tail; + } + + public static boolean isSupported() { + // enable ANSI colors on a standard terminal (if running with interactive console) + return System.console() != null && "xterm-256color".equals(System.getenv("TERM")); + } + } }