我正在尝试从第三方应用程序(使用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 );
唯一的缺点是我可能必须抓住每个记录器并执行此操作。当我查看调试器时,我注意到它们都没有父(它是空的)
答案 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();
}
}
}
将根记录器的回溯级别设置为debug
或trace
。与设置logback控制台appender的级别相同。
唯一的缺点是我可能必须抓住每个记录器并执行此操作。
Iteration over the installed the loggers可以执行,但记录树会随着时间的推移而改变。
唯一的缺点是我可能必须抓住每个记录器并执行此操作。当我查看调试器时,我注意到它们都没有父(它是空的)
这很奇怪。如果记录器是根记录器,则父级应该只为null。也许你正在使用的LogManager中的bug?
或者,您可以向要监视的每个记录器添加new SLF4JBridgeHandler()
,但这不如监视根记录器那么好。