4

我正在使用 logback 来记录 Java Web 服务应用程序,使用嵌入式 Jetty。日志记录基于 logback.xml 文件按预期工作......除了一些源自 Java 的日志,但显示在 jsvc 输出到 stderr 中。

我特别想查看我所有的 Java 生成的日志,其时间戳与我的其他日志相匹配,而显示在 jsvc stderr 输出中的日志只显示到第二个。

jsvc 标准输出日志主要是从 Jersey 生成的,我看到我自己的代码被引用为在 Guice 注册的对象,这让我希望它可以通过 logback 进行控制。我不明白是什么原因导致这些日志显示在 jsvc 的 stderr 输出中,而不是在 logback 中。有没有人在使用 jsvc 时在他们的代码或配置中解决了类似的问题?

4

3 回答 3

2

该解决方案需要在几个地方进行更改,并且主要是 slf4j 配置问题。我的应用程序有许多依赖项,它们引入了各种日志记录实现。Slf4j 旨在将它们全部聚集在一起,并且该过程通常只是一个简单的 jar 插件,但 java.util.logging 需要更多的努力。

slf4j Bridging Legacy APIs页面(主要)描述了如何连接 Jersey 引入的 JUL 依赖项。我已经包含了 jul-to-slf4j.jar,但它没有正确连接。我需要SLF4JBridgeHandler.install()在我的应用程序的初始化中执行。此外,除非我还在 logback.xml 文件中包含以下内容,否则该页面会警告对性能的负面影响:

<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
    <resetJUL>true</resetJUL>
</contextListener>

这让我走了大部分路,但引入了日志事件的重复——一个去了 slf4j,另一个继续到 stderr。Google 将我引向 Claus Neilsen 博客中的一篇文章,“将 java.util.logging 与 SLF4J 桥接”。这包含一个有用的代码片段:

// Jersey uses java.util.logging - bridge to slf4
java.util.logging.Logger rootLogger = LogManager.getLogManager().getLogger("");
Handler[] handlers = rootLogger.getHandlers();
for (int i = 0; i < handlers.length; i++) {
    rootLogger.removeHandler(handlers[i]);
}
SLF4JBridgeHandler.install();

有了这些,在我的 jsvc stderr 输出中显示的 Jersey 日志现在与我的其余日志一起显示,并按照 logback.xml 的指示进行了很好的格式化。

于 2012-04-18T17:06:55.890 回答
1

据我了解,它jsvc是一个用 C 语言编写的管理 Java 应用程序的守护进程。它并没有真正在 Java 本身中运行,并且它的日志记录受限于stdoutstderr. 您可以将jsvc输出重定向到命名管道并让一些进程读取它们并为您提供毫秒时间戳。由您决定要为解决方案付出多少努力。

于 2012-04-17T01:54:51.643 回答
0

根据客户端或容器过滤器 javadoc,Jersey 默认使用 JDK Logging API 生成其日志行System.out

因此,您必须参考Java Logging 指南来设置它,LogManager以便按类或级别进行过滤,甚至将日志行转移(或复制)System.out到您自己的文件中。

您自己的代码使用slf4j,您必须配置 logback 以ConsoleAppender替换FileAppender.

于 2012-04-17T21:50:12.853 回答