You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2012/10/01 01:09:31 UTC

svn commit: r1392129 - in /logging/log4j/log4j2/trunk: core/ core/src/main/java/org/apache/logging/log4j/core/appender/ core/src/main/java/org/apache/logging/log4j/core/pattern/ core/src/test/java/org/apache/logging/log4j/core/pattern/ core/src/test/re...

Author: rgoers
Date: Sun Sep 30 23:09:30 2012
New Revision: 1392129

URL: http://svn.apache.org/viewvc?rev=1392129&view=rev
Log:
Add support for ANSI styling in PatternLayout

Added:
    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/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java
      - copied, changed from r1391705, logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/RegexReplacementConverter.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java
      - copied, changed from r1391705, logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementTest.java
    logging/log4j/log4j2/trunk/core/src/test/resources/log4j-style.xml
      - copied, changed from r1391705, logging/log4j/log4j2/trunk/core/src/test/resources/log4j-replace.xml
Modified:
    logging/log4j/log4j2/trunk/core/pom.xml
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
    logging/log4j/log4j2/trunk/core/src/test/resources/log4j-replace.xml
    logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/Category.java
    logging/log4j/log4j2/trunk/src/changes/changes.xml
    logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml

Modified: logging/log4j/log4j2/trunk/core/pom.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/pom.xml?rev=1392129&r1=1392128&r2=1392129&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/pom.xml (original)
+++ logging/log4j/log4j2/trunk/core/pom.xml Sun Sep 30 23:09:30 2012
@@ -51,6 +51,12 @@
       <optional>true</optional>
     </dependency>
     <dependency>
+      <groupId>org.fusesource.jansi</groupId>
+      <artifactId>jansi</artifactId>
+      <version>1.9</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
       <groupId>oro</groupId>
       <artifactId>oro</artifactId>
       <version>2.0.8</version>

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java?rev=1392129&r1=1392128&r2=1392129&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java Sun Sep 30 23:09:30 2012
@@ -22,9 +22,13 @@ import org.apache.logging.log4j.core.con
 import org.apache.logging.log4j.core.config.plugins.PluginAttr;
 import org.apache.logging.log4j.core.config.plugins.PluginElement;
 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.core.helpers.Loader;
 import org.apache.logging.log4j.core.layout.PatternLayout;
 
 import java.io.OutputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 
 /**
  * ConsoleAppender appends log events to <code>System.out</code> or
@@ -86,10 +90,28 @@ public final class ConsoleAppender exten
 
     private static OutputStreamManager getManager(Target target) {
         String type = target.name();
-        OutputStream os = target == Target.SYSTEM_OUT ? System.out : System.err;
-        OutputStreamManager manager = OutputStreamManager.getManager(target.name(), new FactoryData(os, type), factory
-        );
-        return manager;
+        OutputStream os = getOutputStream(target);
+        return OutputStreamManager.getManager(target.name(), new FactoryData(os, type), factory);
+    }
+
+    private static OutputStream getOutputStream(Target target) {
+        if (!System.getProperty("os.name").startsWith("Windows")) {
+            return target == Target.SYSTEM_OUT ? System.out : System.err;
+        } else {
+            try {
+                ClassLoader loader = Loader.getClassLoader();
+                Class clazz = loader.loadClass("org.fusesource.jansi.WindowsAnsiOutputStream");
+                Constructor constructor = clazz.getConstructor(OutputStream.class);
+                return (OutputStream) constructor.newInstance(target == Target.SYSTEM_OUT ? System.out : System.err);
+            } catch (ClassNotFoundException cnfe) {
+                LOGGER.debug("Jansi is not installed");
+            } catch (NoSuchMethodException nsme) {
+                LOGGER.warn("WindowsAnsiOutputStream is missing the proper constructor");
+            } catch (Exception ex) {
+                LOGGER.warn("Unable to instantiate WindowsAnsiOutputStream");
+            }
+            return target == Target.SYSTEM_OUT ? System.out : System.err;
+        }
     }
 
     /**

Added: 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=1392129&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java Sun Sep 30 23:09:30 2012
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+package org.apache.logging.log4j.core.pattern;
+
+/**
+ *
+ */
+public enum AnsiEscape {
+
+    PREFIX("\u001b["),
+    SUFFIX("m"),
+    SEPARATOR(";"),
+
+    NORMAL("0"),
+    BRIGHT("1"),
+    DIM("2"),
+    UNDERLINE("3"),
+    BLINK("5"),
+    REVERSE("7"),
+    HIDDEN("8"),
+
+    BLACK("30"),
+    FG_BLACK("30"),
+    RED("31"),
+    FG_RED("31"),
+    GREEN("32"),
+    FG_GREEN("32"),
+    YELLOW("33"),
+    FG_YELLOW("33"),
+    BLUE("34"),
+    FG_BLUE("34"),
+    MAGENTA("35"),
+    FG_MAGENTA("35"),
+    CYAN("36"),
+    FG_CYAN("36"),
+    WHITE("37"),
+    FG_WHITE("37"),
+    DEFAULT("39"),
+    FG_DEFAULT("39"),
+
+    BG_BLACK("40"),
+    BG_RED("41"),
+    BG_GREEN("42"),
+    BG_YELLOW("43"),
+    BG_BLUE("44"),
+    BG_MAGENTA("45"),
+    BG_CYAN("46"),
+    BG_WHITE("47");
+
+    public static String getDefaultStyle() {
+        return PREFIX.getCode() + SUFFIX.getCode();
+    }
+
+    private final String code;
+
+    private AnsiEscape(String code) {
+        this.code = code;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public static String createSequence(String[] values) {
+        if (values == null) {
+            return getDefaultStyle();
+        }
+        StringBuilder sb = new StringBuilder(AnsiEscape.PREFIX.getCode());
+        boolean first = true;
+        for (String value : values) {
+            try {
+                AnsiEscape escape = AnsiEscape.valueOf(value.trim().toUpperCase());
+                if (!first) {
+                    sb.append(AnsiEscape.SEPARATOR.getCode());
+                }
+                first = false;
+                sb.append(escape.getCode());
+            } catch (Exception ex) {
+                // Ignore the error.
+            }
+        }
+        sb.append(AnsiEscape.SUFFIX.getCode());
+        return sb.toString();
+    }
+
+}

Added: 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=1392129&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java Sun Sep 30 23:09:30 2012
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+package org.apache.logging.log4j.core.pattern;
+
+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.
+ */
+@Plugin(name = "highlight", type = "Converter")
+@ConverterKeys({"highlight" })
+public final class HighlightConverter extends LogEventPatternConverter {
+
+    private List<PatternFormatter> formatters;
+
+    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;
+
+    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));
+    }
+
+    /**
+     * Construct the converter.
+     * @param formatters The PatternFormatters to generate the text to manipulate.
+     */
+    private HighlightConverter(List<PatternFormatter> formatters) {
+        super("style", "style");
+        this.formatters = formatters;
+    }
+
+    /**
+     * 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.
+     * @return instance of class.
+     */
+    public static HighlightConverter newInstance(Configuration config, final String[] options) {
+        if (options.length < 1) {
+            LOGGER.error("Incorrect number of options on style. Expected at least 1, received " + options.length);
+            return null;
+        }
+        if (options[0] == null) {
+            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);
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void format(final LogEvent event, final StringBuilder toAppendTo) {
+        StringBuilder buf = new StringBuilder();
+        for (PatternFormatter formatter : formatters) {
+            formatter.format(event, buf);
+        }
+
+        if (buf.length() > 0) {
+            toAppendTo.append(LEVEL_STYLES.get(event.getLevel())).append(buf.toString()).
+                append(AnsiEscape.getDefaultStyle());
+        }
+    }
+}

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java?rev=1392129&r1=1392128&r2=1392129&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java Sun Sep 30 23:09:30 2012
@@ -209,13 +209,27 @@ public final class PatternParser {
      */
     private static int extractOptions(String pattern, int i, List<String> options) {
         while ((i < pattern.length()) && (pattern.charAt(i) == '{')) {
-            int end = pattern.indexOf('}', i);
+            int begin = i;
+            int end;
+            int depth = 0;
+            do {
+                end = pattern.indexOf('}', i);
+                if (end != -1) {
+                    int next = pattern.indexOf("{", i + 1);
+                    if (next != -1 && next < end) {
+                        i = end + 1;
+                        ++depth;
+                    } else if (depth > 0) {
+                        --depth;
+                    }
+                }
+            } while (depth > 0);
 
             if (end == -1) {
                 break;
             }
 
-            String r = pattern.substring(i + 1, end);
+            String r = pattern.substring(begin + 1, end);
             options.add(r);
             i = end + 1;
         }

Copied: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java (from r1391705, logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/RegexReplacementConverter.java)
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java?p2=logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java&p1=logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/RegexReplacementConverter.java&r1=1391705&r2=1392129&rev=1392129&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/RegexReplacementConverter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java Sun Sep 30 23:09:30 2012
@@ -16,39 +16,36 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+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;
 import java.util.regex.Pattern;
 
 /**
- * Replacement pattern converter.
+ * Style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
  */
-@Plugin(name = "replace", type = "Converter")
-@ConverterKeys({"replace" })
-public final class RegexReplacementConverter extends LogEventPatternConverter {
-
-    private final Pattern pattern;
-
-    private final String substitution;
+@Plugin(name = "style", type = "Converter")
+@ConverterKeys({"style" })
+public final class StyleConverter extends LogEventPatternConverter {
 
     private List<PatternFormatter> formatters;
 
+    private final String style;
+
     /**
      * Construct the converter.
      * @param formatters The PatternFormatters to generate the text to manipulate.
-     * @param pattern The regular expression Pattern.
-     * @param substitution The substitution string.
+     * @param styling The styling that should encapsulate the pattern.
      */
-    private RegexReplacementConverter(List<PatternFormatter> formatters,
-                                      Pattern pattern, String substitution) {
-        super("replace", "replace");
-        this.pattern = pattern;
-        this.substitution = substitution;
+    private StyleConverter(List<PatternFormatter> formatters, String styling) {
+        super("style", "style");
         this.formatters = formatters;
+        this.style = styling;
     }
 
     /**
@@ -59,27 +56,24 @@ public final class RegexReplacementConve
      *                only the first line of the throwable will be formatted.
      * @return instance of class.
      */
-    public static RegexReplacementConverter newInstance(Configuration config, final String[] options) {
-        if (options.length != 3) {
-            LOGGER.error("Incorrect number of options on replace. Expected 3 received " + options.length);
+    public static StyleConverter newInstance(Configuration config, final String[] options) {
+        if (options.length < 1) {
+            LOGGER.error("Incorrect number of options on style. Expected at least 1, received " + options.length);
             return null;
         }
         if (options[0] == null) {
-            LOGGER.error("No pattern supplied on replace");
+            LOGGER.error("No pattern supplied on style");
             return null;
         }
         if (options[1] == null) {
-            LOGGER.error("No regular expression supplied on replace");
-            return null;
-        }
-        if (options[2] == null) {
-            LOGGER.error("No substitution supplied on replace");
+            LOGGER.error("No style attributes provided");
             return null;
         }
-        Pattern p = Pattern.compile(options[1]);
+
         PatternParser parser = PatternLayout.createPatternParser(config);
         List<PatternFormatter> formatters = parser.parse(options[0]);
-        return new RegexReplacementConverter(formatters, p, options[2]);
+        String style = AnsiEscape.createSequence(options[1].split(","));
+        return new StyleConverter(formatters, style);
     }
 
 
@@ -92,6 +86,9 @@ public final class RegexReplacementConve
         for (PatternFormatter formatter : formatters) {
             formatter.format(event, buf);
         }
-        toAppendTo.append(pattern.matcher(buf.toString()).replaceAll(substitution));
+
+        if (buf.length() > 0) {
+            toAppendTo.append(style).append(buf.toString()).append(AnsiEscape.getDefaultStyle());
+        }
     }
 }

Copied: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java (from r1391705, logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementTest.java)
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java?p2=logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java&p1=logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementTest.java&r1=1391705&r2=1392129&rev=1392129&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java Sun Sep 30 23:09:30 2012
@@ -38,15 +38,15 @@ import static org.junit.Assert.assertTru
 /**
  *
  */
-public class RegexReplacementTest {
-    private static final String CONFIG = "log4j-replace.xml";
+public class StyleConverterTest {
+    private static final String CONFIG = "log4j-style.xml";
     private static Configuration config;
     private static ListAppender app;
-    private static ListAppender app2;
     private static LoggerContext ctx;
-    
+
     private static final String LINE_SEP = System.getProperty("line.separator");
-    private static final String EXPECTED = "/RegexReplacementTest" + LINE_SEP;
+
+    private static final String EXPECTED = "\u001B[1;31mERROR\u001B[m \u001B[1;36mLoggerTest\u001B[m o.a.l.l.c.p.StyleConverterTest org.apache.logging.log4j.core.pattern.StyleConverterTest" + LINE_SEP;
 
     @BeforeClass
     public static void setupClass() {
@@ -57,9 +57,6 @@ public class RegexReplacementTest {
             if (entry.getKey().equals("List")) {
                 app = (ListAppender) entry.getValue();
             }
-            if (entry.getKey().equals("List2")) {
-                app2 = (ListAppender) entry.getValue();
-            }
         }
     }
 
@@ -72,32 +69,15 @@ public class RegexReplacementTest {
     }
 
     org.apache.logging.log4j.Logger logger = LogManager.getLogger("LoggerTest");
-    org.apache.logging.log4j.Logger logger2 = LogManager.getLogger("ReplacementTest");
 
     @Test
     public void testReplacement() {
         logger.error(this.getClass().getName());
+
         List<String> msgs = app.getMessages();
         assertNotNull(msgs);
         assertTrue("Incorrect number of messages. Should be 1 is " + msgs.size(), msgs.size() == 1);
-        assertTrue("Replacement failed - expected ending " + EXPECTED + " Actual " + msgs.get(0), msgs.get(0).endsWith(EXPECTED));
+        assertTrue("Replacement failed - expected ending " + EXPECTED + ", actual " + msgs.get(0), msgs.get(0).endsWith(EXPECTED));
         app.clear();
-        ThreadContext.put("MyKey", "Apache");
-        logger.error("This is a test for ${ctx:MyKey}");
-        msgs = app.getMessages();
-        assertNotNull(msgs);
-        assertTrue("Incorrect number of messages. Should be 1 is " + msgs.size(), msgs.size() == 1);
-        assertEquals("LoggerTest This is a test for Apache" + LINE_SEP , msgs.get(0));
-        app.clear();
-
-    }
-     @Test
-    public void testConverter() {
-        logger2.error(this.getClass().getName());
-        List<String> msgs = app2.getMessages();
-        assertNotNull(msgs);
-        assertTrue("Incorrect number of messages. Should be 1 is " + msgs.size(), msgs.size() == 1);
-         assertTrue("Replacement failed - expected ending " + EXPECTED + " Actual " + msgs.get(0), msgs.get(0).endsWith(EXPECTED));
-        app2.clear();
     }
 }

Modified: logging/log4j/log4j2/trunk/core/src/test/resources/log4j-replace.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/resources/log4j-replace.xml?rev=1392129&r1=1392128&r2=1392129&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/resources/log4j-replace.xml (original)
+++ logging/log4j/log4j2/trunk/core/src/test/resources/log4j-replace.xml Sun Sep 30 23:09:30 2012
@@ -26,7 +26,7 @@
     </List>
     <List name="List2">
        <PatternLayout>
-         <pattern>%replace{%logger %msg%n}{\.}{/}</pattern>
+         <pattern>%replace{%logger %C{1.} %msg%n}{\.}{/}</pattern>
       </PatternLayout>
     </List>
   </Appenders>

Copied: logging/log4j/log4j2/trunk/core/src/test/resources/log4j-style.xml (from r1391705, logging/log4j/log4j2/trunk/core/src/test/resources/log4j-replace.xml)
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/resources/log4j-style.xml?p2=logging/log4j/log4j2/trunk/core/src/test/resources/log4j-style.xml&p1=logging/log4j/log4j2/trunk/core/src/test/resources/log4j-replace.xml&r1=1391705&r2=1392129&rev=1392129&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/resources/log4j-replace.xml (original)
+++ logging/log4j/log4j2/trunk/core/src/test/resources/log4j-style.xml Sun Sep 30 23:09:30 2012
@@ -16,25 +16,16 @@
  limitations under the License.
 
 -->
-<configuration status="error" name="RegexReplacementTest" packages="org.apache.logging.log4j.test">
+<configuration status="error" name="StyleTest" packages="org.apache.logging.log4j.test">
   <Appenders>
     <List name="List">
        <PatternLayout>
-         <replace regex="\." replacement="/"/>
-         <pattern>%logger %msg%n</pattern>
-      </PatternLayout>
-    </List>
-    <List name="List2">
-       <PatternLayout>
-         <pattern>%replace{%logger %msg%n}{\.}{/}</pattern>
+         <pattern>%d %highlight{%p} %style{%logger}{bright,cyan} %C{1.} %msg%n</pattern>
       </PatternLayout>
     </List>
   </Appenders>
 
   <loggers>
-    <logger level="trace" name="ReplacementTest" additivity="false">
-      <appender-ref ref="List2"/>
-    </logger>
     <root level="trace">
       <appender-ref ref="List"/>
     </root>

Modified: logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/Category.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/Category.java?rev=1392129&r1=1392128&r2=1392129&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/Category.java (original)
+++ logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/Category.java Sun Sep 30 23:09:30 2012
@@ -21,8 +21,6 @@ import org.apache.logging.log4j.core.hel
 import org.apache.logging.log4j.message.LocalizedMessage;
 import org.apache.logging.log4j.message.Message;
 import org.apache.logging.log4j.message.ObjectMessage;
-import org.apache.logging.log4j.message.ParameterizedMessage;
-import org.apache.logging.log4j.message.SimpleMessage;
 
 import java.util.Map;
 import java.util.ResourceBundle;

Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1392129&r1=1392128&r2=1392129&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/changes/changes.xml (original)
+++ logging/log4j/log4j2/trunk/src/changes/changes.xml Sun Sep 30 23:09:30 2012
@@ -23,6 +23,10 @@
 
   <body>
     <release version="2.0-beta2" date="TBD" description="Bug fixes and enhancements">
+      <action dev="rgoers" type="add">
+        Add support for ANSI colors by adding the highlight and style pattern converters. Fix pattern
+        parsing to allow nested patterns.
+      </action>
       <action issue="LOG4J2-92" dev="rgoers" type="fix">
         Converted DynamicThresholdFilter to use KeyValuePair. Fixed bugs in the Map-based filters
         to allow declaration of multiple values for a key to match the documentation.

Modified: logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml?rev=1392129&r1=1392128&r2=1392129&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml (original)
+++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml Sun Sep 30 23:09:30 2012
@@ -266,6 +266,16 @@
             </tr>
             <tr>
               <td align="center">
+                <b>highlight</b>{pattern}
+              </td>
+              <td>
+                Adds ANSI colors to the result of the enclosed pattern based on the current event's logging level.
+                The result will be in blinking bright red when the level is FATAL, bright red when the level is
+                ERROR, red when the level is WARN, blue when the level is INFO and normal for DEBUG and TRACE levels.
+              </td>
+            </tr>
+            <tr>
+              <td align="center">
                 <b>K</b>{key}<br />
                 <b>map</b>{key}<br />
                 <b>MAP</b>{key}
@@ -401,6 +411,119 @@
             </tr>
             <tr>
               <td align="center">
+                <b>style</b>{pattern}{ANSI style}
+              </td>
+              <td>
+                <p>
+                  Uses ANSI escape sequences to style the result of the enclosed pattern. The style can consist of
+                  a comma separated list of style names from the following table.
+                  <table border="1" width="100%">
+                    <tr>
+                      <th>Style Name</th>
+                      <th>Description</th>
+                    </tr>
+                    <tr>
+                      <td>Normal</td>
+                      <td>Normal display</td>
+                    </tr>
+                    <tr>
+                      <td>Bright</td>
+                      <td>Bold</td>
+                    </tr>
+                    <tr>
+                      <td>Dim</td>
+                      <td>Dimmed or faint characters</td>
+                    </tr>
+                    <tr>
+                      <td>Underline</td>
+                      <td>Underlined characters</td>
+                    </tr>
+                    <tr>
+                      <td>Blink</td>
+                      <td>Blinking characters</td>
+                    </tr>
+                    <tr>
+                      <td>Reverse</td>
+                      <td>Reverse video</td>
+                    </tr>
+                    <tr>
+                      <td>Hidden</td>
+                      <td></td>
+                    </tr>
+                    <tr>
+                      <td>Black or FG_Black</td>
+                      <td>Set foreground color to black</td>
+                    </tr>
+                    <tr>
+                      <td>Red or FG_Red</td>
+                      <td>Set foreground color to red</td>
+                    </tr>
+                    <tr>
+                      <td>Green or FG_Green</td>
+                      <td>Set foreground color to green</td>
+                    </tr>
+                    <tr>
+                      <td>Yellow or FG_Yellow</td>
+                      <td>Set foreground color to yellow</td>
+                    </tr>
+                    <tr>
+                      <td>Blue or FG_Blue</td>
+                      <td>Set foreground color to blue</td>
+                    </tr>
+                    <tr>
+                      <td>Magenta or FG_Magenta</td>
+                      <td>Set foreground color to magenta</td>
+                    </tr>
+                    <tr>
+                      <td>Cyan or FG_Cyan</td>
+                      <td>Set foreground color to cyan</td>
+                    </tr>
+                    <tr>
+                      <td>White or FG_White</td>
+                      <td>Set foreground color to white</td>
+                    </tr>
+                    <tr>
+                      <td>Default or FG_Default</td>
+                      <td>Set foreground color to default (white)</td>
+                    </tr>
+                    <tr>
+                      <td>BG_Black</td>
+                      <td>Set background color to black</td>
+                    </tr>
+                    <tr>
+                      <td>BG_Red</td>
+                      <td>Set background color to red</td>
+                    </tr>
+                    <tr>
+                      <td>BG_Green</td>
+                      <td>Set background color to green</td>
+                    </tr>
+                    <tr>
+                      <td>BG_Yellow</td>
+                      <td>Set background color to yellow</td>
+                    </tr>
+                    <tr>
+                      <td>BG_Blue</td>
+                      <td>Set background color to blue</td>
+                    </tr>
+                    <tr>
+                      <td>BG_Magenta</td>
+                      <td>Set background color to magenta</td>
+                    </tr>
+                    <tr>
+                      <td>BG_Cyan</td>
+                      <td>Set background color to cyan</td>
+                    </tr>
+                    <tr>
+                      <td>BG_White</td>
+                      <td>Set background color to white</td>
+                    </tr>
+                  </table>
+                </p>
+              </td>
+            </tr>
+            <tr>
+              <td align="center">
                 <b>t</b><br />
                 <b>thread</b>
               </td>
@@ -581,6 +704,15 @@
             </tr>
             <caption align="top">Pattern Converters</caption>
           </table>
+          <h4>Example Patterns</h4>
+          <h5>Ansi Styled</h5>
+          <p>The log level will be highlighted according to the event's log level. All the content that follows
+            the level will be bright green.</p>
+          <source><![CDATA[
+      <PatternLayout>
+        <pattern>%d %highlight{%p} %style{%C{1.} [%t] %m}{bold,green}%n</pattern>
+      </PatternLayout>
+  ]]></source>
         </subsection>
         <a name="RFC5424Layout"/>
         <subsection name="RFC5424Layout">