排查log4j不输出日志到文件的问题

问题描述

项目使用Spring Boot框架,在pom文件中添加了如下配置:

<span style="color:#444444"><span style="background-color:#f6f6f6"><<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>org.slf4j</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>slf4j-api</<span style="color:#333333"><strong>artifactId</strong></span>>
    <<span style="color:#333333"><strong>version</strong></span>>1.7.36</<span style="color:#333333"><strong>version</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>>
<<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>org.slf4j</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>slf4j-simple</<span style="color:#333333"><strong>artifactId</strong></span>>
    <<span style="color:#333333"><strong>version</strong></span>>1.7.30</<span style="color:#333333"><strong>version</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>>
<<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>org.springframework.boot</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>spring-boot-starter-log4j2</<span style="color:#333333"><strong>artifactId</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>></span></span>

使用 SLF4J 的API进行日志输出,并且也明确配置了log4j2写日志文件。

<span style="color:#444444"><span style="background-color:#f6f6f6"><span style="color:#333333"><strong>import</strong></span> org.slf4j.Logger;
<span style="color:#333333"><strong>import</strong></span> org.slf4j.LoggerFactory;

<span style="color:#333333"><strong>private</strong></span> <span style="color:#880000">Logger</span> log = <span style="color:#880000">LoggerFactory</span>.getLogger(<span style="color:#880000">TestController</span>.<span style="color:#333333"><strong>class</strong></span>);</span></span>

但是在项目代码中输出的日志信息始终不输出到文件中,只在控制台输出。

一开始我以为是log4j的配置问题:只输出到控制台,不输出到文件,但是反复确认配置没问题。

解决步骤

由于这是一个新介入的老项目,一开始并没有从"配置依赖可能有问题"这个角度去考虑,另外一点就是项目的启动日志太多了,在启动的时候很快就产生许多信息,把关键的的错误信息错过了。

后来经过反复查看启动日志才发现,原来是因为项目中同时添加了 配置,项目启动时默认加载它作为日志实现。因此,log4j2的配置就不生效了。slf4j-simple

<span style="color:#444444"><span style="background-color:#f6f6f6"><span style="color:#880000">SLF4J:</span> Class path contains multiple SLF4J bindings.
<span style="color:#880000">SLF4J:</span> Found binding <span style="color:#333333"><strong>in</strong></span> [<span style="color:#880000">jar:</span><span style="color:#880000">file:</span><span style="color:#bc6060">/D:/</span>.m2<span style="color:#bc6060">/repository/</span>org<span style="color:#bc6060">/slf4j/</span>slf4j-simple<span style="color:#bc6060">/1.7.30/</span>slf4j-simple<span style="color:#880000">-1.7</span><span style="color:#880000">.30</span>.jar!<span style="color:#bc6060">/org/</span>slf4j<span style="color:#bc6060">/impl/</span>StaticLoggerBinder.<span style="color:#333333"><strong>class</strong></span>]
<span style="color:#880000">SLF4J:</span> Found binding <span style="color:#333333"><strong>in</strong></span> [<span style="color:#880000">jar:</span><span style="color:#880000">file:</span><span style="color:#bc6060">/D:/</span>.m2<span style="color:#bc6060">/repository/</span>org<span style="color:#bc6060">/apache/</span>logging<span style="color:#bc6060">/log4j/</span>log4j-slf4j-impl<span style="color:#bc6060">/2.13.3/</span>log4j-slf4j-impl<span style="color:#880000">-2.13</span><span style="color:#880000">.3</span>.jar!<span style="color:#bc6060">/org/</span>slf4j<span style="color:#bc6060">/impl/</span>StaticLoggerBinder.<span style="color:#333333"><strong>class</strong></span>]
<span style="color:#880000">SLF4J:</span> See <span style="color:#880000">http:</span><span style="color:#888888">//www.slf4j.org/codes.html#multiple_bindings for an explanation.</span>
<span style="color:#880000">SLF4J:</span> Actual binding is of type [org.slf4j.impl.SimpleLoggerFactory]  <span style="color:#888888">// 这里是关键日志,明确了项目启动时加载的日志实现</span>
[restartedMain] INFO org.apache.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler [<span style="color:#880000">"http-nio-8080"</span>]
[restartedMain] INFO org.apache.catalina.core.StandardService - Starting service [Tomcat]
[restartedMain] INFO org.apache.catalina.core.StandardEngine - Starting Servlet <span style="color:#880000">engine:</span> [Apache Tomcat/<span style="color:#880000">9.0</span><span style="color:#880000">.44</span>]
[restartedMain] INFO org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext</span></span>

定位到是因为同时加载了 的缘故,只要去除该依赖即可。slf4j-simple

虽然已经解决了问题,但同时也不禁让我疑惑,难道Slf4j会优先加载 吗?带着这个疑问,继续追踪一下源码。slf4j-simple

原因追踪

追踪 的源码发现,当classpath路径存在 时,是一定会优先加载其中的 类的。slf4j-apislf4j-simpleorg.slf4j.impl.StaticLoggerBinder

也就是说,当 存在classpath下时,总是优先使用它作为 的默认实现;此时,即使同时配置了log4j,也无法使用log4j进行日志输出。slf4j-simpleslf4j-api

详细源码解读如下:

<span style="color:#444444"><span style="background-color:#f6f6f6"><span style="color:#888888">// slf4j-api.jar</span>
<span style="color:#888888">// org.slf4j.LoggerFactory</span>
public <span style="color:#333333"><strong>final</strong></span> <span style="color:#333333"><strong>class</strong></span> <span style="color:#880000"><strong>LoggerFactory</strong></span> {
    private <span style="color:#333333"><strong>static</strong></span> <span style="color:#397300">String</span> STATIC_LOGGER_BINDER_PATH = <span style="color:#880000">"org/slf4j/impl/StaticLoggerBinder.class"</span>;

    <span style="color:#888888">// bind()方法是绑定日志实现的入口</span>
    private <span style="color:#333333"><strong>final</strong></span> <span style="color:#333333"><strong>static</strong></span> <span style="color:#333333"><strong>void</strong></span> bind() {
        <span style="color:#333333"><strong>try</strong></span> {
            <span style="color:#397300">Set</span><URL> staticLoggerBinderPathSet = <span style="color:#333333"><strong>null</strong></span>;
            <span style="color:#888888">// skip check under android, see also</span>
            <span style="color:#888888">// http://jira.qos.ch/browse/SLF4J-328</span>
            <span style="color:#333333"><strong>if</strong></span> (!isAndroid()) {
                staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
                reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
            }
            <span style="color:#888888">// 这一句是最关键的,当classpath路径下存在slf4j-simple时,总是会优先加载slf4j-simple中定义的StaticLoggerBinder</span>
            <span style="color:#888888">// the next line does the binding</span>
            StaticLoggerBinder.getSingleton();
            INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
            reportActualBinding(staticLoggerBinderPathSet);
        } <span style="color:#333333"><strong>catch</strong></span> (NoClassDefFoundError ncde) {
            <span style="color:#888888">// 省略部分代码...</span>
        }
    }

    <span style="color:#888888">// 在findPossibleStaticLoggerBinderPathSet()方法中加载slf4j接口的日志实现类</span>
    <span style="color:#333333"><strong>static</strong></span> <span style="color:#397300">Set</span><URL> findPossibleStaticLoggerBinderPathSet() {
        <span style="color:#888888">// use Set instead of list in order to deal with bug #138</span>
        <span style="color:#888888">// LinkedHashSet appropriate here because it preserves insertion order</span>
        <span style="color:#888888">// during iteration</span>
        <span style="color:#397300">Set</span><URL> staticLoggerBinderPathSet = <span style="color:#333333"><strong>new</strong></span> LinkedHashSet<URL>();
        <span style="color:#333333"><strong>try</strong></span> {
            ClassLoader loggerFactoryClassLoader = LoggerFactory.<span style="color:#333333"><strong>class</strong></span>.getClassLoader();
            Enumeration<URL> paths;
            <span style="color:#888888">// 使用类加载器加载类定义</span>
            <span style="color:#888888">// 有意思的是在slf4j-simple和log4j-slf4j-impl包中都同时存在org.slf4j.impl.StaticLoggerBinder类</span>
            <span style="color:#888888">// 所以当使用路径“org/slf4j/impl/StaticLoggerBinder.class”加载类时,会同时把2个类都加载出来</span>
            <span style="color:#888888">// 但是只会使用slf4j-simple中的StaticLoggerBinder</span>
            <span style="color:#333333"><strong>if</strong></span> (loggerFactoryClassLoader == <span style="color:#333333"><strong>null</strong></span>) {
                paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);
            } <span style="color:#333333"><strong>else</strong></span> {
                paths = loggerFactoryClassLoader.getResources(STATIC_LOGGER_BINDER_PATH);
            }
            <span style="color:#333333"><strong>while</strong></span> (paths.hasMoreElements()) {
                URL path = paths.nextElement();
                staticLoggerBinderPathSet.add(path);
            }
        } <span style="color:#333333"><strong>catch</strong></span> (IOException ioe) {
            Util.report(<span style="color:#880000">"Error getting resources from path"</span>, ioe);
        }
        <span style="color:#333333"><strong>return</strong></span> staticLoggerBinderPathSet;
    }
}</span></span>

另外:当使用logback作为slf4j的日志实现组件时,不再允许依赖其他日志实现组件,即: 不能与 或 共存, logback-classicslf4j-simplelog4j-slf4j-impl

这是因为在加载logback时了做了检查:

<span style="color:#444444"><span style="background-color:#f6f6f6">private LoggerContext getLoggerContext() {
    ILoggerFactory <span style="color:#333333"><strong>factory</strong></span> = StaticLoggerBinder.getSingleton().getLoggerFactory();
    <span style="color:#888888">// 判断加载的日志工厂类是否为logback的LoggerContext,如果不是则抛出异常</span>
    Assert.isInstanceOf(LoggerContext.<span style="color:#333333"><strong>class</strong></span>, <span style="color:#333333"><strong>factory</strong></span>,
            () -> <span style="color:#397300">String</span>.format(
                    <span style="color:#880000">"LoggerFactory is not a Logback LoggerContext but Logback is on "</span>
                            + <span style="color:#880000">"the classpath. Either remove Logback or the competing "</span>
                            + <span style="color:#880000">"implementation (%s loaded from %s). If you are using "</span>
                            + <span style="color:#880000">"WebLogic you will need to add 'org.slf4j' to "</span>
                            + <span style="color:#880000">"prefer-application-packages in WEB-INF/weblogic.xml"</span>,
                    <span style="color:#333333"><strong>factory</strong></span>.getClass(), getLocation(<span style="color:#333333"><strong>factory</strong></span>)));
    <span style="color:#333333"><strong>return</strong></span> (LoggerContext) <span style="color:#333333"><strong>factory</strong></span>;
}</span></span>

如果使用logback作为slf4j的日志实现组件,则只允许添加 和 依赖,此时如果还添加了 或 依赖,则项目无法启动。 slf4j-apilogback-classicslf4j-simplelog4j-slf4j-impl

添加如下配置时启动正常:

<span style="color:#444444"><span style="background-color:#f6f6f6"><span style="color:#888888"><!-- 使用loback作为slf4j的日志实现组件 --></span>
<<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>org.slf4j</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>slf4j-api</<span style="color:#333333"><strong>artifactId</strong></span>>
    <<span style="color:#333333"><strong>version</strong></span>>1.7.36</<span style="color:#333333"><strong>version</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>>
<<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>ch.qos.logback</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>logback-classic</<span style="color:#333333"><strong>artifactId</strong></span>>
    <<span style="color:#333333"><strong>version</strong></span>>1.2.10</<span style="color:#333333"><strong>version</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>></span></span>

同时添加 和 时启动失败: logbacklog4j2

<span style="color:#444444"><span style="background-color:#f6f6f6"><span style="color:#888888"><!-- logback无法与log4j2共存 --></span>
<<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>org.slf4j</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>slf4j-api</<span style="color:#333333"><strong>artifactId</strong></span>>
    <<span style="color:#333333"><strong>version</strong></span>>1.7.36</<span style="color:#333333"><strong>version</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>>
<<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>ch.qos.logback</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>logback-classic</<span style="color:#333333"><strong>artifactId</strong></span>>
    <<span style="color:#333333"><strong>version</strong></span>>1.2.10</<span style="color:#333333"><strong>version</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>>
<<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>org.springframework.boot</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>spring-boot-starter-log4j2</<span style="color:#333333"><strong>artifactId</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>></span></span>

报错信息如下:

<span style="color:#444444"><span style="background-color:#f6f6f6"># “<span style="color:#bc6060">/D:/</span>.m2<span style="color:#bc6060">/repository/</span>org<span style="color:#bc6060">/apache/</span>logging<span style="color:#bc6060">/log4j/</span>log4j-slf4j-impl<span style="color:#bc6060">/2.13.3/</span>log4j-slf4j-impl-<span style="color:#880000">2.13</span>.<span style="color:#880000">3</span>.jar”是本地Maven仓库路径
Caused by: java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the <span style="color:#333333"><strong>classpath</strong></span>. Either remove Logback or the competing implementation (<span style="color:#333333"><strong>class</strong></span> org.apache.logging.slf4j.Log4jLoggerFactory loaded <span style="color:#333333"><strong>from</strong></span> <span style="color:#333333"><strong>file</strong></span>:<span style="color:#bc6060">/D:/</span>.m2<span style="color:#bc6060">/repository/</span>org<span style="color:#bc6060">/apache/</span>logging<span style="color:#bc6060">/log4j/</span>log4j-slf4j-impl<span style="color:#bc6060">/2.13.3/</span>log4j-slf4j-impl-<span style="color:#880000">2.13</span>.<span style="color:#880000">3</span>.jar). <span style="color:#333333"><strong>If</strong></span> you are using WebLogic you will need to add <span style="color:#880000">'org.slf4j'</span> to prefer-application-packages in WEB-INF<span style="color:#bc6060">/weblogic.xml: org.apache.logging.slf4j.Log4jLoggerFactory</span></span></span>

同时添加 和 时启动失败: lobackslf4j-simple

<span style="color:#444444"><span style="background-color:#f6f6f6"><span style="color:#888888"><!-- logback无法与slf4j-simple共存 --></span>
<<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>org.slf4j</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>slf4j-api</<span style="color:#333333"><strong>artifactId</strong></span>>
    <<span style="color:#333333"><strong>version</strong></span>>1.7.36</<span style="color:#333333"><strong>version</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>>
<<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>ch.qos.logback</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>logback-classic</<span style="color:#333333"><strong>artifactId</strong></span>>
    <<span style="color:#333333"><strong>version</strong></span>>1.2.10</<span style="color:#333333"><strong>version</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>>
<<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>org.slf4j</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>slf4j-simple</<span style="color:#333333"><strong>artifactId</strong></span>>
    <<span style="color:#333333"><strong>version</strong></span>>1.7.30</<span style="color:#333333"><strong>version</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>></span></span>

报错信息如下:

<span style="color:#444444"><span style="background-color:#f6f6f6"># “<span style="color:#bc6060">/D:/</span>.m2<span style="color:#bc6060">/repository/</span>org<span style="color:#bc6060">/slf4j/</span>slf4j-simple<span style="color:#bc6060">/1.7.30/</span>slf4j-simple-<span style="color:#880000">1.7</span>.<span style="color:#880000">30</span>.jar”是本地Maven仓库路径
Caused by: java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the <span style="color:#333333"><strong>classpath</strong></span>. Either remove Logback or the competing implementation (<span style="color:#333333"><strong>class</strong></span> org.slf4j.impl.SimpleLoggerFactory loaded <span style="color:#333333"><strong>from</strong></span> <span style="color:#333333"><strong>file</strong></span>:<span style="color:#bc6060">/D:/</span>.m2<span style="color:#bc6060">/repository/</span>org<span style="color:#bc6060">/slf4j/</span>slf4j-simple<span style="color:#bc6060">/1.7.30/</span>slf4j-simple-<span style="color:#880000">1.7</span>.<span style="color:#880000">30</span>.jar). <span style="color:#333333"><strong>If</strong></span> you are using WebLogic you will need to add <span style="color:#880000">'org.slf4j'</span> to prefer-application-packages in WEB-INF<span style="color:#bc6060">/weblogic.xml: org.slf4j.impl.SimpleLoggerFactory</span></span></span>

但是! 和 是可以共存的,但是优先只会使用 作为slf4j的日志实现。 slf4j-simplelog4j-slf4j-implslf4j-simple

如下配置不会导致项目启动失败:

<span style="color:#444444"><span style="background-color:#f6f6f6"><span style="color:#888888"><!-- slf4j-simple可以与log4j-slf4j-impl共存,但是优先使用slf4j-simple --></span>
<<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>org.slf4j</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>slf4j-simple</<span style="color:#333333"><strong>artifactId</strong></span>>
    <<span style="color:#333333"><strong>version</strong></span>>1.7.30</<span style="color:#333333"><strong>version</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>>
<<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>org.springframework.boot</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>spring-boot-starter-log4j2</<span style="color:#333333"><strong>artifactId</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>></span></span>

最后总结

在使用Spring Boot框架时,默认使用的日志实现组件是logback,如果需要使用其他日志实现组件(如:log4j2),需要做2步:

第一,排除默认对 模块的依赖。 spring-boot-starter-logging

<span style="color:#444444"><span style="background-color:#f6f6f6"><<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>org.springframework.boot</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>spring-boot-starter-web</<span style="color:#333333"><strong>artifactId</strong></span>>
    <<span style="color:#333333"><strong>exclusions</strong></span>>
        <<span style="color:#333333"><strong>exclusion</strong></span>>
            <span style="color:#888888"><!-- 排除Spring Boot默认使用的日志依赖 --></span>
            <<span style="color:#333333"><strong>groupId</strong></span>>org.springframework.boot</<span style="color:#333333"><strong>groupId</strong></span>>
            <<span style="color:#333333"><strong>artifactId</strong></span>>spring-boot-starter-logging</<span style="color:#333333"><strong>artifactId</strong></span>>
        </<span style="color:#333333"><strong>exclusion</strong></span>>
    </<span style="color:#333333"><strong>exclusions</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>></span></span>

第二,明确引入对log4j2的依赖配置。

<span style="color:#444444"><span style="background-color:#f6f6f6"><<span style="color:#333333"><strong>dependency</strong></span>>
    <<span style="color:#333333"><strong>groupId</strong></span>>org.springframework.boot</<span style="color:#333333"><strong>groupId</strong></span>>
    <<span style="color:#333333"><strong>artifactId</strong></span>>spring-boot-starter-log4j2</<span style="color:#333333"><strong>artifactId</strong></span>>
</<span style="color:#333333"><strong>dependency</strong></span>></span></span>

同时,需要确定在项目启动的classpath路径下有对应log4j2的配置文件存在,如:classpath:log4j2.xml。

如下是log4j2的简单配置示例。

<span style="color:#444444"><span style="background-color:#f6f6f6"><span style="color:#1f7199"><?</span>xml version=<span style="color:#880000">"1.0"</span> encoding=<span style="color:#880000">"UTF-8"</span><span style="color:#1f7199">?></span>
<<span style="color:#333333"><strong>configuration</strong></span> status=<span style="color:#880000">"warn"</span> debug=<span style="color:#880000">"true"</span> packages=<span style="color:#880000">"qs.config"</span>>
    <<span style="color:#333333"><strong>Properties</strong></span>>
        <span style="color:#888888"><!-- 配置日志文件输出目录 $</span><span style="color:#bc6060">{sys:user.home}</span><span style="color:#888888"> --></span>
        <<span style="color:#333333"><strong>Property</strong></span> name=<span style="color:#880000">"LOG_HOME"</span>>$<span style="color:#bc6060">{sys:user.home}</span>/test-springboot-simple</<span style="color:#333333"><strong>Property</strong></span>>
        <<span style="color:#333333"><strong>property</strong></span> name=<span style="color:#880000">"PATTERN"</span>>%d<span style="color:#bc6060">{MM-dd HH:mm:ss.SSS}</span> [%t-%L] %-5level %logger<span style="color:#bc6060">{36}</span> - %msg%n</<span style="color:#333333"><strong>property</strong></span>>
    </<span style="color:#333333"><strong>Properties</strong></span>>

    <<span style="color:#333333"><strong>appenders</strong></span>>
        <<span style="color:#333333"><strong>Console</strong></span> name=<span style="color:#880000">"Console"</span> target=<span style="color:#880000">"SYSTEM_OUT"</span>>
            <<span style="color:#333333"><strong>ThresholdFilter</strong></span> level=<span style="color:#880000">"DEBUG"</span> onMatch=<span style="color:#880000">"ACCEPT"</span> onMismatch=<span style="color:#880000">"DENY"</span>/>
            <<span style="color:#333333"><strong>PatternLayout</strong></span> pattern=<span style="color:#880000">"[%d</span><span style="color:#bc6060">{HH:mm:ss.SSS}</span><span style="color:#880000">] %-5level %class</span><span style="color:#bc6060">{36}</span><span style="color:#880000"> %L %M - %msg%xEx%n"</span>/>
        </<span style="color:#333333"><strong>Console</strong></span>>

        <<span style="color:#333333"><strong>RollingFile</strong></span> name=<span style="color:#880000">"RollingFileInfo"</span> fileName=<span style="color:#880000">"$</span><span style="color:#bc6060">{LOG_HOME}</span><span style="color:#880000">/info.log"</span> filePattern=<span style="color:#880000">"$</span><span style="color:#bc6060">{LOG_HOME}</span><span style="color:#880000">/$$</span><span style="color:#bc6060">{date:yyyy-MM}</span><span style="color:#880000">/info-%d</span><span style="color:#bc6060">{yyyy-MM-dd}</span><span style="color:#880000">-%i.log"</span>>
            <<span style="color:#333333"><strong>ThresholdFilter</strong></span> level=<span style="color:#880000">"info"</span> onMatch=<span style="color:#880000">"ACCEPT"</span> onMismatch=<span style="color:#880000">"DENY"</span>/>
            <<span style="color:#333333"><strong>PatternLayout</strong></span> pattern=<span style="color:#880000">"%d</span><span style="color:#bc6060">{yyyy-MM-dd HH:mm:ss.SSS}</span><span style="color:#880000"> [%t] %-5level %logger</span><span style="color:#bc6060">{36}</span><span style="color:#880000"> - %msg%n"</span>/>
            <<span style="color:#333333"><strong>Policies</strong></span>>
                <<span style="color:#333333"><strong>TimeBasedTriggeringPolicy</strong></span> interval=<span style="color:#880000">"1"</span> modulate=<span style="color:#880000">"true"</span>/>
                <<span style="color:#333333"><strong>SizeBasedTriggeringPolicy</strong></span> size=<span style="color:#880000">"100MB"</span>/>
            </<span style="color:#333333"><strong>Policies</strong></span>>
        </<span style="color:#333333"><strong>RollingFile</strong></span>>
    </<span style="color:#333333"><strong>appenders</strong></span>>

    <<span style="color:#333333"><strong>loggers</strong></span>>
        <<span style="color:#333333"><strong>root</strong></span> level=<span style="color:#880000">"info"</span>>
            <<span style="color:#333333"><strong>appender-ref</strong></span> ref=<span style="color:#880000">"RollingFileInfo"</span>/>
            <<span style="color:#333333"><strong>appender-ref</strong></span> ref=<span style="color:#880000">"Console"</span>/>
        </<span style="color:#333333"><strong>root</strong></span>>
    </<span style="color:#333333"><strong>loggers</strong></span>>
</<span style="color:#333333"><strong>configuration</strong></span>></span></span>
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 以下是一个简单的log4j的XML配置文件例子: ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> <param name="Target" value="System.out"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/> </layout> </appender> <appender name="FILE" class="org.apache.log4j.RollingFileAppender"> <param name="File" value="logs/mylog.log"/> <param name="Append" value="true"/> <param name="MaxFileSize" value="10MB"/> <param name="MaxBackupIndex" value="10"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/> </layout> </appender> <logger name="com.mycompany"> <level value="INFO"/> <appender-ref ref="FILE"/> </logger> <root> <level value="ERROR"/> <appender-ref ref="CONSOLE"/> </root> </log4j:configuration> ``` 在这个例子中,我们定义了两个appender:CONSOLE和FILE。CONSOLE是一个ConsoleAppender,将日志输出到控制台上;FILE是一个RollingFileAppender,将日志输出到logs/mylog.log文件中。我们还定义了两个logger:com.mycompany和root。com.mycompany的日志级别设置为INFO,将日志输出到FILE中;root的日志级别设置为ERROR,将日志输出到CONSOLE中。 这个配置文件使用了log4j.dtd,用于指定DTD及其命名空间。DTD是一种XML文档类型定义,它定义了XML文档中允许出现的元素、属性和实体,以及它们之间的关系。 ### 回答2: log4j的XML配置文件是用于配置log4j日志框架的关键文件之一。通过该文件,我们可以定义日志输出格式、输出级别、输出目标等。 XML配置文件中的关键元素包括: 1. `<log4j:configuration>`:配置文件的根元素,表示一个log4j的配置文件。 2. `<appender>`:定义将日志信息发送到哪个目标,比如文件、控制台等。可以配置多个appender。 3. `<layout>`:定义日志输出格式,如时间、日志级别、类名、消息等。常用的layout有`PatternLayout`和`SimpleLayout`。 4. `<root>`:定义根Logger的输出级别和appender。根Logger是所有Logger的父Logger,可以定义全局的输出级别和appender。 5. `<logger>`:定义特定包或类的Logger的输出级别和appender。 在XML配置文件中,我们可以通过配置不同元素的属性来实现对日志的灵活配置。比如可以通过设置`threshold`属性来指定输出级别,通过设置`file`属性来指定日志输出文件等。 一个简单的log4j的XML配置文件示例如下: ```xml <?xml version="1.0" encoding="UTF-8"?> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" /> </layout> </appender> <root> <priority value="DEBUG" /> <appender-ref ref="CONSOLE" /> </root> </log4j:configuration> ``` 以上配置定义了一个名为`CONSOLE`的appender,将日志输出到控制台,并使用`PatternLayout`作为输出格式。根Logger的输出级别为DEBUG,并将日志输出到`CONSOLE` appender中。 通过灵活配置log4j的XML配置文件,我们可以根据实际需求定义日志的格式和输出目标,从而更好地进行日志管理和排查问题。 ### 回答3: log4j是一个开源的Java日志管理工具,用于记录应用程序的日志信息。XML配置文件log4j的一种配置方式,用于指定日志输出的格式、位置和级别等信息。 XML配置文件的结构主要包括根元素<log4j:configuration>和子元素<appender>、<logger>等。 <log4j:configuration>元素是XML配置文件的根元素,包含了整个配置的信息。它可以包含多个<appender>和<logger>。 <appender>元素用于定义日志记录的输出目标。它可以定义不同的输出方式,如控制台输出文件输出等。每个<appender>元素都有一个唯一的名称,并可以通过<appender-ref>元素来引用。 <logger>元素用于定义应用程序的日志记录器。每个<logger>元素都有一个唯一的名称和一个级别。可以使用<appender-ref>元素将<logger>元素与<appender>元素关联起来,以将日志信息入指定的输出目标。 XML配置文件还可以定义日志级别、日志格式等信息日志级别包括DEBUG、INFO、WARN、ERROR和FATAL等,可以根据不同的需求进行设置。日志格式可以使用PatternLayout指定,包括日期、日志级别、类名、线程名等信息。 通过修改XML配置文件,可以方便地调整日志输出方式和级别,使程序的日志信息更易读、更易管理。同时,XML配置文件的结构清晰,易于理解和维护。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值