【问题标题】:slf4j in library seems to ignore my log4j2 configuration库中的 slf4j 似乎忽略了我的 log4j2 配置
【发布时间】:2017-09-22 12:44:40
【问题描述】:

我们在 java-ee 应用程序中使用 Log4j2。我们使用一个库,其中的日志记录是针对 SLF4J 编程的。在这个库中有一个类,它记录了很多我不想要的东西 -> 所以我想将此 Logger 的 LogLevel 设置为 OFF。

我的 log4j2.xml 看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="trace" shutdownHook="disable">
    <Appenders>
        <Console name="ConsoleAppender" target="SYSTEM_OUT" ignoreExceptions="false" >
            <PatternLayout pattern="%d{ISO8601} %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
        <JDBC name="DatabaseAppender" tableName="logentry" ignoreExceptions="false" >
            <ConnectionFactory class="xx.xx.xx.xx.LoggingConnectionFactory" method="getDatabaseConnection" />
            <Column name="eventDate" isEventTimestamp="true" />
            <Column name="level" pattern="%level" isUnicode="false"/>
            <Column name="logger" pattern="%logger" isUnicode="false"/>
            <Column name="message" pattern="%message" isUnicode="false"/>
            <Column name="exception" pattern="%throwable{50}" isUnicode="false"/>
        </JDBC>
    </Appenders>
    <Loggers>
        <Logger name="net.rubyeye.xmemcached.transcoders.BaseSerializingTranscoder" level="off" additivity="false">
            <AppenderRef ref="ConsoleAppender"/>
        </Logger>
        <Root level="INFO">
            <AppenderRef ref="DatabaseAppender"/>
            <AppenderRef ref="ConsoleAppender"/>
        </Root>
    </Loggers>
</Configuration>

BaseSerializingTranscoder 仍然会记录错误。 如果我做一个简单的测试并将在 BaseSerializingTranscoder 中找到的日志代码放到一个测试函数中,我会看到通过 org.slf4j.Logger.LoggerFactory 检索的记录器(由库完成的操作)与我检索的配置不同org.apache.logging.log4j.LogManager 上的记录器(我的配置已正确应用):

import net.rubyeye.xmemcached.transcoders.BaseSerializingTranscoder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.slf4j.LoggerFactory;

org.slf4j.Logger logger1 = LoggerFactory.getLogger(BaseSerializingTranscoder.class);
logger1.error("log test the same way as in library");

Logger logger2 = LogManager.getLogger(BaseSerializingTranscoder.class);
logger2.error("log test");

logger1 的输出是可见的,我想消除它。怎么了?

编辑
我们使用 Wildfly 10.1。我能够创建一个具有完全相同问题的最小示例。

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>test</groupId>
    <artifactId>test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>org.jboss.spec</groupId>
            <artifactId>jboss-javaee-all-7.0</artifactId>
            <version>1.0.1.Final</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.9.1</version>
        </dependency>

    </dependencies>

</project>

log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">

    <Appenders>
        <Console name="consoleAppender" target="SYSTEM_OUT">
            <PatternLayout pattern="%d %p %c [%t] %m%n" />
        </Console>
    </Appenders>

    <Loggers>
        <Logger name="blah" level="off" additivity="false">
            <AppenderRef ref="consoleAppender" />
        </Logger>
        <Root level="info">
            <AppenderRef ref="consoleAppender" />
        </Root>
    </Loggers>
</Configuration>

Service.java:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;

@Singleton
@Startup
public class Service {

    private static final Logger loggerBlah = LoggerFactory.getLogger("blah");

    private static final Logger logger = LoggerFactory.getLogger(Service.class);

    @PostConstruct
    private void startup() {
        logger.info("test1");
        logger.error("test2");
        loggerBlah.info("test3");
        loggerBlah.error("test4");
    }
}

输出:

21:13:11,641 INFO  [Service] (ServerService Thread Pool -- 40) test1
21:13:11,641 ERROR [Service] (ServerService Thread Pool -- 40) test2
21:13:11,641 INFO  [blah] (ServerService Thread Pool -- 40) test3
21:13:11,641 ERROR [blah] (ServerService Thread Pool -- 40) test4

test3 和 test4 不应该被记录! 怎么了?

【问题讨论】:

  • 您使用的是哪个版本的 servlet API?
  • 我认为您现在可以做的最好的事情是创建一个简单的 Web 应用程序(从无到有,构建一个新应用程序)并尝试重新创建您的问题。如果您可以重新创建它,您将知道问题出在哪里。我没有你的环境的所有细节或你如何构建和运行代码的细节。通常在 stackoverflow 上,我们要求问题作者提供Minimal, Complete, and Verifiable Example,所以我认为这就是您现在需要解决的问题。
  • 我用 EJB 做了一个最小的例子,并将它部署到 Wildfly 10.1。 -> 正是我的问题。我更新了显示此示例中所有文件的问题。这里我提供下载:pubstore.webhop.org/misc/issues/java/logging1.zip
  • 您是否注意到您的输出模式与您在 log4j2.xml 中指定的模式不匹配?我敢打赌 Wildfly 有一个默认的日志记录实现,您需要先禁用它,然后您的应用程序配置会处理日志。事实上,当我搜索此内容时,我会找到 this answer,虽然它适用于 Wildfly 9,但它可能仍适用于版本 10。

标签: jakarta-ee slf4j log4j2


【解决方案1】:

更新 #2:

在您更新后,我能够复制问题。根据我的最新评论,我可以使用 this answer 来指导我解决问题。

我在 web 项目的 META-INF 中添加了以下 jboss-deployment-structure.xml:

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
    <deployment>
        <exclusions>
            <module name="org.apache.log4j" />
        </exclusions>
        <exclude-subsystems>
            <subsystem name="logging"/>
        </exclude-subsystems>
    </deployment>
</jboss-deployment-structure>

我还稍微修改了 log4j2.xml,以便毫无疑问地确定正在使用此文件指定的配置。我更改了PatternLayout 以添加字符串“MY_PATTERN”作为每条消息的前缀:

&lt;PatternLayout pattern="MY_PATTERN %d %p %c [%t] %m%n" /&gt;

输出:

09:30:38,074 INFO  [stdout] (ServerService Thread Pool -- 137) MY_PATTERN 2017-09-24 09:30:38,073 INFO example.Service [ServerService Thread Pool -- 137] test1
09:30:38,077 INFO  [stdout] (ServerService Thread Pool -- 137) MY_PATTERN 2017-09-24 09:30:38,077 ERROR example.Service [ServerService Thread Pool -- 137] test2

消息 test3 和 test4 不再记录到控制台。


以前的回答和更新:

我怀疑您的问题与您的类路径配置方式有关。我强烈建议您检查您的依赖层次结构,以确保您拥有所需的所有正确日志库。

这里是一个使用 SLF4J 和 log4j2 的 OFF 级别的简单示例:

package blah;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class Main {

    private static final Logger log = LoggerFactory.getLogger(Main.class);

    public static void main(String[] args) {

        log.trace("trace log");
        log.debug("debug log");
        log.info("info log");
        log.warn("warn log");
        log.error("error log");
    }

}

这里是 log4j2.xml 配置:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">

    <Appenders>
        <Console name="consoleAppender" target="SYSTEM_OUT">
            <PatternLayout pattern="%d %p %c [%t] %m%n" />
        </Console>
    </Appenders>

    <Loggers>
        <Logger name="blah" level="off" additivity="false">
            <AppenderRef ref="consoleAppender" />
        </Logger>
        <Root level="info">
            <AppenderRef ref="consoleAppender" />
        </Root>
    </Loggers>
</Configuration>

以下是依赖项:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.9.1</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.9.1</version>
</dependency>

当我将“blah”记录器的级别设置为关闭时,我在控制台上根本看不到任何日志。当我将其更改为类似跟踪的内容时,我会看到所有日志。

更新:

我能够使用 servlet API 3.1.0 组合一个简单的 Web 应用程序,并使用上面示例中提到的依赖项使日志记录正常工作(我可以将级别设置为 OFF 并且看不到 ERROR 级别消息)。所以这肯定是某种配置问题。仅供参考,我将我的简单应用程序部署到 Tomcat 8。

【讨论】:

  • 我调整了我的pom.xml 文件;但是,行为仍然相同。只是为了正确理解您:您在 log4j2.xml 中定义的 blah 记录器也会影响您的 LoggerFactory.getLogger(Main.class) 记录器的行为,只是因为它位于包 blah 中?
  • 您能否更新您的问题以提供有关您的 POM 文件的更多详细信息 - 任何与 log4j 或 slf4j 相关的内容都会有所帮助。关于配置,是的,通过该调用获得的记录器是 blah 记录器,因为记录器是分层的 - 它没有找到 blah.Main 所以它寻找 blah。如果它没有找到 blah,它将使用 root。
  • 非常感谢,D.B.为您提供惊人的帮助!
猜你喜欢
  • 2020-07-08
  • 1970-01-01
  • 1970-01-01
  • 2015-10-11
  • 2013-09-12
  • 2020-03-29
  • 1970-01-01
  • 2016-11-11
  • 1970-01-01
相关资源
最近更新 更多