简单说一下log4j2的改进,引用一下百度上的:
1、丢数据这种情况少,可以用来做审计功能。而且自身内部报的exception会被发现,但是logback和log4j不会。
2、log4j2使用了disruptor技术,在多线程环境下,据说性能高于logback等10倍以上。
3、(garbage free)之前的版本会产生非常多的临时对象,会造成GC频繁,log4j2则在这方面上做了优化,减少产生临时对象。尽可能少的GC
4、利用插件系统,使得扩展新的appender,filter,layout等变得容易,log4j不可以扩展 插件????
5、因为插件系统的简单性,所以在配置的时候,可以不用具体指定所要处理的类型。class
6、可以自定义level
7、Java 8 lambda support for lazy logging
8、Support for Message objects
9、对filter的功能支持的更强大
10、系统日志(Syslog)协议supports both TCP and UDP
11、利用jdk1.5并发的特性,减少了死锁的发生。
12、Socket LogEvent SerializedLayout
13、支持kafka queue
然后就是看怎么集成了:
1、用maven引入jar支持:
<!-- log4j2 支持 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.10.0</version>
</dependency>
<!-- log4j2 异步化需要添加 -->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.6</version>
</dependency>
<!-- log4j2 支持end -->
需要注意的是,如果你引入了spring boot整合的库,比如:spring-cloud-starter。。。等这些包,记得要先排除其他日志框架,否则可能会造成jar冲突。举个例子:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.4.RELEASE</version>
<exclusions>
<!--移除其他日志框架,以免冲突-->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
<exclusion>
<artifactId>*</artifactId>
<groupId>ch.qos.logback</groupId>
</exclusion>
<exclusion>
<artifactId>*</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
2、再就是添加log2j的配置文件了,直接看吧,注释比较清楚:
<?xml version="1.0" encoding="UTF-8"?>
<!-- (1)请根据实际情况配置各项参数 (2)需要注意日志文件备份数和日志文件大小,注意预留目录空间 (3)实际部署的时候backupFilePatch变量需要修改成linux目录 -->
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!-- %p:输出日志信息的优先级,即DEBUG,INFO,WARN,ERROR,FATAL。 %d:输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,如:%d{yyyy/MM/dd
HH:mm:ss,SSS}。 %r:输出自应用程序启动到输出该log信息耗费的毫秒数。 %t:输出产生该日志事件的线程名。 %l:输出日志事件的发生位置,相当于%c.%M(%F:%L)的组合,包括类全名、方法、文件名以及在代码中的行数。例如:test.TestLog4j.main(TestLog4j.java:10)。
%c:输出日志信息所属的类目,通常就是所在类的全名。 %M:输出产生日志信息的方法名。 %F:输出日志消息产生时所在的文件名称。 %L::输出代码中的行号。
%m::输出代码中指定的具体日志信息。 %n:输出一个回车换行符,Windows平台为"rn",Unix平台为"n"。 %x:输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java
servlets这样的多客户多线程的应用中。 %%:输出一个"%"字符。 -->
<!-- status : 这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,会看到log4j2内部各种详细输出 monitorInterval
: Log4j能够自动检测修改配置文件和重新配置本身, 设置间隔秒数。monitorInterval="300" 每隔300秒重新读取配置文件,对web应用很实用 -->
<configuration status="INFO">
<!-- 配置日志文件输出目录 -->
<Properties>
<!-- 日志文件名称 -->
<Property name="fileName">rblZuulServer</Property>
<!-- 日志文件存放目录,根据你的需要设置 -->
<Property name="backupFilePatch">/usr/log</Property>
</Properties>
<!--先定义所有的appender -->
<appenders>
<!--这个是输出到控制台的配置 target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT -->
<Console name="Console" target="SYSTEM_OUT">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
<ThresholdFilter level="trace" onMatch="ACCEPT"
onMismatch="DENY" />
<!--输出日志的格式 -->
<PatternLayout pattern="%d{yyyy.MM.dd HH:mm:ss.SSS} %p %c %M - %m%n" />
</Console>
<!--这个文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,挺有用的,适合临时测试用,或者查看本次运行时间的日志 -->
<File name="File" fileName="${backupFilePatch}/${fileName}_test.log"
append="false">
<ThresholdFilter level="trace" onMatch="ACCEPT"
onMismatch="DENY" />
<PatternLayout pattern="%d{yyyy.MM.dd HH:mm:ss.SSS} %p %c %M - %m%n" />
</File>
<!--这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 (service.log.年份.gz) -->
<!-- 注意%d{MM-dd-yyyy}要用年月日格式,不能加上时分秒,并且最后要有%i,这样log4j2才能判断出哪天一共产生几个文件,便于自动删除配置 -->
<RollingFile name="service_appender" fileName="${backupFilePatch}/${fileName}.log"
filePattern="${backupFilePatch}/${fileName}.log.%d{yyyy-MM-dd}-%i.log.gz"
immediateFlush="true">
<!-- %d{yyyy-MM-dd HH:mm:ss, SSS} : 日志生产时间 %p : 日志输出格式 %c : logger的名称
%m : 日志内容,即 logger.info("message") %n : 换行符 %C : Java类名 %L : 日志输出所在行数 %M
: 日志输出所在方法名 hostName : 本地机器名 hostAddress : 本地ip地址 -->
<PatternLayout pattern="%d{yyyy.MM.dd HH:mm:ss.SSS} %p %c %M - %m%n" />
<Policies>
<TimeBasedTriggeringPolicy interval="1"
modulate="true" />
<!-- 每个日志文件大小设置,超过大小自动压缩打包 -->
<SizeBasedTriggeringPolicy size="30MB" />
</Policies>
<!-- 最多保留文件数 -->
<DefaultRolloverStrategy max="20">
<Delete basePath="${backupFilePatch}/" maxDepth="1">
<!-- 指定要删除的后缀 -->
<IfFileName glob="*.log.gz" />
<!-- 超过20天自动删除 -->
<IfLastModified age="20D" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效 ,异步是 AsyncLogger 、asyncRoot,同步则是Logger、Root,推荐异步,性能高 -->
<loggers>
<!--过滤掉spring和mybatis等的一些无用的DEBUG信息 -->
<AsyncLogger name="org.springframework" level="ERROR">
</AsyncLogger>
<AsyncLogger name="org.mybatis" level="error">
</AsyncLogger>
<AsyncLogger name="org.hibernate" level="error">
</AsyncLogger>
<AsyncLogger name="org.apache" level="error">
</AsyncLogger>
<!-- 需要打印的日志级别,以及包的设置,additivity="true"则是打印时同时输出到控制台 -->
<AsyncLogger name="com.poly.zuul" level="DEBUG"
additivity="true">
</AsyncLogger>
<!-- 指定打印根的级别 -->
<asyncRoot level="INFO">
<!-- 设置要打印的appender -->
<AppenderRef ref="Console" />
<AppenderRef ref="File" />
<AppenderRef ref="service_appender" />
</asyncRoot>
</loggers>
</configuration>
3、在你的工程引入配置文件,比如命名为log4j2.xml,然后在工程配置文件中指定日志配置文件。如在application.properties中加入:
#log4j2指定配置文件路径
logging.config=classpath:xml/log4j2.xml
4、到此为止,基本配置已经完成,可以直接使用了,为了方便,这里给一个日志工具类 LoggerUtil,便于大家使用:
/*
* 文件名:LoggerUtils.java 版权:Copyright by www.huawei.com 描述: 修改人:kokJuis 修改时间:2017年8月9日 跟踪单号: 修改单号:
* 修改内容:
*/
package com.poly.rbl.utils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* 日志工具类
*
* @author gogym
* @version 2017年8月9日
* @see LoggerUtils
* @since
*/
public class LoggerUtil
{
/**
* 是否开启Debug
*/
public static boolean isDebug = LogManager.getLogger(LoggerUtils.class).isDebugEnabled();
public static void info(String message)
{
Logger logger = LogManager.getLogger();
logger.info(message);
}
/**
* Description: info输出
*
* @param clazz
* 目标.Class
* @param message
* 输出信息
* @see
*/
public static void info(Class<? extends Object> clazz, String message)
{
Logger logger = LogManager.getLogger(clazz);
logger.info(message);
}
/**
* info 输出
*
* @param clazz
* 目标.Class
* @param fmtString
* 输出信息key
* @param value
* 输出信息value
*/
public static void fmtInfo(Class<? extends Object> clazz, String key, Object... value)
{
if (StringUtils.isBlank(key))
{
return;
}
if (null != value && value.length != 0)
{
Logger logger = LogManager.getLogger(clazz);
logger.info("{}:{}", key, value);
}
}
/**
* Debug 输出
*
* @param clazz
* 目标.Class
* @param message
* 输出信息
*/
public static void debug(Class<? extends Object> clazz, String message)
{
if (!isDebug) return;
Logger logger = LogManager.getLogger(clazz);
logger.debug(message);
}
/**
* Debug 输出
*
* @param clazz
* 目标.Class
* @param fmtString
* 输出信息key
* @param value
* 输出信息value
*/
public static void fmtDebug(Class<? extends Object> clazz, String key, Object... value)
{
if (!isDebug) return;
if (StringUtils.isBlank(key))
{
return;
}
if (null != value && value.length != 0)
{
Logger logger = LogManager.getLogger(clazz);
logger.debug("{}:{}", key, value);
}
}
/**
* Error 输出
*
* @param clazz
* 目标.Class
* @param message
* 输出信息
* @param e
* 异常类
*/
public static void error(Class<? extends Object> clazz, String message, Exception e)
{
Logger logger = LogManager.getLogger(clazz);
if (null == e)
{
logger.error(message);
return;
}
logger.error(message, e);
}
/**
* Error 输出
*
* @param clazz
* 目标.Class
* @param message
* 输出信息
*/
public static void error(Class<? extends Object> clazz, String message)
{
error(clazz, message, null);
}
/**
* 异常填充值输出
*
* @param clazz
* 目标.Class
* @param fmtString
* 输出信息key
* @param e
* 异常类
* @param value
* 输出信息value
*/
public static void fmtError(Class<? extends Object> clazz, Exception e, String key,
Object... value)
{
if (StringUtils.isBlank(key))
{
return;
}
if (StringUtils.isBlank(key))
{
return;
}
if (null != value && value.length != 0)
{
Logger logger = LogManager.getLogger(clazz);
logger.error("{}:{}", key, value);
}
}
/**
* 异常填充值输出
*
* @param clazz
* 目标.Class
* @param fmtString
* 输出信息key
* @param value
* 输出信息value
*/
public static void fmtError(Class<? extends Object> clazz, String key, Object... value)
{
if (StringUtils.isBlank(key))
{
return;
}
if (StringUtils.isBlank(key))
{
return;
}
if (null != value && value.length != 0)
{
Logger logger = LogManager.getLogger(clazz);
logger.error("{}:{}", key, value);
}
}
}
使用方式很简单,直接复制上面的类到你的工程。使用示例:
//最简单的使用
LoggerUtils.info("我是日志");
//加上class出处
LoggerUtils.info(getClass(), "我是日志");
//debug级别
LoggerUtils.debug(getClass(), "我是debug日志");
//error级别
LoggerUtils.error(clazz, "我是error日志");
//error级别,并打印异常
LoggerUtils.error(clazz, "我是error日志",Exception e);
//自定义输出信息
LoggerUtils.fmtInfo(getClass(),String key,Object... value);
//...............