LOG4J2-1694 Add builds to XmlLayout and YamlLayout, add additionalFields property to JsonLayout, XmlLayout and YamlLayout (currently no-op, W.I.P.)
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/b2e2d06d Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/b2e2d06d Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/b2e2d06d Branch: refs/heads/master Commit: b2e2d06d23cc6c5d1e5da7857f9b2cd52e95ab5e Parents: 9383ab7 Author: Mikael Ståldal <[email protected]> Authored: Thu Apr 27 18:09:13 2017 +0200 Committer: Mikael Ståldal <[email protected]> Committed: Thu Apr 27 18:09:13 2017 +0200 ---------------------------------------------------------------------- .../core/layout/AbstractJacksonLayout.java | 89 +++++++++++++++++++- .../logging/log4j/core/layout/JsonLayout.java | 88 ++++++------------- .../logging/log4j/core/layout/XmlLayout.java | 46 ++++++++-- .../logging/log4j/core/layout/YamlLayout.java | 63 ++++++++++---- 4 files changed, 200 insertions(+), 86 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b2e2d06d/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java index 7afd1d4..172cf14 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java @@ -23,7 +23,9 @@ import java.nio.charset.Charset; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginElement; import org.apache.logging.log4j.core.impl.MutableLogEvent; +import org.apache.logging.log4j.core.util.KeyValuePair; import org.apache.logging.log4j.core.util.StringBuilderWriter; import org.apache.logging.log4j.util.Strings; @@ -47,6 +49,22 @@ abstract class AbstractJacksonLayout extends AbstractStringLayout { @PluginBuilderAttribute private boolean complete; + @PluginBuilderAttribute + private boolean locationInfo; + + @PluginBuilderAttribute + private boolean properties; + + @PluginBuilderAttribute + private boolean includeStacktrace = true; + + @PluginElement("AdditionalField") + private KeyValuePair[] additionalFields; + + protected String toStringOrNull(final byte[] header) { + return header == null ? null : new String(header, Charset.defaultCharset()); + } + public boolean getEventEol() { return eventEol; } @@ -59,6 +77,26 @@ abstract class AbstractJacksonLayout extends AbstractStringLayout { return complete; } + public boolean isLocationInfo() { + return locationInfo; + } + + public boolean isProperties() { + return properties; + } + + /** + * If "true", includes the stacktrace of any Throwable in the generated data, defaults to "true". + * @return If "true", includes the stacktrace of any Throwable in the generated data, defaults to "true". + */ + public boolean isIncludeStacktrace() { + return includeStacktrace; + } + + public KeyValuePair[] getAdditionalFields() { + return additionalFields; + } + public B setEventEol(final boolean eventEol) { this.eventEol = eventEol; return asBuilder(); @@ -74,21 +112,70 @@ abstract class AbstractJacksonLayout extends AbstractStringLayout { return asBuilder(); } + public B setLocationInfo(boolean locationInfo) { + this.locationInfo = locationInfo; + return asBuilder(); + } + + public B setProperties(boolean properties) { + this.properties = properties; + return asBuilder(); + } + + /** + * If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true". + * @param includeStacktrace If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true". + * @return this builder + */ + public B setIncludeStacktrace(boolean includeStacktrace) { + this.includeStacktrace = includeStacktrace; + return asBuilder(); + } + + /** + * Additional fields to set on each log event. + * + * @return this builder + */ + public B setAdditionalFields(KeyValuePair[] additionalFields) { + this.additionalFields = additionalFields; + return asBuilder(); + } } protected final String eol; protected final ObjectWriter objectWriter; protected final boolean compact; protected final boolean complete; + protected final KeyValuePair[] additionalFields; + + @Deprecated + protected AbstractJacksonLayout(final Configuration config, final ObjectWriter objectWriter, final Charset charset, + final boolean compact, final boolean complete, final boolean eventEol, final Serializer headerSerializer, + final Serializer footerSerializer) { + this(config, objectWriter, charset, compact, complete, eventEol, headerSerializer, footerSerializer, null); + } protected AbstractJacksonLayout(final Configuration config, final ObjectWriter objectWriter, final Charset charset, final boolean compact, final boolean complete, final boolean eventEol, final Serializer headerSerializer, - final Serializer footerSerializer) { + final Serializer footerSerializer, final KeyValuePair[] additionalFields) { super(config, charset, headerSerializer, footerSerializer); this.objectWriter = objectWriter; this.compact = compact; this.complete = complete; this.eol = compact && !eventEol ? COMPACT_EOL : DEFAULT_EOL; + this.additionalFields = additionalFields != null ? additionalFields : new KeyValuePair[0]; + if (config == null) { + for (KeyValuePair additionalField : this.additionalFields) { + if (valueNeedsLookup(additionalField.getValue())) { + throw new IllegalArgumentException("configuration needs to be set when there are additional fields with variables"); + } + } + } + } + + protected static boolean valueNeedsLookup(final String value) { + return value != null && value.contains("${"); } /** http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b2e2d06d/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java index c630836..a24e460 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java @@ -33,8 +33,7 @@ import org.apache.logging.log4j.core.config.plugins.PluginAttribute; import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute; import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory; import org.apache.logging.log4j.core.config.plugins.PluginConfiguration; -import org.apache.logging.log4j.core.config.plugins.PluginFactory; -import org.apache.logging.log4j.core.layout.SyslogLayout.Builder; +import org.apache.logging.log4j.core.util.KeyValuePair; /** * Appends a series of JSON events as strings serialized as bytes. @@ -74,17 +73,8 @@ public final class JsonLayout extends AbstractJacksonLayout { implements org.apache.logging.log4j.core.util.Builder<JsonLayout> { @PluginBuilderAttribute - private boolean locationInfo; - - @PluginBuilderAttribute - private boolean properties; - - @PluginBuilderAttribute private boolean propertiesAsList; - @PluginBuilderAttribute - private boolean includeStacktrace = true; - public Builder() { super(); setCharset(StandardCharsets.UTF_8); @@ -92,72 +82,46 @@ public final class JsonLayout extends AbstractJacksonLayout { @Override public JsonLayout build() { - final boolean encodeThreadContextAsList = properties && propertiesAsList; + final boolean encodeThreadContextAsList = isProperties() && propertiesAsList; final String headerPattern = toStringOrNull(getHeader()); final String footerPattern = toStringOrNull(getFooter()); - return new JsonLayout(getConfiguration(), locationInfo, properties, encodeThreadContextAsList, isComplete(), - isCompact(), getEventEol(), headerPattern, footerPattern, getCharset(), includeStacktrace); - } - - private String toStringOrNull(final byte[] header) { - return header == null ? null : new String(header, Charset.defaultCharset()); - } - - public boolean isLocationInfo() { - return locationInfo; - } - - public boolean isProperties() { - return properties; + return new JsonLayout(getConfiguration(), isLocationInfo(), isProperties(), encodeThreadContextAsList, isComplete(), + isCompact(), getEventEol(), headerPattern, footerPattern, getCharset(), isIncludeStacktrace(), getAdditionalFields()); } public boolean isPropertiesAsList() { return propertiesAsList; } - /** - * If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true". - * @return If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true". - */ - public boolean isIncludeStacktrace() { - return includeStacktrace; - } - - public B setLocationInfo(boolean locationInfo) { - this.locationInfo = locationInfo; - return asBuilder(); - } - - public B setProperties(boolean properties) { - this.properties = properties; - return asBuilder(); - } - public B setPropertiesAsList(boolean propertiesAsList) { this.propertiesAsList = propertiesAsList; return asBuilder(); } - - /** - * If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true". - * @param includeStacktrace If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true". - * @return this builder - */ - public B setIncludeStacktrace(boolean includeStacktrace) { - this.includeStacktrace = includeStacktrace; - return asBuilder(); - } } + /** + * @deprecated Use {@link #newBuilder()} instead + */ + @Deprecated protected JsonLayout(final Configuration config, final boolean locationInfo, final boolean properties, final boolean encodeThreadContextAsList, final boolean complete, final boolean compact, final boolean eventEol, final String headerPattern, final String footerPattern, final Charset charset, final boolean includeStacktrace) { + this(config, locationInfo, properties, encodeThreadContextAsList, complete, compact, eventEol, + headerPattern, footerPattern, charset, includeStacktrace, null); + } + + private JsonLayout(final Configuration config, final boolean locationInfo, final boolean properties, + final boolean encodeThreadContextAsList, + final boolean complete, final boolean compact, final boolean eventEol, final String headerPattern, + final String footerPattern, final Charset charset, final boolean includeStacktrace, + final KeyValuePair[] additionalFields) { super(config, new JacksonFactory.JSON(encodeThreadContextAsList, includeStacktrace).newWriter( - locationInfo, properties, compact), - charset, compact, complete, eventEol, - PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(), - PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build()); + locationInfo, properties, compact), + charset, compact, complete, eventEol, + PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(), + PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build(), + additionalFields); } /** @@ -206,10 +170,10 @@ public final class JsonLayout extends AbstractJacksonLayout { return result; } - @Override /** * @return The content type. */ + @Override public String getContentType() { return CONTENT_TYPE + "; charset=" + this.getCharset(); } @@ -243,6 +207,8 @@ public final class JsonLayout extends AbstractJacksonLayout { * @param includeStacktrace * If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true". * @return A JSON Layout. + * + * @deprecated Use {@link #newBuilder()} instead */ @Deprecated public static JsonLayout createLayout( @@ -262,7 +228,7 @@ public final class JsonLayout extends AbstractJacksonLayout { ) { final boolean encodeThreadContextAsList = properties && propertiesAsList; return new JsonLayout(config, locationInfo, properties, encodeThreadContextAsList, complete, compact, eventEol, - headerPattern, footerPattern, charset, includeStacktrace); + headerPattern, footerPattern, charset, includeStacktrace, null); } @PluginBuilderFactory @@ -277,7 +243,7 @@ public final class JsonLayout extends AbstractJacksonLayout { */ public static JsonLayout createDefaultLayout() { return new JsonLayout(new DefaultConfiguration(), false, false, false, false, false, false, - DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8, true); + DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8, true, null); } @Override http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b2e2d06d/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java index b3a8121..f7f667c 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java @@ -22,11 +22,13 @@ import java.util.HashMap; import java.util.Map; import org.apache.logging.log4j.core.Layout; +import org.apache.logging.log4j.core.config.Configuration; 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; -import org.apache.logging.log4j.core.config.plugins.PluginFactory; +import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory; import org.apache.logging.log4j.core.jackson.XmlConstants; +import org.apache.logging.log4j.core.util.KeyValuePair; /** * Appends a series of {@code event} elements as defined in the <a href="log4j.dtd">log4j.dtd</a>. @@ -57,10 +59,35 @@ public final class XmlLayout extends AbstractJacksonLayout { private static final String ROOT_TAG = "Events"; + public static class Builder<B extends Builder<B>> extends AbstractJacksonLayout.Builder<B> + implements org.apache.logging.log4j.core.util.Builder<XmlLayout> { + + public Builder() { + super(); + setCharset(StandardCharsets.UTF_8); + } + + @Override + public XmlLayout build() { + return new XmlLayout(getConfiguration(), isLocationInfo(), isProperties(), isComplete(), + isCompact(), getCharset(), isIncludeStacktrace(), getAdditionalFields()); + } + } + + /** + * @deprecated Use {@link #newBuilder()} instead + */ + @Deprecated protected XmlLayout(final boolean locationInfo, final boolean properties, final boolean complete, final boolean compact, final Charset charset, final boolean includeStacktrace) { - super(null, new JacksonFactory.XML(includeStacktrace).newWriter( - locationInfo, properties, compact), charset, compact, complete, false, null, null); + this(null, locationInfo, properties, complete, compact, charset, includeStacktrace, null); + } + + private XmlLayout(final Configuration config, final boolean locationInfo, final boolean properties, + final boolean complete, final boolean compact, final Charset charset, + final boolean includeStacktrace, final KeyValuePair[] additionalFields) { + super(config, new JacksonFactory.XML(includeStacktrace).newWriter( + locationInfo, properties, compact), charset, compact, complete, false, null, null, additionalFields); } /** @@ -140,8 +167,10 @@ public final class XmlLayout extends AbstractJacksonLayout { * @param includeStacktrace * If "true", includes the stacktrace of any Throwable in the generated XML, defaults to "true". * @return An XML Layout. + * + * @deprecated Use {@link #newBuilder()} instead */ - @PluginFactory + @Deprecated public static XmlLayout createLayout( // @formatter:off @PluginAttribute(value = "locationInfo") final boolean locationInfo, @@ -152,7 +181,12 @@ public final class XmlLayout extends AbstractJacksonLayout { @PluginAttribute(value = "includeStacktrace", defaultBoolean = true) final boolean includeStacktrace) // @formatter:on { - return new XmlLayout(locationInfo, properties, complete, compact, charset, includeStacktrace); + return new XmlLayout(null, locationInfo, properties, complete, compact, charset, includeStacktrace, null); + } + + @PluginBuilderFactory + public static <B extends Builder<B>> B newBuilder() { + return new Builder<B>().asBuilder(); } /** @@ -161,6 +195,6 @@ public final class XmlLayout extends AbstractJacksonLayout { * @return an XML Layout. */ public static XmlLayout createDefaultLayout() { - return new XmlLayout(false, false, false, false, StandardCharsets.UTF_8, true); + return new XmlLayout(null, false, false, false, false, StandardCharsets.UTF_8, true, null); } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b2e2d06d/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java index c762548..f43ddcd 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java @@ -16,22 +16,20 @@ */ package org.apache.logging.log4j.core.layout; -import java.io.IOException; -import java.io.Writer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; 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.Node; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.config.plugins.PluginAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory; import org.apache.logging.log4j.core.config.plugins.PluginConfiguration; -import org.apache.logging.log4j.core.config.plugins.PluginFactory; +import org.apache.logging.log4j.core.util.KeyValuePair; import org.apache.logging.log4j.util.Strings; /** @@ -52,13 +50,43 @@ public final class YamlLayout extends AbstractJacksonLayout { static final String CONTENT_TYPE = "application/yaml"; + public static class Builder<B extends Builder<B>> extends AbstractJacksonLayout.Builder<B> + implements org.apache.logging.log4j.core.util.Builder<YamlLayout> { + + public Builder() { + super(); + setCharset(StandardCharsets.UTF_8); + } + + @Override + public YamlLayout build() { + final String headerPattern = toStringOrNull(getHeader()); + final String footerPattern = toStringOrNull(getFooter()); + return new YamlLayout(getConfiguration(), isLocationInfo(), isProperties(), isComplete(), + isCompact(), getEventEol(), headerPattern, footerPattern, getCharset(), isIncludeStacktrace(), + getAdditionalFields()); + } + } + + /** + * @deprecated Use {@link #newBuilder()} instead + */ + @Deprecated protected YamlLayout(final Configuration config, final boolean locationInfo, final boolean properties, final boolean complete, final boolean compact, final boolean eventEol, final String headerPattern, final String footerPattern, final Charset charset, final boolean includeStacktrace) { + this(config, locationInfo, properties, complete, compact, eventEol, headerPattern, footerPattern, charset, includeStacktrace, null); + } + + private YamlLayout(final Configuration config, final boolean locationInfo, final boolean properties, + final boolean complete, final boolean compact, final boolean eventEol, final String headerPattern, + final String footerPattern, final Charset charset, final boolean includeStacktrace, + final KeyValuePair[] additionalFields) { super(config, new JacksonFactory.YAML(includeStacktrace).newWriter(locationInfo, properties, compact), charset, compact, - complete, eventEol, - PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(), - PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build()); + complete, eventEol, + PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(), + PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build(), + additionalFields); } /** @@ -107,10 +135,10 @@ public final class YamlLayout extends AbstractJacksonLayout { return result; } - @Override /** * @return The content type. */ + @Override public String getContentType() { return CONTENT_TYPE + "; charset=" + this.getCharset(); } @@ -133,8 +161,10 @@ public final class YamlLayout extends AbstractJacksonLayout { * @param includeStacktrace * If "true", includes the stacktrace of any Throwable in the generated YAML, defaults to "true". * @return A YAML Layout. + * + * @deprecated Use {@link #newBuilder()} instead */ - @PluginFactory + @Deprecated public static AbstractJacksonLayout createLayout( // @formatter:off @PluginConfiguration final Configuration config, @@ -150,6 +180,11 @@ public final class YamlLayout extends AbstractJacksonLayout { charset, includeStacktrace); } + @PluginBuilderFactory + public static <B extends Builder<B>> B newBuilder() { + return new Builder<B>().asBuilder(); + } + /** * Creates a YAML Layout using the default settings. Useful for testing. * @@ -157,14 +192,6 @@ public final class YamlLayout extends AbstractJacksonLayout { */ public static AbstractJacksonLayout createDefaultLayout() { return new YamlLayout(new DefaultConfiguration(), false, false, false, false, false, DEFAULT_HEADER, - DEFAULT_FOOTER, StandardCharsets.UTF_8, true); - } - - @Override - public void toSerializable(final LogEvent event, final Writer writer) throws IOException { - if (complete && eventCount > 0) { - writer.append(", "); - } - super.toSerializable(event, writer); + DEFAULT_FOOTER, StandardCharsets.UTF_8, true, null); } }
