You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by mi...@apache.org on 2016/01/12 17:50:42 UTC
[34/50] logging-log4j2 git commit: [LOG4J2-1237] Make PatternLayout
header and footer accept a pattern.
[LOG4J2-1237] Make PatternLayout header and footer accept a pattern.
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/c3d8ce82
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/c3d8ce82
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/c3d8ce82
Branch: refs/heads/LOG4J-1181
Commit: c3d8ce8240202ff92da0c239092b13aa347bae36
Parents: 6944134
Author: ggregory <gg...@apache.org>
Authored: Sun Jan 3 22:14:20 2016 -0800
Committer: ggregory <gg...@apache.org>
Committed: Sun Jan 3 22:14:20 2016 -0800
----------------------------------------------------------------------
.../log4j/core/layout/AbstractStringLayout.java | 30 ++--
.../log4j/core/layout/PatternLayout.java | 163 +++++++++++--------
.../log4j/core/layout/PatternLayoutTest.java | 4 +-
src/changes/changes.xml | 3 +
4 files changed, 112 insertions(+), 88 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c3d8ce82/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java
index 68b9fb6..96a80a5 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java
@@ -75,6 +75,21 @@ public abstract class AbstractStringLayout extends AbstractLayout<String> implem
&& (StandardCharsets.ISO_8859_1.equals(charset) || StandardCharsets.US_ASCII.equals(charset));
}
+ /**
+ * Returns a {@code StringBuilder} that this Layout implementation can use to write the formatted log event to.
+ *
+ * @return a {@code StringBuilder}
+ */
+ protected static StringBuilder getStringBuilder() {
+ StringBuilder result = threadLocal.get();
+ if (result == null) {
+ result = new StringBuilder(DEFAULT_STRING_BUILDER_SIZE);
+ threadLocal.set(result);
+ }
+ result.setLength(0);
+ return result;
+ }
+
// LOG4J2-1151: If the built-in JDK 8 encoders are available we should use them.
private static boolean isPreJava8() {
final String version = System.getProperty("java.version");
@@ -98,21 +113,6 @@ public abstract class AbstractStringLayout extends AbstractLayout<String> implem
charset = Charset.forName(csName);
}
- /**
- * Returns a {@code StringBuilder} that this Layout implementation can use to write the formatted log event to.
- *
- * @return a {@code StringBuilder}
- */
- protected StringBuilder getStringBuilder() {
- StringBuilder result = threadLocal.get();
- if (result == null) {
- result = new StringBuilder(DEFAULT_STRING_BUILDER_SIZE);
- threadLocal.set(result);
- }
- result.setLength(0);
- return result;
- }
-
protected byte[] getBytes(final String s) {
if (useCustomEncoding) { // rely on branch prediction to eliminate this check if false
return StringEncoder.encodeSingleByteChars(s);
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c3d8ce82/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
index cda7915..63c44fd 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
@@ -25,6 +25,7 @@ import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.DefaultConfiguration;
+import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.config.Node;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
@@ -38,6 +39,7 @@ import org.apache.logging.log4j.core.pattern.PatternFormatter;
import org.apache.logging.log4j.core.pattern.PatternParser;
import org.apache.logging.log4j.core.pattern.RegexReplacement;
import org.apache.logging.log4j.core.util.StringEncoder;
+import org.apache.logging.log4j.util.Strings;
/**
* A flexible layout configurable with pattern string.
@@ -57,25 +59,20 @@ import org.apache.logging.log4j.core.util.StringEncoder;
public final class PatternLayout extends AbstractStringLayout {
/**
- * Default pattern string for log output. Currently set to the
- * string <b>"%m%n"</b> which just prints the application supplied
- * message.
+ * Default pattern string for log output. Currently set to the string <b>"%m%n"</b> which just prints the
+ * application supplied message.
*/
public static final String DEFAULT_CONVERSION_PATTERN = "%m%n";
/**
- * A conversion pattern equivalent to the TTCCCLayout.
- * Current value is <b>%r [%t] %p %c %x - %m%n</b>.
+ * A conversion pattern equivalent to the TTCCCLayout. Current value is <b>%r [%t] %p %c %x - %m%n</b>.
*/
- public static final String TTCC_CONVERSION_PATTERN =
- "%r [%t] %p %c %x - %m%n";
+ public static final String TTCC_CONVERSION_PATTERN = "%r [%t] %p %c %x - %m%n";
/**
- * A simple pattern.
- * Current value is <b>%d [%t] %p %c - %m%n</b>.
+ * A simple pattern. Current value is <b>%d [%t] %p %c - %m%n</b>.
*/
- public static final String SIMPLE_CONVERSION_PATTERN =
- "%d [%t] %p %c - %m%n";
+ public static final String SIMPLE_CONVERSION_PATTERN = "%d [%t] %p %c - %m%n";
/** Key to identify pattern converters. */
public static final String KEY = "Converter";
@@ -83,87 +80,92 @@ public final class PatternLayout extends AbstractStringLayout {
private static final long serialVersionUID = 1L;
/**
- * Initial converter for pattern.
- */
- private final PatternFormatter[] formatters;
-
- /**
* Conversion pattern.
*/
private final String conversionPattern;
private final PatternSelector patternSelector;
- private final Serializer serializer;
+ private final Serializer eventSerializer;
+
+ private final Serializer headerSerializer;
+ private final Serializer footerSerializer;
/**
* The current Configuration.
*/
private final Configuration config;
- private final RegexReplacement replace;
-
- private final boolean alwaysWriteExceptions;
-
- private final boolean noConsoleNoAnsi;
-
/**
* Constructs a EnhancedPatternLayout using the supplied conversion pattern.
*
* @param config The Configuration.
* @param replace The regular expression to match.
- * @param pattern conversion pattern.
+ * @param eventPattern conversion pattern.
* @param patternSelector The PatternSelector.
* @param charset The character set.
* @param alwaysWriteExceptions Whether or not exceptions should always be handled in this pattern (if {@code true},
* exceptions will be written even if the pattern does not specify so).
* @param noConsoleNoAnsi
* If {@code "true"} (default) and {@link System#console()} is null, do not output ANSI escape codes
- * @param header
+ * @param headerPattern header conversion pattern.
+ * @param footerPattern footer conversion pattern.
*/
- private PatternLayout(final Configuration config, final RegexReplacement replace, final String pattern,
- final PatternSelector patternSelector, final Charset charset,
- final boolean alwaysWriteExceptions, final boolean noConsoleNoAnsi,
- final String header, final String footer) {
- super(charset, StringEncoder.toBytes(header, charset), StringEncoder.toBytes(footer, charset));
- this.replace = replace;
- this.conversionPattern = pattern;
+ private PatternLayout(final Configuration config, final RegexReplacement replace, final String eventPattern,
+ final PatternSelector patternSelector, final Charset charset, final boolean alwaysWriteExceptions,
+ final boolean noConsoleNoAnsi, final String headerPattern, final String footerPattern) {
+ super(charset, StringEncoder.toBytes(headerPattern, charset), StringEncoder.toBytes(footerPattern, charset));
+ this.conversionPattern = eventPattern;
this.patternSelector = patternSelector;
this.config = config;
- this.alwaysWriteExceptions = alwaysWriteExceptions;
- this.noConsoleNoAnsi = noConsoleNoAnsi;
+ this.eventSerializer = createSerializer(config, replace, eventPattern, DEFAULT_CONVERSION_PATTERN, patternSelector,
+ alwaysWriteExceptions, noConsoleNoAnsi);
+ this.headerSerializer = createSerializer(config, replace, headerPattern, null, patternSelector,
+ alwaysWriteExceptions, noConsoleNoAnsi);
+ this.footerSerializer = createSerializer(config, replace, footerPattern, null, patternSelector,
+ alwaysWriteExceptions, noConsoleNoAnsi);
+ }
+
+ private Serializer createSerializer(final Configuration configuration, final RegexReplacement replace,
+ final String pattern, final String defaultPattern, final PatternSelector patternSelector,
+ final boolean alwaysWriteExceptions, final boolean noConsoleNoAnsi) {
+ if (Strings.isEmpty(pattern) && Strings.isEmpty(defaultPattern)) {
+ return null;
+ }
if (patternSelector == null) {
- serializer = new PatternSerializer();
- final PatternParser parser = createPatternParser(config);
+ final PatternParser parser = createPatternParser(configuration);
try {
- List<PatternFormatter> list = parser.parse(pattern == null ? DEFAULT_CONVERSION_PATTERN : pattern,
- this.alwaysWriteExceptions, this.noConsoleNoAnsi);
- this.formatters = list.toArray(new PatternFormatter[0]);
- } catch (RuntimeException ex) {
+ final List<PatternFormatter> list = parser.parse(pattern == null ? defaultPattern : pattern,
+ alwaysWriteExceptions, noConsoleNoAnsi);
+ final PatternFormatter[] formatters = list.toArray(new PatternFormatter[0]);
+ return new PatternSerializer(formatters, replace);
+ } catch (final RuntimeException ex) {
throw new IllegalArgumentException("Cannot parse pattern '" + pattern + "'", ex);
}
- } else {
- this.formatters = null;
- serializer = new PatternSelectorSerializer();
}
- }
-
- private byte[] strSubstitutorReplace(final byte... b) {
- if (b != null && config != null) {
- return getBytes(config.getStrSubstitutor().replace(new String(b, getCharset())));
- }
- return b;
+ return new PatternSelectorSerializer(patternSelector, replace);
}
@Override
public byte[] getHeader() {
- return strSubstitutorReplace(super.getHeader());
+ return serializeHeaderFooter(headerSerializer);
}
@Override
public byte[] getFooter() {
- return strSubstitutorReplace(super.getFooter());
+ return serializeHeaderFooter(footerSerializer);
+ }
+
+ private byte[] serializeHeaderFooter(final Serializer serializer) {
+ if (serializer == null) {
+ return null;
+ }
+ final LoggerConfig rootLogger = config.getRootLogger();
+ // Using "" for the FQCN, does it matter?
+ final LogEvent logEvent = rootLogger.getLogEventFactory().createEvent(rootLogger.getName(), null, Strings.EMPTY,
+ rootLogger.getLevel(), null, null, null);
+ return StringEncoder.toBytes(serializer.toSerializable(logEvent), getCharset());
}
/**
@@ -186,8 +188,7 @@ public final class PatternLayout extends AbstractStringLayout {
* @return Map of content format keys supporting PatternLayout
*/
@Override
- public Map<String, String> getContentFormat()
- {
+ public Map<String, String> getContentFormat() {
final Map<String, String> result = new HashMap<>();
result.put("structured", "false");
result.put("formatType", "conversion");
@@ -203,7 +204,7 @@ public final class PatternLayout extends AbstractStringLayout {
*/
@Override
public String toSerializable(final LogEvent event) {
- return serializer.toSerializable(event);
+ return eventSerializer.toSerializable(event);
}
/**
@@ -246,9 +247,9 @@ public final class PatternLayout extends AbstractStringLayout {
* If {@code "true"} (default) exceptions are always written even if the pattern contains no exception tokens.
* @param noConsoleNoAnsi
* If {@code "true"} (default is false) and {@link System#console()} is null, do not output ANSI escape codes
- * @param header
+ * @param headerPattern
* The footer to place at the top of the document, once.
- * @param footer
+ * @param footerPattern
* The footer to place at the bottom of the document, once.
* @return The PatternLayout.
*/
@@ -262,8 +263,8 @@ public final class PatternLayout extends AbstractStringLayout {
@PluginAttribute(value = "charset") final Charset charset,
@PluginAttribute(value = "alwaysWriteExceptions", defaultBoolean = true) final boolean alwaysWriteExceptions,
@PluginAttribute(value = "noConsoleNoAnsi", defaultBoolean = false) final boolean noConsoleNoAnsi,
- @PluginAttribute("header") final String header,
- @PluginAttribute("footer") final String footer) {
+ @PluginAttribute("header") final String headerPattern,
+ @PluginAttribute("footer") final String footerPattern) {
return newBuilder()
.withPattern(pattern)
.withPatternSelector(patternSelector)
@@ -272,18 +273,27 @@ public final class PatternLayout extends AbstractStringLayout {
.withCharset(charset)
.withAlwaysWriteExceptions(alwaysWriteExceptions)
.withNoConsoleNoAnsi(noConsoleNoAnsi)
- .withHeader(header)
- .withFooter(footer)
+ .withHeader(headerPattern)
+ .withFooter(footerPattern)
.build();
}
-
private interface Serializer {
-
- String toSerializable(final LogEvent event);
+
+ String toSerializable(final LogEvent event);
}
- private class PatternSerializer implements Serializer {
+ private static class PatternSerializer implements Serializer {
+
+ private final PatternFormatter[] formatters;
+ private final RegexReplacement replace;
+
+ private PatternSerializer(final PatternFormatter[] formatters, final RegexReplacement replace) {
+ super();
+ this.formatters = formatters;
+ this.replace = replace;
+ }
+
@Override
public String toSerializable(final LogEvent event) {
final StringBuilder buf = getStringBuilder();
@@ -299,11 +309,21 @@ public final class PatternLayout extends AbstractStringLayout {
}
}
- private class PatternSelectorSerializer implements Serializer {
+ private static class PatternSelectorSerializer implements Serializer {
+
+ private final PatternSelector patternSelector;
+ private final RegexReplacement replace;
+
+ private PatternSelectorSerializer(final PatternSelector patternSelector, final RegexReplacement replace) {
+ super();
+ this.patternSelector = patternSelector;
+ this.replace = replace;
+ }
+
@Override
public String toSerializable(final LogEvent event) {
final StringBuilder buf = getStringBuilder();
- PatternFormatter[] formatters = patternSelector.getFormatters(event);
+ final PatternFormatter[] formatters = patternSelector.getFormatters(event);
final int len = formatters.length;
for (int i = 0; i < len; i++) {
formatters[i].format(event, buf);
@@ -328,21 +348,21 @@ public final class PatternLayout extends AbstractStringLayout {
}
/**
- * Creates a PatternLayout using the default options and the given
- * configuration. These options include using UTF-8, the default conversion
- * pattern, exceptions being written, and with ANSI escape codes.
+ * Creates a PatternLayout using the default options and the given configuration. These options include using UTF-8,
+ * the default conversion pattern, exceptions being written, and with ANSI escape codes.
*
* @param configuration The Configuration.
*
* @return the PatternLayout.
* @see #DEFAULT_CONVERSION_PATTERN Default conversion pattern
*/
- public static PatternLayout createDefaultLayout(Configuration configuration) {
+ public static PatternLayout createDefaultLayout(final Configuration configuration) {
return newBuilder().withConfiguration(configuration).build();
}
/**
* Creates a builder for a custom PatternLayout.
+ *
* @return a PatternLayout builder.
*/
@PluginBuilderFactory
@@ -398,7 +418,6 @@ public final class PatternLayout extends AbstractStringLayout {
return this;
}
-
public Builder withConfiguration(final Configuration configuration) {
this.configuration = configuration;
return this;
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c3d8ce82/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
index 53335d6..b10c8f5 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
@@ -82,6 +82,7 @@ public class PatternLayoutTest {
assertTrue(headerStr, headerStr.contains("(build "));
assertTrue(headerStr, headerStr.contains(" from "));
assertTrue(headerStr, headerStr.contains(" architecture: "));
+ assertFalse(headerStr, headerStr.contains("%d{UNIX}"));
//
final byte[] footer = layout.getFooter();
assertNotNull("No footer", footer);
@@ -91,6 +92,7 @@ public class PatternLayoutTest {
assertTrue(footerStr, footerStr.contains("(build "));
assertTrue(footerStr, footerStr.contains(" from "));
assertTrue(footerStr, footerStr.contains(" architecture: "));
+ assertFalse(footerStr, footerStr.contains("%d{UNIX}"));
}
/**
@@ -323,7 +325,7 @@ public class PatternLayoutTest {
.setIncludeLocation(true)
.setMessage(new SimpleMessage("entry")).build();
final String result1 = new FauxLogger().formatEvent(event1, layout);
- final String expectSuffix1 = String.format("====== PatternLayoutTest.testPatternSelector:325 entry ======%n");
+ final String expectSuffix1 = String.format("====== PatternLayoutTest.testPatternSelector:327 entry ======%n");
assertTrue("Unexpected result: " + result1, result1.endsWith(expectSuffix1));
final LogEvent event2 = Log4jLogEvent.newBuilder() //
.setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c3d8ce82/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index a4b6798..6c36be1 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -28,6 +28,9 @@
Added option to discard events below a certain log level if the async logger ring buffer
or async appender queue remaining capacity falls below a certain ratio.
</action>
+ <action issue="LOG4J2-1237" dev="ggregory" type="add" due-to="Mike Calmus, Gary Gregory">
+ Make PatternLayout header and footer accept a pattern.
+ </action>
<action issue="LOG4J2-908" dev="ggregory" type="fix" due-to="Konstantinos Liakos, Patrick Flaherty, Robin Coe, Gary Gregory">
JSONLayout doesn't add a comma between log events.
</action>