使用 logback 定义父或超级记录器名称

Defining parent or super-logger name with logback

我正在处理一个包含许多子模块的大项目。在调试组件 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 完成,每个人都会忘记哪些包与其相关,因此保留这些父记录器将有助于解决未来的问题。

如果我理解你的要求,你有一个跨 Java 包的 "component" 的概念,并且你想根据哪个组件来处理设置日志记录级别它在,但不一定在哪个包中。我看到了一些可以采取的方法。

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

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

    在您的 com.a.b.d.core.xyz class 中获取记录器:

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

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

  2. 另一种方法是保留日志名称层次结构不变,但使用 SLF4J/Logback 的 Marker 机制来 "mark" 每个组件的每个日志消息。

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

    然后您可以根据您要查找的标记在 Logback 中设置 Filters。它确实要求您保持一致并确保您关心的每条消息都标记有适当的标记,但它是 SLF4J 架构所具有的最接近 "super logger" 或 "group logger" 的东西。 Marker 机制非常强大,您可以用它做任何事情,只要您的消息上有正确的 Marker 并且您设置日志记录配置以仅使用正确的过滤器过滤消息。

  3. 我能想到的另一种方法是基本上继续做你现在正在做的事情,并在调试级别指定很多单独的记录器,但是有这个 "debug" 日志记录每个组件在单独文件中的配置设置。然后,当您需要调试组件时,您只需在主日志设置中添加(或取消注释?)适当的 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 有 很多 的力量和可能性,这(像往常一样)既是优势也是劣势,因为它可能需要一段时间才能了解他们所了解的一切可以做。但通常人们可以找到一种方法让它们按照自己想要的方式工作,有时甚至可以找到一种比自己想象的更好的方法。