Направление ведения журнала JUL на SLF4J не работает
Я использую стороннюю библиотеку ( Sphinx), которая использует java.util.logging. Я пробовал несколько подходов, чтобы направить его журналы на slf4j. Я хочу использовать библиотеку журналов Log4j2, которая настроена так:
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
Я безуспешно применил все решения, которые смог найти на этом и других форумах. Среди прочего:
Я добавил эту maven-зависимость к своему POM:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.20</version>
</dependency>
Я также попытался вызвать это в статическом блоке:
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
И попытался установить системное свойство:
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
В моей последней попытке я передал аргумент VM:
-Djava.util.logging.manager = org.apache.logging.log4j.jul.LogManager
и получил исключение ниже:
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)
Я делаю что-то неправильно? Что еще я могу попробовать?
Обновить:
Я также попытался перенаправить jul на log4j2, минуя slf4j, и, следовательно, изменил мою первоначальную стратегию (спасибо за предложение @rgoers). Чтобы сделать это, я добавил зависимость ниже:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jul</artifactId>
<version>2.5</version>
</dependency>
а также установить свойство System java.util.logging.manager
чтобы: org.apache.logging.log4j.jul.LogManager
Тогда журналы сфинкса исчезли. Я знаю, что они не маршрутизируются на мой логгер log4j2, так как большинство журналов Sphinx имеют уровень INFO, и они должны обрабатываться log4j2. Так что все равно не правильно.
3 ответа
Если вы хотите перенаправить сообщения в Log4j 2, почему бы просто не использовать мост Log4j 2? log4j-июль-2.5.jar
У нас здесь есть решение, и я заметил разницу: logger.setUseParentHandler(false) and logger.addHandler(new org.slf4j.bridge.SLF4JBridgeHandler());
Я проверяю, что у меня нет другого обработчика, а затем присоединяю SLF4JBridgeHandler
к экземпляру Logger.
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);
}
}
}
У меня есть JEE-Webapp, который хочет регистрировать сервлет-фильтр. Базовый Tomcat 8.5 уже инициализировал JUL при запуске. Поэтому мне нужно было переопределить инициализацию Tomcat. Этот код работал для меня.
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);