You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by vy...@apache.org on 2020/11/13 14:53:53 UTC
[logging-log4j2] branch release-2.x updated: LOG4J2-2961 Fix
reading of JsonTemplateLayout event additional fields from config.
This is an automated email from the ASF dual-hosted git repository.
vy pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/release-2.x by this push:
new 06101a9 LOG4J2-2961 Fix reading of JsonTemplateLayout event additional fields from config.
06101a9 is described below
commit 06101a978a993a356da6dc413863734f72874948
Author: Volkan Yazici <vo...@gmail.com>
AuthorDate: Fri Nov 13 15:47:03 2020 +0100
LOG4J2-2961 Fix reading of JsonTemplateLayout event additional fields from config.
---
.../layout/template/json/JsonTemplateLayout.java | 92 +++-------------------
.../log4j/layout/template/json/EcsLayoutTest.java | 29 +++----
.../log4j/layout/template/json/GelfLayoutTest.java | 19 ++---
.../JsonTemplateLayoutAdditionalFieldTest.java | 73 +++++++++++++++++
.../template/json/JsonTemplateLayoutTest.java | 7 +-
.../log4j/layout/template/json/LogstashIT.java | 50 +++++-------
...onalFieldEnrichedJsonTemplateLayoutLogging.xml} | 35 ++++----
.../resources/gcFreeJsonTemplateLayoutLogging.xml | 39 +++++----
...nullEventDelimitedJsonTemplateLayoutLogging.xml | 39 +++++----
.../json/JsonTemplateLayoutBenchmarkState.java | 45 +++++------
.../src/main/config-repo/log4j2.xml | 34 ++++----
src/changes/changes.xml | 3 +
.../asciidoc/manual/json-template-layout.adoc.vm | 9 +--
src/site/markdown/manual/cloud.md | 75 +++++++++---------
14 files changed, 257 insertions(+), 292 deletions(-)
diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
index 17b9a20..33c73ef 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
@@ -43,7 +43,6 @@ import org.apache.logging.log4j.layout.template.json.util.Uris;
import org.apache.logging.log4j.util.Strings;
import java.nio.charset.Charset;
-import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
@@ -140,6 +139,10 @@ public class JsonTemplateLayout implements StringLayout {
final int maxStringByteCount =
Math.toIntExact(Math.round(
maxByteCountPerChar * builder.maxStringLength));
+ final EventTemplateAdditionalField[] eventTemplateAdditionalFields =
+ builder.eventTemplateAdditionalFields != null
+ ? builder.eventTemplateAdditionalFields
+ : new EventTemplateAdditionalField[0];
final EventResolverContext resolverContext = EventResolverContext
.newBuilder()
.setConfiguration(configuration)
@@ -151,7 +154,7 @@ public class JsonTemplateLayout implements StringLayout {
.setLocationInfoEnabled(builder.locationInfoEnabled)
.setStackTraceEnabled(builder.stackTraceEnabled)
.setStackTraceElementObjectResolver(stackTraceElementObjectResolver)
- .setEventTemplateAdditionalFields(builder.eventTemplateAdditionalFields.additionalFields)
+ .setEventTemplateAdditionalFields(eventTemplateAdditionalFields)
.build();
return TemplateResolvers.ofTemplate(resolverContext, eventTemplate);
}
@@ -316,9 +319,8 @@ public class JsonTemplateLayout implements StringLayout {
private String eventTemplateUri =
JsonTemplateLayoutDefaults.getEventTemplateUri();
- @PluginElement("EventTemplateAdditionalFields")
- private EventTemplateAdditionalFields eventTemplateAdditionalFields
- = EventTemplateAdditionalFields.EMPTY;
+ @PluginElement("EventTemplateAdditionalField")
+ private EventTemplateAdditionalField[] eventTemplateAdditionalFields;
@PluginBuilderAttribute
private String stackTraceElementTemplate =
@@ -404,12 +406,12 @@ public class JsonTemplateLayout implements StringLayout {
return this;
}
- public EventTemplateAdditionalFields getEventTemplateAdditionalFields() {
+ public EventTemplateAdditionalField[] getEventTemplateAdditionalFields() {
return eventTemplateAdditionalFields;
}
public Builder setEventTemplateAdditionalFields(
- final EventTemplateAdditionalFields eventTemplateAdditionalFields) {
+ final EventTemplateAdditionalField[] eventTemplateAdditionalFields) {
this.eventTemplateAdditionalFields = eventTemplateAdditionalFields;
return this;
}
@@ -492,7 +494,6 @@ public class JsonTemplateLayout implements StringLayout {
throw new IllegalArgumentException(
"both eventTemplate and eventTemplateUri are blank");
}
- Objects.requireNonNull(eventTemplateAdditionalFields, "eventTemplateAdditionalFields");
if (stackTraceEnabled &&
Strings.isBlank(stackTraceElementTemplate)
&& Strings.isBlank(stackTraceElementTemplateUri)) {
@@ -510,78 +511,6 @@ public class JsonTemplateLayout implements StringLayout {
}
- // We need this ugly model and its builder just to be able to allow
- // key-value pairs in a dedicated element.
- @SuppressWarnings({"unused", "WeakerAccess"})
- @Plugin(name = "EventTemplateAdditionalFields",
- category = Node.CATEGORY,
- printObject = true)
- public static final class EventTemplateAdditionalFields {
-
- private static final EventTemplateAdditionalFields EMPTY = newBuilder().build();
-
- private final EventTemplateAdditionalField[] additionalFields;
-
- private EventTemplateAdditionalFields(final Builder builder) {
- this.additionalFields = builder.additionalFields != null
- ? builder.additionalFields
- : new EventTemplateAdditionalField[0];
- }
-
- public EventTemplateAdditionalField[] getAdditionalFields() {
- return additionalFields;
- }
-
- @Override
- public boolean equals(Object object) {
- if (this == object) return true;
- if (object == null || getClass() != object.getClass()) return false;
- EventTemplateAdditionalFields that = (EventTemplateAdditionalFields) object;
- return Arrays.equals(additionalFields, that.additionalFields);
- }
-
- @Override
- public int hashCode() {
- return Arrays.hashCode(additionalFields);
- }
-
- @Override
- public String toString() {
- return Arrays.toString(additionalFields);
- }
-
- @PluginBuilderFactory
- public static Builder newBuilder() {
- return new Builder();
- }
-
- public static class Builder
- implements org.apache.logging.log4j.core.util.Builder<EventTemplateAdditionalFields> {
-
- @PluginElement("AdditionalField")
- private EventTemplateAdditionalField[] additionalFields;
-
- private Builder() {}
-
- public EventTemplateAdditionalField[] getAdditionalFields() {
- return additionalFields;
- }
-
- public Builder setAdditionalFields(
- final EventTemplateAdditionalField[] additionalFields) {
- this.additionalFields = additionalFields;
- return this;
- }
-
- @Override
- public EventTemplateAdditionalFields build() {
- return new EventTemplateAdditionalFields(this);
- }
-
- }
-
- }
-
@Plugin(name = "EventTemplateAdditionalField",
category = Node.CATEGORY,
printObject = true)
@@ -644,10 +573,13 @@ public class JsonTemplateLayout implements StringLayout {
public static class Builder
implements org.apache.logging.log4j.core.util.Builder<EventTemplateAdditionalField> {
+ @PluginBuilderAttribute
private String key;
+ @PluginBuilderAttribute
private String value;
+ @PluginBuilderAttribute
private Type type = Type.STRING;
public Builder setKey(final String key) {
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/EcsLayoutTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/EcsLayoutTest.java
index 4449041..4be0c7f 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/EcsLayoutTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/EcsLayoutTest.java
@@ -43,23 +43,18 @@ public class EcsLayoutTest {
.setConfiguration(CONFIGURATION)
.setEventTemplateUri("classpath:EcsLayout.json")
.setEventTemplateAdditionalFields(
- JsonTemplateLayout
- .EventTemplateAdditionalFields
- .newBuilder()
- .setAdditionalFields(
- new EventTemplateAdditionalField[]{
- EventTemplateAdditionalField
- .newBuilder()
- .setKey("service.name")
- .setValue(SERVICE_NAME)
- .build(),
- EventTemplateAdditionalField
- .newBuilder()
- .setKey("event.dataset")
- .setValue(EVENT_DATASET)
- .build()
- })
- .build())
+ new EventTemplateAdditionalField[]{
+ EventTemplateAdditionalField
+ .newBuilder()
+ .setKey("service.name")
+ .setValue(SERVICE_NAME)
+ .build(),
+ EventTemplateAdditionalField
+ .newBuilder()
+ .setKey("event.dataset")
+ .setValue(EVENT_DATASET)
+ .build()
+ })
.build();
private static final EcsLayout ECS_LAYOUT = EcsLayout
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/GelfLayoutTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/GelfLayoutTest.java
index fed0205..9d32cf3 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/GelfLayoutTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/GelfLayoutTest.java
@@ -43,18 +43,13 @@ public class GelfLayoutTest {
.setConfiguration(CONFIGURATION)
.setEventTemplateUri("classpath:GelfLayout.json")
.setEventTemplateAdditionalFields(
- JsonTemplateLayout
- .EventTemplateAdditionalFields
- .newBuilder()
- .setAdditionalFields(
- new EventTemplateAdditionalField[]{
- EventTemplateAdditionalField
- .newBuilder()
- .setKey("host")
- .setValue(HOST_NAME)
- .build()
- })
- .build())
+ new EventTemplateAdditionalField[]{
+ EventTemplateAdditionalField
+ .newBuilder()
+ .setKey("host")
+ .setValue(HOST_NAME)
+ .build()
+ })
.build();
private static final GelfLayout GELF_LAYOUT = GelfLayout
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutAdditionalFieldTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutAdditionalFieldTest.java
new file mode 100644
index 0000000..465bcc6
--- /dev/null
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutAdditionalFieldTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.layout.template.json;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.junit.LoggerContextSource;
+import org.apache.logging.log4j.junit.Named;
+import org.apache.logging.log4j.layout.template.json.util.JsonReader;
+import org.apache.logging.log4j.test.appender.ListAppender;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+@LoggerContextSource("additionalFieldEnrichedJsonTemplateLayoutLogging.xml")
+class JsonTemplateLayoutAdditionalFieldTest {
+
+ @Test
+ void test_additional_fields_are_resolved(
+ final LoggerContext loggerContext,
+ @Named("List") final ListAppender appender) {
+
+ // Log an event.
+ final Logger logger =
+ loggerContext.getLogger(
+ JsonTemplateLayoutAdditionalFieldTest.class);
+ logger.info("trigger");
+
+ // Verify that the appender has logged the event.
+ final List<byte[]> serializedEvents = appender.getData();
+ Assertions.assertThat(serializedEvents).hasSize(1);
+
+ // Deserialize the serialized event.
+ final byte[] serializedEvent = serializedEvents.get(0);
+ final String serializedEventJson =
+ new String(
+ serializedEvent,
+ JsonTemplateLayoutDefaults.getCharset());
+ final Object serializedEventObject = JsonReader.read(serializedEventJson);
+ Assertions.assertThat(serializedEventObject).isInstanceOf(Map.class);
+ @SuppressWarnings("unchecked")
+ final Map<String, Object> serializedEventMap =
+ (Map<String, Object>) serializedEventObject;
+
+ // Verify the serialized additional fields.
+ Assertions
+ .assertThat(serializedEventMap)
+ .containsEntry("stringField", "string")
+ .containsEntry("numberField", 1)
+ .containsEntry("objectField", Collections.singletonMap("numberField", 1))
+ .containsEntry("listField", Arrays.asList(1, "two"));
+
+ }
+
+}
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java
index 9d2c3d9..ab76eb0 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java
@@ -34,7 +34,6 @@ import org.apache.logging.log4j.core.lookup.MainMapLookup;
import org.apache.logging.log4j.core.net.Severity;
import org.apache.logging.log4j.core.time.MutableInstant;
import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField;
-import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalFields;
import org.apache.logging.log4j.layout.template.json.util.JsonReader;
import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
import org.apache.logging.log4j.layout.template.json.util.MapAccessor;
@@ -1221,7 +1220,7 @@ public class JsonTemplateLayoutTest {
final String eventTemplate = "{}";
// Create the layout.
- final EventTemplateAdditionalField[] additionalFieldPairs = {
+ final EventTemplateAdditionalField[] additionalFields = {
EventTemplateAdditionalField
.newBuilder()
.setKey("number")
@@ -1240,10 +1239,6 @@ public class JsonTemplateLayoutTest {
.setType(EventTemplateAdditionalField.Type.JSON)
.build()
};
- final EventTemplateAdditionalFields additionalFields = EventTemplateAdditionalFields
- .newBuilder()
- .setAdditionalFields(additionalFieldPairs)
- .build();
final JsonTemplateLayout layout = JsonTemplateLayout
.newBuilder()
.setConfiguration(CONFIGURATION)
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/LogstashIT.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/LogstashIT.java
index 0ec0aa3..3bf6241 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/LogstashIT.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/LogstashIT.java
@@ -96,18 +96,14 @@ public class LogstashIT {
.setCharset(CHARSET)
.setEventTemplateUri("classpath:GelfLayout.json")
.setEventDelimiter("\0")
- .setEventTemplateAdditionalFields(JsonTemplateLayout
- .EventTemplateAdditionalFields
- .newBuilder()
- .setAdditionalFields(
- new EventTemplateAdditionalField[]{
- EventTemplateAdditionalField
- .newBuilder()
- .setKey("host")
- .setValue(HOST_NAME)
- .build()
- })
- .build())
+ .setEventTemplateAdditionalFields(
+ new EventTemplateAdditionalField[]{
+ EventTemplateAdditionalField
+ .newBuilder()
+ .setKey("host")
+ .setValue(HOST_NAME)
+ .build()
+ })
.build();
private static final EcsLayout ECS_LAYOUT = EcsLayout
@@ -124,23 +120,19 @@ public class LogstashIT {
.setCharset(CHARSET)
.setEventTemplateUri("classpath:EcsLayout.json")
.setRecyclerFactory(ThreadLocalRecyclerFactory.getInstance())
- .setEventTemplateAdditionalFields(JsonTemplateLayout
- .EventTemplateAdditionalFields
- .newBuilder()
- .setAdditionalFields(
- new EventTemplateAdditionalField[]{
- EventTemplateAdditionalField
- .newBuilder()
- .setKey("service.name")
- .setValue(SERVICE_NAME)
- .build(),
- EventTemplateAdditionalField
- .newBuilder()
- .setKey("event.dataset")
- .setValue(EVENT_DATASET)
- .build()
- })
- .build())
+ .setEventTemplateAdditionalFields(
+ new EventTemplateAdditionalField[]{
+ EventTemplateAdditionalField
+ .newBuilder()
+ .setKey("service.name")
+ .setValue(SERVICE_NAME)
+ .build(),
+ EventTemplateAdditionalField
+ .newBuilder()
+ .setKey("event.dataset")
+ .setValue(EVENT_DATASET)
+ .build()
+ })
.build();
private static final int LOG_EVENT_COUNT = 100;
diff --git a/log4j-layout-template-json/src/test/resources/nullEventDelimitedJsonTemplateLayoutLogging.xml b/log4j-layout-template-json/src/test/resources/additionalFieldEnrichedJsonTemplateLayoutLogging.xml
similarity index 57%
copy from log4j-layout-template-json/src/test/resources/nullEventDelimitedJsonTemplateLayoutLogging.xml
copy to log4j-layout-template-json/src/test/resources/additionalFieldEnrichedJsonTemplateLayoutLogging.xml
index 39d87a9..3449c6d 100644
--- a/log4j-layout-template-json/src/test/resources/nullEventDelimitedJsonTemplateLayoutLogging.xml
+++ b/log4j-layout-template-json/src/test/resources/additionalFieldEnrichedJsonTemplateLayoutLogging.xml
@@ -14,26 +14,21 @@
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="OFF">
- <Appenders>
- <Socket name="Socket"
- host="localhost"
- port="50514"
- protocol="TCP"
- ignoreExceptions="false"
- reconnectionDelay="100"
- immediateFlush="true">
- <JsonTemplateLayout eventTemplate='{"$resolver": "message"}'
- eventDelimiter=""
- nullEventDelimiterEnabled="true"
- charset="US-ASCII"/>
- </Socket>
- </Appenders>
- <Loggers>
- <Root level="TRACE">
- <AppenderRef ref="Socket"/>
- </Root>
- </Loggers>
+ <Appenders>
+ <List name="List" raw="true">
+ <JsonTemplateLayout>
+ <EventTemplateAdditionalField key="stringField" value="string"/>
+ <EventTemplateAdditionalField key="numberField" value="1" type="JSON"/>
+ <EventTemplateAdditionalField key="objectField" value='{"numberField":1}' type="JSON"/>
+ <EventTemplateAdditionalField key="listField" value='[1, "two"]' type="JSON"/>
+ </JsonTemplateLayout>
+ </List>
+ </Appenders>
+ <Loggers>
+ <Root level="TRACE">
+ <AppenderRef ref="List"/>
+ </Root>
+ </Loggers>
</Configuration>
diff --git a/log4j-layout-template-json/src/test/resources/gcFreeJsonTemplateLayoutLogging.xml b/log4j-layout-template-json/src/test/resources/gcFreeJsonTemplateLayoutLogging.xml
index 245ff06..2a2bc82 100644
--- a/log4j-layout-template-json/src/test/resources/gcFreeJsonTemplateLayoutLogging.xml
+++ b/log4j-layout-template-json/src/test/resources/gcFreeJsonTemplateLayoutLogging.xml
@@ -14,26 +14,25 @@
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="OFF">
- <Appenders>
- <Console name="Console" target="SYSTEM_OUT">
- <PatternLayout pattern="%p %c{1.} [%t] %X{aKey} %X %m%ex%n" />
- </Console>
- <File name="File"
- fileName="target/gcFreeJsonTemplateLayoutLogging.log"
- bufferedIO="false"
- append="false">
- <JsonTemplateLayout recyclerFactory="threadLocal"/>
- </File>
- </Appenders>
- <Loggers>
- <Root level="trace" includeLocation="false">
- <Property name="prop1">value1</Property>
- <Property name="prop2">value2</Property>
- <appender-ref ref="Console" level="FATAL"/>
- <appender-ref ref="File"/>
- </Root>
- </Loggers>
+ <Appenders>
+ <Console name="Console" target="SYSTEM_OUT">
+ <PatternLayout pattern="%p %c{1.} [%t] %X{aKey} %X %m%ex%n"/>
+ </Console>
+ <File name="File"
+ fileName="target/gcFreeJsonTemplateLayoutLogging.log"
+ bufferedIO="false"
+ append="false">
+ <JsonTemplateLayout recyclerFactory="threadLocal"/>
+ </File>
+ </Appenders>
+ <Loggers>
+ <Root level="trace" includeLocation="false">
+ <Property name="prop1">value1</Property>
+ <Property name="prop2">value2</Property>
+ <appender-ref ref="Console" level="FATAL"/>
+ <appender-ref ref="File"/>
+ </Root>
+ </Loggers>
</Configuration>
diff --git a/log4j-layout-template-json/src/test/resources/nullEventDelimitedJsonTemplateLayoutLogging.xml b/log4j-layout-template-json/src/test/resources/nullEventDelimitedJsonTemplateLayoutLogging.xml
index 39d87a9..547aac8 100644
--- a/log4j-layout-template-json/src/test/resources/nullEventDelimitedJsonTemplateLayoutLogging.xml
+++ b/log4j-layout-template-json/src/test/resources/nullEventDelimitedJsonTemplateLayoutLogging.xml
@@ -14,26 +14,25 @@
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="OFF">
- <Appenders>
- <Socket name="Socket"
- host="localhost"
- port="50514"
- protocol="TCP"
- ignoreExceptions="false"
- reconnectionDelay="100"
- immediateFlush="true">
- <JsonTemplateLayout eventTemplate='{"$resolver": "message"}'
- eventDelimiter=""
- nullEventDelimiterEnabled="true"
- charset="US-ASCII"/>
- </Socket>
- </Appenders>
- <Loggers>
- <Root level="TRACE">
- <AppenderRef ref="Socket"/>
- </Root>
- </Loggers>
+ <Appenders>
+ <Socket name="Socket"
+ host="localhost"
+ port="50514"
+ protocol="TCP"
+ ignoreExceptions="false"
+ reconnectionDelay="100"
+ immediateFlush="true">
+ <JsonTemplateLayout eventTemplate='{"$resolver": "message"}'
+ eventDelimiter=""
+ nullEventDelimiterEnabled="true"
+ charset="US-ASCII"/>
+ </Socket>
+ </Appenders>
+ <Loggers>
+ <Root level="TRACE">
+ <AppenderRef ref="Socket"/>
+ </Root>
+ </Loggers>
</Configuration>
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmarkState.java b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmarkState.java
index 7b59e08..90dd89d 100644
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmarkState.java
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmarkState.java
@@ -26,7 +26,6 @@ import org.apache.logging.log4j.core.layout.JsonLayout;
import org.apache.logging.log4j.core.util.KeyValuePair;
import org.apache.logging.log4j.core.util.NetUtils;
import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField;
-import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalFields;
import org.apache.logging.log4j.layout.template.json.util.ThreadLocalRecyclerFactory;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
@@ -87,17 +86,14 @@ public class JsonTemplateLayoutBenchmarkState {
}
private static JsonTemplateLayout createJsonTemplateLayout4EcsLayout() {
- final EventTemplateAdditionalFields additionalFields = EventTemplateAdditionalFields
- .newBuilder()
- .setAdditionalFields(
- new EventTemplateAdditionalField[]{
- EventTemplateAdditionalField
- .newBuilder()
- .setKey("service.name")
- .setValue("benchmark")
- .build()
- })
- .build();
+ final EventTemplateAdditionalField[] additionalFields =
+ new EventTemplateAdditionalField[]{
+ EventTemplateAdditionalField
+ .newBuilder()
+ .setKey("service.name")
+ .setValue("benchmark")
+ .build()
+ };
return JsonTemplateLayout
.newBuilder()
.setConfiguration(CONFIGURATION)
@@ -115,20 +111,17 @@ public class JsonTemplateLayoutBenchmarkState {
.setCharset(CHARSET)
.setEventTemplateUri("classpath:GelfLayout.json")
.setRecyclerFactory(ThreadLocalRecyclerFactory.getInstance())
- .setEventTemplateAdditionalFields(EventTemplateAdditionalFields
- .newBuilder()
- .setAdditionalFields(
- new EventTemplateAdditionalField[]{
- // Adding "host" as a constant rather than using
- // the "hostName" property lookup at runtime, which
- // is what GelfLayout does as well.
- EventTemplateAdditionalField
- .newBuilder()
- .setKey("host")
- .setValue(NetUtils.getLocalHostname())
- .build()
- })
- .build())
+ .setEventTemplateAdditionalFields(
+ new EventTemplateAdditionalField[]{
+ // Adding "host" as a constant rather than using
+ // the "hostName" property lookup at runtime, which
+ // is what GelfLayout does as well.
+ EventTemplateAdditionalField
+ .newBuilder()
+ .setKey("host")
+ .setValue(NetUtils.getLocalHostname())
+ .build()
+ })
.build();
}
diff --git a/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-server/src/main/config-repo/log4j2.xml b/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-server/src/main/config-repo/log4j2.xml
index 8921f4f..e88234f 100644
--- a/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-server/src/main/config-repo/log4j2.xml
+++ b/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-server/src/main/config-repo/log4j2.xml
@@ -107,24 +107,22 @@
protocol="tcp"
bufferedIo="true">
<JsonTemplateLayout eventTemplateUri="classpath:GelfLayout.json" nullEventDelimiterEnabled="true">
- <EventTemplateAdditionalFields>
- <EventTemplateAdditionalField key="containerId" value="\${docker:containerId:-}"/>
- <EventTemplateAdditionalField key="application" value="\${lower:${spring:spring.application.name:-spring}}"/>
- <EventTemplateAdditionalField key="kubernetes.serviceAccountName" value="\${k8s:accountName:-}"/>
- <EventTemplateAdditionalField key="kubernetes.containerId" value="\${k8s:containerId:-}"/>
- <EventTemplateAdditionalField key="kubernetes.containerName" value="\${k8s:containerName:-}"/>
- <EventTemplateAdditionalField key="kubernetes.host" value="\${k8s:host:-}"/>
- <EventTemplateAdditionalField key="kubernetes.labels.app" value="\${k8s:labels.app:-}"/>
- <EventTemplateAdditionalField key="kubernetes.labels.pod-template-hash" value="\${k8s:labels.podTemplateHash:-}"/>
- <EventTemplateAdditionalField key="kubernetes.master_url" value="\${k8s:masterUrl:-}"/>
- <EventTemplateAdditionalField key="kubernetes.namespaceId" value="\${k8s:namespaceId:-}"/>
- <EventTemplateAdditionalField key="kubernetes.namespaceName" value="\${k8s:namespaceName:-}"/>
- <EventTemplateAdditionalField key="kubernetes.podID" value="\${k8s:podId:-}"/>
- <EventTemplateAdditionalField key="kubernetes.podIP" value="\${k8s:podIp:-}"/>
- <EventTemplateAdditionalField key="kubernetes.podName" value="\${k8s:podName:-}"/>
- <EventTemplateAdditionalField key="kubernetes.imageId" value="\${k8s:imageId:-}"/>
- <EventTemplateAdditionalField key="kubernetes.imageName" value="\${k8s:imageName:-}"/>
- </EventTemplateAdditionalFields>
+ <EventTemplateAdditionalField key="containerId" value="\${docker:containerId:-}"/>
+ <EventTemplateAdditionalField key="application" value="\${lower:${spring:spring.application.name:-spring}}"/>
+ <EventTemplateAdditionalField key="kubernetes.serviceAccountName" value="\${k8s:accountName:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.containerId" value="\${k8s:containerId:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.containerName" value="\${k8s:containerName:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.host" value="\${k8s:host:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.labels.app" value="\${k8s:labels.app:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.labels.pod-template-hash" value="\${k8s:labels.podTemplateHash:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.master_url" value="\${k8s:masterUrl:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.namespaceId" value="\${k8s:namespaceId:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.namespaceName" value="\${k8s:namespaceName:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.podID" value="\${k8s:podId:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.podIP" value="\${k8s:podIp:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.podName" value="\${k8s:podName:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.imageId" value="\${k8s:imageId:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.imageName" value="\${k8s:imageName:-}"/>
</JsonTemplateLayout>
</Socket>
<Console name="Console" target="SYSTEM_OUT">
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 700e1f5..1a0ea85 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -30,6 +30,9 @@
- "remove" - Removed
-->
<release version="2.14.1" date="2020-MM-DD" description="GA Release 2.14.1">
+ <action issue="LOG4J2-2961" dev="vy" type="fix">
+ Fix reading of JsonTemplateLayout event additional fields from config.
+ </action>
<action issue="LOG4J2-2916" dev="vy" type="fix" due-to="wuqian0808">
Avoid redundant Kafka producer instantiation causing thread leaks.
</action>
diff --git a/src/site/asciidoc/manual/json-template-layout.adoc.vm b/src/site/asciidoc/manual/json-template-layout.adoc.vm
index d90f607..2536e9b 100644
--- a/src/site/asciidoc/manual/json-template-layout.adoc.vm
+++ b/src/site/asciidoc/manual/json-template-layout.adoc.vm
@@ -242,14 +242,13 @@ custom fields:
[source,xml]
----
<JsonTemplateLayout eventTemplateUri="classpath:GelfLayout.json">
- <EventTemplateAdditionalFields>
- <EventTemplateAdditionalField key="host" value="www.apache.org"/>
- <EventTemplateAdditionalField key="_serviceName" value="auth-service"/>
- <EventTemplateAdditionalField key="_containerId" value="6ede3f0ca7d9"/>
- </EventTemplateAdditionalFields>
+ <EventTemplateAdditionalField key="host" value="www.apache.org"/>
+ <EventTemplateAdditionalField key="_serviceName" value="auth-service"/>
+ <EventTemplateAdditionalField key="_containerId" value="6ede3f0ca7d9"/>
</JsonTemplateLayout>
----
+The default `type` for the added new fields are `String`.
One can also pass JSON literals into additional fields:
[source,xml]
diff --git a/src/site/markdown/manual/cloud.md b/src/site/markdown/manual/cloud.md
index 84fb63f..07692c9 100644
--- a/src/site/markdown/manual/cloud.md
+++ b/src/site/markdown/manual/cloud.md
@@ -140,28 +140,26 @@ will be formatted without newlines.
port="12345"
protocol="tcp"
bufferedIo="true">
- <JsonTemplateLayout eventTemplateUri="classpath:EcsLayout.json">
- <EventTemplateAdditionalFields>
- <EventTemplateAdditionalField key="containerId" value="${docker:containerId:-}"/>
- <EventTemplateAdditionalField key="application" value="${lower:${spring:spring.application.name:-spring}}"/>
- <EventTemplateAdditionalField key="kubernetes.serviceAccountName" value="${k8s:accountName:-}"/>
- <EventTemplateAdditionalField key="kubernetes.containerId" value="${k8s:containerId:-}"/>
- <EventTemplateAdditionalField key="kubernetes.containerName" value="${k8s:containerName:-}"/>
- <EventTemplateAdditionalField key="kubernetes.host" value="${k8s:host:-}"/>
- <EventTemplateAdditionalField key="kubernetes.labels.app" value="${k8s:labels.app:-}"/>
- <EventTemplateAdditionalField key="kubernetes.labels.pod-template-hash" value="${k8s:labels.podTemplateHash:-}"/>
- <EventTemplateAdditionalField key="kubernetes.master_url" value="${k8s:masterUrl:-}"/>
- <EventTemplateAdditionalField key="kubernetes.namespaceId" value="${k8s:namespaceId:-}"/>
- <EventTemplateAdditionalField key="kubernetes.namespaceName" value="${k8s:namespaceName:-}"/>
- <EventTemplateAdditionalField key="kubernetes.podID" value="${k8s:podId:-}"/>
- <EventTemplateAdditionalField key="kubernetes.podIP" value="${k8s:podIp:-}"/>
- <EventTemplateAdditionalField key="kubernetes.podName" value="${k8s:podName:-}"/>
- <EventTemplateAdditionalField key="kubernetes.imageId" value="${k8s:imageId:-}"/>
- <EventTemplateAdditionalField key="kubernetes.imageName" value="${k8s:imageName:-}"/>
- </EventTemplateAdditionalFields>
- </JsonTemplateLayout>
+ <JsonTemplateLayout eventTemplateUri="classpath:EcsLayout.json">
+ <EventTemplateAdditionalField key="containerId" value="${docker:containerId:-}"/>
+ <EventTemplateAdditionalField key="application" value="${lower:${spring:spring.application.name:-spring}}"/>
+ <EventTemplateAdditionalField key="kubernetes.serviceAccountName" value="${k8s:accountName:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.containerId" value="${k8s:containerId:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.containerName" value="${k8s:containerName:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.host" value="${k8s:host:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.labels.app" value="${k8s:labels.app:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.labels.pod-template-hash" value="${k8s:labels.podTemplateHash:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.master_url" value="${k8s:masterUrl:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.namespaceId" value="${k8s:namespaceId:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.namespaceName" value="${k8s:namespaceName:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.podID" value="${k8s:podId:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.podIP" value="${k8s:podIp:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.podName" value="${k8s:podName:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.imageId" value="${k8s:imageId:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.imageName" value="${k8s:imageName:-}"/>
+ </JsonTemplateLayout>
</Socket>
-
+
The JsonTemplateLayout can also be used to generate JSON that matches the GELF specification which can
format the message attribute using a pattern in accordance with the PatternLayout. For example, the following
template, named EnhancedGelf.json, can be used to generate GELF-compliant data that can be passed to Logstash.
@@ -221,26 +219,25 @@ The logging configuration to use this template would be
protocol="tcp"
bufferedIo="true">
<JsonTemplateLayout eventTemplateUri="classpath:EnhancedGelf.json" nullEventDelimiterEnabled="true">
- <EventTemplateAdditionalFields>
- <EventTemplateAdditionalField key="containerId" value="${docker:containerId:-}"/>
- <EventTemplateAdditionalField key="application" value="${lower:${spring:spring.application.name:-spring}}"/>
- <EventTemplateAdditionalField key="kubernetes.serviceAccountName" value="${k8s:accountName:-}"/>
- <EventTemplateAdditionalField key="kubernetes.containerId" value="${k8s:containerId:-}"/>
- <EventTemplateAdditionalField key="kubernetes.containerName" value="${k8s:containerName:-}"/>
- <EventTemplateAdditionalField key="kubernetes.host" value="${k8s:host:-}"/>
- <EventTemplateAdditionalField key="kubernetes.labels.app" value="${k8s:labels.app:-}"/>
- <EventTemplateAdditionalField key="kubernetes.labels.pod-template-hash" value="${k8s:labels.podTemplateHash:-}"/>
- <EventTemplateAdditionalField key="kubernetes.master_url" value="${k8s:masterUrl:-}"/>
- <EventTemplateAdditionalField key="kubernetes.namespaceId" value="${k8s:namespaceId:-}"/>
- <EventTemplateAdditionalField key="kubernetes.namespaceName" value="${k8s:namespaceName:-}"/>
- <EventTemplateAdditionalField key="kubernetes.podID" value="${k8s:podId:-}"/>
- <EventTemplateAdditionalField key="kubernetes.podIP" value="${k8s:podIp:-}"/>
- <EventTemplateAdditionalField key="kubernetes.podName" value="${k8s:podName:-}"/>
- <EventTemplateAdditionalField key="kubernetes.imageId" value="${k8s:imageId:-}"/>
- <EventTemplateAdditionalField key="kubernetes.imageName" value="${k8s:imageName:-}"/>
- </EventTemplateAdditionalFields>
+ <EventTemplateAdditionalField key="containerId" value="${docker:containerId:-}"/>
+ <EventTemplateAdditionalField key="application" value="${lower:${spring:spring.application.name:-spring}}"/>
+ <EventTemplateAdditionalField key="kubernetes.serviceAccountName" value="${k8s:accountName:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.containerId" value="${k8s:containerId:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.containerName" value="${k8s:containerName:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.host" value="${k8s:host:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.labels.app" value="${k8s:labels.app:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.labels.pod-template-hash" value="${k8s:labels.podTemplateHash:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.master_url" value="${k8s:masterUrl:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.namespaceId" value="${k8s:namespaceId:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.namespaceName" value="${k8s:namespaceName:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.podID" value="${k8s:podId:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.podIP" value="${k8s:podIp:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.podName" value="${k8s:podName:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.imageId" value="${k8s:imageId:-}"/>
+ <EventTemplateAdditionalField key="kubernetes.imageName" value="${k8s:imageName:-}"/>
</JsonTemplateLayout>
</Socket>
+
The significant difference with this configuration from the first example is that it references the
custom template and it specifies an event delimiter of a null character ('\0');