当配置 org.hibernate.SQL 记录器时,Logback 显示带有根级别 INFO 的 DEBUG 输出

Posted

技术标签:

【中文标题】当配置 org.hibernate.SQL 记录器时,Logback 显示带有根级别 INFO 的 DEBUG 输出【英文标题】:Logback shows DEBUG output with root at level INFO when org.hibernate.SQL logger configured 【发布时间】:2019-02-22 14:27:51 【问题描述】:

为什么 logback 允许通过设置为级别 INFO 的根记录器进行 DEBUG 输出?

上下文是一个使用 Hibernate 的 spring-boot-starter 项目。 POM 在 1.2.0 版本中命名为 logback-classic 和 logback-core。以下配置文件位于其类路径(src/main/resources)中,将根记录器设置为 INFO 级别。

logback-test.xml:

<configuration scan="true" debug="false">
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>logs/test.log</file>
    <encoder>
      <pattern>%d&quot;yyyy-MM-dd'T'HH:mm:ss.SSSXXX&quot;, UTC [%thread] %-5level %logger5 - %msg%n</pattern>
    </encoder>
  </appender>
  <root level="INFO">
    <appender-ref ref="FILE" />
  </root>
  <logger name="org.hibernate.SQL" level="DEBUG" />
</configuration>

在 JUnit 测试期间,文件中会出现大量 INFO/WARN/ERROR 消息。但我很惊讶地看到来自 org.hibernate.SQL 的以下 DEBUG 输出,这是唯一提供调试级输出的包。我想我必须将根记录器设置为 DEBUG 级别才能允许这样做;我认为级别 INFO 会阻止它:

2018-09-18T13:31:02.596Z [http-nio-auto-1-exec-4] DEBUG o.h.SQL - delete from C_NOTIF_XYZ where ID=?

在幕后,Hibernate 似乎通过注释使用 org.jboss.logging.Logger,请参阅https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/internal/CoreLogging.java

由于使用了注释,我不确定是否找到了创建上面显示的删除输出的确切类。我从谷歌搜索中看到,有些人建议记录 shim 类的交互;但我不确定。

非常相似的 SO 问题(所以我并不孤单:)但没有答案:Using logback, debug messages are still being logged though root level is set to "Error"

提前感谢任何提示。

【问题讨论】:

【参考方案1】:

目前我没有找到对文档的参考,但我确认了这种操作模式:通过可加性达到的祖先记录器的行为,默认情况下设置为 true,跳过日志级别检查。 然后无论日志级别如何,日志消息都会发送到根日志记录器。

【讨论】:

我没有问关于加法的问题。我完全不明白这个答案。 在您的 logback-test.xml 配置文件中将 additivity 设置为 false 以停止“传播”到根记录器,如答案中所述,在传播日志的情况下不检查日志级别,总是要写已经到达的消息。此配置将停止写入根记录器: ... ...【参考方案2】:

来自the docs:

给定记录器 L 的有效级别等于其层次结构中的第一个非空级别,从 L 本身开始,并在层次结构中向上到根记录器。

因此,您可以为记录器定义一个覆盖根级别的有效级别。您看到的行为是默认的 Logback 行为。

如果您想禁用来自org.hibernate.SQL logger 的 DEBUG 日志记录,那么:

删除org.hibernate.SQL 记录器配置,因为这将导致org.hibernate.SQL 记录器采用root 记录器级别 为org.hibernate.SQL logger 分配除DEBUG 以外的日志级别

【讨论】:

logger org.hibernate.SQL 的有效级别实际上是 DEBUG(直接设置)还是 INFO(设置在 root 上)? 在您的配置中,org.hibernate.SQL 的有效级别是 DEBUG,因为该级别设置在层次结构中低于 root 级别 INFO 的位置。 docs 中有四个有用的示例(以表格形式)显示了如何确定有效级别。 我想我将继承/有效级别与过滤器/截止级别混淆了。我现在了解根配置在所有记录器上设置了默认有效级别。因此,通过有效的级别调试,org.hibernate.SQL 记录器让 DEBUG 及更高版本通过。我的文件附加程序没有过滤器子句,因此这些事件出现在输出中。这是思考这个案子的正确方式吗? 您的文件附加程序没有过滤子句,因此它将接受日志子系统提供的任何内容。日志子系统将为它提供级别 >= INFO 的日志事件和org.hibernate.sql 发出的级别 >= DEBUG 的所有日志事件。【参考方案3】:

删除这一行:

  <logger name="org.hibernate.SQL" level="DEBUG" />

【讨论】:

是的,谢谢,我发现删除该行确实会抑制调试输出,但想了解原因。 他们使用的 JBoss 记录器与许多其他日志记录框架兼容,如果它不是主要使用的,则向他们发送日志消息,例如当它是库的一部分时休眠。在我从事的一个项目中,我在启动时添加了System.setProperty("org.jboss.logging.provider", "slf4j");,它使 JBoss 记录器将消息发送到正在使用的任何 SLF4J 实现。很可能,Spring 要么告诉它使用 logback,要么它自动检测到它。 至于为什么采用该设置,而不是rootroot 定义了它默认的最低优先级值,并且这些消息具体发送到org.hibernate.SQL,它有更高的优先级设置。

以上是关于当配置 org.hibernate.SQL 记录器时,Logback 显示带有根级别 INFO 的 DEBUG 输出的主要内容,如果未能解决你的问题,请参考以下文章

如何计算 Hibernate 在一个 Grails 请求中执行了多少 SQL 查询?

怎样把hibernate产生的SQL语句,输出到log4j文件

如何将Hibernate生成的SQL语句打印到日志文件

如何让hibernate显示执行sql的参数

Log4j配置详解

如何设置hibernate打印sql语句