通配符的Logback日志记录器名称

15

可以使用通配符来匹配不同的日志包名,这样我们就不需要逐个指定它们了吗?因此,我们可以写成

<logger name="com.package1.web" level="debug"   
<logger name="com.package2.web" level="debug"  
<logger name="com.package3.web" level="debug"  

我希望只指定一个条目,类似于这样:

<logger name="com.*.web" level="debug"  

如果有人知道一种方法,或者只是知道这不可能实现,那我将非常感激。

2个回答

23

TL;DR

Logback不支持在日志记录器名称的中间级别使用通配符。

详细信息

Logback(隐式地)支持在日志记录器名称的末尾使用通配符,因此<logger name="com.package1.web" ...>实际上表示:

  • com.package1.web中的类其所有子包中的类

Logback通过创建日志记录器层次结构来实现这一点。 对于com.package1.web的日志记录器是由com.package1的日志记录器作为父级,而它又是由com的日志记录器作为父级,最后是由ROOT日志记录器作为父级。

因此,如果您声明<logger name="com.package1.web" level="debug">,然后尝试为com.package1.web.foo.bar上的日志记录器发出调试日志消息,Logback将沿着该记录器的层次结构向上走,直到找到已启用DEBUG级别的记录器,它会在com.package1.web处找到并因此发出DEBUG日志事件。

但是,Logback不会基于日志记录器名称中间级别的通配符创建层次结构。 因此,这个...

<logger name="com.*.web" level="debug">

...不会导致Logback创建以下日志记录器:

  • com.package1.web
  • com.package2.web
  • com.package3.web

当通配符在记录器名称的中间层出现时,Logback的层次结构行为将不会被应用。

可能的解决方案

此层次结构行为的一个好处是,它允许您将记录器配置应用于一个包及其下面所有的类,即基于它们的父类关系创建一个 关联 的记录器实例。您可以通过提供显式记录器名称而不是将其默认为当前类名来创建此关联。

例如:

<logger name="DEBUG_LOGGER" level="debug">

然后,无论在何处使用调试记录器,只需像这样创建一个Logger实例:

private final Logger logger = LoggerFactory.getLogger("DEBUG_LOGGER");

显然,这种方法也有缺点。我只是提出它来展示除了完全限定类名之外,还有另一种方式可以将记录器实例关联起来并对其应用级别。


12

你可以使用appender中的过滤器来实现。基本上,你需要为com.*设置一个DEBUG级别的记录器,并应用一个过滤器,该过滤器拒绝不是com.*.web的所有DEBUG(或更低级别)事件。

我承认这很复杂。

从性能方面来看,它也很差:对于所有com.*事件都会创建DEBUG事件,只有在appender处才被丢弃或保留。

无论如何,以下是示例logback.xml文件:

<configuration scan="true" debug="true">
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
            <evaluator class="ch.qos.logback.classic.boolex.GEventEvaluator">
                <expression>
                    !(e.loggerName ==~ "com\\..*\\.web") &amp;&amp;
                    DEBUG.toInt() >= e.level.toInt()
                </expression>
            </evaluator>
            <OnMismatch>NEUTRAL</OnMismatch>
            <OnMatch>DENY</OnMatch>
        </filter>
        <encoder>
            <pattern>%p [%d{HH:mm:ss,SSS}] %c - %m\n</pattern>
        </encoder>
    </appender>

    <logger name="com" level="DEBUG" />

    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>

测试代码:

public void test() throws Exception{
    getLogger("com.package1.web").debug("some debug onto com.package1.web");
    getLogger("com.package2.web").debug("some debug onto com.package2.web");
    getLogger("com.package3.web").debug("some debug onto com.package3.web");
    getLogger("com.package1.web").info("some info onto com.package1.web");
    getLogger("com.package2.web").info("some info onto com.package2.web");
    getLogger("com.package3.web").info("some info onto com.package3.web");
    getLogger("com.package3.notweb").debug("some debug onto com.package3.notweb");
    getLogger("com.package3.notweb").info("some info onto com.package3.notweb");
}

public Logger getLogger(String loggerName) {
    return LoggerFactory.getLogger(loggerName);
}

结果:

DEBUG [12:30:46] com.package1.web - some debug onto com.package1.web
DEBUG [12:30:46] com.package2.web - some debug onto com.package2.web
DEBUG [12:30:46] com.package3.web - some debug onto com.package3.web
INFO [12:30:46] com.package1.web - some info onto com.package1.web
INFO [12:30:46] com.package2.web - some info onto com.package2.web
INFO [12:30:46] com.package3.web - some info onto com.package3.web
INFO [12:30:46] com.package3.notweb - some info onto com.package3.notweb

你可以看到,DEBUG日志只被写入com.*.web


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接