Author: ggregory
Date: Thu Nov 1 17:42:49 2012
New Revision: 1404688
URL: http://svn.apache.org/viewvc?rev=1404688&view=rev
Log:
Allow custom ANSI mappings for Levels using a STYLE options: STYLE can be one
of Log4J, Default, or Logback.
Added:
logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutLogbackMain.java
(with props)
logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight-logback.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
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=1404688&r1=1404687&r2=1404688&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 17:42:49 2012
@@ -16,7 +16,9 @@
*/
package org.apache.logging.log4j.core.pattern;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
/**
@@ -88,7 +90,7 @@ public enum AnsiEscape {
}
/**
- * Creates a Map from a source string. The format is:
+ * Creates a Map from a source array where values are ANSI escape
sequences. The format is:
*
* <pre>
* Key1=Value, Key2=Value, ...
@@ -105,14 +107,16 @@ public enum AnsiEscape {
*
* @param values
* the source string to parse.
+ * @param dontEscapeKeys
+ * do not escape these keys, leave the values as is in the map
* @return a new map
*/
- public static Map<String, String> createMap(String values) {
- return createMap(values.split("\\s*,\\s*"));
+ public static Map<String, String> createMap(String values, String[]
dontEscapeKeys) {
+ return createMap(values.split("\\s*,\\s*"), dontEscapeKeys);
}
/**
- * Creates a Map from a source array. Each array entry must be in the
format:
+ * Creates a Map from a source array where values are ANSI escape
sequences. Each array entry must be in the format:
*
* <pre>
* Key1 = Value
@@ -129,29 +133,42 @@ public enum AnsiEscape {
*
* @param values
* the source array to parse.
+ * @param dontEscapeKeys
+ * do not escape these keys, leave the values as is in the map
* @return a new map
*/
- public static Map<String, String> createMap(String[] values) {
+ public static Map<String, String> createMap(String[] values, String[]
dontEscapeKeys) {
+ final String[] sortedIgnoreKeys = dontEscapeKeys != null ?
dontEscapeKeys.clone() : new String[0];
+ Arrays.sort(sortedIgnoreKeys);
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")));
+ final String key = keyValue[0].toUpperCase(Locale.ENGLISH);
+ final String value = keyValue[1];
+ final boolean escape = Arrays.binarySearch(sortedIgnoreKeys,
key) < 0;
+ map.put(key, escape ? createSequence(value.split("\\s")) :
value);
}
}
return map;
}
- public static String createSequence(String[] values) {
- if (values == null) {
+ /**
+ * Creates an ANSI escape sequence from the given {@linkplain AnsiEscape}
names.
+ *
+ * @param names
+ * {@linkplain AnsiEscape} names.
+ * @return An ANSI escape sequence.
+ */
+ public static String createSequence(String[] names) {
+ if (names == null) {
return getDefaultStyle();
}
StringBuilder sb = new StringBuilder(AnsiEscape.PREFIX.getCode());
boolean first = true;
- for (String value : values) {
+ for (String name : names) {
try {
- AnsiEscape escape =
AnsiEscape.valueOf(value.trim().toUpperCase());
+ AnsiEscape escape =
AnsiEscape.valueOf(name.trim().toUpperCase(Locale.ENGLISH));
if (!first) {
sb.append(AnsiEscape.SEPARATOR.getCode());
}
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=1404688&r1=1404687&r2=1404688&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 17:42:49 2012
@@ -16,8 +16,11 @@
*/
package org.apache.logging.log4j.core.pattern;
+import java.util.Arrays;
import java.util.EnumMap;
+import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import org.apache.logging.log4j.Level;
@@ -30,18 +33,34 @@ import org.apache.logging.log4j.core.lay
* 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>
+ *
* <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>
+ *
+ * <p>
+ * You can use a predefined style:
+ *
+ * <pre>
+ * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}{STYLE=Log4J}
+ * </pre>
+ * The available predefined styles are:
+ * <ul>
+ * <li>{@code Default}</li>
+ * <li>{@code Log4J} - The same as {@code Default}</li>
+ * <li>{@code Logback}</li>
+ * </ul>
+ * </p>
+ *
* <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.
@@ -51,28 +70,43 @@ import org.apache.logging.log4j.core.lay
@ConverterKeys({ "highlight" })
public final class HighlightConverter extends LogEventPatternConverter {
+ private static final String STYLE_KEY_DEFAULT = "DEFAULT";
+
+ private static final String STYLE_KEY_LOGBACK = "LOGBACK";
+
+ private static final String STYLE_KEY_LOG4J = "LOG4J";
+
+ private static final String STYLE_KEY = "STYLE";
+
private static final EnumMap<Level, String> DEFAULT_STYLES = new
EnumMap<Level, String>(Level.class);
private static final EnumMap<Level, String> LOGBACK_STYLES = new
EnumMap<Level, String>(Level.class);
+ private static final Map<String, EnumMap<Level, String>> STYLES = new
HashMap<String, EnumMap<Level, String>>();
+
static {
+ // Default styles:
DEFAULT_STYLES.put(Level.FATAL, AnsiEscape.createSequence(new String[]
{ "BRIGHT", "RED" }));
DEFAULT_STYLES.put(Level.ERROR, AnsiEscape.createSequence(new String[]
{ "BRIGHT", "RED" }));
DEFAULT_STYLES.put(Level.WARN, AnsiEscape.createSequence(new String[]
{ "YELLOW" }));
DEFAULT_STYLES.put(Level.INFO, AnsiEscape.createSequence(new String[]
{ "GREEN" }));
DEFAULT_STYLES.put(Level.DEBUG, AnsiEscape.createSequence(new String[]
{ "CYAN" }));
DEFAULT_STYLES.put(Level.TRACE, AnsiEscape.createSequence(new String[]
{ "BLACK" }));
- //
+ // Logback styles:
LOGBACK_STYLES.put(Level.FATAL, AnsiEscape.createSequence(new String[]
{ "BLINK", "BRIGHT", "RED" }));
LOGBACK_STYLES.put(Level.ERROR, AnsiEscape.createSequence(new String[]
{ "BRIGHT", "RED" }));
LOGBACK_STYLES.put(Level.WARN, AnsiEscape.createSequence(new String[]
{ "RED" }));
LOGBACK_STYLES.put(Level.INFO, AnsiEscape.createSequence(new String[]
{ "BLUE" }));
LOGBACK_STYLES.put(Level.DEBUG, AnsiEscape.createSequence(null));
LOGBACK_STYLES.put(Level.TRACE, AnsiEscape.createSequence(null));
+ // Style map:
+ STYLES.put(STYLE_KEY_DEFAULT, DEFAULT_STYLES);
+ STYLES.put(STYLE_KEY_LOG4J, DEFAULT_STYLES);
+ STYLES.put(STYLE_KEY_LOGBACK, LOGBACK_STYLES);
}
/**
- * Creates a level style map given configuration options in {@code
option[1]}.
+ * Creates a level style map where values are ANSI escape sequences given
configuration options in {@code option[1]}.
* <p/>
* The format of the option string in {@code option[1]} is:
*
@@ -97,14 +131,25 @@ public final class HighlightConverter ex
if (options.length < 2) {
return DEFAULT_STYLES;
}
- Map<String, String> styles = AnsiEscape.createMap(options[1]);
+ Map<String, String> styles = AnsiEscape.createMap(options[1], new
String[] { STYLE_KEY });
EnumMap<Level, String> levelStyles = new EnumMap<Level,
String>(DEFAULT_STYLES);
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());
+ final String key = entry.getKey().toUpperCase(Locale.ENGLISH);
+ final String value = entry.getValue();
+ if (STYLE_KEY.equalsIgnoreCase(key)) {
+ final EnumMap<Level, String> enumMap =
STYLES.get(value.toUpperCase(Locale.ENGLISH));
+ if (enumMap == null) {
+ LOGGER.error("Unkown level style: " + value + ". Use one
of " + Arrays.toString(STYLES.keySet().toArray()));
+ } else {
+ levelStyles.putAll(enumMap);
+ }
} else {
- levelStyles.put(key, entry.getValue());
+ final Level level = Level.valueOf(key);
+ if (level == null) {
+ LOGGER.error("Unkown level name: " + key + ". Use one of "
+ Arrays.toString(DEFAULT_STYLES.keySet().toArray()));
+ } else {
+ levelStyles.put(level, value);
+ }
}
}
return levelStyles;
Added:
logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutLogbackMain.java
URL:
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutLogbackMain.java?rev=1404688&view=auto
==============================================================================
---
logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutLogbackMain.java
(added)
+++
logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutLogbackMain.java
Thu Nov 1 17:42:49 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 ConsoleAppenderHighlightLayoutLogbackMain {
+
+ private static final Logger LOG =
LogManager.getLogger(ConsoleAppenderHighlightLayoutLogbackMain.class);
+
+ public static void main(String[] args) {
+ LoggerContext ctx =
Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), null,
+ "target/test-classes/log4j2-console-highlight-logback.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/ConsoleAppenderHighlightLayoutLogbackMain.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutLogbackMain.java
------------------------------------------------------------------------------
svn:keywords = Id
Added:
logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight-logback.xml
URL:
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight-logback.xml?rev=1404688&view=auto
==============================================================================
---
logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight-logback.xml
(added)
+++
logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight-logback.xml
Thu Nov 1 17:42:49 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}{style=Log4J}" />
+ </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-logback.xml
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-console-highlight-logback.xml
------------------------------------------------------------------------------
svn:keywords = Id