记录 System.out.println 在 JBoss 中迷路
Posted
技术标签:
【中文标题】记录 System.out.println 在 JBoss 中迷路【英文标题】:logging System.out.println getting lost in JBoss 【发布时间】:2017-06-13 19:31:50 【问题描述】:我正在使用简单的 System.out.printf
/ System.out.println
语句来执行 JBoss 日志记录(我正在部署到 JBoss EAP 6.2)。我注意到,当发生异常时,我倾向于在抛出异常之前立即丢失println
消息。这使得无法调试异常。
为了验证这一点,我在我的 WAR 中输入了以下代码:
System.out.println("foo");
int i = 0; if (i==0) throw new RuntimeException();
...
(int i = 0; if (i==0)
部分只是为了让编译器静音,否则会抱怨)
确实,当执行此代码时,在服务器的日志文件 (standalone/log/server.log
) 中我根本看不到 foo
。我看到了异常的报告,但上面什么也没有。
我尝试在循环中打印相同的消息 100 次,明确地执行 System.out.flush()
并在抛出异常之前执行 java.util.concurrent.TimeUnit.MINUTES.sleep(1)
。没有任何改变,在server.log
中根本看不到任何输出。仅显示异常跟踪,但其上方没有 foo
。
我了解 JBoss 将 std:out
和 std:err
包装到自己的日志框架中,我假设其中涉及某种缓冲导致 System.out.println
输出丢失。
我的 WAR 中没有任何 logging.properties
文件,并且没有修改我正在使用的关于日志记录的标准配置 (standalone-full.xml
)。我曾经有一个logging.properties
文件,但我删除了它,因为它导致all System.out.println
丢失,如question 中所述。一旦logging.properties
文件被删除,一些 System.out.println
输出至少会在异常之前看到,即当我最需要它的时候。
我的问题是:
-
为什么我会丢失此输出,如何确保
System.out.println
始终包含在 server.log
中?
有哪些技巧可以简化 JBoss 中的日志记录情况?整个事情非常复杂且无证。
【问题讨论】:
我在 JBoss 中部署了多个应用程序。在某些应用程序中,即使我没有使用任何特定的记录器框架并且仅使用 System.out。我从来没有遇到过这样的问题。您可以尝试(远程)在 Eclipse 等 IDE 中调试您的代码吗? 我建议使用带有 logback 或 log4j 的日志框架 SLF4J @RAS 将其标记为 JBoss 6.x(实际上是 6.2)。 @MarcusJuniusBrutus,是的,我也在使用 JBoss 6.x。请尝试在不打印输出的 Eclipse 中调试您的代码。 【参考方案1】:原来还有一个logging.properties
文件潜伏在周围。删除它后,我可以再次看到 server.log
线索上的所有 System.out.println
消息。我仍然不清楚为什么 logging.properties
文件的存在应该与普通的 STD:OUT
输出混淆。
更新
尝试按照 James R. Perkins 的建议尝试在我的 META-INF
目录中添加一个 jboss-deployment-structure.xml
文件以禁用日志子系统对我的组件的处理并添加以下内容:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">
<deployment>
<exclusions>
<module name="org.jboss.logging"/>
<module name="org.apache.log4j"/>
</exclusions>
</deployment>
</jboss-deployment-structure>
……这没用。 System.out.println
输出仍然丢失。所以唯一的解决方法是删除logging.properties
和log4j.xml
文件。感谢 James R. Perkins 建议这实际上可能是 JBoss EAP 6.2.0 中的 bug
【讨论】:
它允许用户在他们的部署中包含他们自己的日志配置。如果您不想删除 logging.properties 文件,您可以添加jboss-deployment-descriptor.xml
并从处理您的部署中排除日志记录子系统。
@JamesR.Perkins 如果我要“从处理我的部署中排除日志记录子系统”,我还会在server.log
上看到普通的旧 System.out.println 消息吗?
是的。它们包装在记录器中,您的部署将使用服务器级别的记录上下文。
@JamesR.Perkins 添加了jboss-deployment-structure.xml
(不是-descriptor
,也许这是您评论中的拼写错误?)但没有任何反应(请参阅问题末尾的更新)。 System.out.println
输出仍然丢失。所以唯一的解决方法是删除 log4j.xml
和 logging.properties
文件。
抱歉打错了,应该是jboss-deployment-structure.xml
。我的意思是排除logging
子系统。 <exclude-subsystems><subsystem name="logging"/></exclude-subsystems>
docs.jboss.org/author/display/WFLY10/…【参考方案2】:
遇到与操作相同的问题并找到this。它本质上说你应该添加
<console-handler name="STDOUT">
<level name="INFO"/>
<formatter>
<pattern-formatter pattern="%s%E%n"/>
</formatter>
</console-handler>
<logger category="stdout" use-parent-handlers="false">
<level name="INFO"/>
<handlers>
<handler name="STDOUT"/>
</handlers>
</logger>
在standalone.xml 或 domain.xml 中或使用 CLI 中的 JBoss 日志记录子系统,您可以这样做:
/subsystem=logging/console-handler=STDOUT:add(level=INFO,formatter="%s%E%n")
/subsystem=logging/logger=stdout:add(level=INFO,handlers=[handler=STDOUT],use-parent-handlers=false)
您可以通过将“stdout”替换为“stderr”来对 STDERR 执行相同的操作。
上面的配置是这样工作的:
添加第二个 ConsoleHandler 这将仅用于调用 System.out.println(...)。 定义标准输出记录器 这无论如何都被 JBoss Logging 使用,但在这里我们明确定义它以便我们可以配置它。 仅将 STDOUT 处理程序添加到标准输出记录器 设置 use-parent-handler=false 这样我们就不会得到重复的日志记录 在第二个 ConsoleHandler 中更改格式化程序模式,这样它就可以简单地按原样打印字符串 - 没有额外的格式化。这意味着您可能不需要删除您的 logging.properties 和 log4j.xml 文件。希望这能解决问题。
【讨论】:
以上是关于记录 System.out.println 在 JBoss 中迷路的主要内容,如果未能解决你的问题,请参考以下文章
log4j 与 System.out.println - 记录器的优势?