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

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

commit db408cb5f34535baab1a53d05dce00117dd6c170
Author: Volkan Yazıcı <[email protected]>
AuthorDate: Wed Nov 29 14:17:15 2023 +0100

    Use recycler in `StructuredDataFilter` (#1969)
---
 .../core/filter/StructuredDataFilterTest.java      |  5 +-
 .../log4j/core/filter/StructuredDataFilter.java    | 58 ++++++++++++----------
 2 files changed, 36 insertions(+), 27 deletions(-)

diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/StructuredDataFilterTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/StructuredDataFilterTest.java
index 406f656e89..fd44535715 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/StructuredDataFilterTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/StructuredDataFilterTest.java
@@ -22,6 +22,7 @@ import java.util.Collection;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.DefaultConfiguration;
 import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
 import org.apache.logging.log4j.core.util.KeyValuePair;
 import org.apache.logging.log4j.message.StructuredDataMessage;
@@ -35,7 +36,7 @@ public class StructuredDataFilterTest {
         final KeyValuePair[] pairs = new KeyValuePair[] {
             new KeyValuePair("id.name", "AccountTransfer"), new 
KeyValuePair("ToAccount", "123456")
         };
-        StructuredDataFilter filter = StructuredDataFilter.createFilter(pairs, 
"and", null, null);
+        StructuredDataFilter filter = StructuredDataFilter.createFilter(new 
DefaultConfiguration(), pairs, "and", null, null);
         assertNotNull(filter);
         filter.start();
         StructuredDataMessage msg = new 
StructuredDataMessage("AccountTransfer@18060", "Transfer Successful", "Audit");
@@ -46,7 +47,7 @@ public class StructuredDataFilterTest {
         assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.DEBUG, 
null, msg, null));
         msg.put("ToAccount", "111111");
         assertSame(Filter.Result.DENY, filter.filter(null, Level.ERROR, null, 
msg, null));
-        filter = StructuredDataFilter.createFilter(pairs, "or", null, null);
+        filter = StructuredDataFilter.createFilter(new DefaultConfiguration(), 
pairs, "or", null, null);
         assertNotNull(filter);
         filter.start();
         msg = new StructuredDataMessage("AccountTransfer@18060", "Transfer 
Successful", "Audit");
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/StructuredDataFilter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/StructuredDataFilter.java
index 3245c158ae..408d0845d3 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/StructuredDataFilter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/StructuredDataFilter.java
@@ -25,6 +25,8 @@ import org.apache.logging.log4j.Marker;
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
 import org.apache.logging.log4j.core.util.KeyValuePair;
 import org.apache.logging.log4j.message.Message;
 import org.apache.logging.log4j.message.StructuredDataMessage;
@@ -33,6 +35,8 @@ import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.PluginAttribute;
 import org.apache.logging.log4j.plugins.PluginElement;
 import org.apache.logging.log4j.plugins.PluginFactory;
+import org.apache.logging.log4j.spi.Recycler;
+import org.apache.logging.log4j.spi.RecyclerFactory;
 import org.apache.logging.log4j.util.IndexedReadOnlyStringMap;
 import org.apache.logging.log4j.util.PerformanceSensitive;
 import org.apache.logging.log4j.util.StringBuilders;
@@ -46,11 +50,17 @@ import org.apache.logging.log4j.util.StringBuilders;
 public final class StructuredDataFilter extends MapFilter {
 
     private static final int MAX_BUFFER_SIZE = 2048;
-    private static final ThreadLocal<StringBuilder> threadLocalStringBuilder = 
new ThreadLocal<>();
+
+    private final Recycler<StringBuilder> stringBuilderRecycler;
 
     private StructuredDataFilter(
-            final Map<String, List<String>> map, final boolean oper, final 
Result onMatch, final Result onMismatch) {
+            final RecyclerFactory recyclerFactory,
+            final Map<String, List<String>> map,
+            final boolean oper,
+            final Result onMatch,
+            final Result onMismatch) {
         super(map, oper, onMatch, onMismatch);
+        this.stringBuilderRecycler = 
recyclerFactory.create(StringBuilder::new);
     }
 
     @Override
@@ -74,22 +84,29 @@ public final class StructuredDataFilter extends MapFilter {
     protected Result filter(final StructuredDataMessage message) {
         boolean match = false;
         final IndexedReadOnlyStringMap map = getStringMap();
-        for (int i = 0; i < map.size(); i++) {
-            final StringBuilder toMatch = getValue(message, map.getKeyAt(i));
-            if (toMatch != null) {
-                match = listContainsValue((List<String>) map.getValueAt(i), 
toMatch);
-            } else {
-                match = false;
-            }
-            if ((!isAnd() && match) || (isAnd() && !match)) {
-                break;
+        final StringBuilder sb = stringBuilderRecycler.acquire();
+        try {
+            for (int i = 0; i < map.size(); i++) {
+                final StringBuilder toMatch = getValue(sb, message, 
map.getKeyAt(i));
+                if (toMatch != null) {
+                    final List<String> candidates = map.getValueAt(i);
+                    match = listContainsValue(candidates, toMatch);
+                } else {
+                    match = false;
+                }
+                if ((!isAnd() && match) || (isAnd() && !match)) {
+                    break;
+                }
+                StringBuilders.trimToMaxSize(sb, MAX_BUFFER_SIZE);
+                sb.setLength(0);
             }
+        } finally {
+            stringBuilderRecycler.release(sb);
         }
         return match ? onMatch : onMismatch;
     }
 
-    private StringBuilder getValue(final StructuredDataMessage data, final 
String key) {
-        final StringBuilder sb = getStringBuilder();
+    private StringBuilder getValue(final StringBuilder sb, final 
StructuredDataMessage data, final String key) {
         if (key.equalsIgnoreCase("id")) {
             data.getId().formatTo(sb);
             return sb;
@@ -105,17 +122,6 @@ public final class StructuredDataFilter extends MapFilter {
         }
     }
 
-    private StringBuilder getStringBuilder() {
-        StringBuilder result = threadLocalStringBuilder.get();
-        if (result == null) {
-            result = new StringBuilder();
-            threadLocalStringBuilder.set(result);
-        }
-        StringBuilders.trimToMaxSize(result, MAX_BUFFER_SIZE);
-        result.setLength(0);
-        return result;
-    }
-
     private StringBuilder appendOrNull(final String value, final StringBuilder 
sb) {
         if (value == null) {
             return null;
@@ -157,6 +163,7 @@ public final class StructuredDataFilter extends MapFilter {
     // TODO Consider refactoring to use AbstractFilter.AbstractFilterBuilder
     @PluginFactory
     public static StructuredDataFilter createFilter(
+            @PluginConfiguration final Configuration configuration,
             @PluginElement final KeyValuePair[] pairs,
             @PluginAttribute final String operator,
             @PluginAttribute final Result onMatch,
@@ -191,6 +198,7 @@ public final class StructuredDataFilter extends MapFilter {
             return null;
         }
         final boolean isAnd = operator == null || 
!operator.equalsIgnoreCase("or");
-        return new StructuredDataFilter(map, isAnd, onMatch, onMismatch);
+        final RecyclerFactory recyclerFactory = 
configuration.getRecyclerFactory();
+        return new StructuredDataFilter(recyclerFactory, map, isAnd, onMatch, 
onMismatch);
     }
 }

Reply via email to