【问题标题】:Defining parent or super-logger name with logback使用 logback 定义父或超级记录器名称
【发布时间】:2018-06-07 09:00:31
【问题描述】:

我正在开发一个包含许多子模块的大型项目。在调试组件 xyz 时,该组件通常会访问其他模块中的服务。要记录每条调试消息,我们必须在 logback.xml 中定义许多记录器。

是否可以定义总体超级记录器或父记录器?

示例: 而不是这样写:

<logger name="com.a.b.c.xyz" level="debug" />
<logger name="com.a.b.d.core.xyz" level="debug" />
<logger name="com.a.b.e.xyz" level="debug" />
<logger name="com.a.b.e.f.xyz" level="debug" />
<logger name="com.a.b.t.services.xyz" level="debug" />

可以这样定义:

<logger name="xyz-super" level="debug">
    <child-logger name="..." />
    <child-logger name="..." />
    ...
</logger>

一旦调试模块 xyz 完成,每个人都会忘记与它相关的包,因此保留这些父记录器将有助于解决未来的问题。

【问题讨论】:

    标签: debugging logging logback slf4j


    【解决方案1】:

    如果我理解你的要求,你有一个跨 Java 包的“组件”的概念,并且你想根据它所在的组件来设置日志记录级别,而不一定是在哪个组件上将其打包。我看到了一些可以采取的方法。

    1. 虽然记录器名称的标准基于类名(以及该类所在的 Java 包),但您不需要将其用于记录器名称。也就是说,您可能有一个不同于您的包层次结构的记录器层次结构。在您的 com.a.b.c.xyz 课程中,您可以获得一个记录器:

      final Logger logger = LoggerFactory.getLogger("com.a.b.xyz.c");
      

      在您的com.a.b.d.core.xyz 课程中,获取一个记录器:

      final Logger logger = LoggerFactory.getLogger("com.a.b.xyz.d.core");
      

      然后您就可以使用普通的记录器级别定义,为com.a.b.xyz 设置记录级别以获取该组件下的所有记录器。这有点不合常规,可能会让刚接触您项目的开发人员感到困惑,但如果您真的希望日志层次结构和包层次结构有所不同,那么您可以这样做。

    2. 另一种方法是保持日志名称层次结构不变,但使用 SLF4J/Logback 的 Marker 机制为每个组件“标记”每个日志消息。

      final Logger logger = LoggerFactory.getLogger(getClass());
      final Marker xyzComponent = MarkerFactory.getMarker("XYZ");
      …
      logger.info(xyzComponent, "A log message");
      

      然后您可以根据您正在寻找的标记在 Logback 中设置Filters。它确实要求您保持一致并确保您关心的每条消息都使用适当的标记进行标记,但它最接近 SLF4J 架构所具有的“超级记录器”或“组记录器”。 Marker 机制非常强大,只要您的消息上有正确的 Marker 并且您将日志配置设置为仅使用正确的过滤器过滤消息,您就可以使用它来做任何事情。

    3. 我能想到的另一种方法是基本上继续做你现在正在做的事情,并在调试级别指定许多单独的记录器,但是在单独的文件中为每个组件设置这个“调试”日志记录配置设置。然后,当您需要调试组件时,您只需在主日志记录设置中添加(或取消注释?)适当的include element

      在 xyz-debug.xml 文件中:

      <included>
          <logger name="com.a.b.c.xyz" level="debug" />
          <logger name="com.a.b.d.core.xyz" level="debug" />
          <logger name="com.a.b.e.xyz" level="debug" />
          <logger name="com.a.b.e.f.xyz" level="debug" />
          <logger name="com.a.b.t.services.xyz" level="debug" />
      </included>
      

      在 abc-debug.xml 文件中:

      <included>
          <logger name="com.a.b.c.abc" level="debug" />
          <logger name="com.a.b.d.core.abc" level="debug" />
          <logger name="com.a.b.e.abc" level="debug" />
          <logger name="com.a.b.e.f.abc" level="debug" />
          <logger name="com.a.b.t.services.abc" level="debug" />
      </included>
      

      然后在你的主 logback.xml 中:

      <!--<include file="xyz-debug.xml"/>-->
      <!--<include file="abc-debug.xml"/>-->
      

      当您需要调试该组件时,您只需取消注释相应的行。也许有点繁琐和简单化,如果当 xyz 组件是新包的一部分时有人忘记更新 xyz-debug.xml 可能会让人感到困惑,但我可以想象这对于某些团队来说已经足够好了。它也不需要任何代码更改,这可能是一个加分项。

    Logback 和 SLF4J 具有很多的功能和可能性,这(像往常一样)既是优势也是劣势,因为可能需要一段时间才能了解它们可以做的所有事情。但通常人们可以找到一种方法让他们按照自己想要的方式工作,有时人们可以找到一种比自己想象的更好的方法。

    【讨论】:

    • 选项 2 看起来很有希望,我会看看,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2013-06-15
    • 2018-07-17
    • 1970-01-01
    • 2015-11-20
    • 2015-08-13
    • 2013-06-11
    • 2013-06-03
    • 2018-02-13
    相关资源
    最近更新 更多