From 07de6cb3836591a5dd432ea6f800e840a2af4af5 Mon Sep 17 00:00:00 2001 From: Rassyan Date: Wed, 30 Jul 2025 18:16:56 +0800 Subject: [PATCH 01/13] Upgrade to log4j 2.25.1 --- build-tools-internal/version.properties | 2 +- gradle/verification-metadata.xml | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/build-tools-internal/version.properties b/build-tools-internal/version.properties index c552581a81738..d25daf6c08464 100644 --- a/build-tools-internal/version.properties +++ b/build-tools-internal/version.properties @@ -10,7 +10,7 @@ jackson = 2.15.0 snakeyaml = 2.0 icu4j = 77.1 supercsv = 2.4.0 -log4j = 2.19.0 +log4j = 2.25.1 slf4j = 2.0.6 ecsLogging = 1.2.0 jna = 5.12.1 diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index bb4ae5da279fb..dc0d5fbdd98a0 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -3023,6 +3023,11 @@ + + + + + @@ -3048,6 +3053,11 @@ + + + + + @@ -3073,16 +3083,31 @@ + + + + + + + + + + + + + + + From fa58bb55611284ac496005fed17617e04b716ea1 Mon Sep 17 00:00:00 2001 From: Rassyan Date: Wed, 30 Jul 2025 18:21:11 +0800 Subject: [PATCH 02/13] Update docs/changelog/132166.yaml --- docs/changelog/132166.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/changelog/132166.yaml diff --git a/docs/changelog/132166.yaml b/docs/changelog/132166.yaml new file mode 100644 index 0000000000000..ad3348fe926f3 --- /dev/null +++ b/docs/changelog/132166.yaml @@ -0,0 +1,6 @@ +pr: 132166 +summary: Upgrade to log4j 2.25.1 +area: Infra/Logging +type: upgrade +issues: + - 132035 From d4978680cea7eaa9c793b353e3368af279bfe309 Mon Sep 17 00:00:00 2001 From: Rassyan Date: Wed, 30 Jul 2025 20:32:48 +0800 Subject: [PATCH 03/13] Upgrade to log4j 2.25.1 --- .../xpack/core/security/support/NoOpLogger.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/support/NoOpLogger.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/support/NoOpLogger.java index 8844fec09cf53..bd71882bb10a4 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/support/NoOpLogger.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/support/NoOpLogger.java @@ -10,6 +10,7 @@ import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.message.EntryMessage; +import org.apache.logging.log4j.message.FlowMessageFactory; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.MessageFactory; import org.apache.logging.log4j.util.MessageSupplier; @@ -930,6 +931,11 @@ public MF getMessageFactory() { return null; } + @Override + public FlowMessageFactory getFlowMessageFactory() { + return null; + } + @Override public String getName() { return null; From 8555df57d5c3db252afcf7a72d24a6acc0ee1eb2 Mon Sep 17 00:00:00 2001 From: Rassyan Date: Wed, 30 Jul 2025 18:16:56 +0800 Subject: [PATCH 04/13] Upgrade to log4j 2.25.1 --- build-tools-internal/version.properties | 2 +- gradle/verification-metadata.xml | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/build-tools-internal/version.properties b/build-tools-internal/version.properties index b3e291138afdf..6974845fefd1d 100644 --- a/build-tools-internal/version.properties +++ b/build-tools-internal/version.properties @@ -10,7 +10,7 @@ jackson = 2.15.0 snakeyaml = 2.0 icu4j = 77.1 supercsv = 2.4.0 -log4j = 2.19.0 +log4j = 2.25.1 slf4j = 2.0.6 ecsLogging = 1.2.0 jna = 5.12.1 diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index a92bda3c2b877..96ade2c8a35fe 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -3095,6 +3095,11 @@ + + + + + @@ -3160,11 +3165,21 @@ + + + + + + + + + + From 4f8bd146050ecc09fc650710ff7139b013595781 Mon Sep 17 00:00:00 2001 From: Rassyan Date: Wed, 30 Jul 2025 18:21:11 +0800 Subject: [PATCH 05/13] Update docs/changelog/132166.yaml --- docs/changelog/132166.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/changelog/132166.yaml diff --git a/docs/changelog/132166.yaml b/docs/changelog/132166.yaml new file mode 100644 index 0000000000000..ad3348fe926f3 --- /dev/null +++ b/docs/changelog/132166.yaml @@ -0,0 +1,6 @@ +pr: 132166 +summary: Upgrade to log4j 2.25.1 +area: Infra/Logging +type: upgrade +issues: + - 132035 From ddcbe348efe87a28da33953fa436641686aea0b5 Mon Sep 17 00:00:00 2001 From: Rassyan Date: Wed, 30 Jul 2025 20:32:48 +0800 Subject: [PATCH 06/13] Upgrade to log4j 2.25.1 --- .../xpack/core/security/support/NoOpLogger.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/support/NoOpLogger.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/support/NoOpLogger.java index 8844fec09cf53..bd71882bb10a4 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/support/NoOpLogger.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/support/NoOpLogger.java @@ -10,6 +10,7 @@ import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.message.EntryMessage; +import org.apache.logging.log4j.message.FlowMessageFactory; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.MessageFactory; import org.apache.logging.log4j.util.MessageSupplier; @@ -930,6 +931,11 @@ public MF getMessageFactory() { return null; } + @Override + public FlowMessageFactory getFlowMessageFactory() { + return null; + } + @Override public String getName() { return null; From 96b5069cae2a290062034174fd160ade1eb07554 Mon Sep 17 00:00:00 2001 From: Rassyan Date: Tue, 16 Sep 2025 00:33:03 +0800 Subject: [PATCH 07/13] run ./gradlew precommit --write-verification-metadata sha256 --- gradle/verification-metadata.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 96ade2c8a35fe..1fa8cc270c09a 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -502,6 +502,11 @@ + + + + + @@ -692,6 +697,11 @@ + + + + + @@ -4368,6 +4378,11 @@ + + + + + @@ -4923,6 +4938,11 @@ + + + + + From 55eb69ca939967716fca284d8c182b2b73876749 Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Wed, 17 Sep 2025 13:59:14 +0200 Subject: [PATCH 08/13] fix thirdPartyAudit --- server/build.gradle | 16 ++++++++++++++-- x-pack/plugin/core/build.gradle | 4 +--- x-pack/plugin/ent-search/build.gradle | 7 ------- x-pack/plugin/identity-provider/build.gradle | 2 -- x-pack/plugin/security/build.gradle | 2 -- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/server/build.gradle b/server/build.gradle index 20557aefba731..2bcd6e5322d21 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -202,12 +202,12 @@ tasks.named("thirdPartyAudit").configure { 'com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider', 'com.fasterxml.jackson.databind.ser.std.StdScalarSerializer', 'com.fasterxml.jackson.databind.ser.std.StdSerializer', + 'com.fasterxml.jackson.databind.util.ClassUtil', 'com.fasterxml.jackson.dataformat.xml.JacksonXmlModule', 'com.fasterxml.jackson.dataformat.xml.XmlMapper', 'com.fasterxml.jackson.dataformat.xml.util.DefaultXmlPrettyPrinter', - 'org.fusesource.jansi.Ansi', - 'org.fusesource.jansi.AnsiRenderer$Code', 'com.lmax.disruptor.EventFactory', + 'com.lmax.disruptor.EventHandler', 'com.lmax.disruptor.EventTranslator', 'com.lmax.disruptor.EventTranslatorTwoArg', 'com.lmax.disruptor.EventTranslatorVararg', @@ -246,6 +246,7 @@ tasks.named("thirdPartyAudit").configure { 'org.apache.commons.csv.QuoteMode', 'org.apache.kafka.clients.producer.Producer', 'org.apache.kafka.clients.producer.RecordMetadata', + 'org.apache.kafka.common.serialization.ByteArraySerializer', 'org.codehaus.stax2.XMLStreamWriter2', 'org.jctools.queues.MpscArrayQueue', 'org.osgi.framework.Bundle', @@ -257,13 +258,24 @@ tasks.named("thirdPartyAudit").configure { 'org.osgi.framework.ServiceReference', 'org.osgi.framework.ServiceRegistration', 'org.osgi.framework.SynchronousBundleListener', + 'org.osgi.framework.wiring.BundleRevision', 'org.osgi.framework.wiring.BundleWire', 'org.osgi.framework.wiring.BundleWiring', + 'org.zeromq.SocketType', + 'org.zeromq.ZContext', + 'org.zeromq.ZMonitor', + 'org.zeromq.ZMonitor$Event', + 'org.zeromq.ZMonitor$ZEvent', 'org.zeromq.ZMQ$Context', 'org.zeromq.ZMQ$Socket', 'org.zeromq.ZMQ', ) ignoreMissingClasses 'javax.xml.bind.DatatypeConverter' + + ignoreViolations( + 'org.apache.logging.log4j.core.util.internal.UnsafeUtil', + 'org.apache.logging.log4j.core.util.internal.UnsafeUtil$1', + ) } tasks.named("dependencyLicenses").configure { diff --git a/x-pack/plugin/core/build.gradle b/x-pack/plugin/core/build.gradle index 1c5a081948bad..c80ae9a6b91a9 100644 --- a/x-pack/plugin/core/build.gradle +++ b/x-pack/plugin/core/build.gradle @@ -32,7 +32,7 @@ esplugin { tasks.named("dependencyLicenses").configure { mapping from: /http.*/, to: 'httpclient' // pulled in by rest client mapping from: /commons-.*/, to: 'commons' // pulled in by rest client - mapping from: /slf4j-.*/, to: 'slf4j' + mapping from: /slf4j-.*/, to: 'slf4j' } configurations { @@ -157,8 +157,6 @@ tasks.named("thirdPartyAudit").configure { 'javax.jms.Message', // HttpClient5 can use Conscrypt (TLS using BoringSSL), but we don't want that 'org.conscrypt.Conscrypt', - // SLF4j via HttpClient5 - 'org.slf4j.ext.EventData' ) } diff --git a/x-pack/plugin/ent-search/build.gradle b/x-pack/plugin/ent-search/build.gradle index b9802566b6c2f..c9f39759cb2fc 100644 --- a/x-pack/plugin/ent-search/build.gradle +++ b/x-pack/plugin/ent-search/build.gradle @@ -63,13 +63,6 @@ tasks.named("dependencyLicenses") { mapping from: /jackson.*/, to: 'jackson' } -tasks.named("thirdPartyAudit") { - ignoreMissingClasses( - // [missing classes] SLF4j includes an optional class that depends on an extension class (!) - 'org.slf4j.ext.EventData' - ) -} - tasks.named("yamlRestTest") { usesDefaultDistribution("uses the xpack/usage api") } diff --git a/x-pack/plugin/identity-provider/build.gradle b/x-pack/plugin/identity-provider/build.gradle index 6478694110e00..0e318666521fb 100644 --- a/x-pack/plugin/identity-provider/build.gradle +++ b/x-pack/plugin/identity-provider/build.gradle @@ -249,8 +249,6 @@ tasks.named("thirdPartyAudit").configure { 'org.bouncycastle.operator.jcajce.JcaContentSignerBuilder', 'org.bouncycastle.util.Arrays', 'org.bouncycastle.util.io.Streams', - // SLF4j - 'org.slf4j.ext.EventData' ) ignoreViolations( diff --git a/x-pack/plugin/security/build.gradle b/x-pack/plugin/security/build.gradle index 3dc27687d079f..d9502b6a1836f 100644 --- a/x-pack/plugin/security/build.gradle +++ b/x-pack/plugin/security/build.gradle @@ -426,8 +426,6 @@ tasks.named("thirdPartyAudit").configure { 'javax.activation.DataSource', 'javax.activation.FileDataSource', 'javax.activation.FileTypeMap', - // SLF4j - 'org.slf4j.ext.EventData' ) } From efb6f6c3bc7cfaa276def15eb6de0f35ce34979c Mon Sep 17 00:00:00 2001 From: Rassyan Date: Thu, 18 Sep 2025 16:11:35 +0800 Subject: [PATCH 09/13] Ignore Log4j package scanning deprecation warning in tests --- .../src/main/java/org/elasticsearch/test/ESTestCase.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java index e173790c285ed..0657092259f94 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java @@ -823,7 +823,8 @@ public void log(StatusData data) { "JNDI lookup class is not available because this JRE does not support JNDI. " + "JNDI string lookups will not be available, continuing configuration.", "JMX runtime input lookup class is not available because this JRE does not support JMX. " - + "JMX lookups will not be available, continuing configuration. " + + "JMX lookups will not be available, continuing configuration. ", + "The use of package scanning to locate Log4j plugins is deprecated." ); // separate method so that this can be checked again after suite scoped cluster is shut down @@ -839,7 +840,8 @@ protected static void checkStaticState() throws Exception { anyOf( emptyCollectionOf(String.class), contains(startsWith(LOG_4J_MSG_PREFIXES.get(0)), startsWith(LOG_4J_MSG_PREFIXES.get(1))), - contains(startsWith(LOG_4J_MSG_PREFIXES.get(1))) + contains(startsWith(LOG_4J_MSG_PREFIXES.get(1))), + contains(startsWith(LOG_4J_MSG_PREFIXES.get(2))) ) ); } finally { From 959249c69c8f06c7f534fa52bf922008d00e13bc Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Thu, 18 Sep 2025 18:43:06 +0200 Subject: [PATCH 10/13] Silence more log4j2 warnings --- .../common/logging/config/log4j2.properties | 2 +- .../logging/deprecation/log4j2.properties | 2 +- .../logging/no_node_name/log4j2.properties | 2 +- .../common/logging/settings/log4j2.properties | 2 +- .../resources/es-v7-log4j2.properties | 2 +- .../org/elasticsearch/test/ESTestCase.java | 37 ++++++++++--------- .../src/main/resources/log4j2-test.properties | 2 +- 7 files changed, 26 insertions(+), 23 deletions(-) diff --git a/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/config/log4j2.properties b/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/config/log4j2.properties index 255c53a8d7dd8..a8e7ce57d6329 100644 --- a/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/config/log4j2.properties +++ b/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/config/log4j2.properties @@ -30,7 +30,7 @@ appender.header_warning.type = HeaderWarningAppender appender.header_warning.name = header_warning logger.deprecation.name = deprecation -logger.deprecation.level = deprecation +logger.deprecation.level = warn logger.deprecation.appenderRef.deprecation_file.ref = deprecation_file logger.deprecation.appenderRef.header_warning.ref = header_warning logger.deprecation.additivity = false diff --git a/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/deprecation/log4j2.properties b/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/deprecation/log4j2.properties index e488da2f95f58..5f7d4dbe5347c 100644 --- a/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/deprecation/log4j2.properties +++ b/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/deprecation/log4j2.properties @@ -24,7 +24,7 @@ appender.header_warning.type = HeaderWarningAppender appender.header_warning.name = header_warning logger.deprecation.name = deprecation -logger.deprecation.level = deprecation +logger.deprecation.level = warn logger.deprecation.appenderRef.deprecation_file.ref = deprecation_file logger.deprecation.appenderRef.header_warning.ref = header_warning logger.deprecation.additivity = false diff --git a/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/no_node_name/log4j2.properties b/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/no_node_name/log4j2.properties index 1a1f70c7a2657..ce749ecbdfd05 100644 --- a/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/no_node_name/log4j2.properties +++ b/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/no_node_name/log4j2.properties @@ -24,7 +24,7 @@ appender.header_warning.type = HeaderWarningAppender appender.header_warning.name = header_warning logger.deprecation.name = deprecation -logger.deprecation.level = deprecation +logger.deprecation.level = warn logger.deprecation.appenderRef.deprecation_file.ref = deprecation_file logger.deprecation.appenderRef.header_warning.ref = header_warning logger.deprecation.additivity = false diff --git a/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/settings/log4j2.properties b/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/settings/log4j2.properties index 284b7bda1f7b0..7bf19d2b41875 100644 --- a/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/settings/log4j2.properties +++ b/qa/evil-tests/src/test/resources/org/elasticsearch/common/logging/settings/log4j2.properties @@ -24,7 +24,7 @@ appender.header_warning.type = HeaderWarningAppender appender.header_warning.name = header_warning logger.deprecation.name = org.elasticsearch.deprecation.common.settings -logger.deprecation.level = deprecation +logger.deprecation.level = warn logger.deprecation.appenderRef.deprecation_console.ref = console logger.deprecation.appenderRef.deprecation_file.ref = deprecation_file logger.deprecation.appenderRef.header_warning.ref = header_warning diff --git a/qa/logging-config/src/javaRestTest/resources/es-v7-log4j2.properties b/qa/logging-config/src/javaRestTest/resources/es-v7-log4j2.properties index d45bfc6826d6a..2793177a3ea75 100644 --- a/qa/logging-config/src/javaRestTest/resources/es-v7-log4j2.properties +++ b/qa/logging-config/src/javaRestTest/resources/es-v7-log4j2.properties @@ -102,7 +102,7 @@ appender.header_warning.type = HeaderWarningAppender appender.header_warning.name = header_warning ################################################# logger.deprecation.name = org.elasticsearch.deprecation -logger.deprecation.level = deprecation +logger.deprecation.level = warn logger.deprecation.appenderRef.deprecation_rolling.ref = deprecation_rolling logger.deprecation.appenderRef.deprecation_rolling_old.ref = deprecation_rolling_old logger.deprecation.appenderRef.header_warning.ref = header_warning diff --git a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java index 0657092259f94..4716eca2b8395 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java @@ -223,10 +223,9 @@ import static java.util.Collections.emptyMap; import static org.elasticsearch.common.util.CollectionUtils.arrayAsArrayList; import static org.hamcrest.Matchers.anyOf; -import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.emptyCollectionOf; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.everyItem; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.startsWith; @@ -819,12 +818,20 @@ public void log(StatusData data) { // Tolerate the absence or otherwise denial of these specific lookup classes. // At some future time, we should require the JDNI warning. - private static final List LOG_4J_MSG_PREFIXES = List.of( - "JNDI lookup class is not available because this JRE does not support JNDI. " - + "JNDI string lookups will not be available, continuing configuration.", - "JMX runtime input lookup class is not available because this JRE does not support JMX. " - + "JMX lookups will not be available, continuing configuration. ", - "The use of package scanning to locate Log4j plugins is deprecated." + private static final Matcher LOG_4J_MSG_PREFIXES = anyOf( + startsWith( + "JNDI lookup class is not available because this JRE does not support JNDI. " + + "JNDI string lookups will not be available, continuing configuration." + ), + startsWith( + "JMX runtime input lookup class is not available because this JRE does not support JMX. " + + "JMX lookups will not be available, continuing configuration. " + ), + // TODO migrate to annotation processor https://github.com/elastic/elasticsearch/issues/135022 + startsWith("The use of package scanning to locate Log4j plugins is deprecated."), + startsWith("Some custom `Core` Log4j plugins are not properly registered"), + startsWith("Some custom `Converter` Log4j plugins are not properly registered"), + startsWith("No Root logger was configured, creating default ERROR-level Root logger with Console appender") ); // separate method so that this can be checked again after suite scoped cluster is shut down @@ -835,15 +842,11 @@ protected static void checkStaticState() throws Exception { try { // ensure that there are no status logger messages which would indicate a problem with our Log4j usage; we map the // StatusData instances to Strings as otherwise their toString output is useless - assertThat( - statusData.stream().map(status -> status.getMessage().getFormattedMessage()).collect(Collectors.toList()), - anyOf( - emptyCollectionOf(String.class), - contains(startsWith(LOG_4J_MSG_PREFIXES.get(0)), startsWith(LOG_4J_MSG_PREFIXES.get(1))), - contains(startsWith(LOG_4J_MSG_PREFIXES.get(1))), - contains(startsWith(LOG_4J_MSG_PREFIXES.get(2))) - ) - ); + List collect = statusData.stream() + .map(status -> status.getMessage().getFormattedMessage()) + .collect(Collectors.toList()); + + assertThat(collect, everyItem(LOG_4J_MSG_PREFIXES)); } finally { // we clear the list so that status data from other tests do not interfere with tests within the same JVM statusData.clear(); diff --git a/test/framework/src/main/resources/log4j2-test.properties b/test/framework/src/main/resources/log4j2-test.properties index a78bb3ab2dfad..8b23dd49efa59 100644 --- a/test/framework/src/main/resources/log4j2-test.properties +++ b/test/framework/src/main/resources/log4j2-test.properties @@ -10,5 +10,5 @@ appender.header_warning.type = HeaderWarningAppender appender.header_warning.name = header_warning logger.deprecation.name = org.elasticsearch.deprecation -logger.deprecation.level = deprecation +logger.deprecation.level = info logger.deprecation.appenderRef.header_warning.ref = header_warning From 2ffa8841fc38e12746b476182b9bc768c47f7a21 Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Thu, 18 Sep 2025 18:54:18 +0200 Subject: [PATCH 11/13] consistently use warn as level for logger.deprecation.level --- test/framework/src/main/resources/log4j2-test.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/framework/src/main/resources/log4j2-test.properties b/test/framework/src/main/resources/log4j2-test.properties index 8b23dd49efa59..e8076cab58b5f 100644 --- a/test/framework/src/main/resources/log4j2-test.properties +++ b/test/framework/src/main/resources/log4j2-test.properties @@ -10,5 +10,5 @@ appender.header_warning.type = HeaderWarningAppender appender.header_warning.name = header_warning logger.deprecation.name = org.elasticsearch.deprecation -logger.deprecation.level = info +logger.deprecation.level = warn logger.deprecation.appenderRef.header_warning.ref = header_warning From 714291bd2847014765a8c6efedec506ff565d7ae Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Fri, 19 Sep 2025 13:34:05 +0200 Subject: [PATCH 12/13] Ensure SearchPhaseExecutionException returns a stable and consistent cause --- .../search/SearchPhaseExecutionException.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/search/SearchPhaseExecutionException.java b/server/src/main/java/org/elasticsearch/action/search/SearchPhaseExecutionException.java index 4117d3c33efa4..3d2f8bfe53247 100644 --- a/server/src/main/java/org/elasticsearch/action/search/SearchPhaseExecutionException.java +++ b/server/src/main/java/org/elasticsearch/action/search/SearchPhaseExecutionException.java @@ -26,21 +26,26 @@ public class SearchPhaseExecutionException extends ElasticsearchException { private final String phaseName; private final ShardSearchFailure[] shardFailures; + private final ElasticsearchException guessedCause; // log4j requires a stable cause! public SearchPhaseExecutionException(String phaseName, String msg, ShardSearchFailure[] shardFailures) { this(phaseName, msg, null, shardFailures); } + @SuppressWarnings("this-escape") public SearchPhaseExecutionException(String phaseName, String msg, Throwable cause, ShardSearchFailure[] shardFailures) { super(msg, deduplicateCause(cause, shardFailures)); this.phaseName = phaseName; this.shardFailures = shardFailures; + this.guessedCause = cause == null || super.getCause() == null ? guessFirstRootCause(shardFailures) : null; } + @SuppressWarnings("this-escape") public SearchPhaseExecutionException(StreamInput in) throws IOException { super(in); phaseName = in.readOptionalString(); shardFailures = in.readArray(ShardSearchFailure::readShardSearchFailure, ShardSearchFailure[]::new); + guessedCause = super.getCause() == null ? guessFirstRootCause(shardFailures) : null; } @Override @@ -96,14 +101,9 @@ public ShardSearchFailure[] shardFailures() { @Override public Throwable getCause() { + // note: log4j requires this to return a stable, consistent cause when called multiple times Throwable cause = super.getCause(); - if (cause == null) { - // fall back to guessed root cause - for (ElasticsearchException rootCause : guessRootCauses()) { - return rootCause; - } - } - return cause; + return cause != null ? cause : guessedCause; } @Override @@ -144,6 +144,16 @@ public ElasticsearchException[] guessRootCauses() { return rootCauses.toArray(new ElasticsearchException[0]); } + private static ElasticsearchException guessFirstRootCause(ShardSearchFailure[] shardFailures) { + for (ShardOperationFailedException failure : shardFailures) { + ElasticsearchException[] rootCauses = ElasticsearchException.guessRootCauses(failure.getCause()); + if (rootCauses.length > 0) { + return rootCauses[0]; + } + } + return null; + } + @Override public String toString() { return "Failed to execute phase [" From 96db8d4abc8eeee1dfb1ee8e8cccd23e0b2f63cb Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Thu, 25 Sep 2025 13:31:39 +0200 Subject: [PATCH 13/13] Expand mismatch description in case of unexpected Log4j2 status logs --- .../org/elasticsearch/test/ESTestCase.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java index 111d1aaf1ddf4..1919b615d9035 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java @@ -152,9 +152,11 @@ import org.elasticsearch.xcontent.XContentParser.Token; import org.elasticsearch.xcontent.XContentParserConfiguration; import org.elasticsearch.xcontent.XContentType; +import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; +import org.hamcrest.TypeSafeMatcher; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; @@ -844,13 +846,25 @@ protected static void checkStaticState() throws Exception { assertThat(StatusLogger.getLogger().getLevel(), equalTo(Level.WARN)); synchronized (statusData) { try { - // ensure that there are no status logger messages which would indicate a problem with our Log4j usage; we map the - // StatusData instances to Strings as otherwise their toString output is useless - List collect = statusData.stream() - .map(status -> status.getMessage().getFormattedMessage()) - .collect(Collectors.toList()); + // ensure that there are no status logger messages which would indicate a problem with our Log4j usage; + assertThat(statusData, everyItem(new TypeSafeMatcher() { + @Override + protected boolean matchesSafely(StatusData item) { + return LOG_4J_MSG_PREFIXES.matches(item.getFormattedStatus()); + } + + @Override + public void describeTo(Description description) { + LOG_4J_MSG_PREFIXES.describeTo(description); + } + + @Override + protected void describeMismatchSafely(StatusData item, Description mismatchDescription) { + // make sure we see log4j exceptions in case of issues + mismatchDescription.appendText("was ").appendValue(item.getFormattedStatus()); + } + })); - assertThat(collect, everyItem(LOG_4J_MSG_PREFIXES)); } finally { // we clear the list so that status data from other tests do not interfere with tests within the same JVM statusData.clear();