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>

Reply via email to