【问题标题】:Initialize slf4j with log4j2.xml用 log4j2.xml 初始化 slf4j
【发布时间】:2018-09-12 16:48:35
【问题描述】:

我想在 log4j 上使用 slf4j。我在 pom.xml 中添加了以下依赖项(我对 slf4j 使用 1.7.25,对 log4j2 使用 2.10.0):

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
    </dependency>


    <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-slf4j-impl</artifactId>
       <version>${log4j.version}</version>
    </dependency>

    <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-api</artifactId>
       <version>${log4j.version}</version>
    </dependency>

    <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-core</artifactId>
       <version>${log4j.version}</version>
    </dependency>
</dependencies> 

一切都构建得很好,没有编译错误或缺少依赖项,但我未能在我的类中指定负责初始化 Logger 的配置 (log4j2.xml) 文件。在这种情况下,它总是打印相同的警告

log4j:WARN No appenders could be found for logger (com.mypackage.etc).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

我搜索了提供配置文件的正确方法,结果如下:

LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
File file = new File("path/to/a/different/log4j2.xml");
context.setConfigLocation(file.toURI());

问题是,在我的情况下,LogManager.getContext(false) 将始终返回 Slf4JLoggerContext 的实例(考虑到我使用 slf4j 作为记录器的外观)并且初始化将失败并出现 ClassCastException。我试图存储 Slf4JLoggerContext 的实例,但它没有为上下文提供设置器。我也找不到从 log4j 中检索 LoggerContext 的方法。

有什么方法可以将配置文件(log4j2.xml)提供给 slf4j 以查看所有的 appender 和 loggers?

更新 考虑这是我的配置文件(我替换了原始包和附加程序名称):

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Properties>
        <Property name="def.files.backup.count">10</Property>
        <Property name="log.file.path">${oo.home}/var/logs</Property>
        <Property name="def.file.max.size">10MB</Property>
        <Property name="log.level">WARN</Property>
    </Properties>

    <ThresholdFilter/>

    <Appenders>
        <RollingFile name="Appender1" fileName="${log.file.path}/file1.log" maxFileSize="${def.file.max.size}"
                     maxBackupIndex="${def.files.backup.count}">
            <PatternLayout>org.apache.log4j.PatternLayout</PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="10MB"/>
            </Policies>
        </RollingFile>

        <RollingFile name="Appender2" fileName="${log.file.path}/file2.log"
                     maxFileSize="${def.file.max.size}"
                     maxBackupIndex="${def.files.backup.count}">
            <PatternLayout>org.apache.log4j.PatternLayout</PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="10MB"/>
            </Policies>
        </RollingFile>

        <RollingFile name="Appender3" fileName="${log.file.path}/file3.log"
                     maxFileSize="${def.file.max.size}"
                     maxBackupIndex="${def.files.backup.count}">
            <PatternLayout>org.apache.log4j.PatternLayout</PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="10MB"/>
            </Policies>
        </RollingFile>

    </Appenders>

    <Loggers>
        <AsyncLogger name="com.package1.oo" level="${log.level}" additivity="false">
            <AppenderRef ref="Appender1"/>
        </AsyncLogger>

        <AsyncLogger name="io.package2" level="${log.level}" additivity="false">
            <AppenderRef ref="Appender2"/>
        </AsyncLogger>

        <AsyncLogger name="com.package3.package3" level="${log.level}" additivity="false">
            <AppenderRef ref="Appender3"/>
        </AsyncLogger>

        <AsyncLogger name="org.package4" level="${log.level}">

        </AsyncLogger>

        <AsyncLogger name="com.package5.Class1" level="${log.level}">

        </AsyncLogger>

        <AsyncRoot level="${log.level}">
            <AppenderRef ref="Appender1"/>
            <AppenderRef ref="Appender2"/>
            <AppenderRef ref="Appender3"/>

        </AsyncRoot>
    </Loggers>

</Configuration>

【问题讨论】:

    标签: java log4j2 slf4j


    【解决方案1】:

    我已经测试过这个配置。 log4j2 文件必须在您的类路径中。

    Maven

    <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
        </dependency>
    

    log4j2.xml

    此外,添加 xsd 可以帮助您创建配置。我为 spring 框架添加了 Logger。请注意,需要 jcl-over-slf4j 才能使用 Spring 的内部日志记录

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="error"
                   xmlns="http://logging.apache.org/log4j/2.0/config"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://logging.apache.org/log4j/2.0/config
                    https://raw.githubusercontent.com/apache/logging-log4j2/master/log4j-core/src/main/resources/Log4j-config.xsd">
        <Appenders>
            <Console name="Console" target="SYSTEM_OUT">
                <PatternLayout pattern="%highlight{%d{HH:mm:ss.SSS} [%t] %-5level %logger{36}} - %msg%n"/>
            </Console>
        </Appenders>
        <Loggers>
            <Root level="debug">
                <AppenderRef ref="Console"/>
            </Root>
            <Logger name="org.springframework" level="error">
                <AppenderRef ref="Console"/>
            </Logger>
        </Loggers>
    </Configuration>
    

    【讨论】:

      【解决方案2】:

      从您的问题来看,您似乎没有尝试指定 custom 配置位置!请参阅Automatic Configuration 部分in the docs

      Log4j 能够在运行期间自动配置自身 初始化。当 Log4j 启​​动时,它将找到所有 ConfigurationFactory 插件并按加权顺序排列它们 从最高到最低。交付时,Log4j 包含四个 ConfigurationFactory 实现:一种用于 JSON,一种用于 YAML,一种用于 一个用于属性,一个用于 XML。

      Log4j 将检查“log4j.configurationFile”系统属性,并且, 如果设置,将尝试使用 与文件扩展名匹配的 ConfigurationFactory。

      • 如果未设置系统属性,则 ConfigurationFactory 将在类路径中查找 log4j2-test.properties。

      • 如果未找到此类文件,YAML ConfigurationFactory 将在类路径中查找 log4j2-test.yaml 或 log4j2-test.yml。

      • 如果未找到此类文件,JSON ConfigurationFactory 将在类路径中查找 log4j2-test.json 或 log4j2-test.jsn。

      • 如果没有找到这样的文件,XML ConfigurationFactory 将寻找 类路径中的 log4j2-test.xml。

      • 如果找不到测试文件,属性 ConfigurationFactory 将在类路径中查找 log4j2.properties。

      • 如果找不到属性文件,YAML ConfigurationFactory 将在 类路径。

      • 如果找不到 YAML 文件,JSON ConfigurationFactory 将在类路径中查找 log4j2.json 或 log4j2.jsn。

      • 如果找不到 JSON 文件,XML ConfigurationFactory 将尝试在类路径中找到 log4j2.xml。

      • 如果找不到配置文件,将使用 DefaultConfiguration。这将导致日志输出转到控制台。

      你可能在这里想多了。

      您可以通过将其放在src/main/resources 文件夹中或在命令行中使用-cp/-classpath 指定它来将其放在“类路径上”。

      【讨论】:

      • 我已经提供了名为“log4j.configurationFile”的参数,其值表示我的 log4j2.xml 文件的路径。我认为问题在于我使用 slf4j 作为门面这一事实。它也知道搜索那个参数吗?在我提供的示例中,它可能会在 ClassCastException 之后破坏记录器,但我尝试了另一种方法,记录器也无法设置上下文,因为它期望 LoggerContext 来自 log4j 而不是 Slf4JLoggerContext,但它不会抛出异常(它只是简单地返回null,并且没有NullPointerExc)。
      • 只要你已经在你的部门(你有)中包含了桥,slf4j 的东西应该通过 log4j2 记录下来。你是如何传递论点的?当您尝试我在底部提到的默认类路径位置时发生了什么?
      • 我在命令行 -Dlog4j.configuration=fullPathToMyFile 传递了参数。该文件放置在类路径(src/main/resources)上。我不创建日志文件。相反,它在几乎任何操作后都会在我的包装器中记录一个警告。警告与帖子中的警告完全相同(找不到记录器的附加程序)。
      • 我的意思是,你在那里基本上做对了。你的log4j xml config 是什么样的?
      • 用 org.slf4j 中的 log4j-over-slf4j 替换当前网桥 (log4j-slf4j-impl) 怎么样?
      猜你喜欢
      • 2015-06-30
      • 2016-08-21
      • 2014-11-08
      • 1970-01-01
      • 1970-01-01
      • 2021-02-18
      • 2012-04-17
      • 2019-05-11
      • 1970-01-01
      相关资源
      最近更新 更多