简体   繁体   English

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

[英]Directing JUL logging to SLF4J does not work

I am using a third party library ( Sphinx ) which uses java.util.logging.我正在使用使用 java.util.logging 的第三方库 ( Sphinx )。 I have been trying several approaches to route its logs to slf4j.我一直在尝试几种方法将其日志路由到 slf4j。 The logging library I wish to use is Log4j2, which is configured like this:我希望使用的日志库是 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

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:我将此 maven 依赖项添加到我的 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:我还尝试在 static 块中调用它:

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:在我最后一次尝试中,我通过了 VM 参数:

-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -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).我还尝试将 jul 重定向到 log4j2,绕过 slf4j,从而改变了我原来的策略(感谢@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并将系统属性java.util.logging.manager设置为: 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.我知道它们没有路由到我的 log4j2 记录器,因为大多数 Sphinx 日志都具有 INFO 级别,它们应该由 log4j2 处理。 So still not correct.所以还是不正确。

If you want to route the messages to Log4j 2 why not just use Log4j 2's bridge? 如果要将消息路由到Log4j 2,为什么不只使用Log4j 2的网桥? log4j-jul-2.5.jar 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()); 我们这里有一个有效的解决方案,我注意到的区别是: 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. 我确保没有其他处理程序,然后将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);
        }
    }

}

I have a JEE-Webapp, an wanted to log servlet-filter.我有一个 JEE-Webapp,想要记录 servlet-filter。 The underlying Tomcat 8.5 has already initialized the JUL at startup.底层 Tomcat 8.5 已经在启动时初始化了 JUL。 So I needed to override the Tomcat-initialization.所以我需要覆盖 Tomcat 初始化。 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM