[KARAF-2401] Improve log coloring
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/5686ccf6 Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/5686ccf6 Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/5686ccf6 Branch: refs/heads/KARAF-2401 Commit: 5686ccf651600790197b9ca4e5ce69e0930107f5 Parents: 844bacf Author: Guillaume Nodet <[email protected]> Authored: Fri Oct 20 10:01:29 2017 +0200 Committer: Guillaume Nodet <[email protected]> Committed: Fri Oct 20 10:01:29 2017 +0200 ---------------------------------------------------------------------- .../resources/etc/org.ops4j.pax.logging.cfg | 12 +- .../standard/src/main/feature/feature.xml | 8 +- .../src/test/filtered-resources/etc/feature.xml | 8 +- .../log/core/internal/layout/PatternParser.java | 154 ++++++++++++++++++- 4 files changed, 174 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/karaf/blob/5686ccf6/assemblies/features/base/src/main/resources/resources/etc/org.ops4j.pax.logging.cfg ---------------------------------------------------------------------- diff --git a/assemblies/features/base/src/main/resources/resources/etc/org.ops4j.pax.logging.cfg b/assemblies/features/base/src/main/resources/resources/etc/org.ops4j.pax.logging.cfg index 0c9d54e..42d6c80 100644 --- a/assemblies/features/base/src/main/resources/resources/etc/org.ops4j.pax.logging.cfg +++ b/assemblies/features/base/src/main/resources/resources/etc/org.ops4j.pax.logging.cfg @@ -17,8 +17,18 @@ # ################################################################################ +# Colors for log level rendering +color.fatal = bright red +color.error = bright red +color.warn = bright yellow +color.info = bright green +color.debug = cyan +color.trace = cyan + # Common pattern layout for appenders log4j2.pattern = %d{ISO8601} | %-5p | %-16t | %-32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n +log4j2.out.pattern = \u001b[90m%d{HH:mm:ss\.SSS}\u001b[0m %highlight{%-5level}{FATAL=${color.fatal}, ERROR=${color.error}, WARN=${color.warn}, INFO=${color.info}, DEBUG=${color.debug}, TRACE=${color.trace}} \u001b[90m[%t]\u001b[0m %msg%n%throwable + # Root logger log4j2.rootLogger.level = INFO @@ -49,7 +59,7 @@ log4j2.logger.audit.appenderRef.AuditRollingFile.ref = AuditRollingFile log4j2.appender.console.type = Console log4j2.appender.console.name = Console log4j2.appender.console.layout.type = PatternLayout -log4j2.appender.console.layout.pattern = ${log4j2.pattern} +log4j2.appender.console.layout.pattern = ${log4j2.out.pattern} # Rolling file appender log4j2.appender.rolling.type = RollingRandomAccessFile http://git-wip-us.apache.org/repos/asf/karaf/blob/5686ccf6/assemblies/features/standard/src/main/feature/feature.xml ---------------------------------------------------------------------- diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml index d785e80..49a2d2b 100644 --- a/assemblies/features/standard/src/main/feature/feature.xml +++ b/assemblies/features/standard/src/main/feature/feature.xml @@ -520,7 +520,13 @@ # The pattern used to format the log statement when using log:display. This pattern is according # to the log4j layout. You can override this parameter at runtime using log:display with -p. # - pattern = "%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n" + color.fatal = "bright red" + color.error = "bright red" + color.warn = "bright yellow" + color.info = "bright green" + color.debug = "cyan" + color.trace = "cyan" + pattern = "\u001b[90m%d{HH:mm:ss.SSS}\u001b[0m %h{%p}{FATAL=${color.fatal}, ERROR=${color.error}, WARN=${color.warn}, INFO=${color.info}, DEBUG=${color.debug}, TRACE=${color.trace}} \u001b[90m[%t]\u001b[0m %m%n" </config> <bundle start-level="30">mvn:org.apache.karaf.log/org.apache.karaf.log.core/${project.version}</bundle> </feature> http://git-wip-us.apache.org/repos/asf/karaf/blob/5686ccf6/itests/src/test/filtered-resources/etc/feature.xml ---------------------------------------------------------------------- diff --git a/itests/src/test/filtered-resources/etc/feature.xml b/itests/src/test/filtered-resources/etc/feature.xml index 487d4ea..803507c 100644 --- a/itests/src/test/filtered-resources/etc/feature.xml +++ b/itests/src/test/filtered-resources/etc/feature.xml @@ -520,7 +520,13 @@ # The pattern used to format the log statement when using log:display. This pattern is according # to the log4j layout. You can override this parameter at runtime using log:display with -p. # - pattern = "%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n" + color.fatal = "bright red" + color.error = "bright red" + color.warn = "bright yellow" + color.info = "bright green" + color.debug = "cyan" + color.trace = "cyan" + pattern = "\u001b[90m%d{HH:mm:ss.SSS}\u001b[0m %h{%p}{FATAL=${color.fatal}, ERROR=${color.error}, WARN=${color.warn}, INFO=${color.info}, DEBUG=${color.debug}, TRACE=${color.trace}} \u001b[90m[%t]\u001b[0m %m%n" </config> <bundle start-level="30" start="true">mvn:org.apache.karaf.log/org.apache.karaf.log.core/${project.version}</bundle> </feature> http://git-wip-us.apache.org/repos/asf/karaf/blob/5686ccf6/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java ---------------------------------------------------------------------- diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java b/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java index 5232b07..4c67b1d 100644 --- a/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java +++ b/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java @@ -21,8 +21,11 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; +import java.util.HashMap; +import java.util.Locale; import java.util.Map; +import org.ops4j.pax.logging.PaxLogger; import org.ops4j.pax.logging.spi.PaxLocationInfo; import org.ops4j.pax.logging.spi.PaxLoggingEvent; @@ -89,11 +92,21 @@ public class PatternParser { protected String extractOption() { if((i < patternLength) && (pattern.charAt(i) == '{')) { - int end = pattern.indexOf('}', i); - if (end > i) { - String r = pattern.substring(i + 1, end); - i = end+1; - return r; + int end = i; + int nb = 1; + while (++end < patternLength) { + switch (pattern.charAt(end)) { + case '{': + nb++; + break; + case '}': + if (--nb == 0) { + String r = pattern.substring(i + 1, end); + i = end + 1; + return r; + } + break; + } } } return null; @@ -277,6 +290,12 @@ public class PatternParser { //formattingInfo.dump(); currentLiteral.setLength(0); break; + case 'h': + String pat = extractOption(); + String style = extractOption(); + pc = new HighlightPatternConverter(formattingInfo, pat, style); + currentLiteral.setLength(0); + break; /*case 'l': pc = new LocationPatternConverter(formattingInfo, FULL_LOCATION_CONVERTER); @@ -441,6 +460,131 @@ public class PatternParser { } } + private static class HighlightPatternConverter extends PatternConverter { + static Map<String, String> SEQUENCES; + static { + SEQUENCES = new HashMap<>(); + SEQUENCES.put("csi", "\u001b["); + SEQUENCES.put("suffix", "m"); + SEQUENCES.put("separator", ";"); + SEQUENCES.put("normal", "0"); + SEQUENCES.put("bold", "1"); + SEQUENCES.put("bright", "1"); + SEQUENCES.put("dim", "2"); + SEQUENCES.put("underline", "3"); + SEQUENCES.put("blink", "5"); + SEQUENCES.put("reverse", "7"); + SEQUENCES.put("hidden", "8"); + SEQUENCES.put("black", "30"); + SEQUENCES.put("fg_black", "30"); + SEQUENCES.put("red", "31"); + SEQUENCES.put("fg_red", "31"); + SEQUENCES.put("green", "32"); + SEQUENCES.put("fg_green", "32"); + SEQUENCES.put("yellow", "33"); + SEQUENCES.put("fg_yellow", "33"); + SEQUENCES.put("blue", "34"); + SEQUENCES.put("fg_blue", "34"); + SEQUENCES.put("magenta", "35"); + SEQUENCES.put("fg_magenta", "35"); + SEQUENCES.put("cyan", "36"); + SEQUENCES.put("fg_cyan", "36"); + SEQUENCES.put("white", "37"); + SEQUENCES.put("fg_white", "37"); + SEQUENCES.put("default", "39"); + SEQUENCES.put("fg_default", "39"); + SEQUENCES.put("bg_black", "40"); + SEQUENCES.put("bg_red", "41"); + SEQUENCES.put("bg_green", "42"); + SEQUENCES.put("bg_yellow", "43"); + SEQUENCES.put("bg_blue", "44"); + SEQUENCES.put("bg_magenta", "45"); + SEQUENCES.put("bg_cyan", "46"); + SEQUENCES.put("bg_white", "47"); + SEQUENCES.put("bg_default", "49"); + } + private PatternConverter pattern; + private Map<String, String> style; + + HighlightPatternConverter(FormattingInfo formattingInfo, String pattern, String style) { + super(formattingInfo); + this.pattern = new PatternParser(pattern).parse(); + Map<String, String> unparsed = new HashMap<>(); + unparsed.put("trace", "cyan"); + unparsed.put("debug", "cyan"); + unparsed.put("info", "bright green"); + unparsed.put("warn", "bright yellow"); + unparsed.put("error", "bright red"); + unparsed.put("fatal", "bright red"); + if (style != null) { + style = style.toLowerCase(Locale.ENGLISH); + if (style.indexOf(',') < 0 && style.indexOf('=') < 0) { + unparsed.put("trace", style.trim()); + unparsed.put("debug", style.trim()); + unparsed.put("info", style.trim()); + unparsed.put("warn", style.trim()); + unparsed.put("error", style.trim()); + unparsed.put("fatal", style.trim()); + } else { + String[] keys = style.split("\\s*,\\s*"); + for (String key : keys) { + String[] val = key.split("\\s*=\\s*"); + if (val.length > 1) { + unparsed.put(val[0].trim(), val[1].trim()); + } + } + } + } + this.style = new HashMap<>(); + for (Map.Entry<String, String> e : unparsed.entrySet()) { + this.style.put(e.getKey(), createSequence(e.getValue().split("\\s"))); + } + } + + private String createSequence(String... names) { + StringBuilder sb = new StringBuilder(SEQUENCES.get("csi")); + boolean first = true; + for (String name : names) { + name = name.trim(); + if (!first) { + sb.append(SEQUENCES.get("separator")); + } + first = false; + sb.append(SEQUENCES.getOrDefault(name, name)); + } + sb.append(SEQUENCES.get("suffix")); + return sb.toString(); + } + + public + String convert(PaxLoggingEvent event) { + String s; + switch (event.getLevel().toInt()) { + case PaxLogger.LEVEL_TRACE: + s = "trace"; + break; + case PaxLogger.LEVEL_DEBUG: + s = "debug"; + break; + case PaxLogger.LEVEL_INFO: + s = "info"; + break; + case PaxLogger.LEVEL_WARNING: + s = "warn"; + break; + default: + s = "error"; + break; + } + String str = style.get(s); + if (str != null) { + return str + pattern.convert(event) + SEQUENCES.get("csi") + SEQUENCES.get("suffix"); + } else { + return pattern.convert(event); + } + } + } + private class LocationPatternConverter extends PatternConverter { int type;
