Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ERROR StatusConsoleListener Appenders contains an invalid element or attribute "MyAppender" #1386

Closed
yvasyliev opened this issue Mar 23, 2023 · 3 comments

Comments

@yvasyliev
Copy link

yvasyliev commented Mar 23, 2023

Description

It is not possible to use custom logger appender without explicitly specifying appender's package in log4j2.xml.

Configuration

Version: 2.20.0

Operating system: Windows 10, Ubuntu 20.04.5 LTS

JDK: openjdk 17.0.6 2023-01-17 LTS

Logs

WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
ERROR StatusConsoleListener Appenders contains an invalid element or attribute "MyAppender"
ERROR StatusConsoleListener Unable to locate appender "myAppender" for logger config "root"

Reproduction

Project structure
📂log4j2-demo
│   📄pom.xml
└───📂src
     └📂main
        └📂java
        │   └📂demo
        │       └📂log4j2
        │           └📄MyAppender.java
        └📂resources
            └📄log4j2.xml

📄pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>demo.log4j2</groupId>
    <artifactId>log4j2-demo</artifactId>
    <version>1.0.0</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.5.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <configuration>
                            <archive>
                                <manifest>
                                    <mainClass>demo.log4j2.MyAppender</mainClass>
                                </manifest>
                            </archive>
                            <descriptorRefs>
                                <descriptorRef>jar-with-dependencies</descriptorRef>
                            </descriptorRefs>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j2-impl</artifactId>
            <version>2.20.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.20.0</version>
        </dependency>
    </dependencies>
</project>

📄MyAppender.java

package demo.log4j2;

import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Core;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;

@Plugin(name = "MyAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE)
public class MyAppender extends AbstractAppender {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyAppender.class);

    protected MyAppender(String name, Filter filter, Layout<? extends Serializable> layout, boolean ignoreExceptions, Property[] properties) {
        super(name, filter, layout, ignoreExceptions, properties);
    }

    @PluginFactory
    public static MyAppender createAppender(@PluginAttribute("name") String name, @PluginElement("Filter") Filter filter) {
        return new MyAppender(name, filter, PatternLayout.createDefaultLayout(), true, Property.EMPTY_ARRAY);
    }

    public static void main(String[] args) {
        LOGGER.info("Hello world!");
    }

    @Override
    public void append(LogEvent event) {
        System.out.println(event.getMessage().getFormattedMessage());
    }
}

📄log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
    <Appenders>
        <MyAppender name="myAppender"/>
    </Appenders>
    <Loggers>
        <Root level="ALL">
            <AppenderRef ref="myAppender"/>
        </Root>
    </Loggers>
</Configuration>

  1. If I run this code in Intellij Idea, I will get the next output:
    C:\Users\Yevhen\.jdks\corretto-17.0.6\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2020.2.2\lib\idea_rt.jar=50945:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2020.2.2\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\Yevhen\IdeaProjects\log4j2-demo\target\classes;C:\Users\Yevhen\.m2\repository\org\slf4j\slf4j-api\2.0.7\slf4j-api-2.0.7.jar;C:\Users\Yevhen\.m2\repository\org\apache\logging\log4j\log4j-slf4j2-impl\2.20.0\log4j-slf4j2-impl-2.20.0.jar;C:\Users\Yevhen\.m2\repository\org\apache\logging\log4j\log4j-api\2.20.0\log4j-api-2.20.0.jar;C:\Users\Yevhen\.m2\repository\org\apache\logging\log4j\log4j-core\2.20.0\log4j-core-2.20.0.jar demo.log4j2.MyAppender
    Hello world!
    
    Process finished with exit code 0
  2. If I build the project:
    mvn clean package
    and run the jar, I will get the next output:
    C:\Users\Yevhen\IdeaProjects\log4j2-demo\target>java -jar log4j2-demo-1.0.0-jar-with-dependencies.jar
    WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
    ERROR StatusConsoleListener Appenders contains an invalid element or attribute "MyAppender"
    ERROR StatusConsoleListener Unable to locate appender "myAppender" for logger config "root"
  3. If I open 📄log4j2.xml and replace:
    <Configuration status="warn">
    with:
    <Configuration status="warn" packages="demo.log4j2">
    re-build the jar and run it, I will get the next output:
    C:\Users\Yevhen\IdeaProjects\log4j2-demo\target>java -jar log4j2-demo-1.0.0-jar-with-dependencies.jar
    WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
    WARN StatusConsoleListener The use of package scanning to locate plugins is deprecated and will be removed in a future release
    WARN StatusConsoleListener The use of package scanning to locate plugins is deprecated and will be removed in a future release
    WARN StatusConsoleListener The use of package scanning to locate plugins is deprecated and will be removed in a future release
    Hello world!

According to this article MyAppender must be autoconfigured at build time:

Serialized plugin listing files are generated by an annotation processor contained in the log4j-core artifact which
will automatically scan your code for Log4j 2 plugins and output a metadata file in your processed classes. There is
nothing extra that needs to be done to enable this; the Java compiler will automatically pick up the annotation
processor on the class path unless you explicitly disable it.

Even if I add this plugin to pom.xml, nothing will be changed:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <executions>
        <execution>
            <id>log4j-plugin-processor</id>
            <goals>
                <goal>compile</goal>
            </goals>
            <phase>process-classes</phase>
            <configuration>
                <proc>only</proc>
                <annotationProcessors>
                    <annotationProcessor>org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor
                    </annotationProcessor>
                </annotationProcessors>
            </configuration>
        </execution>
    </executions>
</plugin>
@ppkarwasz
Copy link
Contributor

ppkarwasz commented Mar 23, 2023

@yvasyliev,

By shading multiple JAR files into one you break many things necessary for the correct behavior of Log4j2 (multi-release to run on Java 9+, plugin caches to use components without scanning packages, etc.). For all these to work you need the maven-shade-plugin and multiple transformers. A sample configuration can be found in our samples repository. The most important bits are:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <dependencies>
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId>
                <version>0.1.0</version>
           </dependency>
        </dependencies>
        <configuration>
            <transformers>
                <transformer implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer"/>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                    <mainClass>org.apache.logging.log4j.samples.async.Log4J2AsyncLogger</mainClass>
                    <manifestEntries>
                        <Multi-Release>true</Multi-Release>
                    </manifestEntries> 
                </transformer>
            </transformers>
        </configuration>
    </plugin>

@yvasyliev
Copy link
Author

@ppkarwasz thank you for the assistance!


The next config worked for me:

📄pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

    <groupId>demo.log4j2</groupId>
    <artifactId>log4j2-demo</artifactId>
    <version>1.0.0</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.4.1</version>
                <dependencies>
                    <dependency>
                        <groupId>io.github.edwgiz</groupId>
                        <artifactId>log4j-maven-shade-plugin-extensions</artifactId>
                        <version>2.20.0</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <phase>package</phase>
                        <configuration>
                            <shadedArtifactAttached>true</shadedArtifactAttached>
                            <transformers>
                                <transformer implementation="io.github.edwgiz.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer"/>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>demo.log4j2.MyAppender</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j2-impl</artifactId>
            <version>2.20.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.20.0</version>
        </dependency>
    </dependencies>
</project>
C:\Users\Yevhen\IdeaProjects\log4j2-demo\target>java -jar log4j2-demo-1.0.0-shaded.jar
WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
Hello world!

@ppkarwasz
Copy link
Contributor

@yvasyliev:

Remember the Multi-Release setting. The warning about sun.reflect.Reflection has more impact than performance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants