http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/XmlLayoutTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/XmlLayoutTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/XmlLayoutTest.java deleted file mode 100644 index 4ee8f1e..0000000 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/XmlLayoutTest.java +++ /dev/null @@ -1,387 +0,0 @@ -/* - * 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.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.Marker; -import org.apache.logging.log4j.MarkerManager; -import org.apache.logging.log4j.ThreadContext; -import org.apache.logging.log4j.categories.Layouts; -import org.apache.logging.log4j.core.Appender; -import org.apache.logging.log4j.core.BasicConfigurationFactory; -import org.apache.logging.log4j.core.Logger; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.config.ConfigurationFactory; -import org.apache.logging.log4j.core.impl.Log4jLogEvent; -import org.apache.logging.log4j.core.jackson.Log4jXmlObjectMapper; -import org.apache.logging.log4j.core.lookup.JavaLookup; -import org.apache.logging.log4j.core.util.KeyValuePair; -import org.apache.logging.log4j.junit.ThreadContextRule; -import org.apache.logging.log4j.message.SimpleMessage; -import org.apache.logging.log4j.spi.AbstractLogger; -import org.apache.logging.log4j.test.appender.ListAppender; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; -import org.junit.experimental.categories.Category; - -import static org.junit.Assert.*; - -/** - * Tests {@link XmlLayout}. - */ -@Category(Layouts.Xml.class) -public class XmlLayoutTest { - private static final String body = "<Message>empty mdc</Message>"; - static ConfigurationFactory cf = new BasicConfigurationFactory(); - private static final String markerTag = "<Marker name=\"EVENT\"/>"; - - @Rule - public final ThreadContextRule threadContextRule = new ThreadContextRule(); - - @AfterClass - public static void cleanupClass() { - ConfigurationFactory.removeConfigurationFactory(cf); - } - - @BeforeClass - public static void setupClass() { - ConfigurationFactory.setConfigurationFactory(cf); - final LoggerContext ctx = LoggerContext.getContext(); - ctx.reconfigure(); - } - - LoggerContext ctx = LoggerContext.getContext(); - - Logger rootLogger = this.ctx.getRootLogger(); - - private void checkAttribute(final String name, final String value, final boolean compact, final String str) { - Assert.assertTrue(str, str.contains(name + "=\"" + value + "\"")); - } - - private void checkAttributeName(final String name, final boolean compact, final String str) { - Assert.assertTrue(str, str.contains(name + "=\"")); - } - - private void checkContains(final String expected, final List<String> list) { - for (final String string : list) { - final String trimedLine = string.trim(); - if (trimedLine.contains(expected)) { - return; - } - } - Assert.fail("Cannot find " + expected + " in " + list); - } - - private void checkElement(final String key, final String value, final boolean compact, final String str) { - // <item key="MDC.A" value="A_Value"/> - assertTrue(str, str.contains(String.format("<item key=\"%s\" value=\"%s\"/>", key, value))); - } - - private void checkElementName(final String name, final boolean compact, final String str, final boolean withAttributes, - final boolean withChildren) { - // simple checks, don't try to be too smart here, we're just looking for the names and basic shape. - // start - final String startStr = withAttributes ? "<" + name + " " : "<" + name + ">"; - final int startPos = str.indexOf(startStr); - Assert.assertTrue(str, startPos >= 0); - // end - final String endStr = withChildren ? "</" + name + ">" : "/>"; - final int endPos = str.indexOf(endStr, startPos + startStr.length()); - Assert.assertTrue(str, endPos >= 0); - } - - private void checkElementNameAbsent(final String name, final boolean compact, final String str) { - Assert.assertFalse(str.contains("<" + name)); - } - - /** - * @param includeSource TODO - * @param compact - * @param includeContext TODO - * @throws IOException - * @throws JsonParseException - * @throws JsonMappingException - */ - private void testAllFeatures(final boolean includeSource, final boolean compact, final boolean includeContext, final boolean includeStacktrace) throws IOException, - JsonParseException, JsonMappingException { - final Log4jLogEvent expected = LogEventFixtures.createLogEvent(); - final XmlLayout layout = XmlLayout.newBuilder() - .setLocationInfo(includeSource) - .setProperties(includeContext) - .setComplete(false) - .setCompact(compact) - .setIncludeStacktrace(includeStacktrace) - .setCharset(StandardCharsets.UTF_8) - .build(); - final String str = layout.toSerializable(expected); - // System.out.println(str); - assertEquals(str, !compact, str.contains("\n")); - assertEquals(str, includeSource, str.contains("Source")); - assertEquals(str, includeContext, str.contains("ContextMap")); - final Log4jLogEvent actual = new Log4jXmlObjectMapper().readValue(str, Log4jLogEvent.class); - LogEventFixtures.assertEqualLogEvents(expected, actual, includeSource, includeContext, includeStacktrace); - if (includeContext) { - this.checkElement("MDC.A", "A_Value", compact, str); - this.checkElement("MDC.B", "B_Value", compact, str); - } - - // - assertNull(actual.getThrown()); - // check some attrs - assertTrue(str, str.contains("loggerFqcn=\"f.q.c.n\"")); - assertTrue(str, str.contains("loggerName=\"a.B\"")); - // make sure short names are used - assertTrue(str, str.contains("<Event ")); - if (includeStacktrace) { - assertTrue(str, str.contains("class=")); - assertTrue(str, str.contains("method=")); - assertTrue(str, str.contains("file=")); - assertTrue(str, str.contains("line=")); - } - // - // make sure the names we want are used - //this.checkAttributeName("timeMillis", compact, str); - this.checkElementName("Instant", compact, str, true, false); - this.checkAttributeName("epochSecond", compact, str); - this.checkAttributeName("nanoOfSecond", compact, str); - this.checkAttributeName("thread", compact, str); // and not threadName - this.checkAttributeName("level", compact, str); - this.checkAttributeName("loggerName", compact, str); - this.checkElementName("Marker", compact, str, true, true); - this.checkAttributeName("name", compact, str); - this.checkElementName("Parents", compact, str, false, true); - this.checkElementName("Message", compact, str, false, true); - this.checkElementName("Thrown", compact, str, true, true); - this.checkElementName("Cause", compact, str, true, includeStacktrace); - this.checkAttributeName("commonElementCount", compact, str); - this.checkAttributeName("message", compact, str); - this.checkAttributeName("localizedMessage", compact, str); - if (includeStacktrace) { - this.checkElementName("ExtendedStackTrace", compact, str, false, true); - this.checkAttributeName("class", compact, str); - this.checkAttributeName("method", compact, str); - this.checkAttributeName("file", compact, str); - this.checkAttributeName("line", compact, str); - this.checkAttributeName("exact", compact, str); - this.checkAttributeName("location", compact, str); - this.checkAttributeName("version", compact, str); - } else { - this.checkElementNameAbsent("ExtendedStackTrace", compact, str); - } - this.checkElementName("Suppressed", compact, str, false, true); - this.checkAttributeName("loggerFqcn", compact, str); - this.checkAttributeName("endOfBatch", compact, str); - if (includeContext) { - this.checkElementName("ContextMap", compact, str, false, true); - } else { - this.checkElementNameAbsent("ContextMap", compact, str); - } - this.checkElementName("ContextStack", compact, str, false, true); - if (includeSource) { - this.checkElementName("Source", compact, str, true, false); - } else { - this.checkElementNameAbsent("Source", compact, str); - } - // check some attrs - this.checkAttribute("loggerFqcn", "f.q.c.n", compact, str); - this.checkAttribute("loggerName", "a.B", compact, str); - } - - @Test - public void testContentType() { - final XmlLayout layout = XmlLayout.createDefaultLayout(); - assertEquals("text/xml; charset=UTF-8", layout.getContentType()); - } - - @Test - public void testDefaultCharset() { - final XmlLayout layout = XmlLayout.createDefaultLayout(); - assertEquals(StandardCharsets.UTF_8, layout.getCharset()); - } - - /** - * Test case for MDC conversion pattern. - */ - @Test - public void testLayout() throws Exception { - final Map<String, Appender> appenders = this.rootLogger.getAppenders(); - for (final Appender appender : appenders.values()) { - this.rootLogger.removeAppender(appender); - } - // set up appender - final XmlLayout layout = XmlLayout.newBuilder() - .setLocationInfo(true) - .setProperties(true) - .setComplete(true) - .setCompact(false) - .setIncludeStacktrace(true) - .build(); - - final ListAppender appender = new ListAppender("List", null, layout, true, false); - appender.start(); - - // set appender on root and set level to debug - this.rootLogger.addAppender(appender); - this.rootLogger.setLevel(Level.DEBUG); - - // output starting message - this.rootLogger.debug("starting mdc pattern test"); - - this.rootLogger.debug("empty mdc"); - - ThreadContext.put("key1", "value1"); - ThreadContext.put("key2", "value2"); - - this.rootLogger.debug("filled mdc"); - - ThreadContext.remove("key1"); - ThreadContext.remove("key2"); - - this.rootLogger.error("finished mdc pattern test", new NullPointerException("test")); - - final Marker marker = MarkerManager.getMarker("EVENT"); - this.rootLogger.error(marker, "marker test"); - - appender.stop(); - - final List<String> list = appender.getMessages(); - - final String string = list.get(0); - assertTrue("Incorrect header: " + string, string.equals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")); - assertTrue("Incorrect footer", list.get(list.size() - 1).equals("</Events>")); - this.checkContains("loggerFqcn=\"" + AbstractLogger.class.getName() + "\"", list); - this.checkContains("level=\"DEBUG\"", list); - this.checkContains(">starting mdc pattern test</Message>", list); - // this.checkContains("<Message>starting mdc pattern test</Message>", list); - - // <Marker xmlns="" _class="org.apache.logging.log4j.MarkerManager..Log4jMarker" name="EVENT"/> - this.checkContains("<Marker", list); - this.checkContains("name=\"EVENT\"/>", list); - - for (final Appender app : appenders.values()) { - this.rootLogger.addAppender(app); - } - } - - @Test - public void testLayoutLoggerName() { - final XmlLayout layout = XmlLayout.newBuilder() - .setLocationInfo(false) - .setProperties(true) - .setComplete(true) - .setCompact(false) - .setIncludeStacktrace(true) - .build(); - - final Log4jLogEvent event = Log4jLogEvent.newBuilder() // - .setLoggerName("a.B") // - .setLoggerFqcn("f.q.c.n") // - .setLevel(Level.DEBUG) // - .setMessage(new SimpleMessage("M")) // - .setThreadName("threadName") // - .setTimeMillis(1).build(); - final String str = layout.toSerializable(event); - assertTrue(str, str.contains("loggerName=\"a.B\"")); - } - - @Test - public void testAdditionalFields() throws Exception { - final AbstractJacksonLayout layout = XmlLayout.newBuilder() - .setLocationInfo(false) - .setProperties(false) - .setIncludeStacktrace(false) - .setAdditionalFields(new KeyValuePair[] { - new KeyValuePair("KEY1", "VALUE1"), - new KeyValuePair("KEY2", "${java:runtime}"), }) - .setCharset(StandardCharsets.UTF_8) - .setConfiguration(ctx.getConfiguration()) - .build(); - final String str = layout.toSerializable(LogEventFixtures.createLogEvent()); - assertTrue(str, str.contains("<KEY1>VALUE1</KEY1>")); - assertTrue(str, str.contains("<KEY2>" + new JavaLookup().getRuntime() + "</KEY2>")); - } - - @Test - public void testLocationOffCompactOffMdcOff() throws Exception { - this.testAllFeatures(false, false, false, true); - } - - @Test - public void testLocationOnCompactOnMdcOn() throws Exception { - this.testAllFeatures(true, true, true, true); - } - - @Test - public void testExcludeStacktrace() throws Exception { - this.testAllFeatures(false, false, false, false); - } - - @Test - public void testStacktraceAsString() throws Exception { - final String str = prepareXMLForStacktraceTests(true); - assertTrue(str, str.contains("<ExtendedStackTrace>java.lang.NullPointerException")); - } - - @Test - public void testStacktraceAsNonString() throws Exception { - final String str = prepareXMLForStacktraceTests(false); - assertTrue(str, str.contains("<ExtendedStackTrace><ExtendedStackTraceItem")); - } - - private String prepareXMLForStacktraceTests(final boolean stacktraceAsString) { - final Log4jLogEvent expected = LogEventFixtures.createLogEvent(); - // @formatter:off - final AbstractJacksonLayout layout = XmlLayout.newBuilder() - .setCompact(true) - .setIncludeStacktrace(true) - .setStacktraceAsString(stacktraceAsString) - .build(); - // @formatter:off - return layout.toSerializable(expected); - } - - @Test - public void testIncludeNullDelimiterTrue() throws Exception { - final AbstractJacksonLayout layout = XmlLayout.newBuilder() - .setCompact(true) - .setIncludeNullDelimiter(true) - .build(); - final String str = layout.toSerializable(LogEventFixtures.createLogEvent()); - assertTrue(str.endsWith("\0")); - } - - @Test - public void testIncludeNullDelimiterFalse() throws Exception { - final AbstractJacksonLayout layout = XmlLayout.newBuilder() - .setCompact(true) - .setIncludeNullDelimiter(false) - .build(); - final String str = layout.toSerializable(LogEventFixtures.createLogEvent()); - assertFalse(str.endsWith("\0")); - } -}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/YamlLayoutTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/YamlLayoutTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/YamlLayoutTest.java deleted file mode 100644 index 2fef8de..0000000 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/YamlLayoutTest.java +++ /dev/null @@ -1,380 +0,0 @@ -/* - * 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 static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.ThreadContext; -import org.apache.logging.log4j.categories.Layouts; -import org.apache.logging.log4j.core.Appender; -import org.apache.logging.log4j.core.BasicConfigurationFactory; -import org.apache.logging.log4j.core.Logger; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.ConfigurationFactory; -import org.apache.logging.log4j.core.impl.Log4jLogEvent; -import org.apache.logging.log4j.core.jackson.Log4jYamlObjectMapper; -import org.apache.logging.log4j.core.lookup.JavaLookup; -import org.apache.logging.log4j.core.util.KeyValuePair; -import org.apache.logging.log4j.message.SimpleMessage; -import org.apache.logging.log4j.spi.AbstractLogger; -import org.apache.logging.log4j.test.appender.ListAppender; -import org.apache.logging.log4j.util.Strings; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.experimental.categories.Category; - -/** - * Tests the YamlLayout class. - */ -@Category(Layouts.Yaml.class) -public class YamlLayoutTest { - static ConfigurationFactory cf = new BasicConfigurationFactory(); - - @AfterClass - public static void cleanupClass() { - ConfigurationFactory.removeConfigurationFactory(cf); - ThreadContext.clearAll(); - } - - @BeforeClass - public static void setupClass() { - ThreadContext.clearAll(); - ConfigurationFactory.setConfigurationFactory(cf); - final LoggerContext ctx = LoggerContext.getContext(); - ctx.reconfigure(); - } - - LoggerContext ctx = LoggerContext.getContext(); - - Logger rootLogger = this.ctx.getRootLogger(); - - private void checkAt(final String expected, final int lineIndex, final List<String> list) { - final String trimedLine = list.get(lineIndex).trim(); - assertTrue("Incorrect line index " + lineIndex + ": " + Strings.dquote(trimedLine), - trimedLine.equals(expected)); - } - - private void checkContains(final String expected, final List<String> list) { - for (final String string : list) { - final String trimedLine = string.trim(); - if (trimedLine.equals(expected)) { - return; - } - } - Assert.fail("Cannot find " + expected + " in " + list); - } - - private void checkMapEntry(final String key, final String value, final boolean compact, final String str) { - // "name":"value" - //final String expected = String.format("- key: \"%s\"\n value: \"%s\"", key, value); - final String expected = String.format("%s: \"%s\"", key, value); - assertTrue("Cannot find " + expected + " in " + str, str.contains(expected)); - } - - private void checkProperty(final String key, final String value, final boolean compact, final String str, - final boolean isValue) { - final String propSep = this.toPropertySeparator(compact, isValue); - // {"key":"MDC.B","value":"B_Value"} - final String expected = String.format("%s%s\"%s\"", key, propSep, value); - assertTrue("Cannot find " + expected + " in " + str, str.contains(expected)); - } - - private void checkPropertyName(final String name, final boolean compact, final String str, final boolean isValue) { - final String propSep = this.toPropertySeparator(compact, isValue); - assertTrue(str, str.contains(name + propSep)); - } - - private void checkPropertyNameAbsent(final String name, final boolean compact, final String str, final boolean isValue) { - final String propSep = this.toPropertySeparator(compact, isValue); - assertFalse(str, str.contains(name + propSep)); - } - - private void testAllFeatures(final boolean includeSource, final boolean compact, final boolean eventEol, - final boolean includeContext, final boolean contextMapAslist, final boolean includeStacktrace) throws Exception { - final Log4jLogEvent expected = LogEventFixtures.createLogEvent(); - final AbstractJacksonLayout layout = YamlLayout.newBuilder() - .setLocationInfo(includeSource) - .setProperties(includeContext) - .setIncludeStacktrace(includeStacktrace) - .setCharset(StandardCharsets.UTF_8) - .build(); - final String str = layout.toSerializable(expected); - // System.out.println(str); - // Just check for \n since \r might or might not be there. - assertEquals(str, !compact || eventEol, str.contains("\n")); - assertEquals(str, includeSource, str.contains("source")); - assertEquals(str, includeContext, str.contains("contextMap")); - final Log4jLogEvent actual = new Log4jYamlObjectMapper(contextMapAslist, includeStacktrace,false).readValue(str, Log4jLogEvent.class); - LogEventFixtures.assertEqualLogEvents(expected, actual, includeSource, includeContext, includeStacktrace); - if (includeContext) { - this.checkMapEntry("MDC.A", "A_Value", compact, str); - this.checkMapEntry("MDC.B", "B_Value", compact, str); - } - // - assertNull(actual.getThrown()); - // make sure the names we want are used - this.checkPropertyName("instant", compact, str, false); - this.checkPropertyName("thread", compact, str, true); // and not threadName - this.checkPropertyName("level", compact, str, true); - this.checkPropertyName("loggerName", compact, str, true); - this.checkPropertyName("marker", compact, str, false); - this.checkPropertyName("name", compact, str, true); - this.checkPropertyName("parents", compact, str, false); - this.checkPropertyName("message", compact, str, true); - this.checkPropertyName("thrown", compact, str, false); - this.checkPropertyName("cause", compact, str, false); - this.checkPropertyName("commonElementCount", compact, str, true); - this.checkPropertyName("localizedMessage", compact, str, true); - if (includeStacktrace) { - this.checkPropertyName("extendedStackTrace", compact, str, false); - this.checkPropertyName("class", compact, str, true); - this.checkPropertyName("method", compact, str, true); - this.checkPropertyName("file", compact, str, true); - this.checkPropertyName("line", compact, str, true); - this.checkPropertyName("exact", compact, str, true); - this.checkPropertyName("location", compact, str, true); - this.checkPropertyName("version", compact, str, true); - } else { - this.checkPropertyNameAbsent("extendedStackTrace", compact, str, false); - } - this.checkPropertyName("suppressed", compact, str, false); - this.checkPropertyName("loggerFqcn", compact, str, true); - this.checkPropertyName("endOfBatch", compact, str, true); - if (includeContext) { - this.checkPropertyName("contextMap", compact, str, false); - } else { - this.checkPropertyNameAbsent("contextMap", compact, str, false); - } - this.checkPropertyName("contextStack", compact, str, false); - if (includeSource) { - this.checkPropertyName("source", compact, str, false); - } else { - this.checkPropertyNameAbsent("source", compact, str, false); - } - // check some attrs - this.checkProperty("loggerFqcn", "f.q.c.n", compact, str, true); - this.checkProperty("loggerName", "a.B", compact, str, true); - } - - @Test - public void testContentType() { - final AbstractJacksonLayout layout = YamlLayout.createDefaultLayout(); - assertEquals("application/yaml; charset=UTF-8", layout.getContentType()); - } - - @Test - public void testDefaultCharset() { - final AbstractJacksonLayout layout = YamlLayout.createDefaultLayout(); - assertEquals(StandardCharsets.UTF_8, layout.getCharset()); - } - - @Test - public void testEscapeLayout() throws Exception { - final Map<String, Appender> appenders = this.rootLogger.getAppenders(); - for (final Appender appender : appenders.values()) { - this.rootLogger.removeAppender(appender); - } - final Configuration configuration = rootLogger.getContext().getConfiguration(); - // set up appender - final AbstractJacksonLayout layout = YamlLayout.newBuilder() - .setLocationInfo(true) - .setProperties(true) - .setIncludeStacktrace(true) - .setConfiguration(configuration) - .build(); - - final ListAppender appender = new ListAppender("List", null, layout, true, false); - appender.start(); - - // set appender on root and set level to debug - this.rootLogger.addAppender(appender); - this.rootLogger.setLevel(Level.DEBUG); - - // output starting message - this.rootLogger.debug("Here is a quote ' and then a double quote \""); - - appender.stop(); - - final List<String> list = appender.getMessages(); - - this.checkAt("---", 0, list); - this.checkContains("level: \"DEBUG\"", list); - this.checkContains("message: \"Here is a quote ' and then a double quote \\\"\"", list); - this.checkContains("loggerFqcn: \"" + AbstractLogger.class.getName() + "\"", list); - for (final Appender app : appenders.values()) { - this.rootLogger.addAppender(app); - } - } - - /** - * Test case for MDC conversion pattern. - */ - @Test - public void testLayout() throws Exception { - final Map<String, Appender> appenders = this.rootLogger.getAppenders(); - for (final Appender appender : appenders.values()) { - this.rootLogger.removeAppender(appender); - } - final Configuration configuration = rootLogger.getContext().getConfiguration(); - // set up appender - // Use [[ and ]] to test header and footer (instead of [ and ]) - final AbstractJacksonLayout layout = YamlLayout.createLayout(configuration, true, true, "[[", "]]", null, true); - final ListAppender appender = new ListAppender("List", null, layout, true, false); - appender.start(); - - // set appender on root and set level to debug - this.rootLogger.addAppender(appender); - this.rootLogger.setLevel(Level.DEBUG); - - // output starting message - this.rootLogger.debug("starting mdc pattern test"); - - this.rootLogger.debug("empty mdc"); - - ThreadContext.put("key1", "value1"); - ThreadContext.put("key2", "value2"); - - this.rootLogger.debug("filled mdc"); - - ThreadContext.remove("key1"); - ThreadContext.remove("key2"); - - this.rootLogger.error("finished mdc pattern test", new NullPointerException("test")); - - appender.stop(); - - final List<String> list = appender.getMessages(); - - this.checkAt("---", 0, list); - this.checkContains("loggerFqcn: \"" + AbstractLogger.class.getName() + "\"", list); - this.checkContains("level: \"DEBUG\"", list); - this.checkContains("message: \"starting mdc pattern test\"", list); - for (final Appender app : appenders.values()) { - this.rootLogger.addAppender(app); - } - } - - @Test - public void testLayoutLoggerName() throws Exception { - final AbstractJacksonLayout layout = YamlLayout.newBuilder() - .setLocationInfo(false) - .setProperties(false) - .setIncludeStacktrace(true) - .setCharset(StandardCharsets.UTF_8) - .build(); - final Log4jLogEvent expected = Log4jLogEvent.newBuilder() // - .setLoggerName("a.B") // - .setLoggerFqcn("f.q.c.n") // - .setLevel(Level.DEBUG) // - .setMessage(new SimpleMessage("M")) // - .setThreadName("threadName") // - .setTimeMillis(1).build(); - final String str = layout.toSerializable(expected); - assertTrue(str, str.contains("loggerName: \"a.B\"")); - final Log4jLogEvent actual = new Log4jYamlObjectMapper(false, true, false).readValue(str, Log4jLogEvent.class); - assertEquals(expected.getLoggerName(), actual.getLoggerName()); - assertEquals(expected, actual); - } - - @Test - public void testAdditionalFields() throws Exception { - final AbstractJacksonLayout layout = YamlLayout.newBuilder() - .setLocationInfo(false) - .setProperties(false) - .setIncludeStacktrace(false) - .setAdditionalFields(new KeyValuePair[] { - new KeyValuePair("KEY1", "VALUE1"), - new KeyValuePair("KEY2", "${java:runtime}"), }) - .setCharset(StandardCharsets.UTF_8) - .setConfiguration(ctx.getConfiguration()) - .build(); - final String str = layout.toSerializable(LogEventFixtures.createLogEvent()); - assertTrue(str, str.contains("KEY1: \"VALUE1\"")); - assertTrue(str, str.contains("KEY2: \"" + new JavaLookup().getRuntime() + "\"")); - } - - @Test - public void testLocationOffCompactOffMdcOff() throws Exception { - this.testAllFeatures(false, false, false, false, false, true); - } - - @Test - public void testLocationOnCompactOffEventEolOffMdcOn() throws Exception { - this.testAllFeatures(true, false, false, true, false, true); - } - - @Test - public void testExcludeStacktrace() throws Exception { - this.testAllFeatures(false, false, false, false, false, false); - } - - @Test - public void testStacktraceAsString() throws Exception { - final String str = prepareYAMLForStacktraceTests(true); - assertTrue(str, str.contains("extendedStackTrace: \"java.lang.NullPointerException")); - } - - @Test - public void testStacktraceAsNonString() throws Exception { - final String str = prepareYAMLForStacktraceTests(false); - assertTrue(str, str.contains("extendedStackTrace:\n - ")); - } - - private String prepareYAMLForStacktraceTests(final boolean stacktraceAsString) { - final Log4jLogEvent expected = LogEventFixtures.createLogEvent(); - // @formatter:off - final AbstractJacksonLayout layout = YamlLayout.newBuilder() - .setIncludeStacktrace(true) - .setStacktraceAsString(stacktraceAsString) - .build(); - // @formatter:off - return layout.toSerializable(expected); - } - - @Test - public void testIncludeNullDelimiterTrue() throws Exception { - final AbstractJacksonLayout layout = YamlLayout.newBuilder() - .setIncludeNullDelimiter(true) - .build(); - final String str = layout.toSerializable(LogEventFixtures.createLogEvent()); - assertTrue(str.endsWith("\0")); - } - - @Test - public void testIncludeNullDelimiterFalse() throws Exception { - final AbstractJacksonLayout layout = YamlLayout.newBuilder() - .setIncludeNullDelimiter(false) - .build(); - final String str = layout.toSerializable(LogEventFixtures.createLogEvent()); - assertFalse(str.endsWith("\0")); - } - - private String toPropertySeparator(final boolean compact, final boolean value) { - return value ? ": " : ":"; - } -} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/AbstractLogEventParserTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/AbstractLogEventParserTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/AbstractLogEventParserTest.java new file mode 100644 index 0000000..69c00c5 --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/AbstractLogEventParserTest.java @@ -0,0 +1,59 @@ +/* + * 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.parser; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.LogEvent; + +import java.util.Arrays; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +/** + * Subclassed by JSON, XML, and YAML modules. + */ +public abstract class AbstractLogEventParserTest { + + protected void assertLogEvent(final LogEvent logEvent) { + assertThat(logEvent, is(notNullValue())); + assertThat(logEvent.getInstant().getEpochMillisecond(), equalTo(1493121664118L)); + assertThat(logEvent.getThreadName(), equalTo("main")); + assertThat(logEvent.getThreadId(), equalTo(1L)); + assertThat(logEvent.getThreadPriority(), equalTo(5)); + assertThat(logEvent.getLevel(), equalTo(Level.INFO)); + assertThat(logEvent.getLoggerName(), equalTo("HelloWorld")); + assertThat(logEvent.getMarker().getName(), equalTo("child")); + assertThat(logEvent.getMarker().getParents()[0].getName(), equalTo("parent")); + assertThat(logEvent.getMarker().getParents()[0].getParents()[0].getName(), + equalTo("grandparent")); + assertThat(logEvent.getMessage().getFormattedMessage(), equalTo("Hello, world!")); + assertThat(logEvent.getThrown(), is(nullValue())); + assertThat(logEvent.getThrownProxy().getMessage(), equalTo("error message")); + assertThat(logEvent.getThrownProxy().getName(), equalTo("java.lang.RuntimeException")); + assertThat(logEvent.getThrownProxy().getExtendedStackTrace()[0].getClassName(), + equalTo("logtest.Main")); + assertThat(logEvent.getLoggerFqcn(), equalTo("org.apache.logging.log4j.spi.AbstractLogger")); + assertThat(logEvent.getContextStack().asList(), equalTo(Arrays.asList("one", "two"))); + assertThat((String) logEvent.getContextData().getValue("foo"), equalTo("FOO")); + assertThat((String) logEvent.getContextData().getValue("bar"), equalTo("BAR")); + assertThat(logEvent.getSource().getClassName(), equalTo("logtest.Main")); + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/JsonLogEventParserTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/JsonLogEventParserTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/JsonLogEventParserTest.java deleted file mode 100644 index 9683d63..0000000 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/JsonLogEventParserTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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.parser; - -import org.apache.logging.log4j.core.LogEvent; -import org.junit.Before; -import org.junit.Test; - -import java.nio.charset.StandardCharsets; - -public class JsonLogEventParserTest extends LogEventParserTest { - - private JsonLogEventParser parser; - - private static final String JSON = "{\n" + - " \"timeMillis\" : 1493121664118,\n" + - " \"instant\":{\"epochSecond\":1493121664,\"nanoOfSecond\":118000000},\n" + - " \"thread\" : \"main\",\n" + - " \"threadId\" : 1,\n" + - " \"threadPriority\" : 5,\n" + - " \"level\" : \"INFO\",\n" + - " \"loggerName\" : \"HelloWorld\",\n" + - " \"marker\" : {\n" + - " \"name\" : \"child\",\n" + - " \"parents\" : [ {\n" + - " \"name\" : \"parent\",\n" + - " \"parents\" : [ {\n" + - " \"name\" : \"grandparent\"\n" + - " } ]\n" + - " } ]\n" + - " },\n" + - " \"message\" : \"Hello, world!\",\n" + - " \"thrown\" : {\n" + - " \"commonElementCount\" : 0,\n" + - " \"message\" : \"error message\",\n" + - " \"name\" : \"java.lang.RuntimeException\",\n" + - " \"extendedStackTrace\" : [ {\n" + - " \"class\" : \"logtest.Main\",\n" + - " \"method\" : \"main\",\n" + - " \"file\" : \"Main.java\",\n" + - " \"line\" : 29,\n" + - " \"exact\" : true,\n" + - " \"location\" : \"classes/\",\n" + - " \"version\" : \"?\"\n" + - " } ]\n" + - " },\n" + - " \"contextStack\" : [ \"one\", \"two\" ],\n" + - " \"loggerFqcn\" : \"org.apache.logging.log4j.spi.AbstractLogger\",\n" + - " \"endOfBatch\" : false,\n" + - " \"contextMap\" : {\n" + - " \"bar\" : \"BAR\",\n" + - " \"foo\" : \"FOO\"\n" + - " },\n" + - " \"source\" : {\n" + - " \"class\" : \"logtest.Main\",\n" + - " \"method\" : \"main\",\n" + - " \"file\" : \"Main.java\",\n" + - " \"line\" : 29\n" + - " }\n" + - "}"; - - @Before - public void setup() { - parser = new JsonLogEventParser(); - } - - @Test - public void testString() throws ParseException { - final LogEvent logEvent = parser.parseFrom(JSON); - assertLogEvent(logEvent); - } - - @Test(expected = ParseException.class) - public void testStringEmpty() throws ParseException { - parser.parseFrom(""); - } - - @Test(expected = ParseException.class) - public void testStringInvalidJson() throws ParseException { - parser.parseFrom("foobar"); - } - - @Test(expected = ParseException.class) - public void testStringJsonArray() throws ParseException { - parser.parseFrom("[]"); - } - - @Test - public void testEmptyObject() throws ParseException { - parser.parseFrom("{}"); - } - - @Test(expected = ParseException.class) - public void testStringWrongPropertyType() throws ParseException { - parser.parseFrom("{\"threadId\":\"foobar\"}"); - } - - @Test - public void testStringIgnoreInvalidProperty() throws ParseException { - parser.parseFrom("{\"foo\":\"bar\"}"); - } - - @Test - public void testByteArray() throws ParseException { - final LogEvent logEvent = parser.parseFrom(JSON.getBytes(StandardCharsets.UTF_8)); - assertLogEvent(logEvent); - } - - @Test - public void testByteArrayOffsetLength() throws ParseException { - final byte[] bytes = ("abc" + JSON + "def").getBytes(StandardCharsets.UTF_8); - final LogEvent logEvent = parser.parseFrom(bytes, 3, bytes.length - 6); - assertLogEvent(logEvent); - } - -} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/LogEventParserTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/LogEventParserTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/LogEventParserTest.java deleted file mode 100644 index cdb3bef..0000000 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/LogEventParserTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.parser; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.core.LogEvent; - -import java.util.Arrays; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - -public abstract class LogEventParserTest { - protected void assertLogEvent(final LogEvent logEvent) { - assertThat(logEvent, is(notNullValue())); - assertThat(logEvent.getInstant().getEpochMillisecond(), equalTo(1493121664118L)); - assertThat(logEvent.getThreadName(), equalTo("main")); - assertThat(logEvent.getThreadId(), equalTo(1L)); - assertThat(logEvent.getThreadPriority(), equalTo(5)); - assertThat(logEvent.getLevel(), equalTo(Level.INFO)); - assertThat(logEvent.getLoggerName(), equalTo("HelloWorld")); - assertThat(logEvent.getMarker().getName(), equalTo("child")); - assertThat(logEvent.getMarker().getParents()[0].getName(), equalTo("parent")); - assertThat(logEvent.getMarker().getParents()[0].getParents()[0].getName(), - equalTo("grandparent")); - assertThat(logEvent.getMessage().getFormattedMessage(), equalTo("Hello, world!")); - assertThat(logEvent.getThrown(), is(nullValue())); - assertThat(logEvent.getThrownProxy().getMessage(), equalTo("error message")); - assertThat(logEvent.getThrownProxy().getName(), equalTo("java.lang.RuntimeException")); - assertThat(logEvent.getThrownProxy().getExtendedStackTrace()[0].getClassName(), - equalTo("logtest.Main")); - assertThat(logEvent.getLoggerFqcn(), equalTo("org.apache.logging.log4j.spi.AbstractLogger")); - assertThat(logEvent.getContextStack().asList(), equalTo(Arrays.asList("one", "two"))); - assertThat((String) logEvent.getContextData().getValue("foo"), equalTo("FOO")); - assertThat((String) logEvent.getContextData().getValue("bar"), equalTo("BAR")); - assertThat(logEvent.getSource().getClassName(), equalTo("logtest.Main")); - } -} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/XmlLogEventParserTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/XmlLogEventParserTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/XmlLogEventParserTest.java deleted file mode 100644 index 72da8ff..0000000 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/XmlLogEventParserTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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.parser; - -import org.apache.logging.log4j.core.LogEvent; -import org.junit.Before; -import org.junit.Test; - -import java.nio.charset.StandardCharsets; - -public class XmlLogEventParserTest extends LogEventParserTest { - - private XmlLogEventParser parser; - - private static final String XML = "<Event xmlns=\"http://logging.apache.org/log4j/2.0/events\"\n" + - " timeMillis=\"1493121664118\"\n" + - " level=\"INFO\"\n" + - " loggerName=\"HelloWorld\"\n" + - " endOfBatch=\"false\"\n" + - " thread=\"main\"\n" + - " loggerFqcn=\"org.apache.logging.log4j.spi.AbstractLogger\"\n" + - " threadId=\"1\"\n" + - " threadPriority=\"5\">\n" + - " <Instant epochSecond=\"1493121664\" nanoOfSecond=\"118000000\"/>\n" + - " <Marker name=\"child\">\n" + - " <Parents>\n" + - " <Marker name=\"parent\">\n" + - " <Parents>\n" + - " <Marker name=\"grandparent\"/>\n" + - " </Parents>\n" + - " </Marker>\n" + - " </Parents>\n" + - " </Marker>\n" + - " <Message>Hello, world!</Message>\n" + - " <ContextMap>\n" + - " <item key=\"bar\" value=\"BAR\"/>\n" + - " <item key=\"foo\" value=\"FOO\"/>\n" + - " </ContextMap>\n" + - " <ContextStack>\n" + - " <ContextStackItem>one</ContextStackItem>\n" + - " <ContextStackItem>two</ContextStackItem>\n" + - " </ContextStack>\n" + - " <Source\n" + - " class=\"logtest.Main\"\n" + - " method=\"main\"\n" + - " file=\"Main.java\"\n" + - " line=\"29\"/>\n" + - " <Thrown commonElementCount=\"0\" message=\"error message\" name=\"java.lang.RuntimeException\">\n" + - " <ExtendedStackTrace>\n" + - " <ExtendedStackTraceItem\n" + - " class=\"logtest.Main\"\n" + - " method=\"main\"\n" + - " file=\"Main.java\"\n" + - " line=\"29\"\n" + - " exact=\"true\"\n" + - " location=\"classes/\"\n" + - " version=\"?\"/>\n" + - " </ExtendedStackTrace>\n" + - " </Thrown>\n" + - "</Event>"; - - @Before - public void setup() { - parser = new XmlLogEventParser(); - } - - @Test - public void testString() throws ParseException { - final LogEvent logEvent = parser.parseFrom(XML); - assertLogEvent(logEvent); - } - - @Test(expected = ParseException.class) - public void testStringEmpty() throws ParseException { - parser.parseFrom(""); - } - - @Test(expected = ParseException.class) - public void testStringInvalidXml() throws ParseException { - parser.parseFrom("foobar"); - } - - @Test - public void testEmptyObject() throws ParseException { - parser.parseFrom("<Event></Event>"); - } - - @Test(expected = ParseException.class) - public void testStringWrongPropertyType() throws ParseException { - parser.parseFrom("<Event><Instant epochSecond=\"bar\">foobar</Instant></Event>"); - } - - @Test - public void testTimeMillisIgnored() throws ParseException { - parser.parseFrom("<Event><timeMillis>foobar</timeMillis></Event>"); - } - - @Test - public void testStringIgnoreInvalidProperty() throws ParseException { - parser.parseFrom("<Event><foo>bar</foo></Event>"); - } - - @Test - public void testByteArray() throws ParseException { - final LogEvent logEvent = parser.parseFrom(XML.getBytes(StandardCharsets.UTF_8)); - assertLogEvent(logEvent); - } - - @Test - public void testByteArrayOffsetLength() throws ParseException { - final byte[] bytes = ("abc" + XML + "def").getBytes(StandardCharsets.UTF_8); - final LogEvent logEvent = parser.parseFrom(bytes, 3, bytes.length - 6); - assertLogEvent(logEvent); - } - -} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/YamlLogEventParserTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/YamlLogEventParserTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/YamlLogEventParserTest.java deleted file mode 100644 index 16c77e7..0000000 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/YamlLogEventParserTest.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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.parser; - -import org.apache.logging.log4j.core.LogEvent; -import org.junit.Before; -import org.junit.Test; - -import java.nio.charset.StandardCharsets; - -public class YamlLogEventParserTest extends LogEventParserTest { - - private YamlLogEventParser parser; - - private static final String YAML = "---\n" + - "timeMillis: 1493121664118\n" + - "instant:\n" + - " epochSecond: 1493121664\n" + - " nanoOfSecond: 118000000\n" + - "thread: \"main\"\n" + - "level: \"INFO\"\n" + - "loggerName: \"HelloWorld\"\n" + - "marker:\n" + - " name: \"child\"\n" + - " parents:\n" + - " - name: \"parent\"\n" + - " parents:\n" + - " - name: \"grandparent\"\n" + - "message: \"Hello, world!\"\n" + - "thrown:\n" + - " commonElementCount: 0\n" + - " message: \"error message\"\n" + - " name: \"java.lang.RuntimeException\"\n" + - " extendedStackTrace:\n" + - " - class: \"logtest.Main\"\n" + - " method: \"main\"\n" + - " file: \"Main.java\"\n" + - " line: 29\n" + - " exact: true\n" + - " location: \"classes/\"\n" + - " version: \"?\"\n" + - "contextStack:\n" + - "- \"one\"\n" + - "- \"two\"\n" + - "endOfBatch: false\n" + - "loggerFqcn: \"org.apache.logging.log4j.spi.AbstractLogger\"\n" + - "contextMap:\n" + - " bar: \"BAR\"\n" + - " foo: \"FOO\"\n" + - "threadId: 1\n" + - "threadPriority: 5\n" + - "source:\n" + - " class: \"logtest.Main\"\n" + - " method: \"main\"\n" + - " file: \"Main.java\"\n" + - " line: 29"; - - @Before - public void setup() { - parser = new YamlLogEventParser(); - } - - @Test - public void testString() throws ParseException { - final LogEvent logEvent = parser.parseFrom(YAML); - assertLogEvent(logEvent); - } - - @Test(expected = ParseException.class) - public void testStringEmpty() throws ParseException { - parser.parseFrom(""); - } - - @Test(expected = ParseException.class) - public void testStringInvalidYaml() throws ParseException { - parser.parseFrom("foobar"); - } - - @Test - public void testEmptyObject() throws ParseException { - parser.parseFrom("---\n"); - } - - @Test - public void testTimeMillisIgnored() throws ParseException { - parser.parseFrom("---\ntimeMillis: \"foobar\"\n"); - } - - @Test(expected = ParseException.class) - public void testStringWrongPropertyType() throws ParseException { - parser.parseFrom("---\nthreadId: \"foobar\"\n"); - } - - @Test - public void testStringIgnoreInvalidProperty() throws ParseException { - parser.parseFrom("---\nfoo: \"bar\"\n"); - } - - @Test - public void testByteArray() throws ParseException { - final LogEvent logEvent = parser.parseFrom(YAML.getBytes(StandardCharsets.UTF_8)); - assertLogEvent(logEvent); - } - - @Test - public void testByteArrayOffsetLength() throws ParseException { - final byte[] bytes = ("abc" + YAML + "def").getBytes(StandardCharsets.UTF_8); - final LogEvent logEvent = parser.parseFrom(bytes, 3, bytes.length - 6); - assertLogEvent(logEvent); - } - -} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/resources/log4j2-xml-layout.xml ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/resources/log4j2-xml-layout.xml b/log4j-core/src/test/resources/log4j2-xml-layout.xml new file mode 100644 index 0000000..c6355d0 --- /dev/null +++ b/log4j-core/src/test/resources/log4j2-xml-layout.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. + +--> +<Configuration status="INFO" packages=""> + <Appenders> + <File name="stdout" ignoreExceptions="false" fileName="target/test-xml-layout.log" append="false"> + <XmlLayout compact="true" eventEol="true"/> + </File> + </Appenders> + + <Loggers> + <Root level="INFO"> + <AppenderRef ref="stdout"/> + </Root> + </Loggers> +</Configuration> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/pom.xml ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson-json/pom.xml b/log4j-layout-jackson-json/pom.xml new file mode 100644 index 0000000..e782338 --- /dev/null +++ b/log4j-layout-jackson-json/pom.xml @@ -0,0 +1,167 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- ~ 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. --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j</artifactId> + <version>3.0.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>log4j-layout-jackson-json</artifactId> + <name>Apache Log4j Layout for Jackson JSON</name> + <description> + Apache Log4j Layout for Jackson JSON. + </description> + <properties> + <log4jParentDir>${basedir}/..</log4jParentDir> + <docLabel>Log4j Layout for Jackson JSON Documentation</docLabel> + <projectDir>/log4j-layout-json</projectDir> + <module.name>org.apache.logging.log4j.jackson.json</module.name> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-layout-jackson</artifactId> + <version>${project.version}</version> + </dependency> + <!-- Test Dependencies --> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-api</artifactId> + <type>test-jar</type> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + <type>test-jar</type> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-layout-jackson</artifactId> + <type>test-jar</type> + <version>${project.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <configuration> + <instructions> + <Fragment-Host>org.apache.logging.log4j.jackson.json</Fragment-Host> + <Export-Package>*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + <reporting> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-changes-plugin</artifactId> + <version>${changes.plugin.version}</version> + <reportSets> + <reportSet> + <reports> + <report>changes-report</report> + </reports> + </reportSet> + </reportSets> + <configuration> + <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate> + <useJql>true</useJql> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-checkstyle-plugin</artifactId> + <version>${checkstyle.plugin.version}</version> + <configuration> + <!--<propertiesLocation>${vfs.parent.dir}/checkstyle.properties</propertiesLocation> --> + <configLocation>${log4jParentDir}/checkstyle.xml</configLocation> + <suppressionsLocation>${log4jParentDir}/checkstyle-suppressions.xml</suppressionsLocation> + <enableRulesSummary>false</enableRulesSummary> + <propertyExpansion>basedir=${basedir}</propertyExpansion> + <propertyExpansion>licensedir=${log4jParentDir}/checkstyle-header.txt</propertyExpansion> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>${javadoc.plugin.version}</version> + <configuration> + <bottom><![CDATA[<p align="center">Copyright © {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.<br /> + Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo, + and the Apache Log4j logo are trademarks of The Apache Software Foundation.</p>]]></bottom> + <!-- module link generation is completely broken in the javadoc plugin for a multi-module non-aggregating project --> + <detectOfflineLinks>false</detectOfflineLinks> + <linksource>true</linksource> + </configuration> + <reportSets> + <reportSet> + <id>non-aggregate</id> + <reports> + <report>javadoc</report> + </reports> + </reportSet> + </reportSets> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>findbugs-maven-plugin</artifactId> + <version>${findbugs.plugin.version}</version> + <configuration> + <fork>true</fork> + <jvmArgs>-Duser.language=en</jvmArgs> + <threshold>Normal</threshold> + <effort>Default</effort> + <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jxr-plugin</artifactId> + <version>${jxr.plugin.version}</version> + <reportSets> + <reportSet> + <id>non-aggregate</id> + <reports> + <report>jxr</report> + </reports> + </reportSet> + <reportSet> + <id>aggregate</id> + <reports> + <report>aggregate</report> + </reports> + </reportSet> + </reportSets> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-pmd-plugin</artifactId> + <version>${pmd.plugin.version}</version> + <configuration> + <targetJdk>${maven.compiler.target}</targetJdk> + </configuration> + </plugin> + </plugins> + </reporting> +</project> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/JsonSetupContextInitializer.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/JsonSetupContextInitializer.java b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/JsonSetupContextInitializer.java new file mode 100644 index 0000000..e7c90a2 --- /dev/null +++ b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/JsonSetupContextInitializer.java @@ -0,0 +1,51 @@ +package org.apache.logging.log4j.jackson.json; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.ThreadContext; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement; +import org.apache.logging.log4j.core.impl.ThrowableProxy; +import org.apache.logging.log4j.core.time.Instant; +import org.apache.logging.log4j.jackson.ExtendedStackTraceElementMixIn; +import org.apache.logging.log4j.jackson.InstantMixIn; +import org.apache.logging.log4j.jackson.LevelMixIn; +import org.apache.logging.log4j.jackson.LogEventJsonMixIn; +import org.apache.logging.log4j.jackson.MarkerMixIn; +import org.apache.logging.log4j.jackson.StackTraceElementMixIn; +import org.apache.logging.log4j.jackson.ThrowableProxyMixIn; +import org.apache.logging.log4j.jackson.ThrowableProxyWithStacktraceAsStringMixIn; +import org.apache.logging.log4j.jackson.ThrowableProxyWithoutStacktraceMixIn; + +import com.fasterxml.jackson.databind.Module.SetupContext; +import com.fasterxml.jackson.databind.module.SimpleModule; + +/** + * Used to set up {@link SetupContext} from different {@link SimpleModule}s. + * <p> + * Differs from SetupContextInitializer by installing {@code LogEventJsonMixIn} for LogEvents, not + * {@code LogEventMixIn}, so it handles {@link ThreadContext} serialization differently. + * </p> + * <p> + * <em>Consider this class private.</em> + * </p> + */ +public class JsonSetupContextInitializer { + + public void setupModule(final SetupContext context, final boolean includeStacktrace, + final boolean stacktraceAsString) { + // JRE classes: we cannot edit those with Jackson annotations + context.setMixInAnnotations(StackTraceElement.class, StackTraceElementMixIn.class); + // Log4j API classes: we do not want to edit those with Jackson annotations because the API module should not + // depend on Jackson. + context.setMixInAnnotations(Marker.class, MarkerMixIn.class); + context.setMixInAnnotations(Level.class, LevelMixIn.class); + context.setMixInAnnotations(Instant.class, InstantMixIn.class); + context.setMixInAnnotations(LogEvent.class, LogEventJsonMixIn.class); // different ThreadContext handling + // Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to. + context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementMixIn.class); + context.setMixInAnnotations(ThrowableProxy.class, includeStacktrace + ? (stacktraceAsString ? ThrowableProxyWithStacktraceAsStringMixIn.class : ThrowableProxyMixIn.class) + : ThrowableProxyWithoutStacktraceMixIn.class); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonModule.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonModule.java b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonModule.java new file mode 100644 index 0000000..ab77411 --- /dev/null +++ b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonModule.java @@ -0,0 +1,58 @@ +/* + * 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.jackson.json; + +import org.apache.logging.log4j.jackson.SetupContextInitializer; +import org.apache.logging.log4j.jackson.SimpleModuleInitializer; + +import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.module.SimpleModule; + +/** + * <p> + * <em>Consider this class private.</em> + * </p> + */ +class Log4jJsonModule extends SimpleModule { + + private static final long serialVersionUID = 1L; + private final boolean encodeThreadContextAsList; + private final boolean includeStacktrace; + private final boolean stacktraceAsString; + + Log4jJsonModule(final boolean encodeThreadContextAsList, final boolean includeStacktrace, final boolean stacktraceAsString, final boolean objectMessageAsJsonObject) { + super(Log4jJsonModule.class.getName(), new Version(2, 0, 0, null, null, null)); + this.encodeThreadContextAsList = encodeThreadContextAsList; + this.includeStacktrace = includeStacktrace; + this.stacktraceAsString = stacktraceAsString; + // MUST initialize() here. + // Calling this from setupModule is too late! + //noinspection ThisEscapedInObjectConstruction + new SimpleModuleInitializer().initialize(this, objectMessageAsJsonObject); + } + + @Override + public void setupModule(final SetupContext context) { + // Calling super is a MUST! + super.setupModule(context); + if (encodeThreadContextAsList) { + new SetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString); + } else { + new JsonSetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString); + } + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonObjectMapper.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonObjectMapper.java b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonObjectMapper.java new file mode 100644 index 0000000..f0df03b --- /dev/null +++ b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonObjectMapper.java @@ -0,0 +1,47 @@ +/* + * 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.jackson.json; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * A Jackson JSON {@link ObjectMapper} initialized for Log4j. + * <p> + * <em>Consider this class private.</em> + * </p> + */ +public class Log4jJsonObjectMapper extends ObjectMapper { + + private static final long serialVersionUID = 1L; + + /** + * Create a new instance using the {@link Log4jJsonModule}. + */ + public Log4jJsonObjectMapper() { + this(false, true, false, false); + } + + /** + * Create a new instance using the {@link Log4jJsonModule}. + */ + public Log4jJsonObjectMapper(final boolean encodeThreadContextAsList, final boolean includeStacktrace, final boolean stacktraceAsString, final boolean objectMessageAsJsonObject) { + this.registerModule(new Log4jJsonModule(encodeThreadContextAsList, includeStacktrace, stacktraceAsString, objectMessageAsJsonObject)); + this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); + } + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/layout/JsonJacksonFactory.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/layout/JsonJacksonFactory.java b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/layout/JsonJacksonFactory.java new file mode 100644 index 0000000..dd7b789 --- /dev/null +++ b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/layout/JsonJacksonFactory.java @@ -0,0 +1,60 @@ +package org.apache.logging.log4j.jackson.json.layout; + +import org.apache.logging.log4j.jackson.AbstractJacksonFactory; +import org.apache.logging.log4j.jackson.JsonConstants; +import org.apache.logging.log4j.jackson.json.Log4jJsonObjectMapper; + +import com.fasterxml.jackson.core.PrettyPrinter; +import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; +import com.fasterxml.jackson.core.util.MinimalPrettyPrinter; +import com.fasterxml.jackson.databind.ObjectMapper; + +class JsonJacksonFactory extends AbstractJacksonFactory { + + private final boolean encodeThreadContextAsList; + private final boolean objectMessageAsJsonObject; + + public JsonJacksonFactory(final boolean encodeThreadContextAsList, final boolean includeStacktrace, + final boolean stacktraceAsString, final boolean objectMessageAsJsonObject) { + super(includeStacktrace, stacktraceAsString); + this.encodeThreadContextAsList = encodeThreadContextAsList; + this.objectMessageAsJsonObject = objectMessageAsJsonObject; + } + + @Override + protected String getPropertyNameForContextMap() { + return JsonConstants.ELT_CONTEXT_MAP; + } + + @Override + protected String getPropertyNameForNanoTime() { + return JsonConstants.ELT_NANO_TIME; + } + + @Override + protected String getPropertyNameForSource() { + return JsonConstants.ELT_SOURCE; + } + + @Override + protected String getPropertyNameForStackTrace() { + return JsonConstants.ELT_EXTENDED_STACK_TRACE; + } + + @Override + protected PrettyPrinter newCompactPrinter() { + return new MinimalPrettyPrinter(); + } + + @Override + protected ObjectMapper newObjectMapper() { + return new Log4jJsonObjectMapper(encodeThreadContextAsList, includeStacktrace, stacktraceAsString, + objectMessageAsJsonObject); + } + + @Override + protected PrettyPrinter newPrettyPrinter() { + return new DefaultPrettyPrinter(); + } + +} \ No newline at end of file