[LOG4J2-1372] XMLLayout indents, but not the first child tag (Event).
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/1d12bf0e Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/1d12bf0e Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/1d12bf0e Branch: refs/heads/master Commit: 1d12bf0e32c41597d8f4a138bea36d146a534126 Parents: f7909e2 Author: ggregory <[email protected]> Authored: Wed Apr 20 09:17:28 2016 -0700 Committer: Ralph Goers <[email protected]> Committed: Mon Apr 25 21:30:27 2016 -0700 ---------------------------------------------------------------------- .../log4j/core/layout/JacksonFactory.java | 39 +++++++++- .../appender/XmlCompleteFileAppenderTest.java | 82 ++++++++++++++++++++ .../core/appender/XmlFileAppenderTest.java | 1 + src/changes/changes.xml | 3 + 4 files changed, 124 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1d12bf0e/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java index 763f42a..3b34957 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java @@ -19,12 +19,15 @@ package org.apache.logging.log4j.core.layout; import java.util.HashSet; import java.util.Set; +import javax.xml.stream.XMLStreamException; + import org.apache.logging.log4j.core.impl.Log4jLogEvent; import org.apache.logging.log4j.core.jackson.JsonConstants; import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper; import org.apache.logging.log4j.core.jackson.Log4jXmlObjectMapper; import org.apache.logging.log4j.core.jackson.Log4jYamlObjectMapper; import org.apache.logging.log4j.core.jackson.XmlConstants; +import org.codehaus.stax2.XMLStreamWriter2; import com.fasterxml.jackson.core.PrettyPrinter; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; @@ -72,6 +75,8 @@ abstract class JacksonFactory { static class XML extends JacksonFactory { + static final int DEFAULT_INDENT = 1; + @Override protected String getPropertNameForContextMap() { return XmlConstants.ELT_CONTEXT_MAP; @@ -100,7 +105,7 @@ abstract class JacksonFactory { @Override protected PrettyPrinter newPrettyPrinter() { - return new DefaultXmlPrettyPrinter(); + return new Log4jXmlPrettyPrinter(DEFAULT_INDENT); } } @@ -137,6 +142,38 @@ abstract class JacksonFactory { } } + /** + * When <Event>s are written into a XML file; the "Event" object is not the root element, but an element named + * <Events> created using {@link #getHeader()} and {@link #getFooter()} methods.<br/> + * {@link com.fasterxml.jackson.dataformat.xml.util.DefaultXmlPrettyPrinter} is used to print the Event object into + * XML; hence it assumes <Event> tag as the root element, so it prints the <Event> tag without any + * indentation. To add an indentation to the <Event> tag; hence an additional indentation for any + * sub-elements, this class is written. As an additional task, to avoid the blank line printed after the ending + * </Event> tag, {@link #writePrologLinefeed(XMLStreamWriter2)} method is also overridden. + */ + static class Log4jXmlPrettyPrinter extends DefaultXmlPrettyPrinter { + + private static final long serialVersionUID = 1L; + + Log4jXmlPrettyPrinter(int nesting) { + _nesting = nesting; + } + + @Override + public void writePrologLinefeed(XMLStreamWriter2 sw) throws XMLStreamException { + // nothing + } + + /** + * Sets the nesting level to 1 rather than 0, so the "Event" tag will get indentation of next level below root. + */ + @Override + public DefaultXmlPrettyPrinter createInstance() { + return new Log4jXmlPrettyPrinter(XML.DEFAULT_INDENT); + } + + } + abstract protected String getPropertNameForContextMap(); abstract protected String getPropertNameForSource(); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1d12bf0e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java index 344b221..2b7fc92 100644 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java @@ -57,6 +57,7 @@ public class XmlCompleteFileAppenderTest { try (final BufferedReader reader = new BufferedReader(new FileReader(file))) { line1 = reader.readLine(); line2 = reader.readLine(); + reader.readLine(); // ignore the empty line after the <Events> root line3 = reader.readLine(); line4 = reader.readLine(); } finally { @@ -81,4 +82,85 @@ public class XmlCompleteFileAppenderTest { final String location = "testFlushAtEndOfBatch"; assertTrue("no location", !line1.contains(location)); } + + /** + * Test the indentation of the Events XML. + * <p>Expected Events XML is as below.</p> + * <pre> +<?xml version="1.0" encoding="UTF-8"?> +<Events xmlns="http://logging.apache.org/log4j/2.0/events"> + + <Event xmlns="http://logging.apache.org/log4j/2.0/events" timeMillis="1460974522088" thread="main" level="INFO" loggerName="com.foo.Bar" endOfBatch="false" loggerFqcn="org.apache.logging.log4j.spi.AbstractLogger" threadId="11" threadPriority="5"> + <Message>First Msg tag must be in level 2 after correct indentation</Message> + </Event> + + <Event xmlns="http://logging.apache.org/log4j/2.0/events" timeMillis="1460974522089" thread="main" level="INFO" loggerName="com.foo.Bar" endOfBatch="true" loggerFqcn="org.apache.logging.log4j.spi.AbstractLogger" threadId="11" threadPriority="5"> + <Message>Second Msg tag must also be in level 2 after correct indentation</Message> + </Event> +</Events> + * </pre> + * @throws Exception + */ + @Test + public void testChildElementsAreCorrectlyIndented() throws Exception { + final File file = new File("target", "XmlCompleteFileAppenderTest.log"); + file.delete(); + final Logger log = LogManager.getLogger("com.foo.Bar"); + final String firstLogMsg = "First Msg tag must be in level 2 after correct indentation"; + log.info(firstLogMsg); + final String secondLogMsg = "Second Msg tag must also be in level 2 after correct indentation"; + log.info(secondLogMsg); + CoreLoggerContexts.stopLoggerContext(false, file); // stop async thread + + String[] lines = new String[9]; + + try (final BufferedReader reader = new BufferedReader(new FileReader(file))) { + + int usefulLinesIndex = 0; + String readLine; + while((readLine = reader.readLine()) != null) { + + if (!"".equals(readLine.trim())) { + lines[usefulLinesIndex] = readLine; + usefulLinesIndex++; + } + } + } finally { + file.delete(); + } + + String currentLine = lines[0]; + assertFalse("line1 incorrect: [" + currentLine + "], must have no indentation", currentLine.startsWith(" ")); + // <EVENTS + currentLine = lines[1]; + assertFalse("line2 incorrect: [" + currentLine + "], must have no indentation", currentLine.startsWith(" ")); + // <EVENT + currentLine = lines[2]; + assertTrue("line3 incorrect: [" + currentLine + "], must have two-space indentation", currentLine.startsWith(" ")); + assertFalse("line3 incorrect: [" + currentLine + "], must not have more than two-space indentation", currentLine.startsWith(" ")); + // <MSG + currentLine = lines[3]; + assertTrue("line4 incorrect: [" + currentLine + "], must have four-space indentation", currentLine.startsWith(" ")); + assertFalse("line4 incorrect: [" + currentLine + "], must not have more than four-space indentation", currentLine.startsWith(" ")); + // </EVENT + currentLine = lines[4]; + assertTrue("line5 incorrect: [" + currentLine + "], must have two-space indentation", currentLine.startsWith(" ")); + assertFalse("line5 incorrect: [" + currentLine + "], must not have more than two-space indentation", currentLine.startsWith(" ")); + + // <EVENT + currentLine = lines[5]; + assertTrue("line6 incorrect: [" + currentLine + "], must have two-space indentation", currentLine.startsWith(" ")); + assertFalse("line6 incorrect: [" + currentLine + "], must not have more than two-space indentation", currentLine.startsWith(" ")); + // <MSG + currentLine = lines[6]; + assertTrue("line7 incorrect: [" + currentLine + "], must have four-space indentation", currentLine.startsWith(" ")); + assertFalse("line7 incorrect: [" + currentLine + "], must not have more than four-space indentation", currentLine.startsWith(" ")); + // </EVENT + currentLine = lines[7]; + assertTrue("line8 incorrect: [" + currentLine + "], must have two-space indentation", currentLine.startsWith(" ")); + assertFalse("line8 incorrect: [" + currentLine + "], must not have more than two-space indentation", currentLine.startsWith(" ")); + // </EVENTS + currentLine = lines[8]; + assertFalse("line9 incorrect: [" + currentLine + "], must have no indentation", currentLine.startsWith(" ")); + } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1d12bf0e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java index b509b30..c3c04d8 100644 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java @@ -54,6 +54,7 @@ public class XmlFileAppenderTest { String line2; String line3; try (final BufferedReader reader = new BufferedReader(new FileReader(file))) { + reader.readLine(); // first line is empty, so ignore it line1 = reader.readLine(); line2 = reader.readLine(); line3 = reader.readLine(); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1d12bf0e/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index cb717ed..0edfea6 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -24,6 +24,9 @@ </properties> <body> <release version="2.6" date="2016-MM-DD" description="GA Release 2.6"> + <action issue="LOG4J2-1372" dev="rgoers" type="fix" due-to="Kamal Mettananda, Gary Gregory"> + XMLLayout indents, but not the first child tag (Event). + </action> <action issue="LOG4J2-1363" dev="rgoers" type="fix"> Properties Configuration did not support includeLocation attribute on Loggers. </action>
