关于log4j的一个坑

前言

这两天改了一下生产环境的log4j的配置,结果踩了一个小坑,记录一下。

正文

在生产环境的日志配置中新加了一个日志文件输出配置,如下注释处:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration>
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{MM-dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\}:%L - %m%n"/>
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="error"/>
<param name="levelMax" value="off"/>
<param name="AcceptOnMatch" value="true"/>
</filter>
</appender>

<appender name="DAILY_ROLLING_FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="../log/main.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd'.log'"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{MM-dd HH:mm:ss SSS\} %-5p] [%t] %c{3\}:%L - %m%n"/>
</layout>
<filter class="org.apache.log4j.varia.LevelMatchFilter">
<param name="LevelToMatch" value="ERROR"/>
<param name="AcceptOnMatch" value="true"/>
</filter>
</appender>

<!-- 新增配置开始 -->
<appender name="ANALYSIS_DAILY_ROLLING_FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="../log/analysis.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd'.log'"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%m%n"/>
</layout>
<filter class="org.apache.log4j.varia.LevelMatchFilter">
<param name="LevelToMatch" value="INFO"/>
<param name="AcceptOnMatch" value="true"/>
</filter>
</appender>

<appender name="ASYNC_ANALYSIS_DAILY_ROLLING_FILE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="ANALYSIS_DAILY_ROLLING_FILE"/>
</appender>

<logger name="LOGGER_ANALYSIS">
<level value="INFO"/>
<appender-ref ref="ASYNC_ANALYSIS_DAILY_ROLLING_FILE"/>
</logger>
<!-- 新增配置结束 -->

<root>
<level value="ERROR"/>
<appender-ref ref="DAILY_ROLLING_FILE"/>
</root>
</log4j:configuration>

这个新增的配置会在原有的日志文件 main.log 外,新增一个全新的日志文件 analysis.log 记录一些信息。结果上线后,不仅日志输出到了 analysis.log,同时也输出到了 main.log 中了一份,冗余了。Google 了一下,原来是 rootadditivity 的问题。

原来,在如下的两个 logger 中,存在着继承关系,LOGGER_ANALYSIS 是继承了 root

1
2
3
4
5
6
7
8
9
<logger name="LOGGER_ANALYSIS">
<level value="INFO"/>
<appender-ref ref="ASYNC_ANALYSIS_DAILY_ROLLING_FILE"/>
</logger>

<root>
<level value="ERROR"/>
<appender-ref ref="DAILY_ROLLING_FILE"/>
</root>

继承,就意味着 LOGGER_ANALYSIS 是继承了 rootappender-ref 的,因此,LOGGER_ANALYSIS 不知输出到了自己的 appender 设置的文件 analysis.log 里,也会输出到 DAILY_ROLLING_FILE 对应的 main.log 里,也就是冗余了。

那么,怎么解决呢?很简单,让儿子不继承爸爸就好了,不做富二代,白手起家,自己打天下。

1
2
3
4
<logger name="LOGGER_ANALYSIS" additivity="false">
<level value="INFO"/>
<appender-ref ref="ASYNC_ANALYSIS_DAILY_ROLLING_FILE"/>
</logger>

注意上边的 additivity="false" 就这个设置,就声明和 root 脱离父子关系了,独立了。问题解决。

参考资料

关于log4j root logger 标签 以及additivity 属性

Appenders and Layouts