有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

爪哇七月至SLF4J大桥

我目前观察到第三方库(即restfb)正在使用java。util。记录日志,我看到这些日志最终会出现在STDOUT中,即使我的日志中没有配置SLF4J控制台追加器。xml。我的类路径中还有jul-to-slf4j桥。安装网桥时,jul-to-slf4j网桥是否只记录到logback配置的Appender,还是也记录到stdout


共 (5) 个答案

  1. # 1 楼答案

    我的解决方案:

    SLF4JBridgeHandler.install();
    java.util.logging.LogManager.getLogManager().getLogger("").setLevel( Level.INFO);
    

    将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>
    

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

  2. # 2 楼答案

    这个解决方案看起来不错(考虑到七月桥接的情况),对我来说很有效,因为我只需要在日志中写下所有内容。groovy文件

    1. 如果您根本没有使用logback.groovy配置或logback,当然您必须将逻辑部分放入某个类中(例如class MyApp { static { /* log init code here */ } ... }

    2. src/logback。groovy

       import org.slf4j.bridge.SLF4JBridgeHandler
       import ch.qos.logback.classic.jul.LevelChangePropagator
      
       // for debug: just to see it in case something is logging/initialized before
       System.out.println( 'my myapp logback.groovy is loading' )
      
       // see also: http://logback.qos.ch/manual/configuration.html#LevelChangePropagator
       // performance speedup for redirected JUL loggers
       def lcp = new LevelChangePropagator()
       lcp.context = context
       lcp.resetJUL = true
       context.addListener(lcp)
      
       // needed only for the JUL bridge: http://stackoverflow.com/a/9117188/1915920
       java.util.logging.LogManager.getLogManager().reset()
       SLF4JBridgeHandler.removeHandlersForRootLogger()
       SLF4JBridgeHandler.install()
       java.util.logging.Logger.getLogger( "global" ).setLevel( java.util.logging.Level.FINEST )
      
       def logPattern = "%date |%.-1level| [%thread] %20.20logger{10}|  %msg%n"
      
       appender("STDOUT", ConsoleAppender) {
           encoder(PatternLayoutEncoder) {
               pattern = logPattern
           }
       }
      
       /*// outcommenting in dev will not create dummy empty file
       appender("ROLLING", RollingFileAppender) {  // prod
           encoder(PatternLayoutEncoder) {
               Pattern = "%date %.-1level [%thread] %20.20logger{10}  %msg%n"
           }
           rollingPolicy(TimeBasedRollingPolicy) {
               FileNamePattern = "${WEBAPP_DIR}/log/orgv-fst-gwt-%d{yyyy-MM-dd}.zip"
           }
       }
       */
      
       appender("FILE", FileAppender) {  // dev
      
           // log to myapp/tmp (independent of running in dev/prod or junit mode:
      
           //System.out.println( 'DEBUG: WEBAPP_DIR env prop:  "."='+new File('.').absolutePath+',  \${WEBAPP_DIR}=${WEBAPP_DIR},  env=' + System.getProperty( "WEBAPP_DIR" ))
           String webappDirName = "war"
           if ( new File( "./../"+webappDirName ).exists() )  // we are not running within a junit test
               file = "../tmp/myapp.log"
           else  // junit test
               file = "tmp/myapp-junit-tests.log"
      
           encoder(PatternLayoutEncoder) { pattern = logPattern }
       }
      
       // without JUL bridge:
       //root(WARN, ["STDOUT", "ROLLING"])  // prod
       //root(DEBUG, ["STDOUT", "FILE"])  // dev
      
       // with JUL bridge: (workaround: see links above)
       def rootLvl = WARN
       root(TRACE, [/*"STDOUT",*/ "FILE"])
       // I manually added all "root package dirs" I know my libs are based on to apply
       // the root level to the second "package dir level" at least
       // depending on your libs used you could remove entries, but I would recommend
       // to add common entries instead (feel free to edit this post if you like to
       // enhance it anywhere)
       logger( "antlr", rootLvl )
       logger( "de", rootLvl )
       logger( "ch", rootLvl )
       logger( "com", rootLvl )
       logger( "java", rootLvl )
       logger( "javassist", rootLvl )
       logger( "javax", rootLvl )
       logger( "junit", rootLvl )
       logger( "groovy", rootLvl )
       logger( "net", rootLvl )
       logger( "org", rootLvl )
       logger( "sun", rootLvl )
      
      
       // my logger setup
      
       logger( "myapp", DEBUG )
      
      
       //logger( "org.hibernate.SQL", DEBUG )  // debug: log SQL statements in DEBUG mode
       //logger( "org.hibernate.type", TRACE )  // debug: log JDBC parameters in TRACE mode
       logger( "org.hibernate.type.BasicTypeRegistry", WARN )  // uninteresting
      
       scan("30 seconds")  // reload/apply-on-change config every x sec
      

    (建议我使用,因为您可以使用Java代码变量/函数,如您在这里看到的,例如,SLF4JBridgeHandler或关于webappDirName的log dir)

    (使文件保持完整,因为它给人一个更好的印象,即如何设置所有内容或将其作为起始模板)

    (可能与某人有关-我的环境:slf4j 1.7.5、logback 1.1.2、groovy 2.1.9

  3. # 3 楼答案

    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();
    

    或者通过日志记录。性质

     // register SLF4JBridgeHandler as handler for the j.u.l. root logger
     handlers = org.slf4j.bridge.SLF4JBridgeHandler
    

    至于性能,关于jul-to-slf4j桥的一节讨论了这个问题。本质上,因为您已经在使用logback,所以启用LevelChangePropagator应该会产生良好的性能,而不管负载如何

  4. # 4 楼答案

    我使用SLF4J和new Postgres driver 42.0.0

    根据changelog它使用java。util。伐木

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

    1. 添加jul-to-slf4j bridge

      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>jul-to-slf4j</artifactId>
          <version>${slf4j.version}</version>
          <scope>runtime</scope>
      </dependency>
      
    2. 添加logback。xml(logbacktest.xml)

      <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
          <resetJUL>true</resetJUL>
      </contextListener>
      
      <appender ...
      
      <logger name="org.postgresql" level="trace"/>
      
    3. 外接程序代码

      static {
          SLF4JBridgeHandler.install();
      }
      
  5. # 5 楼答案

    你需要打电话给^{}。您还需要在java中启用根记录器的所有日志级别(原因见下面的摘录)。util。记录并删除默认控制台追加器

    This handler will redirect jul logging to SLF4J. However, only logs enabled in j.u.l. will be redirected. For example, if a log statement invoking a j.u.l. logger disabled that statement, by definition, will not reach any SLF4JBridgeHandler instance and cannot be redirected.

    整个过程可以这样完成

    import java.util.logging.Logger;
    import org.slf4j.bridge.SLF4JBridgeHandler;
    
    SLF4JBridgeHandler.removeHandlersForRootLogger();
    SLF4JBridgeHandler.install();
    Logger.getLogger("").setLevel(Level.FINEST); // Root logger, for example.
    

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