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">