diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 556b58c3372..ef6ffb18c01 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -81,9 +81,10 @@ updates: # Json Unit 3.x requires Java 17 - dependency-name: "net.javacrumbs.json-unit:*" versions: ["[3.0.0,)"] - # LMAX Disruptor requires Java 11 + # Update both `disruptor.version` to latest 3.x version + # and `disruptor4.version` to latest 4.x version - dependency-name: "com.lmax:disruptor" - versions: ["[4.0.0,)"] + update-types: ["version-update:semver-major"] # WebCompere System Stubs requires Java 11 - dependency-name: "uk.org.webcompere:*" versions: ["2.1.0,)"] diff --git a/log4j-api-java9/pom.xml b/log4j-api-java9/pom.xml index ee07bd93395..5112014f8ac 100644 --- a/log4j-api-java9/pom.xml +++ b/log4j-api-java9/pom.xml @@ -89,8 +89,9 @@ org.apache.maven.plugins maven-surefire-plugin + - test + run-tests test @@ -100,29 +101,4 @@ - - - java8-tests - - - env.CI - true - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - false - - true - - - - - - - diff --git a/log4j-core-test/pom.xml b/log4j-core-test/pom.xml index fb79c45da2d..6b7d0382f9f 100644 --- a/log4j-core-test/pom.xml +++ b/log4j-core-test/pom.xml @@ -59,7 +59,11 @@ java.allocation.instrumenter;substitute="java-allocation-instrumenter", spring.test;substitute="spring-test" + + + 4.0.0 + @@ -371,6 +375,32 @@ + + org.apache.maven.plugins + maven-surefire-plugin + + + test-disruptor-4 + + test + + + + + com.lmax + disruptor + ${disruptor4.version} + + + + com.lmax:disruptor + + org.apache.logging.log4j.core.test.categories.AsyncLoggers + + + + + @@ -422,6 +452,20 @@ + + + disruptor-4 + + + com.lmax + disruptor + ${disruptor4.version} + + + diff --git a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/Tags.java b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/Tags.java new file mode 100644 index 00000000000..ddd0695f9b3 --- /dev/null +++ b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/Tags.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.logging.log4j.core.test.junit; + +/** + * Container for a Junit 5 tags used in tests. + */ +public final class Tags { + + /** + * Tests that use LMAX Disruptor. Same name as the JUnit 4 category. + */ + public static final String ASYNC_LOGGERS = "org.apache.logging.log4j.core.test.categories.AsyncLoggers"; + + private Tags() {} +} diff --git a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/package-info.java b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/package-info.java index e4ee3e70bae..0fedb91e3a2 100644 --- a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/package-info.java +++ b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/package-info.java @@ -20,7 +20,7 @@ * @see org.junit.rules.TestRule */ @Export -@Version("2.21.1") +@Version("2.23.0") package org.apache.logging.log4j.core.test.junit; import org.osgi.annotation.bundle.Export; diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerClassLoadDeadlock.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerClassLoadDeadlock.java index 3e6be938174..fbccd7afcc9 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerClassLoadDeadlock.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerClassLoadDeadlock.java @@ -18,7 +18,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.test.junit.Tags; +import org.junit.jupiter.api.Tag; +@Tag(Tags.ASYNC_LOGGERS) class AsyncLoggerClassLoadDeadlock { static { final Logger log = LogManager.getLogger("com.foo.bar.deadlock"); diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigTest.java index 9c3d7778fab..b8c3fdb9bef 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigTest.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigTest.java @@ -39,13 +39,14 @@ import org.apache.logging.log4j.core.config.NullConfiguration; import org.apache.logging.log4j.core.test.CoreLoggerContexts; import org.apache.logging.log4j.core.test.junit.LoggerContextSource; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.message.SimpleMessage; import org.apache.logging.log4j.test.junit.TempLoggingDir; import org.apache.logging.log4j.test.junit.UsingStatusListener; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; -@Tag("AsyncLoggers") +@Tag(Tags.ASYNC_LOGGERS) @UsingStatusListener public class AsyncLoggerConfigTest { diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerThreadContextTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerThreadContextTest.java index 56f9462252c..93eb835c1c2 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerThreadContextTest.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerThreadContextTest.java @@ -26,6 +26,7 @@ import org.apache.logging.log4j.ThreadContext; import org.apache.logging.log4j.core.test.CoreLoggerContexts; import org.apache.logging.log4j.core.test.junit.LoggerContextSource; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.core.util.Constants; import org.apache.logging.log4j.test.TestProperties; import org.apache.logging.log4j.test.junit.TempLoggingDir; @@ -35,7 +36,7 @@ import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; -@Tag("AsyncLoggers") +@Tag(Tags.ASYNC_LOGGERS) @UsingTestProperties @UsingStatusListener public class AsyncLoggerThreadContextTest { diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggersWithAsyncAppenderTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggersWithAsyncAppenderTest.java index 6e8866d6dcc..9a0ed348177 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggersWithAsyncAppenderTest.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggersWithAsyncAppenderTest.java @@ -25,13 +25,14 @@ import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.test.appender.ListAppender; import org.apache.logging.log4j.core.test.junit.LoggerContextSource; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.core.util.Constants; import org.apache.logging.log4j.test.junit.SetTestProperty; import org.apache.logging.log4j.test.junit.UsingStatusListener; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; -@Tag("AsyncLoggers") +@Tag(Tags.ASYNC_LOGGERS) @SetTestProperty( key = Constants.LOG4J_CONTEXT_SELECTOR, value = "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector") diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncThreadContextCopyOnWriteTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncThreadContextCopyOnWriteTest.java index e69516666aa..d42f350ff51 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncThreadContextCopyOnWriteTest.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncThreadContextCopyOnWriteTest.java @@ -17,13 +17,16 @@ package org.apache.logging.log4j.core.async; import java.nio.file.Path; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.test.junit.TempLoggingDir; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; // Note: the different ThreadContextMap implementations cannot be parameterized: // ThreadContext initialization will result in static final fields being set in various components. // To use a different ThreadContextMap, the test needs to be run in a new JVM. +@Tag(Tags.ASYNC_LOGGERS) public class AsyncThreadContextCopyOnWriteTest extends AbstractAsyncThreadContextTestBase { @TempLoggingDir diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncThreadContextDefaultTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncThreadContextDefaultTest.java index d138e27dd68..0e84e2c8deb 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncThreadContextDefaultTest.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncThreadContextDefaultTest.java @@ -17,13 +17,16 @@ package org.apache.logging.log4j.core.async; import java.nio.file.Path; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.test.junit.TempLoggingDir; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; // Note: the different ThreadContextMap implementations cannot be parameterized: // ThreadContext initialization will result in static final fields being set in various components. // To use a different ThreadContextMap, the test needs to be run in a new JVM. +@Tag(Tags.ASYNC_LOGGERS) public class AsyncThreadContextDefaultTest extends AbstractAsyncThreadContextTestBase { @TempLoggingDir diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncThreadContextGarbageFreeTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncThreadContextGarbageFreeTest.java index 32241cc5519..4ede8163049 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncThreadContextGarbageFreeTest.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncThreadContextGarbageFreeTest.java @@ -17,13 +17,16 @@ package org.apache.logging.log4j.core.async; import java.nio.file.Path; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.test.junit.TempLoggingDir; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; // Note: the different ThreadContextMap implementations cannot be parameterized: // ThreadContext initialization will result in static final fields being set in various components. // To use a different ThreadContextMap, the test needs to be run in a new JVM. +@Tag(Tags.ASYNC_LOGGERS) public class AsyncThreadContextGarbageFreeTest extends AbstractAsyncThreadContextTestBase { @TempLoggingDir diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryIncorrectConfigGlobalLoggersTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryIncorrectConfigGlobalLoggersTest.java index c00a15dd2a2..9f282de5a95 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryIncorrectConfigGlobalLoggersTest.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryIncorrectConfigGlobalLoggersTest.java @@ -17,7 +17,7 @@ package org.apache.logging.log4j.core.async; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.*; +import static org.junit.Assert.assertNull; import static org.junit.jupiter.api.Assertions.assertEquals; import org.apache.logging.log4j.LogManager; @@ -58,10 +58,14 @@ public void testIncorrectConfigWaitStrategyFactory() throws Exception { final AsyncLogger logger = (AsyncLogger) context.getRootLogger(); final AsyncLoggerDisruptor delegate = logger.getAsyncLoggerDisruptor(); - assertEquals( - TimeoutBlockingWaitStrategy.class, delegate.getWaitStrategy().getClass()); - assertThat( - "waitstrategy is TimeoutBlockingWaitStrategy", - delegate.getWaitStrategy() instanceof TimeoutBlockingWaitStrategy); + if (DisruptorUtil.DISRUPTOR_MAJOR_VERSION == 3) { + assertEquals( + TimeoutBlockingWaitStrategy.class, + delegate.getWaitStrategy().getClass()); + } else { + assertEquals( + Class.forName("com.lmax.disruptor.TimeoutBlockingWaitStrategy"), + delegate.getWaitStrategy().getClass()); + } } } diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigLoggingFromToStringTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigLoggingFromToStringTest.java index 8542628835d..65fd8d06f9d 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigLoggingFromToStringTest.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigLoggingFromToStringTest.java @@ -21,8 +21,10 @@ import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.test.junit.LoggerContextSource; import org.apache.logging.log4j.core.test.junit.Named; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.test.junit.SetTestProperty; import org.apache.logging.log4j.util.Constants; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; /** @@ -31,6 +33,7 @@ @SetTestProperty(key = "log4j2.enableThreadlocals", value = "true") @SetTestProperty(key = "log4j2.isWebapp", value = "false") @SetTestProperty(key = "log4j2.asyncLoggerConfigRingBufferSize", value = "128") +@Tag(Tags.ASYNC_LOGGERS) public class QueueFullAsyncLoggerConfigLoggingFromToStringTest extends QueueFullAbstractTest { @Override diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigLoggingFromToStringTest2.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigLoggingFromToStringTest2.java index 86d847d6046..54e5a78a97f 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigLoggingFromToStringTest2.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigLoggingFromToStringTest2.java @@ -17,12 +17,15 @@ package org.apache.logging.log4j.core.async; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.test.junit.SetTestProperty; +import org.junit.jupiter.api.Tag; /** * Tests queue full scenarios with AsyncLoggers in configuration. */ @SetTestProperty(key = "log4j2.formatMsgAsync", value = "true") +@Tag(Tags.ASYNC_LOGGERS) public class QueueFullAsyncLoggerConfigLoggingFromToStringTest2 extends QueueFullAsyncLoggerConfigLoggingFromToStringTest { diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigTest.java index a35edd73841..93db0470ed4 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigTest.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigTest.java @@ -19,13 +19,16 @@ import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.test.junit.LoggerContextSource; import org.apache.logging.log4j.core.test.junit.Named; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.test.junit.SetTestProperty; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; /** * Tests queue full scenarios with AsyncLoggers in configuration. */ @SetTestProperty(key = "log4j2.asyncLoggerConfigRingBufferSize", value = "128") +@Tag(Tags.ASYNC_LOGGERS) public class QueueFullAsyncLoggerConfigTest extends QueueFullAbstractTest { @Override diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigTest2.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigTest2.java index b6d21e83a62..4c56595a405 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigTest2.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerConfigTest2.java @@ -17,12 +17,15 @@ package org.apache.logging.log4j.core.async; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.test.junit.SetTestProperty; +import org.junit.jupiter.api.Tag; /** * Tests queue full scenarios with AsyncLoggers in configuration. */ @SetTestProperty(key = "log4j2.formatMsgAsync", value = "true") +@Tag(Tags.ASYNC_LOGGERS) public class QueueFullAsyncLoggerConfigTest2 extends QueueFullAsyncLoggerConfigTest { @Override diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerLoggingFromToStringTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerLoggingFromToStringTest.java index 41edbb344ee..8e98f61c4ee 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerLoggingFromToStringTest.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerLoggingFromToStringTest.java @@ -19,8 +19,10 @@ import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.test.junit.LoggerContextSource; import org.apache.logging.log4j.core.test.junit.Named; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.core.util.Constants; import org.apache.logging.log4j.test.junit.SetTestProperty; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; /** @@ -30,6 +32,7 @@ key = Constants.LOG4J_CONTEXT_SELECTOR, value = "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector") @SetTestProperty(key = "log4j2.asyncLoggerRingBufferSize", value = "128") +@Tag(Tags.ASYNC_LOGGERS) public class QueueFullAsyncLoggerLoggingFromToStringTest extends QueueFullAbstractTest { @Override diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerLoggingFromToStringTest2.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerLoggingFromToStringTest2.java index 6b05b83167a..343be641454 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerLoggingFromToStringTest2.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerLoggingFromToStringTest2.java @@ -19,13 +19,16 @@ import static org.junit.Assert.*; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.test.junit.SetTestProperty; import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Tag; /** * Tests queue full scenarios with pure AsyncLoggers (all loggers async). */ @SetTestProperty(key = "log4j2.formatMsgAsync", value = "true") +@Tag(Tags.ASYNC_LOGGERS) public class QueueFullAsyncLoggerLoggingFromToStringTest2 extends QueueFullAsyncLoggerLoggingFromToStringTest { @Override diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerTest.java index 54cfed20d04..1aaabfe48dd 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerTest.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerTest.java @@ -19,8 +19,10 @@ import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.test.junit.LoggerContextSource; import org.apache.logging.log4j.core.test.junit.Named; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.core.util.Constants; import org.apache.logging.log4j.test.junit.SetTestProperty; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; /** @@ -30,6 +32,7 @@ key = Constants.LOG4J_CONTEXT_SELECTOR, value = "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector") @SetTestProperty(key = "log4j2.asyncLoggerRingBufferSize", value = "128") +@Tag(Tags.ASYNC_LOGGERS) public class QueueFullAsyncLoggerTest extends QueueFullAbstractTest { @Override diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerTest2.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerTest2.java index 7827bbff234..6271849278f 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerTest2.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerTest2.java @@ -17,13 +17,16 @@ package org.apache.logging.log4j.core.async; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.test.junit.SetTestProperty; +import org.junit.jupiter.api.Tag; /** * Needs to be a separate class since {@link org.apache.logging.log4j.core.util.Constants#FORMAT_MESSAGES_IN_BACKGROUND} * is immutable. */ @SetTestProperty(key = "log4j2.formatMsgAsync", value = "true") +@Tag(Tags.ASYNC_LOGGERS) public class QueueFullAsyncLoggerTest2 extends QueueFullAsyncLoggerTest { @Override diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerTest3.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerTest3.java index c9c5d193b77..7a048091d26 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerTest3.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerTest3.java @@ -26,9 +26,11 @@ import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.test.junit.LoggerContextSource; import org.apache.logging.log4j.core.test.junit.Named; +import org.apache.logging.log4j.core.test.junit.Tags; import org.apache.logging.log4j.core.util.Constants; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.test.junit.SetTestProperty; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; @@ -41,6 +43,7 @@ @SetTestProperty(key = "log4j2.asyncLoggerRingBufferSize", value = "128") @SetTestProperty(key = "log4j2.formatMsgAsync", value = "true") @SetTestProperty(key = "log4j2.asyncQueueFullPolicy", value = "Discard") +@Tag(Tags.ASYNC_LOGGERS) public class QueueFullAsyncLoggerTest3 extends QueueFullAbstractTest { @Override diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java index 1a1715ae641..35f865a7761 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java @@ -17,6 +17,7 @@ package org.apache.logging.log4j.core.async; import com.lmax.disruptor.EventFactory; +import com.lmax.disruptor.EventHandler; import com.lmax.disruptor.EventTranslatorTwoArg; import com.lmax.disruptor.ExceptionHandler; import com.lmax.disruptor.RingBuffer; @@ -40,6 +41,7 @@ import org.apache.logging.log4j.core.util.Log4jThreadFactory; import org.apache.logging.log4j.core.util.Throwables; import org.apache.logging.log4j.message.ReusableMessage; +import org.apache.logging.log4j.util.LoaderUtil; /** * Helper class decoupling the {@code AsyncLoggerConfig} class from the LMAX Disruptor library. @@ -91,13 +93,18 @@ public String toString() { /** * EventHandler performs the work in a separate thread. + *

+ * Warning: this implementation only works with Disruptor 4.x. + *

*/ - private static class Log4jEventWrapperHandler implements SequenceReportingEventHandler { + private static class Log4jEventWrapperHandler implements EventHandler { private static final int NOTIFY_PROGRESS_THRESHOLD = 50; private Sequence sequenceCallback; private int counter; - @Override + /* + * Overrides a method from Disruptor 4.x. Do not remove. + */ public void setSequenceCallback(final Sequence sequenceCallback) { this.sequenceCallback = sequenceCallback; } @@ -124,6 +131,15 @@ private void notifyIntermediateProgress(final long sequence) { } } + /** + * EventHandler performs the work in a separate thread. + *

+ * Warning: this implementation only works with Disruptor 3.x. + *

+ */ + private static final class Log4jEventWrapperHandler3 extends Log4jEventWrapperHandler + implements SequenceReportingEventHandler {} + /** * Factory used to populate the RingBuffer with events. These event objects are then re-used during the life of the * RingBuffer. @@ -155,6 +171,18 @@ private void notifyIntermediateProgress(final long sequence) { ringBufferElement.loggerConfig = loggerConfig; }; + private Log4jEventWrapperHandler createEventHandler() { + if (DisruptorUtil.DISRUPTOR_MAJOR_VERSION == 3) { + try { + return LoaderUtil.newInstanceOf( + "org.apache.logging.log4j.core.async.AsyncLoggerConfigDisruptor$Log4jEventWrapperHandler3"); + } catch (final ReflectiveOperationException | LinkageError e) { + LOGGER.warn("Failed to create event handler for LMAX Disruptor 3.x, trying version 4.x.", e); + } + } + return new Log4jEventWrapperHandler(); + } + private int ringBufferSize; private AsyncQueueFullPolicy asyncQueueFullPolicy; private Boolean mutable = Boolean.FALSE; @@ -220,7 +248,7 @@ public Thread newThread(final Runnable r) { final ExceptionHandler errorHandler = DisruptorUtil.getAsyncLoggerConfigExceptionHandler(); disruptor.setDefaultExceptionHandler(errorHandler); - final Log4jEventWrapperHandler[] handlers = {new Log4jEventWrapperHandler()}; + final Log4jEventWrapperHandler[] handlers = {createEventHandler()}; disruptor.handleEventsWith(handlers); LOGGER.debug( diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerDisruptor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerDisruptor.java index 8cdcf7dc492..7b6b0d8dc13 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerDisruptor.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerDisruptor.java @@ -16,6 +16,7 @@ */ package org.apache.logging.log4j.core.async; +import com.lmax.disruptor.EventHandler; import com.lmax.disruptor.EventTranslatorVararg; import com.lmax.disruptor.ExceptionHandler; import com.lmax.disruptor.RingBuffer; @@ -35,6 +36,7 @@ import org.apache.logging.log4j.core.util.Log4jThreadFactory; import org.apache.logging.log4j.core.util.Throwables; import org.apache.logging.log4j.message.Message; +import org.apache.logging.log4j.util.LoaderUtil; /** * Helper class for async loggers: AsyncLoggerDisruptor handles the mechanics of working with the LMAX Disruptor, and @@ -46,6 +48,20 @@ class AsyncLoggerDisruptor extends AbstractLifeCycle { private static final int SLEEP_MILLIS_BETWEEN_DRAIN_ATTEMPTS = 50; private static final int MAX_DRAIN_ATTEMPTS_BEFORE_SHUTDOWN = 200; + /** + * Creates an appropriate event handler for the Disruptor library used. + */ + private static EventHandler createEventHandler() { + if (DisruptorUtil.DISRUPTOR_MAJOR_VERSION == 3) { + try { + return LoaderUtil.newInstanceOf("org.apache.logging.log4j.core.async.RingBufferLogEventHandler"); + } catch (final ReflectiveOperationException | LinkageError e) { + LOGGER.warn("Failed to create event handler for LMAX Disruptor 3.x, trying version 4.x.", e); + } + } + return new RingBufferLogEventHandler4(); + } + private final Object queueFullEnqueueLock = new Object(); private volatile Disruptor disruptor; @@ -122,8 +138,8 @@ public Thread newThread(final Runnable r) { final ExceptionHandler errorHandler = DisruptorUtil.getAsyncLoggerExceptionHandler(); disruptor.setDefaultExceptionHandler(errorHandler); - final RingBufferLogEventHandler[] handlers = {new RingBufferLogEventHandler()}; - disruptor.handleEventsWith(handlers); + final EventHandler handler = createEventHandler(); + disruptor.handleEventsWith(handler); LOGGER.debug( "[{}] Starting AsyncLogger disruptor for this context with ringbufferSize={}, waitStrategy={}, " diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DefaultAsyncWaitStrategyFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DefaultAsyncWaitStrategyFactory.java index 96544d2b55d..eda242feb4d 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DefaultAsyncWaitStrategyFactory.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DefaultAsyncWaitStrategyFactory.java @@ -74,6 +74,19 @@ static WaitStrategy createDefaultWaitStrategy(final String propertyName) { LOGGER.trace( "DefaultAsyncWaitStrategyFactory creating TimeoutBlockingWaitStrategy(timeout={}, unit=MILLIS)", timeoutMillis); + // Check for the v 4.x version of the strategy, the version in 3.x is not garbage-free. + if (DisruptorUtil.DISRUPTOR_MAJOR_VERSION == 4) { + try { + return (WaitStrategy) Class.forName("com.lmax.disruptor.TimeoutBlockingWaitStrategy") + .getConstructor(long.class, TimeUnit.class) + .newInstance(timeoutMillis, TimeUnit.MILLISECONDS); + } catch (final ReflectiveOperationException | LinkageError e) { + LOGGER.debug( + "DefaultAsyncWaitStrategyFactory failed to load 'com.lmax.disruptor.TimeoutBlockingWaitStrategy', using '{}' instead.", + TimeoutBlockingWaitStrategy.class.getName()); + } + } + // Use our version return new TimeoutBlockingWaitStrategy(timeoutMillis, TimeUnit.MILLISECONDS); } diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java index 07d138a25cf..bdd21bd4ef2 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java @@ -50,6 +50,9 @@ final class DisruptorUtil { static final boolean ASYNC_CONFIG_SYNCHRONIZE_ENQUEUE_WHEN_QUEUE_FULL = PropertiesUtil.getProperties() .getBooleanProperty("AsyncLoggerConfig.SynchronizeEnqueueWhenQueueFull", true); + static final int DISRUPTOR_MAJOR_VERSION = + LoaderUtil.isClassAvailable("com.lmax.disruptor.SequenceReportingEventHandler") ? 3 : 4; + private DisruptorUtil() {} static WaitStrategy createWaitStrategy( diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventHandler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventHandler.java index 6293973b854..a51f0a525ec 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventHandler.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventHandler.java @@ -17,7 +17,6 @@ package org.apache.logging.log4j.core.async; import com.lmax.disruptor.LifecycleAware; -import com.lmax.disruptor.Sequence; import com.lmax.disruptor.SequenceReportingEventHandler; /** @@ -25,60 +24,11 @@ * available. Processing of these messages is done in a separate thread, * controlled by the {@code Executor} passed to the {@code Disruptor} * constructor. + *

+ * Warning: this class only works with Disruptor 3.x. + *

+ * @deprecated Only used internally, will be removed in the next major version. */ -public class RingBufferLogEventHandler implements SequenceReportingEventHandler, LifecycleAware { - - private static final int NOTIFY_PROGRESS_THRESHOLD = 50; - private Sequence sequenceCallback; - private int counter; - private long threadId = -1; - - @Override - public void setSequenceCallback(final Sequence sequenceCallback) { - this.sequenceCallback = sequenceCallback; - } - - @Override - public void onEvent(final RingBufferLogEvent event, final long sequence, final boolean endOfBatch) - throws Exception { - try { - // RingBufferLogEvents are populated by an EventTranslator. If an exception is thrown during event - // translation, the event may not be fully populated, but Disruptor requires that the associated sequence - // still be published since a slot has already been claimed in the ring buffer. Ignore any such unpopulated - // events. The exception that occurred during translation will have already been propagated. - if (event.isPopulated()) { - event.execute(endOfBatch); - } - } finally { - event.clear(); - // notify the BatchEventProcessor that the sequence has progressed. - // Without this callback the sequence would not be progressed - // until the batch has completely finished. - notifyCallback(sequence); - } - } - - private void notifyCallback(final long sequence) { - if (++counter > NOTIFY_PROGRESS_THRESHOLD) { - sequenceCallback.set(sequence); - counter = 0; - } - } - - /** - * Returns the thread ID of the background consumer thread, or {@code -1} if the background thread has not started - * yet. - * @return the thread ID of the background consumer thread, or {@code -1} - */ - public long getThreadId() { - return threadId; - } - - @Override - public void onStart() { - threadId = Thread.currentThread().getId(); - } - - @Override - public void onShutdown() {} -} +@Deprecated +public class RingBufferLogEventHandler extends RingBufferLogEventHandler4 + implements SequenceReportingEventHandler, LifecycleAware {} diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventHandler4.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventHandler4.java new file mode 100644 index 00000000000..6cb1e686126 --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventHandler4.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.logging.log4j.core.async; + +import com.lmax.disruptor.EventHandler; +import com.lmax.disruptor.Sequence; + +/** + * This event handler gets passed messages from the RingBuffer as they become + * available. Processing of these messages is done in a separate thread, + * controlled by the {@code Executor} passed to the {@code Disruptor} + * constructor. + * *

+ * * Warning: this class only works with Disruptor 4.x. + * *

+ */ +class RingBufferLogEventHandler4 implements EventHandler { + + private static final int NOTIFY_PROGRESS_THRESHOLD = 50; + private Sequence sequenceCallback; + private int counter; + private long threadId = -1; + + /* + * Overrides a method from Disruptor 4.x. Do not remove. + */ + public void setSequenceCallback(final Sequence sequenceCallback) { + this.sequenceCallback = sequenceCallback; + } + + @Override + public void onEvent(final RingBufferLogEvent event, final long sequence, final boolean endOfBatch) + throws Exception { + try { + // RingBufferLogEvents are populated by an EventTranslator. If an exception is thrown during event + // translation, the event may not be fully populated, but Disruptor requires that the associated sequence + // still be published since a slot has already been claimed in the ring buffer. Ignore any such unpopulated + // events. The exception that occurred during translation will have already been propagated. + if (event.isPopulated()) { + event.execute(endOfBatch); + } + } finally { + event.clear(); + // notify the BatchEventProcessor that the sequence has progressed. + // Without this callback the sequence would not be progressed + // until the batch has completely finished. + notifyCallback(sequence); + } + } + + private void notifyCallback(final long sequence) { + if (++counter > NOTIFY_PROGRESS_THRESHOLD) { + sequenceCallback.set(sequence); + counter = 0; + } + } + + /** + * Returns the thread ID of the background consumer thread, or {@code -1} if the background thread has not started + * yet. + * + * @return the thread ID of the background consumer thread, or {@code -1} + */ + public long getThreadId() { + return threadId; + } + + /* + * Overrides a method from Disruptor 4.x. Do not remove. + */ + public void onStart() { + threadId = Thread.currentThread().getId(); + } + + /* + * Overrides a method from Disruptor 4.x. Do not remove. + */ + public void onShutdown() {} +} diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/package-info.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/package-info.java index a93e24f2ae1..18545f3065f 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/package-info.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/package-info.java @@ -18,7 +18,7 @@ * Provides Asynchronous Logger classes and interfaces for low-latency logging. */ @Export -@Version("2.21.0") +@Version("2.23.0") package org.apache.logging.log4j.core.async; import org.osgi.annotation.bundle.Export; diff --git a/log4j-jpl/pom.xml b/log4j-jpl/pom.xml index 7ac145daf73..70345ff657e 100644 --- a/log4j-jpl/pom.xml +++ b/log4j-jpl/pom.xml @@ -65,30 +65,26 @@
- - - java8-tests - - - env.CI - true - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - false - - true - - false - - - - - - + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + run-tests + + test + + + + default-test + none + + + + + + diff --git a/pom.xml b/pom.xml index edf7a06e9af..48b63d878d5 100644 --- a/pom.xml +++ b/pom.xml @@ -304,7 +304,7 @@ - 2.22.2-SNAPSHOT + 2.23.0-SNAPSHOT + + default-test + + + [1.8, 9) + + + +
diff --git a/src/changelog/.2.x.x/add_support_for_disruptor_4.xml b/src/changelog/.2.x.x/add_support_for_disruptor_4.xml new file mode 100644 index 00000000000..b01fd47b37f --- /dev/null +++ b/src/changelog/.2.x.x/add_support_for_disruptor_4.xml @@ -0,0 +1,26 @@ + + + + + + Added support for LMAX Disruptor 4.x. + + diff --git a/src/changelog/.2.x.x/deprecate_ring_buffer_log_event_handler.xml b/src/changelog/.2.x.x/deprecate_ring_buffer_log_event_handler.xml new file mode 100644 index 00000000000..2a46c622f07 --- /dev/null +++ b/src/changelog/.2.x.x/deprecate_ring_buffer_log_event_handler.xml @@ -0,0 +1,25 @@ + + + + + Deprecated the `RingBufferLogEventHandler` class for removal from the public API in 3.x. + +