原创文章:log4j2的使用 – 编程屋
目录
1 前言
Apache Log4j2是对Log4j的升级版,参考了logback的一些优秀设计,并且修复了一些问题,因此带来了一些重大的提升
1 异常处理:在logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异常处理机制
2 性能提升:log4j2相较于log4j和logback都具有很明显的提升性能
3 自动重载配置:参考了logback的设计,当然会提供自动刷新参数配置,最实用的就是我们可以在生产上可以动态的修改日志的级别而不需要重启应用
4 无垃圾机制:log4j2在大部分情况下,都可以使用其设计的一套无垃圾机制,避免频繁的日志收集导致jvmgc。
log4j2既可以作为日志实现,也可以作为日志门面来使用,不过在平时开发中,大家都习惯于将log4j2作为日志实现,slf4j作为日志门面来结合使用。
2 log4j2
2.1 log4j2简单使用
log4j2作为日志门面和 实现所需导入依赖:
<!--log4j日志门面--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.11.1</version> </dependency> <!-- log4j的日志实现--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.11.1 </version> </dependency>
slf4j作为日志门面,log4j2作为日志实现所需导入依赖:
<!--使用slf4j作为日志门面--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.28</version> </dependency> <!--使用log4j的适配器进行绑定--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.9.1</version> </dependency> <!--log4j日志门面--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.11.1</version> </dependency> <!-- log4j的日志实现--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.11.1 </version> </dependency>
在我们的resources目录下放置一个log4j2.xml文件
<?xml version="1.0" encoding="UTF-8" ?> <!-- status = "warn" 日志框架本身输出的日志级别 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}/myAccess.log"> <PatternLayout pattern="%d{ yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %l %c{36} ---%m%n"></PatternLayout> </RandomAccessFile> <!--按照一定规则拆分日志文件的appender--> <RollingFile name = "rollingFile" fileName = "${LOG_HOME}/myrolling.log" filePattern = "D:/logs/$${data:yyyy-MM-dd/myrolling-%d{yyyy-MM-dd-HH-mm}-%i.log}"> <!--日志级别过滤器--> <ThresholdFilter level = "debug" onMatch = "DENY"/> <!--指定日志消息的格式--> <PatternLayout pattern="%d{ yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %l %c{36} ---%m%n"></PatternLayout> <!--日志拆分规则--> <Policies> <!--在系统启动时,触发拆分规则,生产一个新的日志文件--> <OnStartupTriggeringPolicy/> <!--按照文件大小进行拆分--> <SizeBasedTriggeringPolicy size = "10 MB"/> <!--按照时间规则进行拆分--> <TimeBasedTriggeringPolicy/> </Policies> <!--在同一个目录下,文件的个数限定为30个 超过进行覆盖--> <DefaultRolloverStrategy max = "30"/> </RollingFile> </Appenders> <!--logger定义--> <Loggers> <Root level = "trace"> <AppenderRef ref ="Console"/> </Root> </Loggers> </Configuration>
2.2 log4j2的异步日志
log4j2的最大的特点就是异步日志,其性能也主要是从异步日志中受益。相对于同步日志来讲,log4j2的异步日志无异于提升许多。
同步日志:主线程执行到我们的日志log.info()时,它会进行一系类的处理,等将这些东西处理完成之后,才会去执行我们的业务逻辑。
异步日志:当主线程依然执行带日志log.info()输出时,它会创建一个Logger对象生成一个LogEvent事件,然后将它放入一个ArrayBlockingQueue阻塞对列中,放入成功后,主线程会返回对我们的业务逻辑进行处理。此时我们的log4j会开启一个新的线程,用新的线程来执行我们的LogEvent对象,再用具体的Appender进行处理。
2.3 异步日志实现方式
Log4j2提供了两种实现日志的方式,一个是AsyncAppender,一个是通过AsyncLogger
2.3.1 AsyncAppender
AsyncAppender:这种使用方式较为简单,只需要在我们上述的Appender中加入以下标签即可:
<Async name = "Async"> <AppenderRef ref = "file"/> </Async>
2.3.2 AsyncLogger
这种异步方式是官方推荐的异步日志方式,它可以使得Logger.log返回的更快。有两种选择:全局异步和混合异步
全局异步:所有日志都进行异步记录,在配置文件上不用做任何改动,只需要添加log4j2.component.properties配置:
Log4jContextSelector = org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
局部异步:我们可以根据项目的实际情况将日志分为异步输出是同步输出。
<!--logger定义-->
<Loggers>
<!--自定义异步logger对象
includeLocation = "false" 关闭日志记录行好信息
additivity = "false" 不再继承rootlogger对象-->
<AsyncLogger name = "com.liubujun" level = "trace" includeLocation = "false" additivity = "false">
<AppenderRef ref="Console"/>
</AsyncLogger>
<Root level = "trace">
<AppenderRef ref ="Console"/>
</Root>
</Loggers>
将以上配置配置到我们之前的log4j2.xml配置文件中,将之前的logger定义替换。此时我们com.liubujun日志时异步的,root日志是同步的。
2.4 log4j的无垃圾记录
垃圾收集暂停是延迟峰值的常见原因,并且对于许多系统而言,花费大量精力来控制这些暂停。许多日志库在稳定日志记录器期间分配临时对象,如日志事件对象,字符串,字符数组,字节数组。这会对垃圾收集器造成压力并增加GC暂停发生的频率。
从版本2.6开始,默认情况下Log4j以“无垃圾模式”运行,其中重用对象和缓冲区,并且尽可能的不分配临时对象,还有一个“低垃圾模式”,但不是完全无垃圾,不使用ThreadLocal字段。
Log4j2.6中的无垃圾日志记录部分通过重用ThreadLocal字段中的对象来使用,部分在将文本转换字符时重用缓冲区来实现。
以上只是部分内容,为了维护方便,本文已迁移到新地址:log4j2的使用 – 编程屋