[LOG4J2-908] JSONLayout doesn't add a comma between log events. Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/7da92dee Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/7da92dee Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/7da92dee
Branch: refs/heads/LOG4J-1181 Commit: 7da92deeae90be56ed314a2721b9a8e683442cd1 Parents: 70ddbaf Author: ggregory <ggreg...@apache.org> Authored: Tue Dec 29 16:57:01 2015 -0800 Committer: ggregory <ggreg...@apache.org> Committed: Tue Dec 29 16:57:01 2015 -0800 ---------------------------------------------------------------------- .../core/layout/AbstractJacksonLayout.java | 19 ++++++-- .../log4j/core/layout/AbstractLayout.java | 9 ++++ .../logging/log4j/core/layout/JsonLayout.java | 51 ++++++++++++-------- src/changes/changes.xml | 3 ++ 4 files changed, 60 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7da92dee/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 ca966fb..3b122e1 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 @@ -16,12 +16,16 @@ */ package org.apache.logging.log4j.core.layout; +import java.io.IOException; +import java.io.Writer; import java.nio.charset.Charset; import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.util.StringBuilderWriter; import org.apache.logging.log4j.util.Strings; -import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectWriter; abstract class AbstractJacksonLayout extends AbstractStringLayout { @@ -51,13 +55,22 @@ abstract class AbstractJacksonLayout extends AbstractStringLayout { */ @Override public String toSerializable(final LogEvent event) { + StringBuilderWriter writer = new StringBuilderWriter(); try { - return this.objectWriter.writeValueAsString(event) + eol; - } catch (final JsonProcessingException e) { + toSerializable(event, writer); + return writer.toString(); + } catch (final IOException e) { // Should this be an ISE or IAE? LOGGER.error(e); return Strings.EMPTY; } } + public void toSerializable(final LogEvent event, Writer writer) + throws JsonGenerationException, JsonMappingException, IOException { + objectWriter.writeValue(writer, event); + writer.write(eol); + markEvent(); + } + } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7da92dee/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractLayout.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractLayout.java index 4fa1d8e..9c5166e 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractLayout.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractLayout.java @@ -50,6 +50,11 @@ public abstract class AbstractLayout<T extends Serializable> implements Layout<T protected final byte[] footer; /** + * The count of events successfully processed by this layout. + */ + protected long eventCount; + + /** * Constructs a layout with an optional header and footer. * * @param header @@ -87,4 +92,8 @@ public abstract class AbstractLayout<T extends Serializable> implements Layout<T public byte[] getHeader() { return header; } + + protected void markEvent() { + eventCount++; + } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7da92dee/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 04cda2d..5f3969c 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 @@ -16,12 +16,15 @@ */ 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.Node; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.config.plugins.PluginAttribute; @@ -32,8 +35,9 @@ import org.apache.logging.log4j.core.config.plugins.PluginFactory; * * <h3>Complete well-formed JSON vs. fragment JSON</h3> * <p> - * If you configure {@code complete="true"}, the appender outputs a well-formed JSON document. By default, with {@code complete="false"}, - * you should include the output as an <em>external file</em> in a separate file to form a well-formed JSON document. + * If you configure {@code complete="true"}, the appender outputs a well-formed JSON document. By default, with + * {@code complete="false"}, you should include the output as an <em>external file</em> in a separate file to form a + * well-formed JSON document. * </p> * <p> * A well-formed JSON event follows this pattern: @@ -773,22 +777,22 @@ import org.apache.logging.log4j.core.config.plugins.PluginFactory; } * </pre> * <p> - * If {@code complete="false"}, the appender does not write the JSON open array character "[" at the start of the document. and "]" and the - * end. + * If {@code complete="false"}, the appender does not write the JSON open array character "[" at the start of the + * document. and "]" and the end. * </p> * <p> * This approach enforces the independence of the JsonLayout and the appender where you embed it. * </p> * <h3>Encoding</h3> * <p> - * Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise events containing non - * ASCII characters could result in corrupted log files. + * Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise + * events containing non ASCII characters could result in corrupted log files. * </p> * <h3>Pretty vs. compact XML</h3> * <p> - * By default, the JSON layout is not compact (a.k.a. not "pretty") with {@code compact="false"}, which means the appender uses end-of-line - * characters and indents lines to format the text. If {@code compact="true"}, then no end-of-line or indentation is used. Message content - * may contain, of course, escaped end-of-lines. + * By default, the JSON layout is not compact (a.k.a. not "pretty") with {@code compact="false"}, which means the + * appender uses end-of-line characters and indents lines to format the text. If {@code compact="true"}, then no + * end-of-line or indentation is used. Message content may contain, of course, escaped end-of-lines. * </p> */ @Plugin(name = "JsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true) @@ -798,9 +802,10 @@ public final class JsonLayout extends AbstractJacksonLayout { private static final long serialVersionUID = 1L; - protected JsonLayout(final boolean locationInfo, final boolean properties, final boolean complete, final boolean compact, - final boolean eventEol, final Charset charset) { - super(new JacksonFactory.JSON().newWriter(locationInfo, properties, compact), charset, compact, complete, eventEol); + protected JsonLayout(final boolean locationInfo, final boolean properties, final boolean complete, + final boolean compact, final boolean eventEol, final Charset charset) { + super(new JacksonFactory.JSON().newWriter(locationInfo, properties, compact), charset, compact, complete, + eventEol); } /** @@ -851,18 +856,18 @@ public final class JsonLayout extends AbstractJacksonLayout { * Creates a JSON Layout. * * @param locationInfo - * If "true", includes the location information in the generated JSON. + * If "true", includes the location information in the generated JSON. * @param properties - * If "true", includes the thread context in the generated JSON. + * If "true", includes the thread context in the generated JSON. * @param complete - * If "true", includes the JSON header and footer, defaults to "false". + * If "true", includes the JSON header and footer, defaults to "false". * @param compact - * If "true", does not use end-of-lines and indentation, defaults to "false". + * If "true", does not use end-of-lines and indentation, defaults to "false". * @param eventEol - * If "true", forces an EOL after each log event (even if compact is "true"), defaults to "false". This - * allows one even per line, even in compact mode. + * If "true", forces an EOL after each log event (even if compact is "true"), defaults to "false". This + * allows one even per line, even in compact mode. * @param charset - * The character set to use, if {@code null}, uses "UTF-8". + * The character set to use, if {@code null}, uses "UTF-8". * @return A JSON Layout. */ @PluginFactory @@ -887,4 +892,12 @@ public final class JsonLayout extends AbstractJacksonLayout { public static AbstractJacksonLayout createDefaultLayout() { return new JsonLayout(false, false, false, false, false, StandardCharsets.UTF_8); } + + @Override + public void toSerializable(final LogEvent event, Writer writer) throws IOException { + if (complete && eventCount > 1) { + writer.append(", "); + } + super.toSerializable(event, writer); + } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7da92dee/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 070596d..cd9ca6f 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-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> <action issue="LOG4J2-1212" dev="rpopma" type="fix"> Fix documentation to correctly specify the blocking wait strategy as the default for async loggers. </action>