org.apache.logging.log4j.core.layout.XmlLayout Maven / Gradle / Ivy
/*
* 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.
*/
package org.apache.logging.log4j.core.layout;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import org.apache.logging.log4j.core.Layout;
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.jackson.XmlConstants;
import org.apache.logging.log4j.core.util.Constants;
/**
* Appends a series of {@code event} elements as defined in the log4j.dtd.
*
* Complete well-formed XML vs. fragment XML
*
* If you configure {@code complete="true"}, the appender outputs a well-formed XML document where the default namespace is the log4j
* namespace {@value XmlConstants#XML_NAMESPACE}. By default, with {@code complete="false"}, you should include the output as an
* external entity in a separate file to form a well-formed XML document.
*
*
* A well-formed XML document follows this pattern:
*
*
<Event xmlns="http://logging.apache.org/log4j/2.0/events" timeMillis="1" thread="MyThreadName" level="DEBUG" loggerName="a.B" loggerFQCN="f.q.c.n" endOfBatch="false">
<Marker name="Marker1">
<Parents>
<Parents name="ParentMarker1">
<Parents>
<Parents name="GrandMotherMarker"/>
<Parents name="GrandFatherMarker"/>
</Parents>
</Parents>
<Parents name="GrandFatherMarker"/>
</Parents>
</Marker>
<Message>Msg</Message>
<ContextMap>
<item key="MDC.B" value="B_Value"/>
<item key="MDC.A" value="A_Value"/>
</ContextMap>
<ContextStack>
<ContextStack>stack_msg1</ContextStack>
<ContextStack>stack_msg2</ContextStack>
</ContextStack>
<Source class="org.apache.logging.log4j.core.layout.LogEventFixtures" method="createLogEvent" file="LogEventFixtures.java" line="54"/>
<Thrown commonElementCount="0" localizedMessage="testIOEx" message="testIOEx" name="java.io.IOException">
<Cause commonElementCount="27" localizedMessage="testNPEx" message="testNPEx" name="java.lang.NullPointerException">
<ExtendedStackTrace>
<ExtendedStackTrace class="org.apache.logging.log4j.core.layout.LogEventFixtures" method="createLogEvent" file="LogEventFixtures.java" line="53" exact="false" location="test-classes/" version="?"/>
</ExtendedStackTrace>
</Cause>
<ExtendedStackTrace>
<ExtendedStackTrace class="org.apache.logging.log4j.core.layout.LogEventFixtures" method="createLogEvent" file="LogEventFixtures.java" line="56" exact="true" location="test-classes/" version="?"/>
<ExtendedStackTrace class="org.apache.logging.log4j.core.layout.XmlLayoutTest" method="testAllFeatures" file="XmlLayoutTest.java" line="122" exact="true" location="test-classes/" version="?"/>
<ExtendedStackTrace class="org.apache.logging.log4j.core.layout.XmlLayoutTest" method="testLocationOnCompactOnMdcOn" file="XmlLayoutTest.java" line="270" exact="true" location="test-classes/" version="?"/>
<ExtendedStackTrace class="sun.reflect.NativeMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
<ExtendedStackTrace class="sun.reflect.NativeMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
<ExtendedStackTrace class="sun.reflect.DelegatingMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
<ExtendedStackTrace class="java.lang.reflect.Method" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
<ExtendedStackTrace class="org.junit.runners.model.FrameworkMethod$1" method="runReflectiveCall" file="FrameworkMethod.java" line="47" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.internal.runners.model.ReflectiveCallable" method="run" file="ReflectiveCallable.java" line="12" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.model.FrameworkMethod" method="invokeExplosively" file="FrameworkMethod.java" line="44" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.internal.runners.statements.InvokeMethod" method="evaluate" file="InvokeMethod.java" line="17" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner" method="runLeaf" file="ParentRunner.java" line="271" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.BlockJUnit4ClassRunner" method="runChild" file="BlockJUnit4ClassRunner.java" line="70" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.BlockJUnit4ClassRunner" method="runChild" file="BlockJUnit4ClassRunner.java" line="50" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner$3" method="run" file="ParentRunner.java" line="238" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner$1" method="schedule" file="ParentRunner.java" line="63" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner" method="runChildren" file="ParentRunner.java" line="236" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner" method="access$000" file="ParentRunner.java" line="53" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner$2" method="evaluate" file="ParentRunner.java" line="229" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.internal.runners.statements.RunBefores" method="evaluate" file="RunBefores.java" line="26" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.internal.runners.statements.RunAfters" method="evaluate" file="RunAfters.java" line="27" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner" method="run" file="ParentRunner.java" line="309" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference" method="run" file="JUnit4TestReference.java" line="50" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.TestExecution" method="run" file="TestExecution.java" line="38" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="runTests" file="RemoteTestRunner.java" line="467" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="runTests" file="RemoteTestRunner.java" line="683" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="run" file="RemoteTestRunner.java" line="390" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="main" file="RemoteTestRunner.java" line="197" exact="true" location=".cp/" version="?"/>
</ExtendedStackTrace>
<Suppressed>
<Suppressed commonElementCount="0" localizedMessage="I am suppressed exception 1" message="I am suppressed exception 1" name="java.lang.IndexOutOfBoundsException">
<ExtendedStackTrace>
<ExtendedStackTrace class="org.apache.logging.log4j.core.layout.LogEventFixtures" method="createLogEvent" file="LogEventFixtures.java" line="57" exact="true" location="test-classes/" version="?"/>
<ExtendedStackTrace class="org.apache.logging.log4j.core.layout.XmlLayoutTest" method="testAllFeatures" file="XmlLayoutTest.java" line="122" exact="true" location="test-classes/" version="?"/>
<ExtendedStackTrace class="org.apache.logging.log4j.core.layout.XmlLayoutTest" method="testLocationOnCompactOnMdcOn" file="XmlLayoutTest.java" line="270" exact="true" location="test-classes/" version="?"/>
<ExtendedStackTrace class="sun.reflect.NativeMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
<ExtendedStackTrace class="sun.reflect.NativeMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
<ExtendedStackTrace class="sun.reflect.DelegatingMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
<ExtendedStackTrace class="java.lang.reflect.Method" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
<ExtendedStackTrace class="org.junit.runners.model.FrameworkMethod$1" method="runReflectiveCall" file="FrameworkMethod.java" line="47" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.internal.runners.model.ReflectiveCallable" method="run" file="ReflectiveCallable.java" line="12" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.model.FrameworkMethod" method="invokeExplosively" file="FrameworkMethod.java" line="44" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.internal.runners.statements.InvokeMethod" method="evaluate" file="InvokeMethod.java" line="17" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner" method="runLeaf" file="ParentRunner.java" line="271" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.BlockJUnit4ClassRunner" method="runChild" file="BlockJUnit4ClassRunner.java" line="70" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.BlockJUnit4ClassRunner" method="runChild" file="BlockJUnit4ClassRunner.java" line="50" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner$3" method="run" file="ParentRunner.java" line="238" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner$1" method="schedule" file="ParentRunner.java" line="63" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner" method="runChildren" file="ParentRunner.java" line="236" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner" method="access$000" file="ParentRunner.java" line="53" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner$2" method="evaluate" file="ParentRunner.java" line="229" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.internal.runners.statements.RunBefores" method="evaluate" file="RunBefores.java" line="26" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.internal.runners.statements.RunAfters" method="evaluate" file="RunAfters.java" line="27" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner" method="run" file="ParentRunner.java" line="309" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference" method="run" file="JUnit4TestReference.java" line="50" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.TestExecution" method="run" file="TestExecution.java" line="38" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="runTests" file="RemoteTestRunner.java" line="467" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="runTests" file="RemoteTestRunner.java" line="683" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="run" file="RemoteTestRunner.java" line="390" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="main" file="RemoteTestRunner.java" line="197" exact="true" location=".cp/" version="?"/>
</ExtendedStackTrace>
</Suppressed>
<Suppressed commonElementCount="0" localizedMessage="I am suppressed exception 2" message="I am suppressed exception 2" name="java.lang.IndexOutOfBoundsException">
<ExtendedStackTrace>
<ExtendedStackTrace class="org.apache.logging.log4j.core.layout.LogEventFixtures" method="createLogEvent" file="LogEventFixtures.java" line="58" exact="true" location="test-classes/" version="?"/>
<ExtendedStackTrace class="org.apache.logging.log4j.core.layout.XmlLayoutTest" method="testAllFeatures" file="XmlLayoutTest.java" line="122" exact="true" location="test-classes/" version="?"/>
<ExtendedStackTrace class="org.apache.logging.log4j.core.layout.XmlLayoutTest" method="testLocationOnCompactOnMdcOn" file="XmlLayoutTest.java" line="270" exact="true" location="test-classes/" version="?"/>
<ExtendedStackTrace class="sun.reflect.NativeMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
<ExtendedStackTrace class="sun.reflect.NativeMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
<ExtendedStackTrace class="sun.reflect.DelegatingMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
<ExtendedStackTrace class="java.lang.reflect.Method" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
<ExtendedStackTrace class="org.junit.runners.model.FrameworkMethod$1" method="runReflectiveCall" file="FrameworkMethod.java" line="47" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.internal.runners.model.ReflectiveCallable" method="run" file="ReflectiveCallable.java" line="12" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.model.FrameworkMethod" method="invokeExplosively" file="FrameworkMethod.java" line="44" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.internal.runners.statements.InvokeMethod" method="evaluate" file="InvokeMethod.java" line="17" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner" method="runLeaf" file="ParentRunner.java" line="271" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.BlockJUnit4ClassRunner" method="runChild" file="BlockJUnit4ClassRunner.java" line="70" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.BlockJUnit4ClassRunner" method="runChild" file="BlockJUnit4ClassRunner.java" line="50" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner$3" method="run" file="ParentRunner.java" line="238" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner$1" method="schedule" file="ParentRunner.java" line="63" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner" method="runChildren" file="ParentRunner.java" line="236" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner" method="access$000" file="ParentRunner.java" line="53" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner$2" method="evaluate" file="ParentRunner.java" line="229" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.internal.runners.statements.RunBefores" method="evaluate" file="RunBefores.java" line="26" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.internal.runners.statements.RunAfters" method="evaluate" file="RunAfters.java" line="27" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.junit.runners.ParentRunner" method="run" file="ParentRunner.java" line="309" exact="true" location="junit-4.11.jar" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference" method="run" file="JUnit4TestReference.java" line="50" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.TestExecution" method="run" file="TestExecution.java" line="38" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="runTests" file="RemoteTestRunner.java" line="467" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="runTests" file="RemoteTestRunner.java" line="683" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="run" file="RemoteTestRunner.java" line="390" exact="true" location=".cp/" version="?"/>
<ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="main" file="RemoteTestRunner.java" line="197" exact="true" location=".cp/" version="?"/>
</ExtendedStackTrace>
</Suppressed>
</Suppressed>
</Thrown>
</Event>
*
* If {@code complete="false"}, the appender does not write the XML processing instruction and the root element.
*
*
* This approach enforces the independence of the XmlLayout and the appender where you embed it.
*
* Encoding
*
* 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.
*
* Pretty vs. compact XML
*
* By default, the XML layout is not compact (compact = not "pretty") with {@code compact="false"}, which means the appender uses
* end-of-line characters and indents lines to format the XML. If {@code compact="true"}, then no end-of-line or indentation is used.
* Message content may contain, of course, end-of-lines.
*
*/
@Plugin(name = "XmlLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
public final class XmlLayout extends AbstractJacksonLayout {
private static final long serialVersionUID = 1L;
private static final String ROOT_TAG = "Events";
protected XmlLayout(final boolean locationInfo, final boolean properties, final boolean complete, final boolean compact, final Charset charset) {
super(new JacksonFactory.XML().newWriter(locationInfo, properties, compact), charset, compact, complete, false);
}
/**
* Returns appropriate XML headers.
*
* - XML processing instruction
* - XML root element
*
*
* @return a byte array containing the header.
*/
@Override
public byte[] getHeader() {
if (!complete) {
return null;
}
final StringBuilder buf = new StringBuilder();
buf.append("");
buf.append(this.eol);
// Make the log4j namespace the default namespace, no need to use more space with a namespace prefix.
buf.append('<');
buf.append(ROOT_TAG);
buf.append(" xmlns=\"" + XmlConstants.XML_NAMESPACE + "\">");
buf.append(this.eol);
return buf.toString().getBytes(this.getCharset());
}
/**
* Returns appropriate XML footer.
*
* @return a byte array containing the footer, closing the XML root element.
*/
@Override
public byte[] getFooter() {
if (!complete) {
return null;
}
return getBytes("' + this.eol);
}
/**
* Gets this XmlLayout's content format. Specified by:
*
* - Key: "dtd" Value: "log4j-events.dtd"
* - Key: "version" Value: "2.0"
*
*
* @return Map of content format keys supporting XmlLayout
*/
@Override
public Map getContentFormat() {
final Map result = new HashMap();
// result.put("dtd", "log4j-events.dtd");
result.put("xsd", "log4j-events.xsd");
result.put("version", "2.0");
return result;
}
@Override
/**
* @return The content type.
*/
public String getContentType() {
return "text/xml; charset=" + this.getCharset();
}
/**
* Creates an XML Layout.
*
* @param locationInfo If "true", includes the location information in the generated XML.
* @param properties If "true", includes the thread context in the generated XML.
* @param complete If "true", includes the XML header and footer, defaults to "false".
* @param compact If "true", does not use end-of-lines and indentation, defaults to "false".
* @param charset The character set to use, if {@code null}, uses "UTF-8".
* @return An XML Layout.
*/
@PluginFactory
public static XmlLayout createLayout(
// @formatter:off
@PluginAttribute(value = "locationInfo", defaultBoolean = false) final boolean locationInfo,
@PluginAttribute(value = "properties", defaultBoolean = false) final boolean properties,
@PluginAttribute(value = "complete", defaultBoolean = false) final boolean complete,
@PluginAttribute(value = "compact", defaultBoolean = false) final boolean compact,
@PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset)
// @formatter:on
{
return new XmlLayout(locationInfo, properties, complete, compact, charset);
}
/**
* Creates an XML Layout using the default settings.
*
* @return an XML Layout.
*/
public static XmlLayout createDefaultLayout() {
return new XmlLayout(false, false, false, false, Constants.UTF_8);
}
}