一、认识Log4j2
1.1、介绍Log4j2
官网: https://logging.apache.org/log4j/2.x/
Log4j2:其是Apache推出一个日志实现框架同时也是一个日志门面,是Log4j的升级版,参考了logback的一些优秀设计并修复了一下问题,包含着重大的提升,主要有如下:
异常处理:在logback中,Appender的异常不会被应用感知到,但是在log4j2中提供了一些异常处理机制。
性能提升:Log4j2相对于log4j和logback都具有很明显的性能提升,大约有18倍。
自动重载配置:参考了logback的设计,会提供自动刷新配置,最实用的是在生产环境中可以动态的修改日志的级别而不需要重启应用,相当于热部署。
无垃圾机制:log4j2在大部分情况下,可以使用其设计的一套无垃圾机制,避免频繁的日志收集,减轻垃圾收集器的压力,并能提供更好的响应时间性能。
1.2、日志等级(6个)
查看org.apache.logging.log4j.Level源码,包含六个日志等级,如下:
OFF = new Level("OFF", StandardLevel.OFF.intLevel());//0 FATAL = new Level("FATAL", StandardLevel.FATAL.intLevel());//100 ERROR = new Level("ERROR", StandardLevel.ERROR.intLevel());//200 WARN = new Level("WARN", StandardLevel.WARN.intLevel());//300 INFO = new Level("INFO", StandardLevel.INFO.intLevel());//400 DEBUG = new Level("DEBUG", StandardLevel.DEBUG.intLevel());//500 TRACE = new Level("TRACE", StandardLevel.TRACE.intLevel());//600 ALL = new Level("ALL", StandardLevel.ALL.intLevel());//Integer.MAX_VALUE
其对应StandardLevel.OFF…是通过一个枚举类进行设置的。
若不进行自定义配置文件,默认日志等级为error
二、配置文件
若使用log4j2,我们可以自定义配置文件log4j2.xml,相关内容如下:
<?xml version="1.0" encoding="UTF-8"?> <!-- status="warn" 日志框架本身的输出日志级别(若是设置debug,log4j的配置过程也会展现出来) monitorInterval="5" (监视时间间隔)自动加载配置文件的间隔时间,不低于5秒(及可以热部署) --> <Configuration status="warn" monitorInterval="5"> <!-- 集中配置属性进行管理,使用可通过:${name值} --> <properties> <property name="LOG_HOME">D:/logs</property> </properties> <!-- 日志处理 --> <Appenders> <!-- 控制台输出 appender --> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n" /> </Console> <!-- 日志文件输出 appender --> <File name="file" fileName="${LOG_HOME}/myfile.log"> <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l%c{36} - %m%n" /> </File> <!-- 使用随机读写流的日志文件输出 appender 能够提高性能 --> <RandomAccessFile name="accessFile" fileName="${LOG_HOME}/myAcclog.log"> <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l%c{36} - %m%n" /> </RandomAccessFile> <!-- 按照一定规则拆分的文件日志的appender fileName:表示输出的文件路径 filePattern:在这里指定了拆分后的文件名,下面是以天为单位创建文件夹,并以分钟为单位创建日志文件 --> <RollingFile name="rollingFile" fileName="${LOG_HOME}/myrollog.log" filePattern="D:/logs/$${date:yyyy-MM-dd}/myrollog-%d{yyyy-MM-dd-HH-mm}-%i.log"> <!-- 日志级别过滤器(模仿的logback)这里设置日志等级为debug,匹配通过,不匹配不通过 --> <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY" /> <!-- 输出日志的消息格式 --> <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l%c{36} - %msg%n" /> <!-- 具体的拆分规则 --> <Policies> <!-- 在系统启动时触发拆分规则,生产出一个新的配置文件(一旦重启即可触发) --> <OnStartupTriggeringPolicy /> <!-- 按照文件指定大小拆分,设置为10MB --> <SizeBasedTriggeringPolicy size="10 MB" /> <!-- 按照时间节点拆分,基于上面的filePattern规则定义 --> <TimeBasedTriggeringPolicy /> </Policies> <!-- 在同一个文件目录下,文件的个数限定为30个,超过则会进行覆盖 --> <DefaultRolloverStrategy max="30" /> </RollingFile> </Appenders> <!-- logger定义(root或自定义) --> <Loggers> <!-- 配置RootLogger日志等级为trace,引用appender为上面配置name为console的ConsoleAppender --> <Root level="trace"> <AppenderRef ref="Console" /> </Root> </Loggers> </Configuration>
三、实际应用
3.1、使用log4j2的日志门面
①引入log4j2的日志门面以及日志实现jar包: <!-- Log4j2 门面API --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.13.3</version> </dependency> <!-- Log4j2的日志实现 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.11.1</version> </dependency>
可以看到log4j-core中自带了日志门面的依赖。
②log4j2.xml配置文件见第二部分。
测试程序:
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class LogTest { public static final Logger LOGGER= LogManager.getLogger(LogTest.class); public static void main(String[] args) { LOGGER.fatal("fatal"); LOGGER.error("error"); LOGGER.warn("warn"); LOGGER.info("info"); LOGGER.debug("debug"); LOGGER.trace("trace"); } }
若是没有自定义配置文件的话会出现下面的情况:
3.2、使用slf4j+log4j2(推荐使用)
现如今主流使用slf4j作为日志门面,能够很方便的切换不同的日志框架
①我们在3.1基础上增加slf4j的日志门面以及slf4j绑定log4j2的适配器
<!--使用slf4j作为日志的门面,使用log4j2来记录日志 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.30</version> </dependency> <!--为slf4j绑定日志实现 log4j2的适配器 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.10.0</version> </dependency> <!-- Log4j2 门面API --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.13.3</version> </dependency> <!-- Log4j2的日志实现 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.11.1</version> </dependency>
我们可以注意到log4j-slf4j-impl的坐标中包含了其他三个坐标的依赖,这里为了演示所以引入了四个坐标,实际上我们直接引入slf4j-api、log4j-slf4j-impl两个坐标即可!!!
②添加log4j2.xml配置文件,见第二部分
测试程序:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Log4j2Test { //获取Logger实例 public static final Logger LOGGER = LoggerFactory.getLogger(LogTest.class); public static void main(String[] args) { System.out.println(LOGGER.getName());//xyz.changlu.LogTest //1、打印日志记录 LOGGER.error("error"); LOGGER.warn("warn"); LOGGER.info("info"); LOGGER.debug("debug"); LOGGER.trace("trace"); //2、占位符输出 String name = "changlu"; int age = 20; LOGGER.info("报错,name:{},age:{}",name,age); //3、打印堆栈信息 try { int i = 5/0; }catch (Exception e){ LOGGER.error("报错",e); } } }
注意到这里使用的slf4j日志门面的API来调用LoggerFactory以及获取Logger实例。