Initialize slf4j with log4j2.xml

Initialize slf4j with log4j2.xml



I want to use slf4j over log4j. I added the following dependencies in my pom.xml (I used 1.7.25 for slf4j and 2.10.0 for log4j2):


<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>$slf4j.version</version>
</dependency>


<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>$log4j.version</version>
</dependency>

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>$log4j.version</version>
</dependency>

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>$log4j.version</version>
</dependency>
</dependencies>



Everything builds just fine, no compilation errors or lack of dependencies, but I failed to specify the configuration (log4j2.xml) file in my class that is responsible for the initialization of the Logger. In this situation it always prints the same warning


log4j:WARN No appenders could be found for logger (com.mypackage.etc).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.



I searched for a proper way to provide the configuration file and ended up with this:


LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
File file = new File("path/to/a/different/log4j2.xml");
context.setConfigLocation(file.toURI());



The problem is that in my case LogManager.getContext(false) will always return an instance of Slf4JLoggerContext (considering that I use slf4j as a facade for the logger) and the initialization will fail with ClassCastException. I tried to store that instance of Slf4JLoggerContext, but it doesn't offer a setter for the context. Also I failed to find a way to retrieve a LoggerContext from log4j.



Is there any way to provide the configuration file (log4j2.xml) to slf4j in order to see all the appenders and loggers?



Update
Consider this my configuration file (I replaced the original packages and appenders name):


<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Properties>
<Property name="def.files.backup.count">10</Property>
<Property name="log.file.path">$oo.home/var/logs</Property>
<Property name="def.file.max.size">10MB</Property>
<Property name="log.level">WARN</Property>
</Properties>

<ThresholdFilter/>

<Appenders>
<RollingFile name="Appender1" fileName="$log.file.path/file1.log" maxFileSize="$def.file.max.size"
maxBackupIndex="$def.files.backup.count">
<PatternLayout>org.apache.log4j.PatternLayout</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
</RollingFile>

<RollingFile name="Appender2" fileName="$log.file.path/file2.log"
maxFileSize="$def.file.max.size"
maxBackupIndex="$def.files.backup.count">
<PatternLayout>org.apache.log4j.PatternLayout</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
</RollingFile>

<RollingFile name="Appender3" fileName="$log.file.path/file3.log"
maxFileSize="$def.file.max.size"
maxBackupIndex="$def.files.backup.count">
<PatternLayout>org.apache.log4j.PatternLayout</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
</RollingFile>

</Appenders>

<Loggers>
<AsyncLogger name="com.package1.oo" level="$log.level" additivity="false">
<AppenderRef ref="Appender1"/>
</AsyncLogger>

<AsyncLogger name="io.package2" level="$log.level" additivity="false">
<AppenderRef ref="Appender2"/>
</AsyncLogger>

<AsyncLogger name="com.package3.package3" level="$log.level" additivity="false">
<AppenderRef ref="Appender3"/>
</AsyncLogger>

<AsyncLogger name="org.package4" level="$log.level">

</AsyncLogger>

<AsyncLogger name="com.package5.Class1" level="$log.level">

</AsyncLogger>

<AsyncRoot level="$log.level">
<AppenderRef ref="Appender1"/>
<AppenderRef ref="Appender2"/>
<AppenderRef ref="Appender3"/>

</AsyncRoot>
</Loggers>

</Configuration>




2 Answers
2



It doesn't seem to me from your question you're trying to specify a custom configuration location! See the Automatic Configuration section in the docs:


Automatic Configuration



Log4j has the ability to automatically configure itself during
initialization. When Log4j starts it will locate all the
ConfigurationFactory plugins and arrange them in weighted order from
highest to lowest. As delivered, Log4j contains four
ConfigurationFactory implementations: one for JSON, one for YAML, one
for properties, and one for XML.



Log4j will inspect the "log4j.configurationFile" system property and,
if set, will attempt to load the configuration using the
ConfigurationFactory that matches the file extension.



If no system property is set the properties ConfigurationFactory will look for log4j2-test.properties in the classpath.



If no such file is found the YAML ConfigurationFactory will look for log4j2-test.yaml or log4j2-test.yml in the classpath.



If no such file is found the JSON ConfigurationFactory will look for log4j2-test.json or log4j2-test.jsn in the classpath.



If no such file is found the XML ConfigurationFactory will look for
log4j2-test.xml in the classpath.



If a test file cannot be located the properties ConfigurationFactory will look for log4j2.properties on the classpath.



If a properties file cannot be located the YAML ConfigurationFactory will look for log4j2.yaml or log4j2.yml on the
classpath.



If a YAML file cannot be located the JSON ConfigurationFactory will look for log4j2.json or log4j2.jsn on the classpath.



If a JSON file cannot be located the XML ConfigurationFactory will try to locate log4j2.xml on the classpath.



If no configuration file could be located the DefaultConfiguration will be used. This will cause logging output to go to the console.



You might be overthinking it here.



You can put it "on the classpath" by placing it in the src/main/resources folder or specifying it on the command line with -cp/-classpath.


src/main/resources


-cp/-classpath






I already provided the argument called "log4j.configurationFile" having the value representing the path to my log4j2.xml file. I think that the problem is represented by the fact that I use slf4j as a facade. Does it know to search for that argument too? In the example that I provided it might break the logger after the ClassCastException, but I tried another method where the logger would also fail to set the context because it would expect LoggerContext from log4j instead of Slf4JLoggerContext, but it would not throw an exception (it just simply returns null, and there was no NullPointerExc).

– Bogdan
Sep 12 '18 at 17:25






As long as you've included the bridge in your deps (which you have), the slf4j stuff should get logged through log4j2. How are you passing in the argument? What happened when you tried a default classpath location like I mentioned at the bottom?

– Dovmo
Sep 12 '18 at 17:39






I passed the argument at command line -Dlog4j.configuration=fullPathToMyFile. The file is placed on the classpath (src/main/resources). I doesn't create the log files. Instead it logs a warn in my wrapper after almost any action. The warn is exactly the same with the one in the post (No appenders could be found for logger).

– Bogdan
Sep 12 '18 at 17:48






I mean, you were basically doing the right thing there. What does your log4j xml config look like?

– Dovmo
Sep 12 '18 at 17:52


log4j xml






How about replacing the current bridge (log4j-slf4j-impl) with: log4j-over-slf4j from org.slf4j?

– Bogdan
Sep 12 '18 at 17:53




I have tested this configuration. The log4j2 file has to be in your classpath.



Maven


<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
</dependency>



log4j2.xml



Also, adding xsd helps you with creating configuration. I have added Logger for spring framework. Note, that jcl-over-slf4j is needed to work with spring's internal logging


<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error"
xmlns="http://logging.apache.org/log4j/2.0/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://logging.apache.org/log4j/2.0/config
https://raw.githubusercontent.com/apache/logging-log4j2/master/log4j-core/src/main/resources/Log4j-config.xsd">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%highlight%dHH:mm:ss.SSS [%t] %-5level %logger36 - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console"/>
</Root>
<Logger name="org.springframework" level="error">
<AppenderRef ref="Console"/>
</Logger>
</Loggers>
</Configuration>



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)