将JUL日志记录定向到SLF4J不起作用

时间:2016-03-31 22:26:21

标签: java slf4j log4j2 sphinx4 jul-to-slf4j

我使用的是使用java.util.logging的第三方库(Sphinx)。我一直在尝试几种方法将其日志路由到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处理。所以仍然不正确。

2 个答案:

答案 0 :(得分:3)

如果您想将消息路由到Log4j 2,为什么不只使用Log4j 2的网桥?的log4j-JUL-2.5.jar

答案 1 :(得分:0)

我们在这里有一个解决方案,我注意到的差异是: 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);
        }
    }

}