首先约定几个值:
[ProjectName],代表自己的项目的名称;
[CatalinaHome],代表自己的Tomcat服务器所在的目录;
现在自己需要的日志系统需求如下:
1,把系统info,warn,error和fatal级别的信息分别分开输出到[CatalinaHome]/logs/[ProjectName]/info.log,warn.log,error.log,fatal.log临时文件中,每次重启后删除原来的文件,记录重启后的信息;
2,debug级别以及以上的信息输出到控制台;
3,trace以及以上级别的信息,按照记录到[CatalinaHome]/logs/[ProjectName]/DetailLog/[ProjectName].log文件中;
并且每过一天进行一次备份,备份的文件格式为:
[CatalinaHome]/logs/[ProjectName]/DetailLog/[ProjectName]-%d{yyyy-MM-dd}.log
我先给出最终实现了该功能的配置,然后针对该配置进行说明;
log4j2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" monitorInterval="30">
<Properties>
<Property name="ProjectName">Study</Property>
<Property name="infoLogFilePath">${sys:catalina.home}/logs/${ProjectName}/info.log</Property>
<Property name="warnLogFilePath">${sys:catalina.home}/logs/${ProjectName}/warn.log</Property>
<Property name="errorLogFilePath">${sys:catalina.home}/logs/${ProjectName}/error.log</Property>
<Property name="fatalLogFilePath">${sys:catalina.home}/logs/${ProjectName}/fatal.log</Property>
<Property name="traceLogFilePath">${sys:catalina.home}/logs/${ProjectName}/DetailLog/${ProjectName}.log</Property>
<Property name="traceLogFilePattern">${sys:catalina.home}/logs/${ProjectName}/DetailLog/${ProjectName}-%d{yyyy-MM-dd}.log</Property>
<Property name="pattern">[%d][%-5level][%logger]:%m%n</Property>
<Property name="detailPattern">[%d{yyyy-MM-dd HH:mm:ss}][%-5level][%class{50}-%M-%L]:%msg%n</Property>
</Properties>
<Appenders>
<Console name="CustomConsole" target="SYSTEM_OUT">
<PatternLayout pattern="${pattern}"/>
</Console>
<File name="faInfo" fileName="${infoLogFilePath}" append="yes">
<PatternLayout pattern="${pattern}"/>
<Filters>
<ThresholdFilter level="debug" onMatch="deny" onMismatch="neutral"/>
<ThresholdFilter level="info" onMatch="accept" onMismatch="deny"/>
</Filters>
</File>
<File name="faWarn" fileName="${warnLogFilePath}" append="yes">
<PatternLayout pattern="${pattern}"/>
<Filters>
<ThresholdFilter level="error" onMatch="deny" onMismatch="neutral"/>
<ThresholdFilter level="warn" onMatch="accept" onMismatch="deny"/>
</Filters>
</File>
<File name="faError" fileName="${errorLogFilePath}" append="yes">
<PatternLayout pattern="${pattern}"/>
<Filters>
<ThresholdFilter level="fatal" onMatch="deny" onMismatch="neutral"/>
<ThresholdFilter level="error" onMatch="accept" onMismatch="deny"/>
</Filters>
</File>
<File name="faFatal" fileName="${fatalLogFilePath}" append="yes">
<PatternLayout pattern="${pattern}"/>
<Filters>
<ThresholdFilter level="fatal" onMatch="accept" onMismatch="deny"/>
</Filters>
</File>
<RollingFile name="rfaTrace" fileName="${traceLogFilePath}" filePattern="${traceLogFilePattern}">
<PatternLayout pattern="${detailPattern}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
</Policies>
<DefaultRolloverStrategy max="3"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="CustomConsole"/>
</Root>
<Logger name="fileLogger" level="fatal">
<AppenderRef ref="faInfo"/>
<AppenderRef ref="faWarn"/>
<AppenderRef ref="faError"/>
<AppenderRef ref="faFatal"/>
</Logger>
<Logger name="fileLogger.rollingFile" level="trace">
<AppenderRef ref="rfaTrace" />
</Logger>
</Loggers>
</Configuration>
2 Properties元素
<Properties>
<Property name="name1">value1</Property>
<Property name="name2" value="value2"/>
<Property name="name3">value3</Property>
</Properties>
1,Properties元素是可选的,在Properties中可以定义若干个Property子元素;
2,每个Property元素,以name和value的方式,定义了一个键值对,在后续的配置中,可以使用name来使用其对应的value;
3,这种键值对方式的常量定义的优势具有普遍的意义,即:一改全改; 如果有很多地方需要使用一个name1的值value1,但是后期变动value1的值需要更改的时候,只需要修改name1常量定义的value1的值就好了,而不需要在每个使用name1的地方去修改;
4,使用的方式为 ${name1}
来通过变量的名称来获取变量的值;
3 File元素
File元素,指的是将LogEvent输出到指定的文件中,且该文件在每次重启的时候,会被删除重建,用来记录临时的信息;
主要的属性有3个,name,fileName,append;
- name,指定Appender的名称,在后续配置的Logger对象中,进行关联;
- fileName,指定产生的日志文件的目录;
元素都有一个fileName的属性,用来指定产生的日志的路径,
如果使用相对路径,例如fileName = "log/test.log"
如果是run as java application,输出在本地项目文件的 LocalProject/log/test.log中;
如果是在servlet中访问,日志是在 [UserDesktop]/log/test.log中;
而为了让日志在tomcat的logs文件夹中,我们需要使用绝对路径,如:
{ProjectName}/info.log
其中${sys:catalina.home}
这种方式,可以获得tomcat的目录;
- append,值为yes和no,指定每次输出是否追加;yes,代表追加,这样在一次服务器启动的期间,输出的日志都可以保留;no,只保留最新输出的日志;
可以包含的子元素有两个,PatternLayout,和Filters; - PatternLayout,用来指定日志的输出格式,详情可以参考球球第2章的文章;
- Filters,定义过滤器,过滤器的使用可以查看本章第5节;
4 RollingFile元素
RollingFile,是将日志输出到指定文件,和File相比有两个区别:
- 重启之后不会删除原来的日志文件,而是继续在原来文件的后部写入;
- 可以按照指定的策略,对日志文件进行备份,然后创建新的文件进行记录,这个动作,叫做rollover;
RollingFile元素的主要属性有,name,fileName,filePattern;
name和fileName的作用和File元素一致,特有的是filePattern属性,该属性指定了当rollover条件满足时,对日志备份的备份文件的命名规则;
RollingFile元素特有的子元素为Policies,用来指定rollover的条件,其中,TimeBasedTriggeringPolicy用来说明时间达到指定条件时rollover,interval属性需要和filePattern结合起来解释:
示范配置中给定的fileName和filePatter分别为:
fileName:
<Property name="traceLogFilePath">${sys:catalina.home}/logs/${ProjectName}/DetailLog/${ProjectName}.log</Property>
filePattern:
<Property name="traceLogFilePattern">${sys:catalina.home}/logs/${ProjectName}/DetailLog/${ProjectName}-%d{yyyy-MM-dd}.log</Property>
使用了%d{yyyy-MM-dd},表示rollover时,按照yyyy-MM-dd的格式将原来的文件进行备份;
其中最小的时间单位为天;
然后interval的值为1,那么结合起来就是每一天备份一次;
假如服务器启动的时间为2019-08-14,初始启动的时候,所有的日志都记录在Study.log中,(球球的项目名称为Study);然后当2019-08-15再输出日志时,会触发rollover条件,首先将Study.log重命名为Study-2019-08-14.log,然后重新生成一个Study.log记录当日的日志,以此类推;
5 只输出一个级别的日志:过滤器的使用规则
1,每个appender中,可以通过定义Filters来详细指定输出的event级别;
2,每个filter的主要属性有:
- level,用来指明该过滤器的等级;
- onMatch,值为3个deny,accept,neutral;当传递过来的LogEvent的等级大于等于level中指定的级别时,使用onMatch指定的策略处理该LogEvent.
-- deny,表示丢弃该LogEvent,该Appender的后续Filter也没有机会处理该LogEvent;
-- accept,表示处理该LogEvent,即按照该Appender的方式进行输出,后续的Filter也不会再处理该LogEvent;
-- neutral,如果当前Filter为最后一个Filter,那么作用相当于Accept;如果不是,将该LogEvent传递给后续Filter处理; - onMismatch,当传递过来的LogEvent的等级小于当前FIlter指定的等级时的处理策略,对应的值也是3个,deny,accept,neutral;作用和上面是一样的;
下面通过讨论几个过滤器的实际作用:
5.1 只输出debug级别以下的信息;
<Filters>
<ThresholdFilter level="debug" onMatch="deny" onMismatch="neutral"/>
</Filters>
该过滤器说明:
当LogEvent传递过来时,大于等于debug级别的,都不处理,丢弃,也不会传给后面的过滤器;
因为当前是最后一个filter,neutral的作用和accept是一样的,所以小于debug级别的,处理并输出;
最终效果是输出debug级别以下的信息;
5.2 只输出info级别以上的信息;
<Filters>
<ThresholdFilter level="info" onMatch="accept" onMismatch="deny"/>
</Filters>
该过滤器说明:
当LogEvent传递过来时,大于等于info级别的,进行输出;
级别小于info的,丢弃掉;
最终效果是输出info级别以上的信息;
5.3 只输出info级别的信息;
<Filters>
<ThresholdFilter level="debug" onMatch="deny" onMismatch="neutral"/>
<ThresholdFilter level="info" onMatch="accept" onMismatch="deny"/>
</Filters>
该过滤器是将前面两个过滤器结合起来了,说明如下:
1a,大于等于debug级别的,都不打印,丢弃掉;
1b,小于debug级别的,交给第二个过滤器定夺;
1b.a,大于等于info级别的,进行输出;
1b.b,小于info级别的,丢弃掉;
最终效果是,只输出info级别的信息;
通常要指定只输出一个级别的信息,需要两个过滤器的搭配使用;
6 Logger和Appender的关联
在配置Logger的时候,使用AppenderRef元素来讲该Logger和对应的Appender关联起来,这样,在使用该Logger对象产生LogEvent的时候,就会分配给每个与该Logger关联的Appender进行处理;
所以,一个重要的问题就是要弄清楚每个Logger究竟管关联了哪些Appender;
每个Logger关联的Appender有两部分:
-
Logger自己关联Appender;
-
Logger继承的父Logger关联的Appender;
所以,需要理解以下Logger的继承
6.1 Logger的定义和继承
主要的规则如下:
- 首先需要配置一个根Logger,每个其他的Logger都会继承这个根Logger,定义方式为:
<Root level="debug">
<AppenderRef ref="CustomConsole"/>
</Root>
- level指定了该Logger所处理的日志级别,只有大于等于指定level的LogEvent,才会交给Appender进行处理,不满足条件的丢弃掉;
- AppenderRef,就是指定当前Logger直接关联的Appender;
- 其余的Logger,根据name属性确定继承关系,定义方式为:
<Logger name="fileLogger" level="info">
<AppenderRef ref="faInfo"/>
<AppenderRef ref="faWarn"/>
<AppenderRef ref="faError"/>
<AppenderRef ref="faFatal"/>
</Logger>
加入定义了4个其他的Logger,名字分别为a,a.b,a.b.c,a.c,这几个Logger的继承关系为:
继承1.jpg
就是通过符号'.'来表示继承关系,如果一个LoggerA的名字,和另一个LoggerB名字的.的前面部分一致,那么这个LoggerA就是LoggerB的父类;
6.2 配置中Logger和Appender的关系
配置中每个Logger和Appender的关系可以用下图表示:
继承2.jpg
所以最后那个Logger实际关联了6个Appender,也是满足本章一开始提的需求的logger了;
6.3 实际使用
实际使用时,使用如下代码获取名为fileLogger.rollingFile的logger并记录:
Logger logger = LogManager.getLogger("fileLogger.rollingFile");
logger.error("This is an error message!");
logger.fatal("This is a fatal message");
logger.info("This is an info message");
logger.trace("This is a trace message");
logger.debug("This is a debug message");
logger.warn("This is a warn message");
Reference
1,log4j2配置文件详解
2,log4j2子节点浅析
3,5-log4j2.xml配置文件各个节点详解
4,log4j2的log输出到tomcat/logs目录下及使用
5,Log4j2研究之lookup
6,Log4j2中RollingFile的文件滚动更新机制
网友评论