You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2020/07/06 21:41:37 UTC

[logging-log4j2] branch master updated: Add ability to format message using PatternLayout

This is an automated email from the ASF dual-hosted git repository.

rgoers pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/master by this push:
     new 6aa8713  Add ability to format message using PatternLayout
6aa8713 is described below

commit 6aa8713dc8a7618c89c409feddeda5be63b97a38
Author: Ralph Goers <rg...@apache.org>
AuthorDate: Mon Jul 6 14:41:18 2020 -0700

    Add ability to format message using PatternLayout
---
 .../layout/json/template/JsonTemplateLayout.java   | 14 +++--
 .../json/template/resolver/MessageResolver.java    | 59 ++++++++++++++++++----
 .../template/resolver/MessageResolverFactory.java  |  2 +-
 .../docker/restartApp.sh                           |  2 +-
 .../pom.xml                                        |  7 ++-
 .../src/main/resources/EnhancedGelf.json           | 41 +++++++++++++++
 .../src/main/config-repo/log4j2.xml                | 32 ++++++++++--
 7 files changed, 137 insertions(+), 20 deletions(-)

diff --git a/log4j-layout-json-template/src/main/java/org/apache/logging/log4j/layout/json/template/JsonTemplateLayout.java b/log4j-layout-json-template/src/main/java/org/apache/logging/log4j/layout/json/template/JsonTemplateLayout.java
index 3ef88af..7ff3ae9 100644
--- a/log4j-layout-json-template/src/main/java/org/apache/logging/log4j/layout/json/template/JsonTemplateLayout.java
+++ b/log4j-layout-json-template/src/main/java/org/apache/logging/log4j/layout/json/template/JsonTemplateLayout.java
@@ -215,7 +215,11 @@ public class JsonTemplateLayout implements StringLayout {
         final StringBuilder stringBuilder = jsonWriter.getStringBuilder();
         try {
             eventResolver.resolve(event, jsonWriter);
-            stringBuilder.append(eventDelimiter);
+            if (eventDelimiter != null && eventDelimiter.equalsIgnoreCase("null")) {
+                stringBuilder.append('\0');
+            } else {
+                stringBuilder.append(eventDelimiter);
+            }
             return stringBuilder.toString();
         } finally {
             contextRecycler.release(context);
@@ -235,7 +239,11 @@ public class JsonTemplateLayout implements StringLayout {
 
             // Render the JSON.
             eventResolver.resolve(event, jsonWriter);
-            stringBuilder.append(eventDelimiter);
+            if (eventDelimiter != null && eventDelimiter.equalsIgnoreCase("null")) {
+                stringBuilder.append('\0');
+            } else {
+                stringBuilder.append(eventDelimiter);
+            }
 
             // Write to the destination.
             if (encoder == null) {
@@ -635,7 +643,7 @@ public class JsonTemplateLayout implements StringLayout {
 
             @org.apache.logging.log4j.plugins.PluginBuilderAttribute
             private String value;
-            
+
             @org.apache.logging.log4j.plugins.PluginBuilderAttribute
             private Type type = Type.STRING;
 
diff --git a/log4j-layout-json-template/src/main/java/org/apache/logging/log4j/layout/json/template/resolver/MessageResolver.java b/log4j-layout-json-template/src/main/java/org/apache/logging/log4j/layout/json/template/resolver/MessageResolver.java
index 53dc7d9..492d447 100644
--- a/log4j-layout-json-template/src/main/java/org/apache/logging/log4j/layout/json/template/resolver/MessageResolver.java
+++ b/log4j-layout-json-template/src/main/java/org/apache/logging/log4j/layout/json/template/resolver/MessageResolver.java
@@ -17,6 +17,9 @@
 package org.apache.logging.log4j.layout.json.template.resolver;
 
 import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.core.util.JsonUtils;
 import org.apache.logging.log4j.layout.json.template.util.JsonWriter;
 import org.apache.logging.log4j.message.MapMessage;
 import org.apache.logging.log4j.message.Message;
@@ -82,21 +85,37 @@ import org.apache.logging.log4j.util.StringBuilderFormattable;
 final class MessageResolver implements EventResolver {
 
     private static final String[] FORMATS = { "JSON" };
+    /**
+     * Default length for new StringBuilder instances: {@value} .
+     */
+    protected static final int DEFAULT_STRING_BUILDER_SIZE = 1024;
 
     private final EventResolver internalResolver;
 
-    MessageResolver(final TemplateResolverConfig config) {
-        this.internalResolver = createInternalResolver(config);
+    private PatternLayout patternLayout;
+
+    MessageResolver(final Configuration configuration, final TemplateResolverConfig config) {
+        this.internalResolver = createInternalResolver(configuration, config);
     }
 
     static String getName() {
         return "message";
     }
 
-    private static EventResolver createInternalResolver(
+    private EventResolver createInternalResolver(final Configuration configuration,
             final TemplateResolverConfig config) {
         final boolean stringified = config.getBoolean("stringified", false);
         final String fallbackKey = config.getString("fallbackKey");
+        final String pattern = config.getString("pattern");
+        final boolean includeStacktrace = config.getBoolean("includeStacktrace", true);
+        if (pattern != null) {
+            patternLayout = PatternLayout.newBuilder().setPattern(pattern)
+                    .setAlwaysWriteExceptions(includeStacktrace)
+                    .setConfiguration(configuration)
+                    .build();
+        } else {
+            patternLayout = null;
+        }
         if (stringified && fallbackKey != null) {
             throw new IllegalArgumentException(
                     "fallbackKey is not allowed when stringified is enable: " + config);
@@ -113,20 +132,26 @@ final class MessageResolver implements EventResolver {
         internalResolver.resolve(logEvent, jsonWriter);
     }
 
-    private static EventResolver createStringResolver(final String fallbackKey) {
+    private EventResolver createStringResolver(final String fallbackKey) {
         return (final LogEvent logEvent, final JsonWriter jsonWriter) ->
                 resolveString(fallbackKey, logEvent, jsonWriter);
     }
 
-    private static void resolveString(
+    private void resolveString(
             final String fallbackKey,
             final LogEvent logEvent,
             final JsonWriter jsonWriter) {
-        final Message message = logEvent.getMessage();
-        resolveString(fallbackKey, message, jsonWriter);
+        if (patternLayout != null) {
+            final StringBuilder messageBuffer = getMessageStringBuilder();
+            patternLayout.serialize(logEvent, messageBuffer);
+            jsonWriter.writeString(messageBuffer.toString());
+        } else {
+            final Message message = logEvent.getMessage();
+            resolveString(fallbackKey, message, jsonWriter);
+        }
     }
 
-    private static void resolveString(
+    private void resolveString(
             final String fallbackKey,
             final Message message,
             final JsonWriter jsonWriter) {
@@ -147,7 +172,7 @@ final class MessageResolver implements EventResolver {
         }
     }
 
-    private static EventResolver createObjectResolver(final String fallbackKey) {
+    private EventResolver createObjectResolver(final String fallbackKey) {
         return (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
 
             // Skip custom serializers for SimpleMessage.
@@ -173,7 +198,7 @@ final class MessageResolver implements EventResolver {
         };
     }
 
-    private static boolean writeMultiformatMessage(
+    private boolean writeMultiformatMessage(
             final JsonWriter jsonWriter,
             final Message message) {
 
@@ -203,7 +228,7 @@ final class MessageResolver implements EventResolver {
 
     }
 
-    private static boolean writeObjectMessage(
+    private boolean writeObjectMessage(
             final JsonWriter jsonWriter,
             final Message message) {
 
@@ -220,4 +245,16 @@ final class MessageResolver implements EventResolver {
 
     }
 
+    private static final ThreadLocal<StringBuilder> messageStringBuilder = new ThreadLocal<>();
+
+    private static StringBuilder getMessageStringBuilder() {
+        StringBuilder result = messageStringBuilder.get();
+        if (result == null) {
+            result = new StringBuilder(DEFAULT_STRING_BUILDER_SIZE);
+            messageStringBuilder.set(result);
+        }
+        result.setLength(0);
+        return result;
+    }
+
 }
diff --git a/log4j-layout-json-template/src/main/java/org/apache/logging/log4j/layout/json/template/resolver/MessageResolverFactory.java b/log4j-layout-json-template/src/main/java/org/apache/logging/log4j/layout/json/template/resolver/MessageResolverFactory.java
index 4d46bb5..59e07f9 100644
--- a/log4j-layout-json-template/src/main/java/org/apache/logging/log4j/layout/json/template/resolver/MessageResolverFactory.java
+++ b/log4j-layout-json-template/src/main/java/org/apache/logging/log4j/layout/json/template/resolver/MessageResolverFactory.java
@@ -35,7 +35,7 @@ final class MessageResolverFactory implements EventResolverFactory<MessageResolv
     public MessageResolver create(
             final EventResolverContext context,
             final TemplateResolverConfig config) {
-        return new MessageResolver(config);
+        return new MessageResolver(context.getConfiguration(), config);
     }
 
 }
diff --git a/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/docker/restartApp.sh b/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/docker/restartApp.sh
index 33d3c09..af20bf4 100755
--- a/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/docker/restartApp.sh
+++ b/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/docker/restartApp.sh
@@ -15,6 +15,6 @@ docker rm -f $containerName
 
 echo Run new container...
 docker run  -e "SERVICE_PARAMS=--spring.config.location=classpath:/,classpath:/application-local-docker.yml" \
-    -e "DOCKER_URI=http://socat:1234" \
+    -e "DOCKER_URI=http://socat:1234" -e "JAVA_OPTS=-Dlogstash.search.host=host.docker.internal" \
     --network=$networkName -d $exposed_ports --name $containerName -h sample $imageName
 #    --log-driver=fluentd --log-opt fluentd-address=host.docker.internal:24224 \
\ No newline at end of file
diff --git a/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/pom.xml b/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/pom.xml
index 42b43b4..95a02fc 100644
--- a/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/pom.xml
+++ b/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/pom.xml
@@ -94,6 +94,11 @@
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-layout-json-template</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-kubernetes</artifactId>
       <version>${project.version}</version>
     </dependency>
@@ -172,7 +177,7 @@
         <configuration>
           <toolchains>
             <jdk>
-              <version>[8, )</version>
+              <version>1.8</version>
             </jdk>
           </toolchains>
         </configuration>
diff --git a/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/src/main/resources/EnhancedGelf.json b/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/src/main/resources/EnhancedGelf.json
new file mode 100644
index 0000000..994b0c7
--- /dev/null
+++ b/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/src/main/resources/EnhancedGelf.json
@@ -0,0 +1,41 @@
+{
+  "version": "1.1",
+  "host": "${hostName}",
+  "short_message": {
+    "$resolver": "message",
+    "stringified": true
+  },
+  "full_message": {
+    "$resolver": "message",
+    "pattern": "[%t] %-5p %X{requestId, sessionId, loginId, userId, ipAddress, corpAcctNumber} %C{1.}.%M:%L - %m",
+    "stringified": true
+  },
+  "timestamp": {
+    "$resolver": "timestamp",
+    "epoch": {
+      "unit": "secs"
+    }
+  },
+  "level": {
+    "$resolver": "level",
+    "field": "severity",
+    "severity": {
+      "field": "code"
+    }
+  },
+  "_logger": {
+    "$resolver": "logger",
+    "field": "name"
+  },
+  "_thread": {
+    "$resolver": "thread",
+    "field": "name"
+  },
+  "_mdc": {
+    "$resolver": "mdc",
+    "flatten": {
+      "prefix": "_"
+    },
+    "stringified": true
+  }
+}
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 2e9dcfa..25c5ac8 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
@@ -101,11 +101,37 @@
       <SizeBasedTriggeringPolicy size="10MB" />
       <DefaultRolloverStrategy max="5"/>
     </RollingFile>-->
-    <Socket name="Elastic" host="\${sys:elastic.search.host:-localhost}" port="12222" protocol="tcp" bufferedIo="true" ignoreExceptions="false">
+    <Socket name="Elastic"
+            host="\${sys:logstash.search.host}"
+            port="12222"
+            protocol="tcp"
+            bufferedIo="true">
+      <JsonTemplateLayout eventTemplateUri="classpath:EnhancedGelf.json" eventDelimiter="null">
+        <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>
+    </Socket>
+    <!--<Socket name="Elastic" host="\${sys:logstash.search.host:-localhost}" port="12222" protocol="tcp" bufferedIo="true" ignoreExceptions="false">
       <GelfLayout includeStackTrace="true" host="${hostName}" includeThreadContext="true" includeNullDelimiter="true"
                   compressionType="OFF">
         <ThreadContextIncludes>requestId,sessionId,loginId,userId,ipAddress,corpAcctNumber,callingHost,ohBehalfOf,onBehalfOfAccount</ThreadContextIncludes>
-        <MessagePattern>%d [%t] %-5p %X{requestId, sessionId, loginId, userId, ipAddress, corpAcctNumber} %C{1.}.%M:%L - %m%n</MessagePattern>
+        <MessagePattern>[%t] %-5p %X{requestId, sessionId, loginId, userId, ipAddress, corpAcctNumber} %C{1.}.%M:%L - %m%n</MessagePattern>
         <KeyValuePair key="docker.containerId" value="\${docker:containerId:-}"/>
         <KeyValuePair key="application" value="$\${lower:\${spring:spring.application.name}}"/>
         <KeyValuePair key="kubernetes.serviceAccountName" value="\${k8s:accountName:-}"/>
@@ -123,7 +149,7 @@
         <KeyValuePair key="kubernetes.imageId" value="\${k8s:imageId:-}"/>
         <KeyValuePair key="kubernetes.imageName" value="\${k8s:imageName:-}"/>
       </GelfLayout>
-    </Socket>
+    </Socket>-->
     <Console name="Console" target="SYSTEM_OUT">
       <RFC5424Layout enterpriseNumber="50177" includeMDC="true" mdcId="RequestContext" appName="SalesforceGateway"
                      mdcPrefix="" newLine="true" mdcIncludes="requestId,sessionId,loginId,userId,ipAddress,corpAcctNumber"/>