log4j及log4j2在Spring MVC中的使用.md
2018-07-28 本文已影响70人
7f2aceb77681
项目已上线许久,项目中使用的是log4j 1.x版本,本来日志也可以正常记录,但是运维报怨说,你们的日志太大了,catalina.out日志输出无限大,以致有些应用出现服务器存储告警,所以建议我们:
“应用日志必须对接公司统一日志平台,若同时也存放在本地服务器,则统一放在容器根目录下的单独文件夹,文件夹名称带有log字样,日志文件按日期或大小归档,单个日志文件超过20M的文件需要在归档时同时压缩,默认只保留最近一个月的日志,由代码实现自动清理。”
总结日志管理需求:
- 日志写入到统一日志平台(ELK日志平台);
- 本地日志文件需按日期或大小归档;
- 单个日志文件如超过20M需在归档时压缩;
- 自动清理日志,默认保留近一个月日志;
- 关闭catalina.out日志输出;
鉴于以上需求,我发现log4j 1.x版本有些做不到,而log4j 2.x版本正好可以很好的满足:
- Tomcat标准部署通过log4j配置无法关闭catalina.out日志输出;
- 无法自动清理日志,仅保存近一个月日志;
- 无法对超过20M的日志文件在归档时自动压缩;
备注:不升级log4j,如何解决以上问题?
1.通过Tomcat配置关闭catalina.out日志输出。
# 直接找到Tomcat下bin/catalina.sh文件中以下代码片段:
if [ -z "$CATALINA_OUT" ] ; then
CATALINA_OUT="$CATALINA_BASE"/logs/catalina.out
# 将上面的内容修改成下面内容即可:
if [ -z "$CATALINA_OUT" ] ; then
CATALINA_OUT=/dev/null # 输入到/dev/null黑洞
2.通过编写服务器脚本、定时任务实现日志清理和压缩;
以上两种方法也可以达到同样的目的,但是运维的同学才不愿意这么干,给你们提供个web容器,其它最好你们程序自己实现:)
log4j2是log4j的升级版,log4j2除了可以满足以上需求,听说性能也更好,将旧项目中的log4j升级到log4j2的成本也较低。
[TOC]
一、log4j配置
官方文档:http://logging.apache.org/log4j/1.2/apidocs
1. Maven包引入
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.19</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.19</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2. log4j.properties配置文件
log4j.properties配置文件log4j约定了其配置文件在默认加载类的路径下,即classpath的根路径,所以如最终发布在classpath根路径下,则在使用时无需指定路径。
### set log levels ###
log4j.rootLogger=debug,stdout,debug,error,rsyslog
#log4j.rootLogger=debug,debug,error,rsyslog
### 配置根Logger:设定日志记录的最低级别 ###
log4j.category.org.springframework=ERROR
log4j.category.org.apache=INFO
log4j.logger.org.hibernate=ERROR
### 输出到控制台 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH:mm:ss}][%t] %l %m %n
### 输出到日志文件 ###
log4j.appender.debug=org.apache.log4j.DailyRollingFileAppender
log4j.appender.debug.File = ${catalina.home}/msp-logs/info.log
log4j.appender.debug.datePattern='.'yyyy-MM-dd
log4j.appender.debug.append=true
log4j.appender.debug.Threshold=DEBUG
log4j.appender.debug.layout=org.apache.log4j.PatternLayout
log4j.appender.debug.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH:mm:ss}][%t] %l %m %n
### ERROR输出到日志文件 ###
log4j.appender.error=org.apache.log4j.DailyRollingFileAppender
log4j.appender.error.File = ${catalina.home}/msp-logs/error.log
log4j.appender.error.datePattern='.'yyyy-MM-dd
log4j.appender.error.append=true
log4j.appender.error.Threshold=ERROR
log4j.appender.error.layout=org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH:mm:ss}] %l %m %n
#appender rsyslog 端口不可配置,使用默认的:514
log4j.appender.rsyslog=org.apache.log4j.net.SyslogAppender
log4j.appender.rsyslog.syslogHost=11.4.74.26
log4j.appender.rsyslog.Facility=local1
log4j.appender.rsyslog.FacilityPrinting=true
log4j.appender.rsyslog.header=true
log4j.appender.rsyslog.layout=org.apache.log4j.PatternLayout
log4j.appender.rsyslog.layout.conversionPattern=WEIXIN-MSP %d [%-5p] [%t] - %m%n
3. web.xml配置
web.xml配置文件中添加log4j监听器,其中webAppRootKey配置,可将对应日志写入到对应的项目下,缺省值是“webapp.root”,最好要定义,值随便填写,否则对于tomcat部署多个项目时,会冲突。
<!-- log4j配置 -->
<!-- 配置文件如放默认路径,log4jConfigLocation可不配 -->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>WEB-INF/log4j.properties</param-value>
</context-param>
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>600000</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>webName.root</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.WebAppRootListener</listener-class>
</listener>
二、log4j2配置
1. Maven包引入
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.3</version>
</dependency>
2. log4j2.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!--status指定log4j本身(log4j2这个程序)打印日志的级别-->
<Configuration status="WARN" packages="">
<Appenders>
<!--输出至控制台的配置-->
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout charset="utf-8" pattern="%d{yyyy-MM-dd HH:mm:ss} %class{36} [%p] %m%n"/>
</Console>
<!--输出至日志文件的配置-->
<RollingFile name="errorFile" fileName="${sys:catalina.base}/logs/error.log"
filePattern="${sys:catalina.base}/logs/error.log.%d{yyyyMMdd}">
<PatternLayout charset="utf-8" pattern="%d{yyyy-MM-dd HH:mm:ss} %class{36} [%p] %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy modulate="true"/>
</Policies>
</RollingFile>
<RollingFile name="infoFile" fileName="${sys:catalina.base}/wx-logs/info.log"
filePattern="${sys:catalina.base}/wx-logs/info.log.%d{yyyyMMdd}">
<PatternLayout charset="utf-8" pattern="%d{yyyy-MM-dd HH:mm:ss} %class{36} [%p] %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy modulate="true"/>
</Policies>
</RollingFile>
<!--输出至日志平台的配置 log4j2写入日志平台无法识别appName,希望采用facility=auth能与其它系统区别开-->
<Syslog name="SYSLOG" format="RFC5424" host="11.4.74.26" port="514"
protocol="UDP" appName="WEIXIN-VUE-API" includeMDC="true"
facility="USER" enterpriseNumber="18060" newLine="true"
messageId="Audit" mdcId="mdc" id="App"
connectTimeoutMillis="1000" reconnectionDelayMillis="5000">
<LoggerFields>
<KeyValuePair key="thread" value="%t"/>
<KeyValuePair key="priority" value="%p"/>
<KeyValuePair key="category" value="%c"/>
<KeyValuePair key="exception" value="%ex"/>
<KeyValuePair key="message" value="%m"/>
</LoggerFields>
</Syslog>
</Appenders>
<!--日志级别:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.-->
<Loggers>
<!--只有定义了logger并引入的appender,appender才会生效-->
<Logger name="error" level="error" additivity="false">
<!--Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root.
如果指定了,那么会在指定的这个Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity="false"
只在自定义的Appender中进行输出-->
<AppenderRef ref="SYSLOG"/>
<AppenderRef ref="errorFile"/>
</Logger>
<!--Root用来指定项目的根日志,没有单独指定Logger,会统一输出到Root中-->
<Root level="Info" additivity="false">
<AppenderRef ref="SYSLOG"/>
<AppenderRef ref="infoFile"/>
</Root>
</Loggers>
</Configuration>
3. 使用方式
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
// 普通使用
private static final Logger LOGGER = LogManager.getLogger(HelloController.class);
LOGGER.error("error log."); // 会命中log4j2配置的Root项
// 高级使用
LogManager.getLogger("LoggerName01").error(error log.); 会命中log4j2配置的LoggerName01项
LogManager.getLogger("LoggerName02").error(error log.); 会命中log4j2配置的LoggerName02项
4. 按天分日志文件
<RollingFile name="error_appender" fileName="${sys:catalina.base}/wx-logs/error.log" filePattern="${sys:catalina.base}/wx-logs/error-%d{yyyy-MM-dd}.log">
<PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} [%thread] %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy modulate="true" interval="1"/>
</Policies>
</RollingFile>
5. 按大小分日志文件
<RollingFile name="error_appender" fileName="${sys:catalina.base}/wx-logs/error.log" filePattern="${sys:catalina.base}/wx-logs/error-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} [%thread] %m%n"/>
<SizeBasedTriggeringPolicy size="100 MB" />
</RollingFile>