log4j升级到log4j2,【日志】Log4j2配置
log4j升级到log4j2,【日志】Log4j2配置详细介绍
本文目录一览: Log4j2基本使用入门
Apache Log4j 2是日志框架Log4j的升级,
它比其前身Log4j 1.x提供了重要的改进,
并且参考了Logback中许多有用的改进,
同时修复了Logback的一些固有问题。
详细请参考官网: Apache Log4j 2
本文介绍Log4j2的常用功能,
给出相应功能的参数配置方法,
最后给出一个完整的log4j2.xml配置文件,
作为工作开发中常用的日志配置参考。
在Maven的父工程pom.xml添加如下依赖:
在Maven的父工程pom.xml添加如下依赖管理:
然后在使用Log4j2的子工程pom.xml添加如下依赖,
这样就不用写具体的版本号了,
保证项目的子工程都使用相同版本的Log4j2。
在复杂场景下,可能不止依赖上面两个jar包,
这种方法可以保证Log4j2模块之间的版本一致。
为了演示Log4j2的功能,创建如下的测试类:
运行上面的测试程序,
在控制台打印出如下日志:
可以看到ERROR报错了,没有找到Log4j2的配置文件,
使用了默认配置,只打印error级别日志到console控制台,
然后控制台输出了error和fatal两个级别的日志信息。
Log4j2共有8种日志级别,
按照优先级从小到大排序:
当日志级别设置为某一级别时,
则会打印大于等于该级别的日志,
比如日志级别设置为ERROR,
则会打印ERROR,FATAL级别的日志。
ALL会把所有级别的日志打印出来,
OFF不会打印任何级别的日志,
所以严格来讲只有6种日志级别。
Log4j2能够在初始化期间自动配置,
它支持4种格式的配置文件:
Properties, YAML, JSON, XML
并且按从高到低的加权顺序查找配置文件。
Log4j2启动时,首先检查系统属性log4j.configurationFile,
如果设置了该属性,则匹配文件扩展名去加载配置文件,
就是说文件名可以是任意的,文件扩展名必须是上面的4种之一。
在启动应用时配置该参数,示例如下:
log4j.configurationFile可以配置如上的绝对路径,
也可以配置相对路径,即只配置文件名myLog4j2.xml,
Log4j2会在classpath路径中查找配置文件。
如果没有设置系统属性,
则在classpath路径中按照顺序查找如下4个文件:
如果找不到上面的文件,
则在classpath路径中按照顺序查找如下4个文件:
如果无法找到任何配置文件,
则使用默认配置文件,
这将导致日志输出到控制台。
在第4步中打印日志找不到配置文件,
使用的默认配置等价于下面的配置:
在上面的默认配置文件中,
主要有两类配置,
一类是Appenders:定义日志输出目的地,内容和格式等。
另一类是Loggers:定义日志级别和使用的Appenders。
表示日志输出到控制台的标准输出。
pattern定义日志输出格式:
实际会输出如下日志:
更多的PatternLayout设置请参考官网:
Log4j2 PatternLayout
新建log4j2.xml文件,
添加上面第7步的默认配置,
放到classpath路径下,
则应用启动时会读取该文件,
下面以该xml文件为例,
通过修改相应的配置,
演示Log4j2的功能。
实际上Log4j2的配置可以通过以下四种方式中的一种来完成:
本文主要介绍第1种,
详解XML格式文件的编写配置。
Log4j2内部日志可以输出到控制台,
status控制Log4j2内部日志的输出级别,
它的值可以填第5步中的日志级别,
Log4j2会输出初始化、翻转和其他内部操作的详细信息。
设置status="TRACE"对定位Log4j2问题非常有用。
也可以设置系统属性log4j2.debug,
也会将Log4j2内部日志打印到控制台,
包括在找到配置文件之前发生的内部日志。
在启动应用时配置该参数,示例如下:
Log4j2能够自动检测配置文件的修改,
并且自动重新加载配置。
通过在Configuration元素上配置monitorInterval属性,
并将其设置为非零值,
那么在下一次计算或记录日志事件,
且自上次检查以来已经超过monitorInterval时间,
则将检查该文件是否被修改。
注意时间单位默认为秒,
而且最小时间间隔是5秒。
如上示例为每隔至少5秒检查一次配置文件,
如果配置文件有变化则自动重新加载。
这里增加了一个类型为File的Appender,
name为File,
FileName为test.log,
表示日志会打印到test.log文件。
这里增加了一个Logger,需要配合上面的Appender使用,
name为Log4j2Test的包路径org.apache.logging.log4j,
level日志级别为EEROR,
AppenderRef指向了上面新增的名称为File的Appender,
表示Log4j2Test的ERROR和FATAL级别的日志会打印到test.log,
test.log文件内容:
同时additivity设置为true,
会将当前的Logger特性会传递给Root,
即上述的日志不仅会输出到test.log文件,
也会输出到Root指向的控制台,
Console控制台内容:
可以看到和上面文件中的内容一模一样。
Log4j2 入门教程
Log4j2 配置文件
Log4j2 Appenders
Frequently Asked Questions
Log4j2简介和异步日志梳理
log4j2是log4j 1.x 的升级版,参考了logback的一些优秀的设计,并且修复了一些问题,因此带来了一些重大的提升,主要有:
之前看官方文档摘抄了一些概念,这里懒得翻译了,使用log4j的都应该清楚,这里只是mark下。
log4j2最大的特点就是异步日志,其性能的提升主要也是从异步日志中受益,我们来看看如何使用log4j2的异步日志。
Log4j2提供了两种实现日志的方式,一个是通过AsyncAppender,一个是通过AsyncLogger,分别对应前面我们说的Appender组件和Logger组件。注意这是两种不同的实现方式,在设计和源码上都是不同的体现。
AsyncAppender是通过引用别的Appender来实现的,当有日志事件到达时,会开启另外一个线程来处理它们。需要注意的是,如果在Appender的时候出现异常,对应用来说是无法感知的。 AsyncAppender应该在它引用的Appender之后配置,默认使用 java.util.concurrent.ArrayBlockingQueue实现而不需要其它外部的类库。 当使用此Appender的时候,在多线程的环境下需要注意,阻塞队列容易受到锁争用的影响,这可能会对性能产生影响。这时候,我们应该考虑使用无所的异步记录器(AsyncLogger)。
AsyncAppender有一些配置项,如下:
除此之外还有一些其他的细节,如果感兴趣可以参考官网文档,这里就不一一列举了。
AsyncLogger才是log4j2 的重头戏,也是官方推荐的异步方式。它可以使得调用Logger.log返回的更快。你可以有两种选择:全局异步和混合异步。
全局异步
配置文件不用动:
在系统初始化的时候,增加全局参数配置:
你可以在你第一次获取Logger之前设置,也可以加载JVM启动参数里,类似
混合异步
混合异步只需要修改配置文件即可:
在上面示例的配置中,root logger就是同步的,但是com.foo.Bar的logger就是异步的。
在使用异步日志的时候需要注意一些事项,如下:
4、如果不是确实需要,不要打印location信息,比如HTML的location,或者pattern模式里的%C or $class, %F or %file, %l or %location, %L or %line, %M or %method, 等,因为Log4j需要在打印日志的时候做一次栈的快照才能获取这些信息,这对于性能来说是个极大的损耗。
关于性能测试,大家可以直奔官网,哪里有很详细的数据,这里给个图:
虽然我测下来,在immediateFlush设置为false的情况下,同步异步差不了多少,但可能是我的测试条件不符合官方的,从设计和原理上来说,异步日志,无疑是个最优的选择。
总的来说,看了一遍log4j的官网文档,对日志系统有了个比较全面的了解,以前只是copy配置来改改,没关注过很多细节,这次算是扫盲了一次。文章也只是做了个介绍,在实际使用中,还是要细细研究下配置。
另外,个人觉得异步模式无非就是在原来同步写盘的前提下,增加消息队列作为缓存,或者交个另一个线程去做,这理论上除了带来一些额外的,较小的cpu和内存的开销,应该会在高流量的时候带来不小的性能提升,对比下来,log4j2无疑是当下最值得使用的日志组件来,且可以使用其异步模式。
当然了,也不能说异步就一定好,如果日志的流量不是特别大,磁盘性能又跟得上,没有必要一定使用异步日志。
java的log4j2输出Exception e信息为什么不会换行?
try {
String myaddress = InetAddress.getLocalHost().getHostAddress().toString();
log.debug("myaddress:\r\n"+myaddress);
} catch (UnknownHostException ex) {
log.debug("message:",ex);
ex.printStackTrace();
}
实际测试,是会换行的
~~~~~
烽火狼烟丨Apache Log4j2远程代码执行漏洞(CVE44832)通告
漏洞概述
近日,WebRAY安全服务部监测到编号为CVE-2021-44832的Apache Log4j2远程代码执行漏洞。攻击者可以通过修改配置文件中JNDI 动态及远程获取数据库源处插入恶意代码,造成远程代码执行漏洞,但想要成功利用该漏洞需要攻击者有权限修改Log4j2的配置文件,利用难度较高。WebRAY安全服务部建议相关用户采取安全措施防止漏洞攻击。
Apache Log4j2是Log4j的升级版本,该版本与之前的log4j1.x相比性能显著提升;在修复了一些存在于Logback中固有的问题的同时,提供了很多在Logback中可用的性能。Apache Struts2、Apache Solr、Apache Druid、Apache Flink等均受影响。
影响范围
2.0-beta7 <= Log4j2<= 2.17.0(不包括安全修复版本 2.3.2 和 2.12.4)
漏洞等级
WebRAY安全服务部风险评级:中危
修复建议
建议用户及时升级到Log4j 2.3.2(适用于Java 6)、2.12.4(适用于Java 7)或 2.17.1(适用于 Java 8 及更高版本),官方下载地址:
https://logging.apache.org/log4j/2.x/download.html
注:从2.17.1版本(适用于 Java 8 及更高版本)、2.12.4(适用于Java 7)、2.3.2(适用于Java 6)开始,已删除对LDAP协议的支持,并且 JNDI 连接仅支持JAVA协议。启用JNDI的属性已从“log4j2.enableJndi”重命名为三个单独的属性:log4j2.enableJndiLookup、log4j2.enableJndiJms和log4j2.enableJndiContextSelector。
参考链接
https://logging.apache.org/log4j/2.x/security.html
https://github.com/apache/logging-log4j2
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44832
【日志】Log4j2配置
在同步日志模式下, Logback的性能是最糟糕的,log4j2的性能无论在同步日志模式还是异步日志模式下都是最佳的。本章主要介绍Spring Boot如何集成并配置使用Log4j2
引入Log4j2依赖包,其它依赖和Logback一样,使用SLF4J统一输出
然后需要在resource下面添加log4j2.xml配置文件,当然了如果你不添加,springboo会提示你没有对应文件,并使用默认的配置文件,这个时候级别可以在application.properties中配置
和logback配置类似,主要是含有loggers、appenders,其中loggers由logger,root组成。appenders由console(控制台),File、RollingFile(输出文件)组成,作用和配置和logback差不多
(1)Console 用来定义输出到控制台的Appender,主要设置输出格式和level级别
ThresholdFilter: 定义打印级别,onMismatch值设置是否拒绝其它 (2)File 用来定义输出到指定位置的文件的Appender
(3)RollingFile 用来定义超过指定条件自动删除旧的,创建新的Appender
参数说明:
Root节点用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出
参数说明:
变量配置,类似常量定义
默认情况下springboot是不将日志输出到日志文件中,这里对日志框架的支持有两种配置方式(和logback一样): (1)application.properties 或 application.yml (系统层面) (2)logback-spring.xml (自定义文件方式)
默认名log4j2-spring.xml,可以省下在application.yml中配置,如果自定义了文件名,需要在application.yml中配置
此种方式可以处理比较复杂的情况,比如区分 info 和 error 日志、每天产生一个日志文件。
通过在DefaultRolloverStrategy 标签下添加Delete标签实现,保留7天的日志
IfLastModified .age要和filePattern精确的时间一致, 否则貌似无效.
log4j2 配置简要分析
对于做后端的同学来说,log是分析bug、查找问题不可或缺的工具,好的日志配置将使我们的开发工作如虎添翼。 把视线聚焦到java,常用的日志工具有log4j,log4j2以及logback等,其中log4j2功能较为强大,运行效率也较高,我们就来用一个例子看一看log4j2的配置思路,下面就是这个配置文件:
我们看到,Configuration有2个属性status和monitorInterval,它们分别是log4j2自身组件的日志级别以及重新刷新配置文件的时间,通过配置status可以看到log4j2相关的日志,配置monitorInterval可以通过修改配置文件来改变日志配置。
从上面的log4j2.xml配置文件中,我们可以看到log4j2的配置文件中主要分为2块,一块为appender,描述了如何记录日志,另外一部分是log config,记录了哪种日志对应哪种级别。 而不同的LogConfig之间其实是有继承关系的,子LogConfig会继承parent的属性,而所有LogConfig都继承自Root LogConfig。所以即使只配置了root logger,你一样可以在任何地方通过LoggerFactory.getLogger获取一个logger对象,记录日志。
那么日志之间的继承关系是由什么决定的呢?看看上面的配置文件中root以外的2个logConfig,只有3个配置:日志级别,name以及appender,从直觉上看应当是name最可能决定了LogConfig的继承关系,其实也正是如此:com.foo是com.foo.Bar的父级;java是java.util的父级,是java.util.vector的祖先(注意name区分大小写)。
理解了这一点,我们就能理清log4j2配置的思路:先配置一个root,让所有需要使用日志的logger继承,然后对有特别需要的logger进行特殊的配置,比如我们希望 org.springframework 包只记录error以及warn级别的log,再比如,我们希望能显示mybatis执行的sql的日志,都可以进行个性化的配置。
appender是LogConfig的重要组成部分,一个LogConfig可以使用多个appender,一个appender也可以被多个LogConfig使用,appender多种多样,不同的appender也有不同的属性和配置,难以一一阐述,需要使用时可以直接查看文档来进行个性化配置。不过就filters可以单独拿出来讨论一下。filter有两个重要属性 onMatch 和 onMismatch 。可以有DENY、ACCEPT或NEUTRAL配置,DENY说明不由当前appender处理,ACCEPT说明由当前filter处理,而NEUTRAL说明如果按顺序还有其他filter则由其他filter处理,如果当前filter已经是最后一个filter,则由当前appender处理。
log4j2的官方文档建议记录程序行为日志异步日志,效率更高。因为异步日志使用的是无锁技术,所以需要引入 Disruptor 。然后可以通过配置异步的appender或Logger来实现异步日志:
或
动态修改日志级别是一个很实用的功能,关于如果动态修改日志级别,请参考美团的一篇文章: 日志级别动态调整——小工具解决大问题
以上就是对log4j2的配置的一些总结,更多信息请关注官方文档。
Log4j2进阶使用(按大小时间备份日志)
本文介绍Log4j2进阶使用,
基本使用请参考 Log4j2基本使用入门 。
本文基于上面的基本使用入门,
主要介绍按照日志大小和时间备份日志,
并且限制备份日志的个数,
以及删除过期的备份日志。
由于日志信息是不断追加到日志文件的,
经过一段时间会导致日志文件很大,
所以需要及时分割过大的日志文件,
以及限制日志文件占用的硬盘空间,
及时清理掉不用的过期的日志文件。
RollingFileAppender能实现上面提出的需求,
它需要配置TriggeringPolicy和RolloverStrategy,
TriggeringPolicy触发策略决定何时执行备份,
RolloverStrategy翻转策略决定如何执行备份。
如果没有配置RolloverStrategy翻转策略,
RollingFileAppender将使用DefaultRolloverStrategy,
而且DefaultRolloverStrategy支持自定义删除文件操作。
LOG_HOME用于指定当前日志存放的目录,
LOG_BACKUP用于指定备份日志存放的目录,
FILE_NAME用于指定日志文件的名称。
在需要的地方使用${LOG_HOME}引用即可。
本章通过配置log4j2.xml,
实现如下目标:
最多保存3个日志备份文件,
每个日志文件大小不超过1MB。
这里增加了一个类型为RollingFile的Appender,
name为RollingSizeFile,
FileName为${LOG_HOME}/${FILE_NAME}.log,
指定了当前正在打印的日志文件名称,
和文件存放的相对路径;
filePattern为${LOG_HOME}/${LOG_BACKUP}/${FILE_NAME}-%i.log,
指定了备份后的日志文件名称和存放路径,
其中%i表示备份文件名按照正整数开始递增。
SizeBasedTriggeringPolicy策略指定了文件大小:
当日志文件达到1MB时生成备份文件,
大小以字节为单位指定,
后缀为KB、MB或GB,例如1GB。
如果不填,默认值为10MB。
AppenderRef指定打印日志到新增的name为RollingSizeFile的Appender。
运行测试程序,
打印一段时间的日志,
在项目下会生成如下目录和文件:
可以看到logs目录下有test.log文件和backup目录,
backup目录下有test-1.log等7个备份文件,
而且每个文件的大小都是1MB。
上面由于没有配置RolloverStrategy滚动策略,
RollingFileAppender使用DefaultRolloverStrategy,
DefaultRolloverStrategy默认最多保存7个备份文件。
RollingFile中增加DefaultRolloverStrategy默认滚动策略,
并且指定最多保存3个备份文件:
修改后效果如下:
本章通过配置log4j2.xml,
实现如下目标:
每1分钟备份一次日志文件,
删除3分钟前备份的日志文件。
这里的配置和第4步中略有不同,
name为RollingTimeFile,
主要是filePattern、TimeBasedTriggeringPolicy配置不一样,
filePattern为${LOG_HOME}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd-HH-mm}.log,
其中$${date:yyyy-MM}指定了备份文件存放的目录为当前年月,
比如目录2019-09,而不是backup了,
${FILE_NAME}-%d{yyyy-MM-dd-HH-mm}.log指定了备份后的日志文件名称,
精确到分钟的一个时间戳。
TimeBasedTriggeringPolicy策略指定了生成备份文件的策略。
这个配置要和filePattern结合使用,
上面filePattern中的命名规则是${FILE_NAME}-%d{yyyy-MM-ddHH-mm}.log,
最小的时间粒度是mm,即分钟,
而TimeBasedTriggeringPolicy设置的interval是1,
结合起来就是每1分钟生成一个新文件。
同理,如果要每1小时生成一个新文件,
则改成%d{yyyy-MM-ddHH},最小粒度为小时,
如果再把interval该为12,
那就是每12小时生成一个新文件。
AppenderRef指定打印日志到新增的name为RollingTimeFile的Appender。
运行测试程序,
打印一段时间的日志,
在项目下会生成如下目录和文件:
可以看到logs目录下有test.log文件和2019-09备份目录,
2019-09目录下有test-2019-09-27-17-20.log等14个备份文件,
而且每个文件的大小都不一样,与该时间段内打印的日志多少有关。
随着时间推移会生成2019-10之类的目录,
而且目录下的备份文件也会越来越多。
RollingFile中增加DefaultRolloverStrategy策略,
删除3分钟前备份的日志文件:
Delete表示删除满足条件的文件,
basePath指定了需要处理的日志目录,
因为备份的日志在basePath下的年月目录($${date:yyyy-MM}),
所以maxDepth设置为2,代表扫描的目录深度,
maxDepth="1"表示当前目录。
指定文件名称:
匹配二级目录下的扩展名为.log的文件。
指定文件过期时间:
age的单位:D、H、M、S,分别表示天、小时、分钟、秒。
匹配最后修改时间为3分钟前的文件。
修改后效果如下:
查看目录时的当前时间是2019-09-29 15:44,
可以看到只保存了3分钟内生成的3个日志,
随着时间的推移,
生成新日志test-2019-09-29-15-44.log,
删除旧日志test-2019-09-29-15-41.log,
该目录下始终只有当前时间3分钟内的备份日志。
可以把按大小和时间备份结合起来使用,
实现更复杂的日志文件备份需求。
本章通过配置log4j2.xml,
实现如下目标:
每1分钟备份一次日志文件,
每个日志文件大小不超过1MB,
如果在1分钟内日志文件超过1MB,
则生成以当前时间+序号的备份日志,
但是每分钟内最多保存3个备份日志,
并且删除5分钟前备份的日志文件。
大部分配置和上面说过的一致,
就是简单的组合起来即可,
需要注意的是filePattern:
备份文件名${FILE_NAME}-%d{yyyy-MM-dd-HH-mm}-%i.log结合了时间和序号。
运行测试程序,
打印一段时间的日志,
在项目下会生成如下目录和文件:
看到2019-09目录下只有5分钟内的备份日志,
每分钟的备份日志最多有3个文件,
根据日志具体打印的情况,
少的时候可能1分钟只有1或者2个文件,
多的时候最多也只有3个文件,
在这1分钟内后生成的日志会覆盖掉前面的。
下面给出完整的配置文件,
供大家开发时参考使用:
slf4j+log4j2基础教程(拿来即用教程)
log4j2 RollingRandomAccessFile配置
log4j2 入门教程
log4j2 异步日志原理及配置
log4j2通过讲打日志流程中的部分阶段进行异步化,使得日志打印性能得到了很大的提升。
要想了解log4j如果实现异步日志,进而提升性能,就需要先了解日志打印的基本过程。
在log4j中,有两个重要的概念,分别是 Logger 、 Appender 。Logger是负责具体的生产日志数据,我们平时的Logger.info(...)就是生产日志数据的过程。Appender则是负责讲数据搬运到目的地,如console、文件、hive、网络设备等等。
而log42实现异步日志,主要包括以下两种方式:
异步Logger通过使用LMAX Disruptor环形队列和单独的处理线程,避免了锁的竞争,从而实现更高的吞吐量。队列大小默认4096,通过以下参数,可以开启异步日志。
异步Appender则是使用了java中的ArrayBlockingQueue,默认队列大小1024。log4j2官方测试,asyncLogger相比asyncAppender有更好的表现。
是否可以同时使用AsyncLogger + AsyncAppender?同时使用是否有更好表现?
据stackoverflow上回答,AsyncLogger是更新的异步机制,有更好的表现。AsyncAppender是之前的异步机制。同时使用也不会增加性能表现。见
https://stackoverflow.com/questions/24177601/difference-between-asynclogger-and-asyncappender-in-log4j2
https://logging.apache.org/log4j/2.x/manual/async.html
https://www.cnblogs.com/yeyang/p/7944906.html
https://bryantchang.github.io/2019/01/15/log4j2-asyncLogger/
SpringBoot-集成Log4j2
? 工作过程中一般我们都是接手的项目,可能只注意到怎么使用log4j,没有亲手设置过项目的log4j。本人也是,出于学习的目地,自己亲手试着在SpringBoot的项目中集成了一下log4j2。之于为什么要集成log4j2,本人网上也查了下,主要是:性能提升、自动重载配置
? SpringBoot默认集成的日志系统是LogBack,logBack是随着spring-boot-starter-logging引进来的,如图:
当然SpringBoot也是支持Log4j2,只需要去掉logback的依赖,引入Log4j2即可。
如果你需要用到Log4j2的AsyncLogger的异步日志实现方式,还需要引入Disruptor
异常说明 如果你的LogBack没有排干净(即被别的系统间接的引入了LogBack的jar),系统会报错,报错信息是很奇怪的
Logging system failed to initialize using configuration from 'classpath:-----.xml'
异常信息是:
? log4j2一般采用的是xml形式的配置,你需要在在resources目录下新建一个log4j2的配置文件,暂时名称为log4j2.xml。另外还需要在application.properties文件中显示声明才行
? 当然如果不配置logging.config,SpringBoot默认加载的文件名是:log4j2.xml、log4j2-file.xml这两个,在源码:org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.loadDefaults中:
? 到此SpringBoot集成Log4j2的工作已经完成,可能很多同学跟我一样,也想了解一下log4j2的配置,下面来介绍一下log4j2的日志配置。
常用的:root为同步日志输出,AsyncLogger为异步日志。异步日志输出注意三点: