簡體   English   中英

將 JUL 日志記錄定向到 SLF4J 不起作用

[英]Directing JUL logging to SLF4J does not work

我正在使用使用 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>

我還嘗試在 static 塊中調用它:

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>

並將系統屬性java.util.logging.manager設置為: org.apache.logging.log4j.jul.LogManager

然后獅身人面像日志不見了。 我知道它們沒有路由到我的 log4j2 記錄器,因為大多數 Sphinx 日志都具有 INFO 級別,它們應該由 log4j2 處理。 所以還是不正確。

如果要將消息路由到Log4j 2,為什么不只使用Log4j 2的網橋? log4j-jul-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,想要記錄 servlet-filter。 底層 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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM