diff --git a/log4j2-appender/src/main/java/pl/tkowalcz/tjahzi/log4j2/labels/Log4jAdapterLabelPrinter.java b/log4j2-appender/src/main/java/pl/tkowalcz/tjahzi/log4j2/labels/Log4jAdapterLabelPrinter.java index db51f9e..7912d17 100644 --- a/log4j2-appender/src/main/java/pl/tkowalcz/tjahzi/log4j2/labels/Log4jAdapterLabelPrinter.java +++ b/log4j2-appender/src/main/java/pl/tkowalcz/tjahzi/log4j2/labels/Log4jAdapterLabelPrinter.java @@ -4,6 +4,7 @@ import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.pattern.LiteralPatternConverter; import org.apache.logging.log4j.core.pattern.LogEventPatternConverter; import org.apache.logging.log4j.core.pattern.PatternFormatter; +import pl.tkowalcz.tjahzi.log4j2.utils.StringBuilders; import java.util.List; import java.util.function.Consumer; @@ -11,7 +12,6 @@ import java.util.function.Consumer; @SuppressWarnings("ForLoopReplaceableByForEach") public class Log4jAdapterLabelPrinter implements LabelPrinter { - private final StringBuilder outputBuffer = new StringBuilder(); private final List formatters; public Log4jAdapterLabelPrinter(List formatters) { diff --git a/log4j2-appender/src/main/java/pl/tkowalcz/tjahzi/log4j2/utils/StringBuilders.java b/log4j2-appender/src/main/java/pl/tkowalcz/tjahzi/log4j2/utils/StringBuilders.java new file mode 100644 index 0000000..a5559cd --- /dev/null +++ b/log4j2-appender/src/main/java/pl/tkowalcz/tjahzi/log4j2/utils/StringBuilders.java @@ -0,0 +1,13 @@ +package pl.tkowalcz.tjahzi.log4j2.utils; + +public class StringBuilders { + + private static final ThreadLocal THREAD_LOCAL = ThreadLocal.withInitial(StringBuilder::new); + + public static StringBuilder threadLocal() { + StringBuilder result = THREAD_LOCAL.get(); + result.setLength(0); + + return result; + } +} diff --git a/log4j2-appender/src/test/java/pl/tkowalcz/tjahzi/log4j2/utils/StringBuildersTest.java b/log4j2-appender/src/test/java/pl/tkowalcz/tjahzi/log4j2/utils/StringBuildersTest.java new file mode 100644 index 0000000..842ea57 --- /dev/null +++ b/log4j2-appender/src/test/java/pl/tkowalcz/tjahzi/log4j2/utils/StringBuildersTest.java @@ -0,0 +1,55 @@ +package pl.tkowalcz.tjahzi.log4j2.utils; + +import org.junit.jupiter.api.Test; + +import java.util.concurrent.atomic.AtomicReference; + +import static org.assertj.core.api.Assertions.assertThat; + +class StringBuildersTest { + + @Test + void shouldClearBufferBeforeUse() { + // Given + StringBuilder stringBuilder = StringBuilders.threadLocal(); + stringBuilder.append("abc"); + + // When + StringBuilder actual = StringBuilders.threadLocal(); + + // Then + assertThat(actual.toString()).isEmpty(); + } + + @Test + void shouldReturnSameBufferInsideSameThread() { + // When + StringBuilder stringBuilder1 = StringBuilders.threadLocal(); + StringBuilder stringBuilder2 = StringBuilders.threadLocal(); + + // Then + assertThat(stringBuilder1).isSameAs(stringBuilder2); + } + + @Test + void shouldReturnDifferentBufferInsideDifferentThreads() throws InterruptedException { + // Given + AtomicReference captor1 = new AtomicReference<>(); + AtomicReference captor2 = new AtomicReference<>(); + + // When + Thread thread1 = new Thread(() -> captor1.set(StringBuilders.threadLocal())); + thread1.start(); + thread1.join(); + + Thread thread2 = new Thread(() -> captor2.set(StringBuilders.threadLocal())); + thread2.start(); + thread2.join(); + + // Then + assertThat(captor1.get()).isNotNull(); + assertThat(captor2.get()).isNotNull(); + + assertThat(captor1.get()).isNotSameAs(captor2.get()); + } +}