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/12 16:48:37 UTC

[logging-log4j2] branch master updated (a42def9 -> d8c8691)

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

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


    from a42def9  LOG4J2-2850 Fix indentation in LocalizedMessageFactoryTest.
     new 749ef13  Improve JTL TemplateResolver docs.
     new d71e0cf  Remove constants in JsonTemplateLayoutDefaults to allow updates at runtime.
     new d8c8691  LOG4J2-2916 Avoid redundant Kafka producer instantiation causing thread leaks.

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../logging/log4j/kafka/appender/KafkaManager.java |   4 +-
 .../KafkaManagerProducerThreadLeakTest.java        |  46 ++++++
 .../template/json/JsonTemplateLayoutDefaults.java  | 178 ++++++---------------
 .../template/json/resolver/TemplateResolver.java   |  27 ++++
 src/changes/changes.xml                            |   3 +
 5 files changed, 131 insertions(+), 127 deletions(-)
 create mode 100644 log4j-kafka/src/test/java/org/apache/logging/log4j/kafka/appender/KafkaManagerProducerThreadLeakTest.java


[logging-log4j2] 02/03: Remove constants in JsonTemplateLayoutDefaults to allow updates at runtime.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit d71e0cf5784bbe9afeef9f8f5e8d0c97eb6ca7f5
Author: Volkan Yazıcı <vo...@gmail.com>
AuthorDate: Wed Nov 11 16:35:24 2020 +0100

    Remove constants in JsonTemplateLayoutDefaults to allow updates at runtime.
---
 .../template/json/JsonTemplateLayoutDefaults.java  | 178 ++++++---------------
 1 file changed, 52 insertions(+), 126 deletions(-)

diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutDefaults.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutDefaults.java
index 9896c1e..4f417ee 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutDefaults.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutDefaults.java
@@ -29,71 +29,7 @@ public enum JsonTemplateLayoutDefaults {;
 
     private static final PropertiesUtil PROPERTIES = PropertiesUtil.getProperties();
 
-    private static final Charset CHARSET = readCharset();
-
-    private static final boolean LOCATION_INFO_ENABLED =
-            PROPERTIES.getBooleanProperty(
-                    "log4j.layout.jsonTemplate.locationInfoEnabled",
-                    false);
-
-    private static final boolean STACK_TRACE_ENABLED =
-            PROPERTIES.getBooleanProperty(
-                    "log4j.layout.jsonTemplate.stackTraceEnabled",
-                    true);
-
-    private static final String TIMESTAMP_FORMAT_PATTERN =
-            PROPERTIES.getStringProperty(
-                    "log4j.layout.jsonTemplate.timestampFormatPattern",
-                    "yyyy-MM-dd'T'HH:mm:ss.SSSZZZ");
-
-    private static final TimeZone TIME_ZONE = readTimeZone();
-
-    private static final Locale LOCALE = readLocale();
-
-    private static final String EVENT_TEMPLATE =
-            PROPERTIES.getStringProperty(
-                    "log4j.layout.jsonTemplate.eventTemplate");
-
-    private static final String EVENT_TEMPLATE_URI =
-            PROPERTIES.getStringProperty(
-                    "log4j.layout.jsonTemplate.eventTemplateUri",
-                    "classpath:EcsLayout.json");
-
-    private static final String STACK_TRACE_ELEMENT_TEMPLATE =
-            PROPERTIES.getStringProperty(
-                    "log4j.layout.jsonTemplate.stackTraceElementTemplate");
-
-    private static final String STACK_TRACE_ELEMENT_TEMPLATE_URI =
-            PROPERTIES.getStringProperty(
-                    "log4j.layout.jsonTemplate.stackTraceElementTemplateUri",
-                    "classpath:StackTraceElementLayout.json");
-
-    private static final String MDC_KEY_PATTERN =
-            PROPERTIES.getStringProperty("log4j.layout.jsonTemplate.mdcKeyPattern");
-
-    private static final String NDC_PATTERN =
-            PROPERTIES.getStringProperty("log4j.layout.jsonTemplate.ndcPattern");
-
-    private static final String EVENT_DELIMITER =
-            PROPERTIES.getStringProperty(
-                    "log4j.layout.jsonTemplate.eventDelimiter",
-                    System.lineSeparator());
-
-    private static final boolean NULL_EVENT_DELIMITER_ENABLED =
-            PROPERTIES.getBooleanProperty(
-                    "log4j.layout.jsonTemplate.nullEventDelimiterEnabled",
-                    false);
-
-    private static final int MAX_STRING_LENGTH = readMaxStringLength();
-
-    private static final String TRUNCATED_STRING_SUFFIX =
-            PROPERTIES.getStringProperty(
-                    "log4j.layout.jsonTemplate.truncatedStringSuffix",
-                    "…");
-
-    private static final RecyclerFactory RECYCLER_FACTORY = readRecyclerFactory();
-
-    private static Charset readCharset() {
+    public static Charset getCharset() {
         final String charsetName =
                 PROPERTIES.getStringProperty("log4j.layout.jsonTemplate.charset");
         return charsetName != null
@@ -101,7 +37,25 @@ public enum JsonTemplateLayoutDefaults {;
                 : StandardCharsets.UTF_8;
     }
 
-    private static TimeZone readTimeZone() {
+    public static boolean isLocationInfoEnabled() {
+        return PROPERTIES.getBooleanProperty(
+                "log4j.layout.jsonTemplate.locationInfoEnabled",
+                false);
+    }
+
+    public static boolean isStackTraceEnabled() {
+        return PROPERTIES.getBooleanProperty(
+                "log4j.layout.jsonTemplate.stackTraceEnabled",
+                true);
+    }
+
+    public static String getTimestampFormatPattern() {
+        return PROPERTIES.getStringProperty(
+                "log4j.layout.jsonTemplate.timestampFormatPattern",
+                "yyyy-MM-dd'T'HH:mm:ss.SSSZZZ");
+    }
+
+    public static TimeZone getTimeZone() {
         final String timeZoneId =
                 PROPERTIES.getStringProperty("log4j.layout.jsonTemplate.timeZone");
         return timeZoneId != null
@@ -109,7 +63,7 @@ public enum JsonTemplateLayoutDefaults {;
                 : TimeZone.getDefault();
     }
 
-    private static Locale readLocale() {
+    public static Locale getLocale() {
         final String locale =
                 PROPERTIES.getStringProperty("log4j.layout.jsonTemplate.locale");
         if (locale == null) {
@@ -124,90 +78,62 @@ public enum JsonTemplateLayoutDefaults {;
         }
     }
 
-    private static int readMaxStringLength() {
-        final int maxStringLength = PROPERTIES.getIntegerProperty(
-                "log4j.layout.jsonTemplate.maxStringLength",
-                16 * 1_024);
-        if (maxStringLength <= 0) {
-            throw new IllegalArgumentException(
-                    "was expecting a non-zero positive maxStringLength: " +
-                            maxStringLength);
-        }
-        return maxStringLength;
-    }
-
-    private static RecyclerFactory readRecyclerFactory() {
-        final String recyclerFactorySpec = PROPERTIES.getStringProperty(
-                "log4j.layout.jsonTemplate.recyclerFactory");
-        return RecyclerFactories.ofSpec(recyclerFactorySpec);
-    }
-
-    public static Charset getCharset() {
-        return CHARSET;
-    }
-
-    public static boolean isLocationInfoEnabled() {
-        return LOCATION_INFO_ENABLED;
-    }
-
-    public static boolean isStackTraceEnabled() {
-        return STACK_TRACE_ENABLED;
-    }
-
-    public static String getTimestampFormatPattern() {
-        return TIMESTAMP_FORMAT_PATTERN;
-    }
-
-    public static TimeZone getTimeZone() {
-        return TIME_ZONE;
-    }
-
-    public static Locale getLocale() {
-        return LOCALE;
-    }
-
     public static String getEventTemplate() {
-        return EVENT_TEMPLATE;
+        return PROPERTIES.getStringProperty(
+                "log4j.layout.jsonTemplate.eventTemplate");
     }
 
     public static String getEventTemplateUri() {
-        return EVENT_TEMPLATE_URI;
+        return PROPERTIES.getStringProperty(
+                "log4j.layout.jsonTemplate.eventTemplateUri",
+                "classpath:EcsLayout.json");
     }
 
     public static String getStackTraceElementTemplate() {
-        return STACK_TRACE_ELEMENT_TEMPLATE;
+        return PROPERTIES.getStringProperty(
+                "log4j.layout.jsonTemplate.stackTraceElementTemplate");
     }
 
     public static String getStackTraceElementTemplateUri() {
-        return STACK_TRACE_ELEMENT_TEMPLATE_URI;
-    }
-
-    public static String getMdcKeyPattern() {
-        return MDC_KEY_PATTERN;
-    }
-
-    public static String getNdcPattern() {
-        return NDC_PATTERN;
+        return PROPERTIES.getStringProperty(
+                "log4j.layout.jsonTemplate.stackTraceElementTemplateUri",
+                "classpath:StackTraceElementLayout.json");
     }
 
     public static String getEventDelimiter() {
-        return EVENT_DELIMITER;
+        return PROPERTIES.getStringProperty(
+                "log4j.layout.jsonTemplate.eventDelimiter",
+                System.lineSeparator());
     }
 
     public static boolean isNullEventDelimiterEnabled() {
-        return NULL_EVENT_DELIMITER_ENABLED;
+        return PROPERTIES.getBooleanProperty(
+                "log4j.layout.jsonTemplate.nullEventDelimiterEnabled",
+                false);
     }
 
     public static int getMaxStringLength() {
-        return MAX_STRING_LENGTH;
+        final int maxStringLength = PROPERTIES.getIntegerProperty(
+                "log4j.layout.jsonTemplate.maxStringLength",
+                16 * 1_024);
+        if (maxStringLength <= 0) {
+            throw new IllegalArgumentException(
+                    "was expecting a non-zero positive maxStringLength: " +
+                            maxStringLength);
+        }
+        return maxStringLength;
     }
 
     public static String getTruncatedStringSuffix() {
-        return TRUNCATED_STRING_SUFFIX;
+        return PROPERTIES.getStringProperty(
+                "log4j.layout.jsonTemplate.truncatedStringSuffix",
+                "…");
     }
 
     public static RecyclerFactory getRecyclerFactory() {
-        return RECYCLER_FACTORY;
+        final String recyclerFactorySpec = PROPERTIES.getStringProperty(
+                "log4j.layout.jsonTemplate.recyclerFactory");
+        return RecyclerFactories.ofSpec(recyclerFactorySpec);
     }
 
 }


[logging-log4j2] 01/03: Improve JTL TemplateResolver docs.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 749ef1373749480fe1a0cfd84100d7e3d9b89d73
Author: Volkan Yazıcı <vo...@gmail.com>
AuthorDate: Wed Nov 11 16:34:38 2020 +0100

    Improve JTL TemplateResolver docs.
---
 .../template/json/resolver/TemplateResolver.java   | 27 ++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolver.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolver.java
index 5db3813..62ce41d 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolver.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolver.java
@@ -21,20 +21,47 @@ import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
 @FunctionalInterface
 public interface TemplateResolver<V> {
 
+    /**
+     * Indicates if the resolution should be appended to the parent JSON object.
+     * <p>
+     * For instance, {@link ThreadContextDataResolver}, i.e., MDC resolver,
+     * uses this flag to indicate whether the contents should be appended to the
+     * parent JSON object or not.
+     */
     default boolean isFlattening() {
         return false;
     }
 
+    /**
+     * Indicates if the resolver if applicable at all.
+     * <p>
+     * For instance, the source line resolver can be short-circuited using this
+     * check if the location information is disabled in the layout configuration.
+     */
     default boolean isResolvable() {
         return true;
     }
 
+    /**
+     * Indicates if the resolver if applicable for the given {@code value}.
+     * <p>
+     * For instance, the stack trace resolver can be short-circuited using this
+     * check if the stack traces are disabled in the layout configuration.
+     */
     default boolean isResolvable(V value) {
         return true;
     }
 
+    /**
+     * Resolves the given {@code value} using the provided {@link JsonWriter}.
+     */
     void resolve(V value, JsonWriter jsonWriter);
 
+    /**
+     * Resolves the given {@code value} using the provided {@link JsonWriter}.
+     *
+     * @param succeedingEntry false, if this is the first element in a collection; true, otherwise
+     */
     default void resolve(V value, JsonWriter jsonWriter, boolean succeedingEntry) {
         resolve(value, jsonWriter);
     }


[logging-log4j2] 03/03: LOG4J2-2916 Avoid redundant Kafka producer instantiation causing thread leaks.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit d8c8691917763451aa43a8d00f147d2c6fc799b1
Author: Volkan Yazıcı <vo...@gmail.com>
AuthorDate: Thu Nov 12 17:46:20 2020 +0100

    LOG4J2-2916 Avoid redundant Kafka producer instantiation causing thread leaks.
---
 .../logging/log4j/kafka/appender/KafkaManager.java |  4 +-
 .../KafkaManagerProducerThreadLeakTest.java        | 46 ++++++++++++++++++++++
 src/changes/changes.xml                            |  3 ++
 3 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/log4j-kafka/src/main/java/org/apache/logging/log4j/kafka/appender/KafkaManager.java b/log4j-kafka/src/main/java/org/apache/logging/log4j/kafka/appender/KafkaManager.java
index a4e4ddb..db03167 100644
--- a/log4j-kafka/src/main/java/org/apache/logging/log4j/kafka/appender/KafkaManager.java
+++ b/log4j-kafka/src/main/java/org/apache/logging/log4j/kafka/appender/KafkaManager.java
@@ -153,7 +153,9 @@ public class KafkaManager extends AbstractManager {
     }
 
     public void startup() {
-        producer = producerFactory.newKafkaProducer(config);
+        if (producer == null) {
+            producer = producerFactory.newKafkaProducer(config);
+        }
     }
 
     public String getTopic() {
diff --git a/log4j-kafka/src/test/java/org/apache/logging/log4j/kafka/appender/KafkaManagerProducerThreadLeakTest.java b/log4j-kafka/src/test/java/org/apache/logging/log4j/kafka/appender/KafkaManagerProducerThreadLeakTest.java
new file mode 100644
index 0000000..2ebf60f
--- /dev/null
+++ b/log4j-kafka/src/test/java/org/apache/logging/log4j/kafka/appender/KafkaManagerProducerThreadLeakTest.java
@@ -0,0 +1,46 @@
+package org.apache.logging.log4j.kafka.appender;
+
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.junit.LoggerContextSource;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Verifies that restarting the {@link LoggerContext} doesn't cause
+ * {@link KafkaManager} to leak threads.
+ *
+ * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-2916">LOG4J2-2916</a>
+ */
+@LoggerContextSource("KafkaAppenderTest.xml")
+class KafkaManagerProducerThreadLeakTest {
+
+    @Test
+    void context_restart_shouldnt_leak_producer_threads(final LoggerContext context) {
+
+        // Determine the initial number of threads.
+        final int initialThreadCount = kafkaProducerThreadCount();
+
+        // Perform context restarts.
+        final int contextRestartCount = 3;
+        for (int i = 0; i < contextRestartCount; i++) {
+            context.reconfigure();
+        }
+
+        // Verify the final thread count.
+        final int lastThreadCount = kafkaProducerThreadCount();
+        assertEquals(initialThreadCount, lastThreadCount);
+
+    }
+
+    private static int kafkaProducerThreadCount() {
+        final long threadCount = Thread
+                .getAllStackTraces()
+                .keySet()
+                .stream()
+                .filter(thread -> thread.getName().startsWith("kafka-producer"))
+                .count();
+        return Math.toIntExact(threadCount);
+    }
+
+}
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 313a922..e191147 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -31,6 +31,9 @@
          - "remove" - Removed
     -->
     <release version="3.0.0" date="2019-xx-xx" description="GA Release 3.0.0">
+      <action issue="LOG4J2-2916" dev="vy" type="fix" due-to="wuqian0808">
+        Avoid redundant Kafka producer instantiation causing thread leaks.
+      </action>
       <action dev="vy" type="update">
         Update jetty-util from 8.2.0.v20160908 to 9.4.31.v20200723.
       </action>