This is an automated email from the ASF dual-hosted git repository.
vy pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/2.x by this push:
new bf873ae58e Extend plugin processor message filtering and add `[Log4j]`
prefixes (#4228)
bf873ae58e is described below
commit bf873ae58e75cb2296ad29c8df9691793e3f3dcf
Author: DragonFSKY <[email protected]>
AuthorDate: Fri Aug 14 17:07:29 2026 +0800
Extend plugin processor message filtering and add `[Log4j]` prefixes (#4228)
Co-authored-by: Ramanathan <[email protected]>
Co-authored-by: Volkan Yazıcı <[email protected]>
---
.../plugins/processor/GraalVmProcessorTest.java | 60 +++++++++++++++++++---
.../processor/PluginProcessorPublicSetterTest.java | 10 ++--
.../config/plugins/processor/GraalVmProcessor.java | 50 ++++++++++++++----
.../config/plugins/processor/PluginProcessor.java | 26 +++++-----
.../.2.x.x/4225_plugin_processor_messages.xml | 13 +++++
.../antora/modules/ROOT/pages/manual/plugins.adoc | 6 +--
6 files changed, 127 insertions(+), 38 deletions(-)
diff --git
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessorTest.java
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessorTest.java
index 4605fcb70b..f46150f4a3 100644
---
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessorTest.java
+++
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessorTest.java
@@ -222,6 +222,7 @@ class GraalVmProcessorTest {
assertThat(diagnostics).hasSize(1);
// The warning message should contain the information about the
missing groupId and artifactId arguments
assertThat(diagnostics.get(0))
+ .startsWith("[Log4j] ")
.contains(
"recommended",
"-A" + GraalVmProcessor.GROUP_ID + "=<groupId>",
@@ -239,8 +240,56 @@ class GraalVmProcessorTest {
.exists();
}
+ @Test
+ void noteEmittedByDefaultWithLog4jPrefix(@TempDir Path outputDir) throws
Exception {
+ List<Diagnostic<? extends JavaFileObject>> diagnostics =
+ generateDiagnostics(sourceDir, GROUP_ID, ARTIFACT_ID,
outputDir);
+
+ assertThat(diagnostics)
+ .anyMatch(diagnostic -> diagnostic.getKind() ==
Diagnostic.Kind.NOTE
+ && diagnostic
+ .getMessage(Locale.ROOT)
+ .startsWith("[Log4j] GraalVmProcessor: writing
GraalVM metadata"));
+ }
+
+ @Test
+ void notesSuppressedWithoutAffectingMetadataGeneration(@TempDir Path
outputDir) throws Exception {
+ List<Diagnostic<? extends JavaFileObject>> diagnostics =
generateDiagnostics(
+ sourceDir,
+ GROUP_ID,
+ ARTIFACT_ID,
+ outputDir,
+ "-A" + PluginProcessor.MIN_ALLOWED_MESSAGE_KIND_OPTION +
"=warning");
+
+ assertThat(diagnostics)
+ .noneMatch(diagnostic -> diagnostic.getKind() ==
Diagnostic.Kind.NOTE
+ &&
diagnostic.getMessage(Locale.ROOT).contains("writing GraalVM metadata"));
+
assertThat(outputDir.resolve("META-INF/native-image/log4j-generated/groupId/artifactId/reflect-config.json"))
+ .exists();
+ }
+
private static List<String> generateDescriptor(
- Path sourceDir, @Nullable String groupId, @Nullable String
artifactId, Path outputDir) throws Exception {
+ Path sourceDir,
+ @Nullable String groupId,
+ @Nullable String artifactId,
+ Path outputDir,
+ String... extraOptions)
+ throws Exception {
+ return generateDiagnostics(sourceDir, groupId, artifactId, outputDir,
extraOptions).stream()
+ .filter(d -> d.getKind() != Diagnostic.Kind.NOTE)
+ .map(d -> d.getMessage(Locale.ROOT))
+ // This message appears when the test runs on JDK 8
+ .filter(m -> !"unknown enum constant
java.lang.annotation.ElementType.MODULE".equals(m))
+ .collect(Collectors.toList());
+ }
+
+ private static List<Diagnostic<? extends JavaFileObject>>
generateDiagnostics(
+ Path sourceDir,
+ @Nullable String groupId,
+ @Nullable String artifactId,
+ Path outputDir,
+ String... extraOptions)
+ throws Exception {
// Instantiate the tooling
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
final StandardJavaFileManager fileManager =
compiler.getStandardFileManager(null, Locale.ROOT, UTF_8);
@@ -267,6 +316,7 @@ class GraalVmProcessorTest {
if (artifactId != null) {
options.add("-A" + GraalVmProcessor.ARTIFACT_ID + "=" +
artifactId);
}
+ options.addAll(asList(extraOptions));
// Compile the sources
final DiagnosticCollector<JavaFileObject> diagnosticCollector = new
DiagnosticCollector<>();
@@ -274,12 +324,6 @@ class GraalVmProcessorTest {
compiler.getTask(null, fileManager, diagnosticCollector,
options, null, sources);
task.call();
- // Verify successful compilation
- return diagnosticCollector.getDiagnostics().stream()
- .filter(d -> d.getKind() != Diagnostic.Kind.NOTE)
- .map(d -> d.getMessage(Locale.ROOT))
- // This message appears when the test runs on JDK 8
- .filter(m -> !"unknown enum constant
java.lang.annotation.ElementType.MODULE".equals(m))
- .collect(Collectors.toList());
+ return diagnosticCollector.getDiagnostics();
}
}
diff --git
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/processor/PluginProcessorPublicSetterTest.java
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/processor/PluginProcessorPublicSetterTest.java
index 2b6a03d1fe..3772cced4d 100644
---
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/processor/PluginProcessorPublicSetterTest.java
+++
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/processor/PluginProcessorPublicSetterTest.java
@@ -99,7 +99,7 @@ public class PluginProcessorPublicSetterTest {
void warnWhenPluginBuilderAttributeLacksPublicSetter() {
assertThat(errorDiagnostics).anyMatch(errorMessage -> errorMessage
.getMessage(Locale.ROOT)
- .contains("The field `attribute` does not have a public
setter"));
+ .startsWith("[Log4j] The field `attribute` does not have a
public setter"));
}
@Test
@@ -117,7 +117,8 @@ public class PluginProcessorPublicSetterTest {
final List<Diagnostic<? extends JavaFileObject>> noteDiagnostics =
diagnosticCollector.getDiagnostics().stream()
.filter(d -> d.getKind() == Diagnostic.Kind.NOTE)
.collect(Collectors.toList());
- assertThat(noteDiagnostics).anyMatch(d ->
d.getMessage(Locale.ROOT).contains("writing plugin descriptor"));
+ assertThat(noteDiagnostics).anyMatch(d -> d.getMessage(Locale.ROOT)
+ .startsWith("[Log4j] PluginProcessor: writing plugin
descriptor"));
}
@Test
@@ -161,6 +162,9 @@ public class PluginProcessorPublicSetterTest {
.filter(d -> d.getKind() == Diagnostic.Kind.WARNING)
.collect(Collectors.toList());
assertThat(warningDiagnostics)
- .anyMatch(d ->
d.getMessage(Locale.ROOT).contains("unrecognized value `INVALID`"));
+ .anyMatch(d -> d.getMessage(Locale.ROOT)
+ .startsWith(
+ "[Log4j]
org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor:")
+ && d.getMessage(Locale.ROOT).contains("unrecognized
value `INVALID`"));
}
}
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessor.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessor.java
index 4603ec5ee9..05528f96a9 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessor.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessor.java
@@ -25,10 +25,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
@@ -71,23 +71,41 @@ import org.jspecify.annotations.Nullable;
"org.apache.logging.log4j.core.config.plugins.PluginValue",
"org.apache.logging.log4j.core.config.plugins.PluginVisitorStrategy"
})
-@SupportedOptions({"log4j.graalvm.groupId", "log4j.graalvm.artifactId"})
+@SupportedOptions({"log4j.graalvm.groupId", "log4j.graalvm.artifactId",
"log4j.plugin.processor.minAllowedMessageKind"})
public class GraalVmProcessor extends AbstractProcessor {
static final String GROUP_ID = "log4j.graalvm.groupId";
static final String ARTIFACT_ID = "log4j.graalvm.artifactId";
private static final String LOCATION_PREFIX =
"META-INF/native-image/log4j-generated/";
private static final String LOCATION_SUFFIX = "/reflect-config.json";
+ private static final String MESSAGE_PREFIX = "[Log4j] ";
private static final String PROCESSOR_NAME =
GraalVmProcessor.class.getSimpleName();
private final Map<String, ReachabilityMetadata.Type> reachableTypes = new
HashMap<>();
private final List<Element> processedElements = new ArrayList<>();
private Annotations annotationUtil;
+ private Diagnostic.Kind minAllowedMessageKind = Diagnostic.Kind.NOTE;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
this.annotationUtil = new Annotations(processingEnv.getElementUtils());
+ final String kindValue =
processingEnv.getOptions().get(PluginProcessor.MIN_ALLOWED_MESSAGE_KIND_OPTION);
+ if (kindValue != null) {
+ try {
+ minAllowedMessageKind =
Diagnostic.Kind.valueOf(kindValue.toUpperCase(Locale.ROOT));
+ } catch (final IllegalArgumentException e) {
+ printMessage(
+ Diagnostic.Kind.WARNING,
+ String.format(
+ "%s: unrecognized value `%s` for option `%s`,
using default `%s`. Valid values: %s",
+ GraalVmProcessor.class.getName(),
+ kindValue,
+
PluginProcessor.MIN_ALLOWED_MESSAGE_KIND_OPTION,
+ Diagnostic.Kind.NOTE,
+ Arrays.toString(Diagnostic.Kind.values())));
+ }
+ }
}
@Override
@@ -97,7 +115,6 @@ public class GraalVmProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
- Messager messager = processingEnv.getMessager();
for (TypeElement annotation : annotations) {
Annotations.Type annotationType =
annotationUtil.classifyAnnotation(annotation);
for (Element element :
roundEnv.getElementsAnnotatedWith(annotation)) {
@@ -115,7 +132,7 @@ public class GraalVmProcessor extends AbstractProcessor {
processFactory(element);
break;
case UNKNOWN:
- messager.printMessage(
+ printMessage(
Diagnostic.Kind.WARNING,
String.format(
"The annotation type `%s` is not
handled by %s", annotation, PROCESSOR_NAME),
@@ -174,7 +191,7 @@ public class GraalVmProcessor extends AbstractProcessor {
break;
default:
String msg = String.format("Invalid Log4j parameter element
`%s`.", element);
-
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, element);
+ printMessage(Diagnostic.Kind.ERROR, msg, element);
throw new IllegalStateException(msg);
}
}
@@ -192,7 +209,7 @@ public class GraalVmProcessor extends AbstractProcessor {
} catch (IOException e) {
String message = String.format(
"%s: an error occurred while generating reachability
metadata: %s", PROCESSOR_NAME, e.getMessage());
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
message);
+ printMessage(Diagnostic.Kind.ERROR, message);
return;
}
byte[] data = arrayOutputStream.toByteArray();
@@ -200,8 +217,7 @@ public class GraalVmProcessor extends AbstractProcessor {
Map<String, String> options = processingEnv.getOptions();
String reachabilityMetadataPath = getReachabilityMetadataPath(
options.get(GROUP_ID), options.get(ARTIFACT_ID),
Integer.toHexString(Arrays.hashCode(data)));
- Messager messager = processingEnv.getMessager();
- messager.printMessage(
+ printMessage(
Diagnostic.Kind.NOTE,
String.format(
"%s: writing GraalVM metadata for %d Java classes to
`%s`.",
@@ -218,7 +234,7 @@ public class GraalVmProcessor extends AbstractProcessor {
} catch (IOException e) {
String message = String.format(
"%s: unable to write reachability metadata to file `%s`",
PROCESSOR_NAME, reachabilityMetadataPath);
- messager.printMessage(Diagnostic.Kind.ERROR, message);
+ printMessage(Diagnostic.Kind.ERROR, message);
throw new IllegalArgumentException(message, e);
}
}
@@ -243,7 +259,7 @@ public class GraalVmProcessor extends AbstractProcessor {
+ " -A%2$s=<groupId>%n"
+ " -A%3$s=<artifactId>%n",
PROCESSOR_NAME, GROUP_ID, ARTIFACT_ID);
- processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
message);
+ printMessage(Diagnostic.Kind.WARNING, message);
return LOCATION_PREFIX + fallbackFolderName + LOCATION_SUFFIX;
}
return LOCATION_PREFIX + groupId + '/' + artifactId + LOCATION_SUFFIX;
@@ -273,10 +289,22 @@ public class GraalVmProcessor extends AbstractProcessor {
String msg = String.format(
"Unexpected type of element `%s`: expecting `%s` but found
`%s`",
element, type.getName(), element.getClass().getName());
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg,
element);
+ printMessage(Diagnostic.Kind.ERROR, msg, element);
throw new IllegalStateException(msg);
}
+ private void printMessage(final Diagnostic.Kind kind, final String
message) {
+ if (kind.ordinal() <= minAllowedMessageKind.ordinal()) {
+ processingEnv.getMessager().printMessage(kind, MESSAGE_PREFIX +
message);
+ }
+ }
+
+ private void printMessage(final Diagnostic.Kind kind, final String
message, final Element element) {
+ if (kind.ordinal() <= minAllowedMessageKind.ordinal()) {
+ processingEnv.getMessager().printMessage(kind, MESSAGE_PREFIX +
message, element);
+ }
+ }
+
/**
* Returns the fully qualified name of a type.
*
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/processor/PluginProcessor.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/processor/PluginProcessor.java
index 94557a7ddb..51b7e09109 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/processor/PluginProcessor.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/processor/PluginProcessor.java
@@ -69,6 +69,8 @@ public class PluginProcessor extends AbstractProcessor {
private static final Element[] EMPTY_ELEMENT_ARRAY = {};
+ private static final String MESSAGE_PREFIX = "[Log4j] ";
+
private static final String SUPPRESS_WARNING_PUBLIC_SETTER_STRING =
"log4j.public.setter";
/**
@@ -105,17 +107,15 @@ public class PluginProcessor extends AbstractProcessor {
try {
minAllowedMessageKind =
Diagnostic.Kind.valueOf(kindValue.toUpperCase(Locale.ROOT));
} catch (final IllegalArgumentException e) {
- processingEnv
- .getMessager()
- .printMessage(
- Diagnostic.Kind.WARNING,
- String.format(
- "%s: unrecognized value `%s` for
option `%s`, using default `%s`. Valid values: %s",
- PluginProcessor.class.getName(),
- kindValue,
- MIN_ALLOWED_MESSAGE_KIND_OPTION,
- Diagnostic.Kind.NOTE,
-
Arrays.toString(Diagnostic.Kind.values())));
+ printMessage(
+ Diagnostic.Kind.WARNING,
+ String.format(
+ "%s: unrecognized value `%s` for option `%s`,
using default `%s`. Valid values: %s",
+ PluginProcessor.class.getName(),
+ kindValue,
+ MIN_ALLOWED_MESSAGE_KIND_OPTION,
+ Diagnostic.Kind.NOTE,
+ Arrays.toString(Diagnostic.Kind.values())));
}
}
}
@@ -134,7 +134,7 @@ public class PluginProcessor extends AbstractProcessor {
*/
private void printMessage(final Diagnostic.Kind kind, final String
message) {
if (kind.ordinal() <= minAllowedMessageKind.ordinal()) {
- processingEnv.getMessager().printMessage(kind, message);
+ processingEnv.getMessager().printMessage(kind, MESSAGE_PREFIX +
message);
}
}
@@ -144,7 +144,7 @@ public class PluginProcessor extends AbstractProcessor {
*/
private void printMessage(final Diagnostic.Kind kind, final String
message, final Element element) {
if (kind.ordinal() <= minAllowedMessageKind.ordinal()) {
- processingEnv.getMessager().printMessage(kind, message, element);
+ processingEnv.getMessager().printMessage(kind, MESSAGE_PREFIX +
message, element);
}
}
diff --git a/src/changelog/.2.x.x/4225_plugin_processor_messages.xml
b/src/changelog/.2.x.x/4225_plugin_processor_messages.xml
new file mode 100644
index 0000000000..f52ac661a7
--- /dev/null
+++ b/src/changelog/.2.x.x/4225_plugin_processor_messages.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns="https://logging.apache.org/xml/ns"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ https://logging.apache.org/xml/ns
+ https://logging.apache.org/xml/ns/log4j-changelog-0.xsd"
+ type="changed">
+ <issue id="4225"
link="https://github.com/apache/logging-log4j2/issues/4225"/>
+ <issue id="4228" link="https://github.com/apache/logging-log4j2/pull/4228"/>
+ <description format="asciidoc">
+ Allow `log4j.plugin.processor.minAllowedMessageKind` to filter
`GraalVmProcessor` diagnostics and prefix all plugin processor messages with
`[Log4j]`.
+ </description>
+</entry>
diff --git a/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
b/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
index f8d6b5ff4b..a647ef5024 100644
--- a/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
@@ -215,13 +215,13 @@ The `GraalVmProcessor` requires your project's `groupId`
and `artifactId` to cor
Provide these values to the processor using the `log4j.graalvm.groupId` and
`log4j.graalvm.artifactId` annotation processor options.
====
-.Suppressing notes from `PluginProcessor` in strict build environments
+.Suppressing annotation processor notes in strict build environments
[%collapsible]
====
Some build environments treat all compiler notes or warnings as errors (e.g.,
Maven with `-Werror` or Gradle with `options.compilerArgs << '-Werror'`).
-By default, `PluginProcessor` emits a `NOTE`-level diagnostic when it writes
the plugin descriptor, which can cause the build to fail in those environments.
+By default, `PluginProcessor` and `GraalVmProcessor` emit `NOTE`-level
diagnostics when they write their descriptors, which can cause the build to
fail in those environments.
To suppress these informational notes, pass the
`log4j.plugin.processor.minAllowedMessageKind` annotation processor option with
a value of `WARNING` or `ERROR`.
-This instructs the processor to only emit diagnostics at or above the
specified severity, silencing routine notes while preserving genuine warnings
and errors.
+This instructs aforementioned processors to only emit diagnostics at or above
the specified severity, silencing routine notes while preserving genuine
warnings and errors.
Accepted values (case-insensitive): `NOTE` (default), `WARNING`,
`MANDATORY_WARNING`, `ERROR`, `OTHER`.