【问题标题】:Do I have any control over the log format of java logs that show up in jsvc stderr output?我是否可以控制显示在 jsvc stderr 输出中的 java 日志的日志格式?
【发布时间】:2012-04-07 01:06:10
【问题描述】:

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

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

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

【问题讨论】:

    标签: java logging logback jsvc


    【解决方案1】:

    该解决方案需要在几个地方进行更改,主要是 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 博客中的一篇文章“Bridging java.util.logging to SLF4J”。这包含一个有用的 sn-p 代码:

    // 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 的指示进行了很好的格式化。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 你正确理解了什么是jsvc。有问题的错误消息由 Jersey 从我自己的应用程序生成并发送到 stderr。我认为 jsvc 正在捕获 stderr 并将输出定向到文件。我正在寻找一种解决方案,可以在 stderr 日志输出到达 jsvc 之前拦截它。
      • 我已经更新了这个问题,以更清楚地反映出我关心的是从 Java 中生成但显示在 jsvc stderr 输出中的日志数据。
      • @phatfingers,你把 logback.xml 放在哪里?如果您在 webapp 的 WEB-INF/classes 文件夹中有它,那么 Jersey 显然不会将它用于自己的日志记录。您需要通过将 logging.xml in the global classpath 设置为默认日志记录。
      • @Old_Pro,我使用的是嵌入式 Jetty 而不是 servlet 容器。我开发的所有类都在一个 jar 文件中,我的外部库在一个子文件夹中,并且 jar 文件的 MANIFEST.MF 在 Class-Path 变量中引用它们。我的主类是pulp.HttpServerMain,logback.xml 位于jar 文件中的同一个“pulp”包中,紧邻HttpServerMain.class 文件。
      • @Old_Pro,我使用外部世界可读 logback.xml 文件的完全限定路径修改了在 -cp 参数中传递给 jsvc 的字符串,但仍然没有乐趣。不过,我认为您正在做一些事情——webapp 上下文尊重 logback.xml 文件,但实际上容器的日志记录只看到标准输出。我会对其进行更多修改并分享我发现的任何内容。
      【解决方案3】:

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

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

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

      【讨论】:

      • 我正在使用 slf4j 将日志输出绑定到 logback。有问题的数据显示在标准错误中。
      • 正如您所说,您想管理 Java 进程中的所有日志行,您需要转移 Jersey 输出,并且您还拥有使用 slf4j/logback 的代码......所以有两个任务要做。
      • 请提供您的 logback XML 配置,可能问题就在那里。
      猜你喜欢
      • 2019-12-09
      • 2017-11-22
      • 1970-01-01
      • 2014-07-13
      • 1970-01-01
      • 1970-01-01
      • 2012-12-05
      • 1970-01-01
      相关资源
      最近更新 更多