JUL到SLF4J大桥

Tay*_*ese 62 java logback slf4j java.util.logging

我目前正在观察第三方库(即restfb)正在使用java.util.logging并且我看到这些日志最终在STDOUT中,即使我没有在我的logback.xml中配置SLF4J控制台appender.我的classpath中也有jul-to-slf4j桥.jul-to-slf4j网桥是否仅在安装网桥时登录到由logback配置的appender,还是还记录到stdout?

Dev*_*Dev 81

你需要打电话SLF4JBridgeHandler.install().您还需要在java.util.logging中的根记录器上启用所有日志级别(以下摘录中的原因)并删除默认的控制台appender.

此处理程序将jul日志记录重定向到SLF4J.但是,只会重定向在jul中启用的日志.例如,如果调用jul logger的日志语句禁用该语句,则根据定义,该语句将不会到达任何SLF4JBridgeHandler实例,并且无法重定向.

整个过程可以像这样完成

import java.util.logging.Logger;
import org.slf4j.bridge.SLF4JBridgeHandler;

SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
Logger.getLogger("").setLevel(Level.FINEST); // Root logger, for example.
Run Code Online (Sandbox Code Playgroud)

出于性能原因,您可以将级别设置为高于最高级别的级别,但是如果不java.util.logging首先启用它们,您将无法打开这些日志(由于上面摘录中提到的原因).

  • 是.原因是jul-to-slf4j桥不能替换`java.util.logging`包中的类来静态地进行重定向,就像对其他桥实现一样.相反,它必须在根记录器上注册一个处理程序,并像任何其他处理程序一样监听记录语句.然后它将重定向那些日志记录语句. (5认同)
  • 我发现如果应用程序的任何部分创建JUL Logger对象(例如在静态初始化程序中),则在执行此过程之前,它们的日志级别不会更改. (4认同)
  • 从Java 1.7开始,`Logger.getLogger("global")`可以替换为`Logger.getGlobal()` - 稍微方便一点! (4认同)
  • 如果使用Logback,LevelChangePropagator可解决性能问题:http://logback.qos.ch/manual/configuration.html#LevelChangePropagator (3认同)
  • 有趣的是,我的印象是在类路径中拥有桥就足够了。这只需要7月吗? (2认同)

Cek*_*eki 38

正如SLF4JBridgeHandler的javadocs中所提到的,您可以通过调用以编程方式安装SLF4JBridgeHandler:

 // Optionally remove existing handlers attached to j.u.l root logger
 SLF4JBridgeHandler.removeHandlersForRootLogger();  // (since SLF4J 1.6.5)

 // add SLF4JBridgeHandler to j.u.l's root logger, should be done once during
 // the initialization phase of your application
 SLF4JBridgeHandler.install();
Run Code Online (Sandbox Code Playgroud)

或通过logging.properties

 // register SLF4JBridgeHandler as handler for the j.u.l. root logger
 handlers = org.slf4j.bridge.SLF4JBridgeHandler
Run Code Online (Sandbox Code Playgroud)

至于性能,jul-to-slf4j桥上的部分讨论了这个问题.实质上,由于您已经在使用logback,因此无论负载如何,启用LevelChangePropagator都应该会产生良好的性能.

  • 您是否见过java.lang.ClassNotFoundException:org.slf4j.bridge.SLF4JBridgeHandler发生的实例,即使类路径上存在SLF4JBridgeHandler?当我使用-Djava.util.logging.config.file =来指定logging.properties文件时,我似乎得到了这个. (2认同)

GKi*_*lin 12

我使用SLF4J和新的Postgres驱动程序42.0.0

根据changelog,它使用java.util.logging

要有驱动程序日志就足够了:

  1. 添加jul-to-slf4j网桥:

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jul-to-slf4j</artifactId>
        <version>${slf4j.version}</version>
        <scope>runtime</scope>
    </dependency>
    
    Run Code Online (Sandbox Code Playgroud)
  2. 添加logback.xml(logback-test.xml)

    <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
        <resetJUL>true</resetJUL>
    </contextListener>
    
    <appender ...
    
    <logger name="org.postgresql" level="trace"/>`
    
    Run Code Online (Sandbox Code Playgroud)
  3. 添加代码

    static {
        SLF4JBridgeHandler.install();
    }
    
    Run Code Online (Sandbox Code Playgroud)


Ben*_*tes 5

我的解决方案:

SLF4JBridgeHandler.install();
java.util.logging.LogManager.getLogManager().getLogger("").setLevel( Level.INFO);
Run Code Online (Sandbox Code Playgroud)

将 jul-to-slf4j 放在您的应用程序库或 glassfish 库上,这些将 JUL 重定向到 SLF4J(因此在我的情况下为 LOG4J)

那么对于泽西岛,您可以执行以下操作:

<logger name="com.sun.jersey" additivity="false">
    <level value="WARN" />
    <appender-ref ref="JVM" />
    <appender-ref ref="CONSOLE" />
</logger>   

<logger name="com.sun.common.util.logging" additivity="false">
    <level value="ERROR" />
    <appender-ref ref="JVM" />
    <appender-ref ref="CONSOLE" />
</logger>
Run Code Online (Sandbox Code Playgroud)

最后一个配置是为了避免被其他记录器污染