公司的项目决定升级log4j,因为log4j2有一个自动删除日志的功能,这样可以减轻运维的一些工作,而且在多线程环境下,log4j2的异步日志系统比log4j和logback提高了十倍的性能(吞吐量和延迟率),官方原文如下:
Log4j 2 contains next-generation Asynchronous Loggers based on the LMAX Disruptor library. In multi-threaded scenarios Asynchronous Loggers have 10 times higher throughput and orders of magnitude lower latency than Log4j 1.x and Logback.
因为是升级,原项目用的是log4j或者self4j打印日志,获取logger的方式不同
比如log4j:
import org.apache.log4j.Logger;
private static final Logger LOGGER = Logger.getLogger(xxxx.class);
比如self4j:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(xxxx.class);
而如果用log4j2的话,API将有所不同:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
private static final Logger logger = LogManager.getLogger(xxxx.class);
而如果是commons-logging,API将是:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
private static final Log log = LogFactory.getLog(XXX.class);
如果在升级的过程中,我们要去改代码的话,那将是一项很大的繁琐工程,log4j2架构已经考虑到这一点,给我们提供了转换的包,我们只需要导入几个转换包就可以使用log4j2,而且还不需要修改代码。
官方原文:
Perhaps the simplest way to convert to using Log4j 2 is to replace the log4j 1.x jar file with Log4j 2's log4j-1.2-api.jar. However, to use this successfully applications must meet the following requirements:
- They must not access methods and classes internal to the Log4j 1.x implementation such as Appenders, LoggerRepository or Category's callAppendersmethod.
- They must not programmatically configure Log4j.
- They must not configure by calling the classes DOMConfigurator or PropertyConfigurator
第一步:我这里是maven项目,就以maven项目为例子,进行讲解
所需版本及jar:
jar包
|
版本
|
备注
|
---|---|---|
slf4j-api | 1.7.2 | jcl-over-slf4j 也需要统一使用 1.7.2 版本 |
log4j-slf4j-impl | 2.3 | |
log4j-api | 2.3 | |
log4j-core | 2.3 | |
log4j-1.2-api | 2.3 |
需清理jar:
需删除jar包
|
说明
|
---|---|
slf4j-log4j12 | slf4j到log4j1的桥接包 |
slf4j-jdk14 | slf4j到java.util.logging的桥接包 |
log4j-to-slf4j | 将log4j2的接口适配到slf4j上,不能和log4j-slf4j-impl同时存在 |
slf4j-jcl | 将slf4j适配到JCL上 |
logback-classic | 将slf4j适配到logback上 |
slf4j-simple | 一个简单桥接实现 |
jar包
|
版本
|
备注
|
---|---|---|
slf4j-api | 1.7.2 | jcl-over-slf4j 也需要统一使用 1.7.2 版本 |
log4j-slf4j-impl | 2.3 | |
log4j-api | 2.3 | |
log4j-core | 2.3 | |
log4j-1.2-api | 2.3 |
<!-- 添加log4j2依赖 - start-->
<!--log4j2核心jar包-->
<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>
<!-- <scope>provided</scope> -->
</dependency>
<!-- slf4j核心包 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.2</version>
</dependency>
<!--用于与slf4j保持桥接-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.3</version>
</dependency>
<!--web工程需要包含log4j-web,非web工程不需要-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.4.1</version>
<scope>runtime</scope>
</dependency>
<!-- 添加log4j2依赖 - end-->
2、log4j整合log4j2
<!-- 添加log4j2依赖 - start-->
<!-- log4j-1.2-api为log4j和log4j2的连接包。 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<version>2.3</version>
</dependency>
<!--log4j2核心jar包-->
<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>
<!-- <scope>provided</scope> -->
</dependency>
<!--web工程需要包含log4j-web,非web工程不需要-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.4.1</version>
<scope>runtime</scope>
</dependency>
<!-- 添加log4j2依赖 - end-->
3、commons-logging与log4j2集成(commons-logging是日志接口,根据底层使用的log插件进行日志输出)
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- 添加log4j2依赖 - start-->
<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-1.2-api</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.3</version>
</dependency>
<!-- 添加log4j2依赖 - end-->
<!--web工程需要包含log4j-web,非web工程不需要-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.3</version>
</dependency>
第二步:删掉以前的log4j.properties,改为log4j2.xml,这里起名字的时候,不要写错了
如果编译后中文乱码可设置编码为UTF-8:
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<Configuration status="info" monitorInterval="60">
<!--定义了两个常量方便后面复用 -->
<properties>
<!--生成的日志文件目录地址 -->
<property name="LOG_HOME">/data/logs/jboss/</property>
<!--日志文件名称 -->
<property name="FILE_NAME">uleWalletEjb</property>
</properties>
<!--先定义所有的appender-->
<Appenders>
<!-- 定义控制台输出 -->
<Console name="Console" target="SYSTEM_OUT">
<!--输出日志的格式-->
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %l - %msg%n" />
</Console>
<!--满足一定条件后,就重命名原日志文件用于备份,并从新生成一个新的日志文件 -->
<!--fileName:指定当前日志文件的位置和文件名称 filePattern:指定当发生Rolling时,文件的转移和重命名规则-->
<RollingFile name="uleWalletEjbLogFile"
fileName="${LOG_HOME}/${FILE_NAME}.log"
filePattern="${LOG_HOME}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %l - %msg%n" />
<Policies>
<!--TimeBasedTriggeringPolicy这个配置需要和filePattern结合使用,
注意filePattern中配置的文件重命名规则是${FILE_NAME}-%d{yyyy-MM-dd HH-mm}-%i,
最小的时间粒度是mm,即分钟,TimeBasedTriggeringPolicy指定的size是1,结合起来就是每1分钟生成一个新文件。
如果改成%d{yyyy-MM-dd HH},最小粒度为小时,则每一个小时生成一个文件。 -->
<TimeBasedTriggeringPolicy interval="1" />
<!--SizeBasedTriggeringPolicy 指定当文件体积大于size指定的值时,触发Rolling-->
<SizeBasedTriggeringPolicy size="2048 MB" />
</Policies>
<DefaultRolloverStrategy max="20" />
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console" />
<AppenderRef ref="uleWalletEjbLogFile" />
</Root>
</Loggers>
</Configuration>
web项目serlet2.5需要添加如下配置
<!-- log4j2设置 -->
<context-param>
<param-name>log4jConfiguration</param-name>
<param-value>classpath:log4j2.xml</param-value>
</context-param>
<listener>
<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>
<filter>
<filter-name>log4jServletFilter</filter-name>
<filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>log4jServletFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
log4jConfiguration可以不配置默认去classpath去找log4j2.xml
导入log4j-web依赖后 如果main方法运行测试日志打印可能控制台不输出日志原因是因为该依赖包中的log4j2.component.properties配置文件中配置了
log4j.shutdownHookEnabled=false 及主线程提前运行完并没有使用shutdownHook来关闭loggerContext所以一些日志不知打印那里去了,
web项目默认是关闭的因为是通过ServletContextListener的contextDestroyed方法关闭loggerContext的
非web项目没有这种问题
查看文章:
https://my.oschina.net/pingpangkuangmo/blog/410224
http://blog.csdn.net/zouxucong/article/details/56005725
http://blog.csdn.net/zouxucong/article/details/56013053