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 2021/03/13 07:35:09 UTC
[logging-log4j2] branch release-2.x updated: LOG4J2-3041 - Allow
GelfLayout to use PatternSelectors
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 6f781e2 LOG4J2-3041 - Allow GelfLayout to use PatternSelectors
6f781e2 is described below
commit 6f781e2d3e82f9abfc55af819bdf9a52ff4b41f9
Author: Ralph Goers <rg...@apache.org>
AuthorDate: Sat Mar 13 00:34:47 2021 -0700
LOG4J2-3041 - Allow GelfLayout to use PatternSelectors
---
.../logging/log4j/core/layout/GelfLayout.java | 23 +++
.../{GelfLayoutTest2.java => GelfLayout2Test.java} | 4 +-
.../{GelfLayoutTest3.java => GelfLayout3Test.java} | 6 +-
...st3.java => GelfLayoutPatternSelectorTest.java} | 38 +++-
.../{GelfLayoutTest2.xml => GelfLayout2Test.xml} | 0
.../{GelfLayoutTest3.xml => GelfLayout3Test.xml} | 0
...Test3.xml => GelfLayoutPatternSelectorTest.xml} | 6 +-
src/changes/changes.xml | 4 +-
src/site/xdoc/manual/layouts.xml.vm | 221 +++++++++++----------
9 files changed, 180 insertions(+), 122 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 83a2550..43622e6 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
@@ -145,6 +145,8 @@ public final class GelfLayout extends AbstractStringLayout {
@PluginBuilderAttribute
private String messagePattern = null;
+ @PluginElement("PatternSelector")
+ private PatternSelector patternSelector = null;
public Builder() {
setCharset(StandardCharsets.UTF_8);
@@ -177,12 +179,23 @@ public final class GelfLayout extends AbstractStringLayout {
checker = ListChecker.NOOP_CHECKER;
}
PatternLayout patternLayout = null;
+ if (messagePattern != null && patternSelector != null) {
+ LOGGER.error("A message pattern and PatternSelector cannot both be specified on GelfLayout, "
+ + "ignoring message pattern");
+ messagePattern = null;
+ }
if (messagePattern != null) {
patternLayout = PatternLayout.newBuilder().withPattern(messagePattern)
.withAlwaysWriteExceptions(includeStacktrace)
.withConfiguration(getConfiguration())
.build();
}
+ if (patternSelector != null) {
+ patternLayout = PatternLayout.newBuilder().withPatternSelector(patternSelector)
+ .withAlwaysWriteExceptions(includeStacktrace)
+ .withConfiguration(getConfiguration())
+ .build();
+ }
return new GelfLayout(getConfiguration(), host, additionalFields, compressionType, compressionThreshold,
includeStacktrace, includeThreadContext, includeNullDelimiter, includeNewLineDelimiter, checker,
patternLayout);
@@ -311,6 +324,16 @@ public final class GelfLayout extends AbstractStringLayout {
}
/**
+ * The PatternSelector to use to format the message.
+ * @param patternSelector the PatternSelector.
+ * @return this builder
+ */
+ public B setPatternSelector(final PatternSelector patternSelector) {
+ this.patternSelector = patternSelector;
+ return asBuilder();
+ }
+
+ /**
* A comma separated list of thread context keys to include;
* @param mdcIncludes the list of keys.
* @return this builder
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest2.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayout2Test.java
similarity index 96%
rename from log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest2.java
rename to log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayout2Test.java
index 2b3f429..f9f44f7 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest2.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayout2Test.java
@@ -30,8 +30,8 @@ import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
-@LoggerContextSource("GelfLayoutTest2.xml")
-public class GelfLayoutTest2 {
+@LoggerContextSource("GelfLayout2Test.xml")
+public class GelfLayout2Test {
@Test
public void gelfLayout(final LoggerContext context, @Named final ListAppender list) throws IOException {
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest3.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayout3Test.java
similarity index 94%
copy from log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest3.java
copy to log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayout3Test.java
index fc9a404..6ebd27c 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest3.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayout3Test.java
@@ -32,10 +32,10 @@ import java.io.IOException;
import static org.junit.jupiter.api.Assertions.*;
-@LoggerContextSource("GelfLayoutTest3.xml")
+@LoggerContextSource("GelfLayout3Test.xml")
@UsingAnyThreadContext
@Tag("json")
-public class GelfLayoutTest3 {
+public class GelfLayout3Test {
@Test
public void gelfLayout(final LoggerContext context, @Named final ListAppender list) throws IOException {
@@ -55,7 +55,7 @@ public class GelfLayoutTest3 {
assertNull(json.get("_requestId"));
String message = json.get("full_message").asText();
assertTrue(message.contains("loginId=rgoers"));
- assertTrue(message.contains("GelfLayoutTest3"));
+ assertTrue(message.contains("GelfLayout3Test"));
}
}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest3.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutPatternSelectorTest.java
similarity index 62%
rename from log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest3.java
rename to log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutPatternSelectorTest.java
index fc9a404..f3f5712 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest3.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutPatternSelectorTest.java
@@ -16,26 +16,32 @@
*/
package org.apache.logging.log4j.core.layout;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
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.junit.UsingAnyThreadContext;
+import org.apache.logging.log4j.spi.AbstractLogger;
import org.apache.logging.log4j.test.appender.ListAppender;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
-import java.io.IOException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
-import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
-@LoggerContextSource("GelfLayoutTest3.xml")
+@LoggerContextSource("GelfLayoutPatternSelectorTest.xml")
@UsingAnyThreadContext
@Tag("json")
-public class GelfLayoutTest3 {
+public class GelfLayoutPatternSelectorTest {
@Test
public void gelfLayout(final LoggerContext context, @Named final ListAppender list) throws IOException {
@@ -44,9 +50,10 @@ public class GelfLayoutTest3 {
ThreadContext.put("loginId", "rgoers");
ThreadContext.put("internalId", "12345");
logger.info("My Test Message");
- final String gelf = list.getMessages().get(0);
+ logger.info(AbstractLogger.FLOW_MARKER, "My Test Message");
+ String gelf = list.getMessages().get(0);
final ObjectMapper mapper = new ObjectMapper();
- final JsonNode json = mapper.readTree(gelf);
+ JsonNode json = mapper.readTree(gelf);
assertEquals("My Test Message", json.get("short_message").asText());
assertEquals("myhost", json.get("host").asText());
assertNotNull(json.get("_loginId"));
@@ -54,8 +61,21 @@ public class GelfLayoutTest3 {
assertNull(json.get("_internalId"));
assertNull(json.get("_requestId"));
String message = json.get("full_message").asText();
+ assertFalse(message.contains("====="));
+ assertTrue(message.contains("loginId=rgoers"));
+ assertTrue(message.contains("GelfLayoutPatternSelectorTest"));
+ gelf = list.getMessages().get(1);
+ 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"));
+ message = json.get("full_message").asText();
+ assertTrue(message.contains("====="));
assertTrue(message.contains("loginId=rgoers"));
- assertTrue(message.contains("GelfLayoutTest3"));
+ assertTrue(message.contains("GelfLayoutPatternSelectorTest"));
}
}
diff --git a/log4j-core/src/test/resources/GelfLayoutTest2.xml b/log4j-core/src/test/resources/GelfLayout2Test.xml
similarity index 100%
rename from log4j-core/src/test/resources/GelfLayoutTest2.xml
rename to log4j-core/src/test/resources/GelfLayout2Test.xml
diff --git a/log4j-core/src/test/resources/GelfLayoutTest3.xml b/log4j-core/src/test/resources/GelfLayout3Test.xml
similarity index 100%
copy from log4j-core/src/test/resources/GelfLayoutTest3.xml
copy to log4j-core/src/test/resources/GelfLayout3Test.xml
diff --git a/log4j-core/src/test/resources/GelfLayoutTest3.xml b/log4j-core/src/test/resources/GelfLayoutPatternSelectorTest.xml
similarity index 78%
rename from log4j-core/src/test/resources/GelfLayoutTest3.xml
rename to log4j-core/src/test/resources/GelfLayoutPatternSelectorTest.xml
index fcb23d3..7fe50f6 100644
--- a/log4j-core/src/test/resources/GelfLayoutTest3.xml
+++ b/log4j-core/src/test/resources/GelfLayoutPatternSelectorTest.xml
@@ -16,11 +16,13 @@
limitations under the License.
-->
-<Configuration status="WARN" name="GelfLayoutTest3">
+<Configuration status="WARN" name="GelfLayoutPatternSelectorTest">
<Appenders>
<List name="list">
<GelfLayout host="myhost" includeThreadContext="true" threadContextIncludes="requestId,loginId">
- <MessagePattern>%d [%t] %-5p %X{requestId, loginId} %C{1.}.%M:%L - %m%n"</MessagePattern>
+ <MarkerPatternSelector defaultPattern="%d [%t] %-5p %X{requestId, loginId} %C{1.}.%M:%L - %m%n">
+ <PatternMatch key="FLOW" pattern="[%-5level] %X{requestId, loginId} ====== %C{1.}.%M:%L %msg ======%n"/>
+ </MarkerPatternSelector>
<KeyValuePair key="foo" value="FOO"/>
<KeyValuePair key="runtime" value="$${java:runtime}"/>
</GelfLayout>
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 2bd31fc..1c4ffad 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -30,7 +30,9 @@
- "remove" - Removed
-->
<release version="2.15.0" date="2021-MM-DD" description="GA Release 2.15.0">
-
+ <action issue="LOG4J2-3041" dev="rgoers" type="update">
+ Allow a PatternSelector to be specified on GelfLayout.
+ </action>
</release>
<release version="2.14.1" date="2021-03-06" description="GA Release 2.14.1">
<!-- FIXES -->
diff --git a/src/site/xdoc/manual/layouts.xml.vm b/src/site/xdoc/manual/layouts.xml.vm
index 52b415d..e8f6368 100644
--- a/src/site/xdoc/manual/layouts.xml.vm
+++ b/src/site/xdoc/manual/layouts.xml.vm
@@ -186,107 +186,6 @@ logger.debug("one={}, two={}, three={}", 1, 2, 3);
Additional <a href="../runtime-dependencies.html">runtime dependencies</a> are required for using CSV layouts.
</p>
</subsection>
- <a name="JsonTemplateLayout"/>
- <subsection name="JSON Template Layout">
- <p>
- <code>JsonTemplateLayout</code> is a customizable, efficient, and
- garbage-free JSON emitting layout. It encodes <code>LogEvent</code>s
- according to the structure described by the JSON template provided.
- For instance, given the following JSON template modelling the
- <a href="https://github.com/logstash/log4j-jsonevent-layout">the
- official Logstash <code>JSONEventLayoutV1</code></a>
- </p>
- <pre class="prettyprint linenums"><![CDATA[
-{
- "mdc": {
- "${dollar}resolver": "mdc"
- },
- "exception": {
- "exception_class": {
- "${dollar}resolver": "exception",
- "field": "className"
- },
- "exception_message": {
- "${dollar}resolver": "exception",
- "field": "message",
- "stringified": true
- },
- "stacktrace": {
- "${dollar}resolver": "exception",
- "field": "stackTrace",
- "stringified": true
- }
- },
- "line_number": {
- "${dollar}resolver": "source",
- "field": "lineNumber"
- },
- "class": {
- "${dollar}resolver": "source",
- "field": "className"
- },
- "@version": 1,
- "source_host": "${dollar}{hostName}",
- "message": {
- "${dollar}resolver": "message",
- "stringified": true
- },
- "thread_name": {
- "${dollar}resolver": "thread",
- "field": "name"
- },
- "@timestamp": {
- "${dollar}resolver": "timestamp"
- },
- "level": {
- "${dollar}resolver": "level",
- "field": "name"
- },
- "file": {
- "${dollar}resolver": "source",
- "field": "fileName"
- },
- "method": {
- "${dollar}resolver": "source",
- "field": "methodName"
- },
- "logger_name": {
- "${dollar}resolver": "logger",
- "field": "name"
- }
-}]]></pre>
- <p>
- in combination with the below Log4j configuration:
- </p>
- <pre class="prettyprint linenums"><![CDATA[
-<JsonTemplateLayout eventTemplateUri="classpath:LogstashJsonEventLayoutV1.json"/>]]></pre>
- <p>
- JSON Template Layout will render JSON documents as follows:
- </p>
- <pre class="prettyprint linenums"><![CDATA[
-{
- "exception": {
- "exception_class": "java.lang.RuntimeException",
- "exception_message": "test",
- "stacktrace": "java.lang.RuntimeException: test\n\tat org.apache.logging.log4j.JsonTemplateLayoutDemo.main(JsonTemplateLayoutDemo.java:11)\n"
- },
- "line_number": 12,
- "class": "org.apache.logging.log4j.JsonTemplateLayoutDemo",
- "@version": 1,
- "source_host": "varlik",
- "message": "Hello, error!",
- "thread_name": "main",
- "@timestamp": "2017-05-25T19:56:23.370+02:00",
- "level": "ERROR",
- "file": "JsonTemplateLayoutDemo.java",
- "method": "main",
- "logger_name": "org.apache.logging.log4j.JsonTemplateLayoutDemo"
-}]]></pre>
- <p>
- See <a href="json-template-layout.html">JSON Template Layout</a>
- page for the complete documentation.
- </p>
- </subsection>
<a name="GELFLayout"/>
<subsection name="GELF Layout">
<!-- From Javadoc of org.apache.logging.log4j.core.layout.GelfLayout -->
@@ -359,9 +258,20 @@ logger.debug("one={}, two={}, three={}", 1, 2, 3);
<tr>
<td>messagePattern</td>
<td>String</td>
- <td>The pattern to use to format the String. If not supplied only the text derived from the logging
- message will be used. See <a href="#PatternLayout">PatternLayout</a> for information on the pattern
- strings.</td>
+ <td>The pattern to use to format the String. A messagePattern and patternSelector cannot both be
+ specified. If both are present the message pattern will be ignored and an error will be logged.
+ If not supplied only the text derived from the logging message will be used. See
+ <a href="#PatternLayout">PatternLayout</a> for information on the pattern strings.</td>
+ </tr>
+ <tr>
+ <td>patternSelector</td>
+ <td>PatternSelector</td>
+ <td>The PatternSelector to use to format the String. A messagePattern and patternSelector cannot both be
+ specified. If both are present the message pattern will be ignored and an error will be logged.
+ If not supplied only the text derived from the logging message will be used.
+ See <a href="#PatternSelectors">PatternSelectors</a> for information on how to specify a
+ PatternSelector.
+ See <a href="#PatternLayout">PatternLayout</a> for information on the pattern strings.</td>
</tr>
<tr>
<td>threadContextExcludes</td>
@@ -657,6 +567,107 @@ logger.debug("one={}, two={}, three={}", 1, 2, 3);
Additional <a href="../runtime-dependencies.html">runtime dependencies</a> are required for using JsonLayout.
</p>
</subsection>
+ <a name="JsonTemplateLayout"/>
+ <subsection name="JSON Template Layout">
+ <p>
+ <code>JsonTemplateLayout</code> is a customizable, efficient, and
+ garbage-free JSON emitting layout. It encodes <code>LogEvent</code>s
+ according to the structure described by the JSON template provided.
+ For instance, given the following JSON template modelling the
+ <a href="https://github.com/logstash/log4j-jsonevent-layout">the
+ official Logstash <code>JSONEventLayoutV1</code></a>
+ </p>
+ <pre class="prettyprint linenums"><![CDATA[
+{
+ "mdc": {
+ "${dollar}resolver": "mdc"
+ },
+ "exception": {
+ "exception_class": {
+ "${dollar}resolver": "exception",
+ "field": "className"
+ },
+ "exception_message": {
+ "${dollar}resolver": "exception",
+ "field": "message",
+ "stringified": true
+ },
+ "stacktrace": {
+ "${dollar}resolver": "exception",
+ "field": "stackTrace",
+ "stringified": true
+ }
+ },
+ "line_number": {
+ "${dollar}resolver": "source",
+ "field": "lineNumber"
+ },
+ "class": {
+ "${dollar}resolver": "source",
+ "field": "className"
+ },
+ "@version": 1,
+ "source_host": "${dollar}{hostName}",
+ "message": {
+ "${dollar}resolver": "message",
+ "stringified": true
+ },
+ "thread_name": {
+ "${dollar}resolver": "thread",
+ "field": "name"
+ },
+ "@timestamp": {
+ "${dollar}resolver": "timestamp"
+ },
+ "level": {
+ "${dollar}resolver": "level",
+ "field": "name"
+ },
+ "file": {
+ "${dollar}resolver": "source",
+ "field": "fileName"
+ },
+ "method": {
+ "${dollar}resolver": "source",
+ "field": "methodName"
+ },
+ "logger_name": {
+ "${dollar}resolver": "logger",
+ "field": "name"
+ }
+}]]></pre>
+ <p>
+ in combination with the below Log4j configuration:
+ </p>
+ <pre class="prettyprint linenums"><![CDATA[
+<JsonTemplateLayout eventTemplateUri="classpath:LogstashJsonEventLayoutV1.json"/>]]></pre>
+ <p>
+ JSON Template Layout will render JSON documents as follows:
+ </p>
+ <pre class="prettyprint linenums"><![CDATA[
+{
+ "exception": {
+ "exception_class": "java.lang.RuntimeException",
+ "exception_message": "test",
+ "stacktrace": "java.lang.RuntimeException: test\n\tat org.apache.logging.log4j.JsonTemplateLayoutDemo.main(JsonTemplateLayoutDemo.java:11)\n"
+ },
+ "line_number": 12,
+ "class": "org.apache.logging.log4j.JsonTemplateLayoutDemo",
+ "@version": 1,
+ "source_host": "varlik",
+ "message": "Hello, error!",
+ "thread_name": "main",
+ "@timestamp": "2017-05-25T19:56:23.370+02:00",
+ "level": "ERROR",
+ "file": "JsonTemplateLayoutDemo.java",
+ "method": "main",
+ "logger_name": "org.apache.logging.log4j.JsonTemplateLayoutDemo"
+}]]></pre>
+ <p>
+ See <a href="json-template-layout.html">JSON Template Layout</a>
+ page for the complete documentation.
+ </p>
+ </subsection>
<a name="PatternLayout"/>
<subsection name="Pattern Layout">
<p>A flexible layout configurable with pattern string. The goal of this class is to format a LogEvent and
@@ -2138,7 +2149,7 @@ at org.apache.logging.log4j.core.pattern.ExtendedThrowableTest.testException(Ext
<pre class="prettyprint linenums"><![CDATA[<PatternLayout>
<pattern>%d %highlight{%p} %style{%C{1.} [%t] %m}{bold,green}%n</pattern>
</PatternLayout>]]></pre>
-
+ <a name="PatternSelectors"/>
<h4>Pattern Selectors</h4>
<p>
The PatternLayout can be configured with a PatternSelector to allow it to choose a pattern to use based on