无法发送JUL - >的logback

时间:2017-07-11 16:06:45

标签: java logging logback rcp

我正在尝试从第三方应用程序(使用JUL ConsoleHandler)发送日志记录来进行回溯。我已经关注了本网站上的所有其他帖子,但无法让它发挥作用。我做错了吗?

  • 我将以下内容添加到实现捆绑激活器

    的RCP类的开头
    public class MyTestActivator implements BundleActivator {
        static {
          LogManager.getLogManager().reset();
          SLF4JBridgeHandler.removeHandlersForRootLogger();
          SLF4JBridgeHandler.install();
          java.util.logging.Logger.getGlobal().setLevel(Level.FINEST);
    
        } 
        @Override
        public void start(final BundleContext bundleContext) throws 
          Exception {
            try {
                LoggerContext context = (LoggerContext) LoggerFactory.
                  getILoggerFactory();
    
                JoranConfigurator configurator = new JoranConfigurator();
                  configurator.setContext(context);
                try {
                    context.reset();
                    configurator.doConfigure(getClass().
                    getResourceAsStream("/logback.xml"));
                } catch (JoranException e) {
                    throw new IOException(e.getMessage(), e);
                }
                StatusPrinter.printInCaseOfErrorsOrWarnings(context);
            } catch (final IOException e) {
                e.printStackTrace();
            }
        }
    }
    
  • 我的feature.xml文件包含:

    <plugin
          id="jul.to.slf4j"
          download-size="0"
          install-size="0"
          version="0.0.0"
          unpack="false"/>
    
    <plugin
          id="ch.qos.logback.classic"
          download-size="0"
          install-size="0"
          version="0.0.0"
          unpack="false"/>
    
    <plugin
          id="ch.qos.logback.core"
          download-size="0"
          install-size="0"
          version="0.0.0"
          unpack="false"/>
    
  • 我的logback.xml包含:

    <configuration>
        <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
            <resetJUL>true</resetJUL>
        </contextListener>
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>
                    %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
                </pattern>
            </encoder>
        </appender>
        <root level="info">
            <appender-ref ref="STDOUT" />
        </root>
    </configuration>
    

更新:我也尝试了以下内容,但它没有按预期工作

    private static final java.util.logging.Logger[] pin;
    static {
        LogManager.getLogManager().reset();
        SLF4JBridgeHandler.removeHandlersForRootLogger();
        SLF4JBridgeHandler.install();
        pin = new java.util.logging.Logger[] { 
            java.util.logging.Logger.getLogger(""),        
            java.util.logging.Logger.getLogger("3rd.party.package") };

        for (java.util.logging.Logger l : pin) {
            l.setLevel(Level.FINEST);
            for (Handler h : l.getHandlers()){
                if (h instanceof ConsoleHandler){
                    h.setFormatter(new Formatter(){
                        public final String format(LogRecord record) { 
                            if (record == null) {
                                return "";
                            } else {
                                return "CONSOLE_MSG:"+record.getMessage();
                            }
                        }
                    });
                }
            }
        }

    }
  • 更新我相信我通过在上一节中添加以下代码代替for循环来实现它:

    java.util.logging.Logger root = java.util.logging.Logger.getLogger("");
    java.util.logging.Logger myLog = java.util.logging.Logger.getLogger("3rd.party.package");
    myLog.setParent(root);
    myLog.setUseParentHandlers(true);
    java.util.logging.LogManager.getLogManager().getLogger( "" ).setLevel( Level.ALL );
    

唯一的缺点是我可能必须抓住每个记录器并执行此操作。当我查看调试器时,我注意到它们都没有父(它是空的)

1 个答案:

答案 0 :(得分:2)

Logger.getGlobal()不是所有JUL记录器的根。所有JUL记录器的根目录是Logger.getLogger("")。如果您对记录器进行编程更改,则必须pin those loggers,以便在垃圾回收时不会还原这些设置。

您需要确保日志记录并发布到parent handlers并一直发布到根记录器。

private static final java.util.logging.Logger[] pin;
static {
    //Pin first.
    pin = new java.util.logging.Logger[] { 
        java.util.logging.Logger.getLogger(""),
        java.util.logging.Logger.getLogger("3rd.party.package") };

    //Setup SLF4J
    LogManager.getLogManager().reset();
    SLF4JBridgeHandler.removeHandlersForRootLogger();
    //SLF4JBridgeHandler.install();
    java.util.logging.Logger.getLogger("").addHandler(new SLF4JBridgeHandler());

    //Change JUL levels.
    for (java.util.logging.Logger l : pin) {
        l.setLevel(Level.FINEST);
    }
}

你也应该尝试:

public class MyTestActivator implements BundleActivator {        
    static {
        //Pin first.
        pin = new java.util.logging.Logger[] { 
        java.util.logging.Logger.getLogger(""),
        java.util.logging.Logger.getLogger("3rd.party.package") };

        //Change JUL levels.
        for (java.util.logging.Logger l : pin) {
           l.setLevel(Level.FINEST);
        }
    }

    @Override
    public void start(final BundleContext bundleContext) throws Exception {
        try {
            LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();

            JoranConfigurator configurator = new JoranConfigurator();
            configurator.setContext(context);
            try {
                context.reset();
                configurator.doConfigure(getClass().getResourceAsStream("/logback.xml"));
                //Setup SLF4J
                SLF4JBridgeHandler.removeHandlersForRootLogger();
                SLF4JBridgeHandler.install();
            } catch (JoranException e) {
                throw new IOException(e.getMessage(), e);
            }
            StatusPrinter.printInCaseOfErrorsOrWarnings(context);
        } catch (final IOException e) {
            e.printStackTrace();
        }
    }
}

将根记录器的回溯级别设置为debugtrace。与设置logback控制台appender的级别相同。

  

唯一的缺点是我可能必须抓住每个记录器并执行此操作。

Iteration over the installed the loggers可以执行,但记录树会随着时间的推移而改变。

  

唯一的缺点是我可能必须抓住每个记录器并执行此操作。当我查看调试器时,我注意到它们都没有父(它是空的)

这很奇怪。如果记录器是根记录器,则父级应该只为null。也许你正在使用的LogManager中的bug?

或者,您可以向要监视的每个记录器添加new SLF4JBridgeHandler(),但这不如监视根记录器那么好。