I am using a third party library ( Sphinx ) which uses java.util.logging. I have been trying several approaches to route its logs to slf4j. The logging library I wish to use is Log4j2, which is configured like this:
Configuration:
properties:
property:
- name: logPath
value: logs
- name: logName
value: flux
- name: rootLevel
value: info
- name: useConsole
value: ALLOW
Appenders:
Console:
name: Console
target: SYSTEM_OUT
ThresholdFilter:
level: ${sys:rootLevel}
onMatch: ${sys:useConsole}
PatternLayout:
pattern: "%d{yyyy.MM.dd G HH:mm:ss,SSS z} %-5p [%t] %C{2} (%F:%L) - %m%n"
RollingRandomAccessFile:
name: File
fileName: "${sys:logPath}/${sys:logName}.log"
filePattern: "${sys:logPath}/${sys:logName}.%d{yyyy-MM-dd}.log"
PatternLayout:
pattern: "%d{yyyy.MM.dd G HH:mm:ss,SSS z} %-5p [%t] %C{2} (%F:%L) - %m%n"
Policies:
TimeBasedTriggeringPolicy:
interval: 1
Loggers:
Root:
level: ${sys:rootLevel}
AppenderRef:
- ref: File
- ref: Console
I applied without success all the solutions I could find on this and other forums. Among others:
I added this maven dependency to my POM:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.20</version>
</dependency>
I also tried with calling this in a static block:
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
And tried setting the system property:
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
In my last attempt I passed the VM argument:
-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
and got the exception below:
Could not load Logmanager "org.apache.logging.log4j.jul.LogManager"
java.lang.ClassNotFoundException: org.apache.logging.log4j.jul.LogManager
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.util.logging.LogManager$1.run(LogManager.java:195)
at java.util.logging.LogManager$1.run(LogManager.java:181)
at java.security.AccessController.doPrivileged(Native Method)
at java.util.logging.LogManager.<clinit>(LogManager.java:181)
at org.chatbot.stt.SttEngineDemo.<clinit>(SttEngineDemo.java:25)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
Am I doing something wrong? What else can I try?
Update:
I also tried redirecting jul to log4j2, bypassing slf4j, hence changing my original strategy (thanks for the suggestion @rgoers). In order to do this, I added the dependency below:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jul</artifactId>
<version>2.5</version>
</dependency>
and also set the System property java.util.logging.manager
to: org.apache.logging.log4j.jul.LogManager
Then the sphinx logs are gone. I know they are not routed to my log4j2 logger since most of the Sphinx logs have the level INFO and they should be processed by log4j2. So still not correct.
If you want to route the messages to Log4j 2 why not just use Log4j 2's bridge? log4j-jul-2.5.jar
We have a solution here working and the difference I noticed is: logger.setUseParentHandler(false) and logger.addHandler(new org.slf4j.bridge.SLF4JBridgeHandler());
I make sure I don't have any other handler and then attach the SLF4JBridgeHandler
to the Logger instance.
import java.io.File;
import java.io.IOException;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.bridge.SLF4JBridgeHandler;
class Helper {
public static Logger get(String name) {
Logger logger = Logger.getLogger(name);
logger.setUseParentHandlers(false);
configureLogger(logger);
return logger;
}
private static void configureLogger(Logger logger) {
try {
// Remove Console Handler
Handler[] handlers = logger.getHandlers();
for (int i = handlers.length - 1; i >= 0; --i) {
logger.removeHandler(handlers[i]);
}
// Add handler for SLF4J
logger.addHandler(new org.slf4j.bridge.SLF4JBridgeHandler());
} catch (Throwable ex) {
logger.log(Level.SEVERE, "configureLogger", ex);
}
}
}
I have a JEE-Webapp, an wanted to log servlet-filter. The underlying Tomcat 8.5 has already initialized the JUL at startup. So I needed to override the Tomcat-initialization. This code worked for me.
SLF4JBridgeHandler.removeHandlersForRootLogger();
LogManager manager = LogManager.getLogManager();
Enumeration<String> loggernames = LogManager.getLogManager().getLoggerNames();
while(loggernames.hasMoreElements()) {
String loggername = loggernames.nextElement();
Logger logger = manager.getLogger(loggername);
Handler[] handlers = logger.getHandlers();
for (int i = handlers.length - 1; i >= 0; --i) {
logger.removeHandler(handlers[i]);
logger.setUseParentHandlers(true);
}
}
SLF4JBridgeHandler.install();
// Decision what to log is on slf4j-Side. So we delegate every log-request.
Logger.getLogger("").setLevel(Level.FINEST);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.