You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2012/11/01 16:49:38 UTC

svn commit: r1404650 - in /logging/log4j/log4j2/trunk/core/src: main/java/org/apache/logging/log4j/core/pattern/ test/java/org/apache/logging/log4j/core/appender/ test/resources/

Author: ggregory
Date: Thu Nov  1 15:49:38 2012
New Revision: 1404650

URL: http://svn.apache.org/viewvc?rev=1404650&view=rev
Log:
Allow custom ANSI mappings for Levels.

Added:
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java   (with props)
    logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight-default.xml   (with props)
Modified:
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java
    logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight.xml

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java?rev=1404650&r1=1404649&r2=1404650&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java Thu Nov  1 15:49:38 2012
@@ -16,6 +16,9 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  *
  */
@@ -84,6 +87,62 @@ public enum AnsiEscape {
         return code;
     }
 
+    /**
+     * Creates a Map from a source string. The format is:
+     * 
+     * <pre>
+     * Key1=Value, Key2=Value, ...
+     * </pre>
+     * 
+     * For example:
+     * 
+     * <pre>
+     * ERROR=red bold, WARN=yellow bold, INFO=green, ...
+     * </pre>
+     * 
+     * You can use whitespace around the comma and equal sign. The names in values MUST come from the {@linkplain AnsiEscape} enum, case is
+     * normalized to upper-case internally.
+     * 
+     * @param values
+     *            the source string to parse.
+     * @return a new map
+     */
+    public static Map<String, String> createMap(String values) {
+        return createMap(values.split("\\s*,\\s*"));
+    }
+
+    /**
+     * Creates a Map from a source array. Each array entry must be in the format:
+     * 
+     * <pre>
+     * Key1 = Value
+     * </pre>
+     * 
+     * For example:
+     * 
+     * <pre>
+     * ERROR=red bold
+     * </pre>
+     * 
+     * You can use whitespace around the equal sign and between the value elements. The names in values MUST come from the
+     * {@linkplain AnsiEscape} enum, case is normalized to upper-case internally.
+     * 
+     * @param values
+     *            the source array to parse.
+     * @return a new map
+     */
+    public static Map<String, String> createMap(String[] values) {
+        Map<String, String> map = new HashMap<String, String>();
+        for (String string : values) {
+            String[] keyValue = string.split("\\s*=\\s*");
+            if (keyValue.length > 1) {
+                final String style = keyValue[1];
+                map.put(keyValue[0], createSequence(style.split("\\s")));
+            }
+        }
+        return map;
+    }
+
     public static String createSequence(String[] values) {
         if (values == null) {
             return getDefaultStyle();

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java?rev=1404650&r1=1404649&r2=1404650&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java Thu Nov  1 15:49:38 2012
@@ -16,58 +16,102 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.layout.PatternLayout;
 
-import java.util.EnumMap;
-import java.util.List;
-
 /**
- * Highlight pattern converter. Formats the result of a pattern using a color appropriate
- * for the Level in the LogEvent.
+ * Highlight pattern converter. Formats the result of a pattern using a color appropriate for the Level in the LogEvent.
+ * <p>
+ * For example:
+ * </p>
+ * 
+ * <pre>
+ * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}
+ * </pre>
+ * <p>
+ * You can define custom colors for each Level:
+ * </p>
+ * 
+ * <pre>
+ * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}{FATAL=red, ERROR=red, WARN=yellow, INFO=green, DEBUG=cyan, TRACE=black}
+ * </pre>
+ * <p>
+ * You can use whitespace around the comma and equal sign. The names in values MUST come from the {@linkplain AnsiEscape} enum, case is
+ * normalized to upper-case internally.
+ * </p>
  */
 @Plugin(name = "highlight", type = "Converter")
-@ConverterKeys({"highlight" })
+@ConverterKeys({ "highlight" })
 public final class HighlightConverter extends LogEventPatternConverter {
 
-    private static final EnumMap<Level, String> LEVEL_STYLES = new EnumMap<Level, String>(Level.class);
-
-    private static final String[] FATAL = new String[]{"BLINK", "BRIGHT", "RED"};
-    private static final String[] ERROR = new String[] {"BRIGHT", "RED"};
-    private static final String[] WARN = new String[] {"RED"};
-    private static final String[] INFO = new String[] {"BLUE"};
-    private static final String[] DEBUG = null;
-    private static final String[] TRACE = null;
-
-    private final List<PatternFormatter> formatters;
+    private static final String[] DEFAULT_FATAL = new String[] { "BLINK", "BRIGHT", "RED" };
+    private static final String[] DEFAULT_ERROR = new String[] { "BRIGHT", "RED" };
+    private static final String[] DEFAULT_WARN = new String[] { "RED" };
+    private static final String[] DEFAULT_INFO = new String[] { "BLUE" };
+    private static final String[] DEFAULT_DEBUG = null;
+    private static final String[] DEFAULT_TRACE = null;
+    
+    private static final EnumMap<Level, String> LEVEL_STYLES_DEFAULT = new EnumMap<Level, String>(Level.class);
 
     static {
-        LEVEL_STYLES.put(Level.FATAL, AnsiEscape.createSequence(FATAL));
-        LEVEL_STYLES.put(Level.ERROR, AnsiEscape.createSequence(ERROR));
-        LEVEL_STYLES.put(Level.WARN, AnsiEscape.createSequence(WARN));
-        LEVEL_STYLES.put(Level.INFO, AnsiEscape.createSequence(INFO));
-        LEVEL_STYLES.put(Level.DEBUG, AnsiEscape.createSequence(DEBUG));
-        LEVEL_STYLES.put(Level.TRACE, AnsiEscape.createSequence(TRACE));
+        LEVEL_STYLES_DEFAULT.put(Level.FATAL, AnsiEscape.createSequence(DEFAULT_FATAL));
+        LEVEL_STYLES_DEFAULT.put(Level.ERROR, AnsiEscape.createSequence(DEFAULT_ERROR));
+        LEVEL_STYLES_DEFAULT.put(Level.WARN, AnsiEscape.createSequence(DEFAULT_WARN));
+        LEVEL_STYLES_DEFAULT.put(Level.INFO, AnsiEscape.createSequence(DEFAULT_INFO));
+        LEVEL_STYLES_DEFAULT.put(Level.DEBUG, AnsiEscape.createSequence(DEFAULT_DEBUG));
+        LEVEL_STYLES_DEFAULT.put(Level.TRACE, AnsiEscape.createSequence(DEFAULT_TRACE));
     }
 
     /**
-     * Construct the converter.
-     * @param formatters The PatternFormatters to generate the text to manipulate.
+     * Creates a level style map given configuration options in {@code option[1]}.
+     * <p/>
+     * The format of the option string in {@code option[1]} is:
+     * 
+     * <pre>
+     * Level1=Value, Level2=Value, ...
+     * </pre>
+     * 
+     * For example:
+     * 
+     * <pre>
+     * ERROR=red bold, WARN=yellow bold, INFO=green, ...
+     * </pre>
+     * 
+     * You can use whitespace around the comma and equal sign. The names in values MUST come from the {@linkplain AnsiEscape} enum, case is
+     * normalized to upper-case internally.
+     * 
+     * @param options
+     *            The second slot can optionally contain the style map.
+     * @return a new map
      */
-    private HighlightConverter(List<PatternFormatter> formatters) {
-        super("style", "style");
-        this.formatters = formatters;
+    private static EnumMap<Level, String> createLevelStyleMap(final String[] options) {
+        Map<String, String> styles = options.length < 2 ? null : AnsiEscape.createMap(options[1]);
+        EnumMap<Level, String> levelStyles = new EnumMap<Level, String>(LEVEL_STYLES_DEFAULT);
+        for (Map.Entry<String, String> entry : styles.entrySet()) {
+            final Level key = Level.valueOf(entry.getKey());
+            if (key == null) {
+                LOGGER.error("Unkown level name: " + entry.getKey());
+            } else {
+                levelStyles.put(key, entry.getValue());
+            }
+        }
+        return levelStyles;
     }
 
     /**
      * Gets an instance of the class.
-     *
-     * @param config The current Configuration.
-     * @param options pattern options, may be null.  If first element is "short",
-     *                only the first line of the throwable will be formatted.
+     * 
+     * @param config
+     *            The current Configuration.
+     * @param options
+     *            pattern options, may be null. If first element is "short", only the first line of the throwable will be formatted.
      * @return instance of class.
      */
     public static HighlightConverter newInstance(Configuration config, final String[] options) {
@@ -79,12 +123,26 @@ public final class HighlightConverter ex
             LOGGER.error("No pattern supplied on style");
             return null;
         }
-
         PatternParser parser = PatternLayout.createPatternParser(config);
         List<PatternFormatter> formatters = parser.parse(options[0]);
-        return new HighlightConverter(formatters);
+        return new HighlightConverter(formatters, createLevelStyleMap(options));
     }
 
+    private final List<PatternFormatter> formatters;
+
+    private final EnumMap<Level, String> levelStyles;
+
+    /**
+     * Construct the converter.
+     * 
+     * @param formatters
+     *            The PatternFormatters to generate the text to manipulate.
+     */
+    private HighlightConverter(List<PatternFormatter> formatters, EnumMap<Level, String> levelStyles) {
+        super("style", "style");
+        this.formatters = formatters;
+        this.levelStyles = levelStyles;
+    }
 
     /**
      * {@inheritDoc}
@@ -97,8 +155,7 @@ public final class HighlightConverter ex
         }
 
         if (buf.length() > 0) {
-            toAppendTo.append(LEVEL_STYLES.get(event.getLevel())).append(buf.toString()).
-                append(AnsiEscape.getDefaultStyle());
+            toAppendTo.append(levelStyles.get(event.getLevel())).append(buf.toString()).append(AnsiEscape.getDefaultStyle());
         }
     }
 }

Added: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java?rev=1404650&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java (added)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java Thu Nov  1 15:49:38 2012
@@ -0,0 +1,34 @@
+package org.apache.logging.log4j.core.appender;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configurator;
+
+/**
+ * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest of the log entry
+ * (time stamp for example) is in the default color for that console.
+ */
+public class ConsoleAppenderHighlightLayoutDefaultMain {
+
+    private static final Logger LOG = LogManager.getLogger(ConsoleAppenderHighlightLayoutDefaultMain.class);
+
+    public static void main(String[] args) {
+        LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), null,
+                "target/test-classes/log4j2-console-highlight-default.xml");
+        try {
+            LOG.fatal("Fatal message.");
+            LOG.error("Error message.");
+            LOG.warn("Warning message.");
+            LOG.info("Information message.");
+            LOG.debug("Debug message.");
+            LOG.trace("Trace message.");
+            LOG.error("Error message.", new IOException("test"));
+        } finally {
+            Configurator.shutdown(ctx);
+        }
+    }
+
+}

Propchange: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight-default.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight-default.xml?rev=1404650&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight-default.xml (added)
+++ logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight-default.xml Thu Nov  1 15:49:38 2012
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<configuration status="OFF">
+  <appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="%highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}" />
+    </Console>
+  </appenders>
+  <loggers>
+    <logger name="org.foo" level="DEBUG" />
+    <root level="TRACE">
+      <appender-ref ref="Console" />
+    </root>
+  </loggers>
+</configuration>
\ No newline at end of file

Propchange: logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight-default.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight-default.xml
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight.xml?rev=1404650&r1=1404649&r2=1404650&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight.xml (original)
+++ logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight.xml Thu Nov  1 15:49:38 2012
@@ -19,7 +19,7 @@
 <configuration status="OFF">
   <appenders>
     <Console name="Console" target="SYSTEM_OUT">
-      <PatternLayout pattern="%highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}" />
+      <PatternLayout pattern="%highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}{FATAL=white, ERROR=red, WARN=blue, INFO=black, DEBUG=green, TRACE=blue}" />
     </Console>
   </appenders>
   <loggers>