This is an automated email from the ASF dual-hosted git repository.
rgoers 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 5db503b LOG4J2-3049 - Allow MapMessage and ThreadContext attributes
to be prefixed
5db503b is described below
commit 5db503bcdcd3f4a9076f727907bf61367c3c2633
Author: Ralph Goers <[email protected]>
AuthorDate: Sat Mar 20 17:16:22 2021 -0700
LOG4J2-3049 - Allow MapMessage and ThreadContext attributes to be prefixed
---
.../logging/log4j/core/layout/GelfLayout.java | 49 ++++++++++++++++++----
.../logging/log4j/core/layout/GelfLayout3Test.java | 22 +++++-----
log4j-core/src/test/resources/GelfLayout3Test.xml | 2 +-
src/changes/changes.xml | 3 ++
src/site/xdoc/manual/layouts.xml.vm | 12 ++++++
5 files changed, 67 insertions(+), 21 deletions(-)
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java
index 85fc942..27f9a5a 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java
@@ -157,6 +157,12 @@ public final class GelfLayout extends AbstractStringLayout
{
@PluginBuilderAttribute
private String messagePattern = null;
+ @PluginBuilderAttribute
+ private String threadContextPrefix = "";
+
+ @PluginBuilderAttribute
+ private String mapPrefix = "";
+
@PluginElement("PatternSelector")
private PatternSelector patternSelector = null;
@@ -188,7 +194,7 @@ public final class GelfLayout extends AbstractStringLayout {
}
return new GelfLayout(getConfiguration(), host, additionalFields,
compressionType, compressionThreshold,
includeStacktrace, includeThreadContext,
includeMapMessage, includeNullDelimiter,
- includeNewLineDelimiter, mdcChecker, mapChecker,
patternLayout);
+ includeNewLineDelimiter, mdcChecker, mapChecker,
patternLayout, threadContextPrefix, mapPrefix);
}
private ListChecker createChecker(String excludes, String includes) {
@@ -400,6 +406,30 @@ public final class GelfLayout extends AbstractStringLayout
{
this.mapMessageExcludes = mapMessageExcludes;
return asBuilder();
}
+
+ /**
+ * The String to prefix the ThreadContext attributes.
+ * @param prefix The prefix value. Null values will be ignored.
+ * @return this builder.
+ */
+ public B setThreadContextPrefix(final String prefix) {
+ if (prefix != null) {
+ this.threadContextPrefix = prefix;
+ }
+ return asBuilder();
+ }
+
+ /**
+ * The String to prefix the MapMessage attributes.
+ * @param prefix The prefix value. Null values will be ignored.
+ * @return this builder.
+ */
+ public B setMapPrefix(final String prefix) {
+ if (prefix != null) {
+ this.mapPrefix = prefix;
+ }
+ return asBuilder();
+ }
}
/**
@@ -409,14 +439,14 @@ public final class GelfLayout extends
AbstractStringLayout {
public GelfLayout(final String host, final KeyValuePair[]
additionalFields, final CompressionType compressionType,
final int compressionThreshold, final boolean
includeStacktrace) {
this(null, host, additionalFields, compressionType,
compressionThreshold, includeStacktrace, true, true,
- false, false, null, null, null);
+ false, false, null, null, null, "", "");
}
private GelfLayout(final Configuration config, final String host, final
KeyValuePair[] additionalFields,
final CompressionType compressionType, final int
compressionThreshold, final boolean includeStacktrace,
final boolean includeThreadContext, final boolean
includeMapMessage, final boolean includeNullDelimiter,
final boolean includeNewLineDelimiter, final ListChecker
mdcChecker, final ListChecker mapChecker,
- final PatternLayout patternLayout) {
+ final PatternLayout patternLayout, final String mdcPrefix, final
String mapPrefix) {
super(config, StandardCharsets.UTF_8, null, null);
this.host = host != null ? host : NetUtils.getLocalHostname();
this.additionalFields = additionalFields != null ? additionalFields :
new KeyValuePair[0];
@@ -437,8 +467,8 @@ public final class GelfLayout extends AbstractStringLayout {
if (includeNullDelimiter && compressionType != CompressionType.OFF) {
throw new IllegalArgumentException("null delimiter cannot be used
with compression");
}
- this.mdcWriter = new FieldWriter(mdcChecker);
- this.mapWriter = new FieldWriter(mapChecker);
+ this.mdcWriter = new FieldWriter(mdcChecker, mdcPrefix);
+ this.mapWriter = new FieldWriter(mapChecker, mapPrefix);
this.layout = patternLayout;
}
@@ -482,8 +512,7 @@ public final class GelfLayout extends AbstractStringLayout {
defaultBoolean = true) final boolean includeStacktrace) {
// @formatter:on
return new GelfLayout(null, host, additionalFields, compressionType,
compressionThreshold, includeStacktrace,
- true, true, false, false,
- null, null, null);
+ true, true, false, false, null, null, null, "", "");
}
@PluginBuilderFactory
@@ -631,16 +660,18 @@ public final class GelfLayout extends
AbstractStringLayout {
private static class FieldWriter implements TriConsumer<String, Object,
StringBuilder> {
private final ListChecker checker;
+ private final String prefix;
- FieldWriter(ListChecker checker) {
+ FieldWriter(ListChecker checker, String prefix) {
this.checker = checker;
+ this.prefix = prefix;
}
@Override
public void accept(final String key, final Object value, final
StringBuilder stringBuilder) {
if (checker.check(key)) {
stringBuilder.append(QU);
- JsonUtils.quoteAsString(key, stringBuilder);
+ JsonUtils.quoteAsString(prefix + key, stringBuilder);
stringBuilder.append("\":\"");
JsonUtils.quoteAsString(toNullSafeString(String.valueOf(value)), stringBuilder);
stringBuilder.append(QC);
diff --git
a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayout3Test.java
b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayout3Test.java
index d2452d4..7bd367b 100644
---
a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayout3Test.java
+++
b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayout3Test.java
@@ -50,10 +50,10 @@ public class GelfLayout3Test {
final JsonNode json = mapper.readTree(gelf);
assertEquals("My Test Message", json.get("short_message").asText());
assertEquals("myhost", json.get("host").asText());
- assertNotNull(json.get("_loginId"));
- assertEquals("rgoers", json.get("_loginId").asText());
- assertNull(json.get("_internalId"));
- assertNull(json.get("_requestId"));
+ assertNotNull(json.get("_mdc.loginId"));
+ assertEquals("rgoers", json.get("_mdc.loginId").asText());
+ assertNull(json.get("_mdc.internalId"));
+ assertNull(json.get("_mdc.requestId"));
String message = json.get("full_message").asText();
assertTrue(message.contains("loginId=rgoers"));
assertTrue(message.contains("GelfLayout3Test"));
@@ -78,17 +78,17 @@ public class GelfLayout3Test {
assertEquals("arg1=\"test1\" arg3=\"test3\" message=\"My Test
Message\"",
json.get("short_message").asText());
assertEquals("myhost", json.get("host").asText());
- assertNotNull(json.get("_loginId"));
- assertEquals("rgoers", json.get("_loginId").asText());
- assertNull(json.get("_internalId"));
- assertNull(json.get("_requestId"));
+ assertNotNull(json.get("_mdc.loginId"));
+ assertEquals("rgoers", json.get("_mdc.loginId").asText());
+ assertNull(json.get("_mdc.internalId"));
+ assertNull(json.get("_mdc.requestId"));
String msg = json.get("full_message").asText();
assertTrue(msg.contains("loginId=rgoers"));
assertTrue(msg.contains("GelfLayout3Test"));
assertTrue(msg.contains("arg1=\"test1\""));
- assertNull(json.get("arg2"));
- assertEquals("test1", json.get("_arg1").asText());
- assertEquals("test3", json.get("_arg3").asText());
+ assertNull(json.get("map.arg2"));
+ assertEquals("test1", json.get("_map.arg1").asText());
+ assertEquals("test3", json.get("_map.arg3").asText());
}
}
diff --git a/log4j-core/src/test/resources/GelfLayout3Test.xml
b/log4j-core/src/test/resources/GelfLayout3Test.xml
index e985737..6851ae1 100644
--- a/log4j-core/src/test/resources/GelfLayout3Test.xml
+++ b/log4j-core/src/test/resources/GelfLayout3Test.xml
@@ -20,7 +20,7 @@
<Appenders>
<List name="list">
<GelfLayout host="myhost" includeThreadContext="true"
threadContextIncludes="requestId,loginId"
- mapMessageIncludes="arg1,arg2,arg3">
+ mapMessageIncludes="arg1,arg2,arg3"
threadContextPrefix="mdc." mapPrefix="map.">
<MessagePattern>%d [%t] %-5p %X{requestId, loginId} %C{1.}.%M:%L -
%m%n"</MessagePattern>
<KeyValuePair key="foo" value="FOO"/>
<KeyValuePair key="runtime" value="$${java:runtime}"/>
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 13ebeef..0056253 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -30,6 +30,9 @@
- "remove" - Removed
-->
<release version="2.15.0" date="2021-MM-DD" description="GA Release
2.15.0">
+ <action issue="LOG4J2-3049" dev="rgoers" type="add">
+ Allow MapMessage and ThreadContext attributes to be prefixed.
+ </action>
<action issue="LOG4J2=3048" dev="rgoers" type="add">
Add improved MapMessge support to GelfLayout.
</action>
diff --git a/src/site/xdoc/manual/layouts.xml.vm
b/src/site/xdoc/manual/layouts.xml.vm
index a004d8d..87c381e 100644
--- a/src/site/xdoc/manual/layouts.xml.vm
+++ b/src/site/xdoc/manual/layouts.xml.vm
@@ -276,6 +276,12 @@ logger.debug("one={}, two={}, three={}", 1, 2, 3);
have no value will be omitted.</td>
</tr>
<tr>
+ <td>mapPrefix</td>
+ <td>String</td>
+ <td>A String to prepend to all elements of the MapMessage when
rendered as a field. Defaults to an
+ empty String.</td>
+ </tr>
+ <tr>
<td>messagePattern</td>
<td>String</td>
<td>The pattern to use to format the String. A messagePattern
and patternSelector cannot both be
@@ -308,6 +314,12 @@ logger.debug("one={}, two={}, three={}", 1, 2, 3);
are also specified this attribute will override them.
ThreadContext fields specified here that
have no value will be omitted.</td>
</tr>
+ <tr>
+ <td>ThreadContextPrefix</td>
+ <td>String</td>
+ <td>A String to prepend to all elements of the ThreadContextMap
when rendered as a field. Defaults to an
+ empty String.</td>
+ </tr>
<caption align="top">GelfLayout Parameters</caption>
</table>
<p>