1、log4j2 简介
Apache Log4j2是对Log4j的升级,它比其前身Log4j 1.x提供了重大改进,并提供了Logback中可用的许多改进,同时修复了Logback架构中的一些问题。被誉为是目前最优秀的Java日志框架。
2、项中引入 log4j2 的方式
2.1、springboot 项目中
<!-- spring-boot-starter 默认引入logback 需要排除 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions><!-- SpringBoot 默认携带自身的 log 日志功能,去掉默认配置 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入 log4j2 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
2.2、普通 java 项目中
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.2</version>
</dependency>
<!---------------log4j与slf4j集成----------------->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.6.2</version>
</dependency>
3、在项目中指定 log4j2 的配置文件
如果 log4j2 框架使用的是 springboot 默认的命名方式 log4j2-spring.xml ,则不需要配置,直接在项目的 resources 目录下创建 log4j2-spring.xml 文件即可;如果使用自定义命名的方式,需要在项目的配置文件中 application.yml 中添加以下配置。
logging:
config: classpath:my_log4j2.xml
4、log4j2 配置文件详解
4.1、configuration 标签
<configuration status="WARN" monitorInterval="30">
status:记录到控制台的内部Log4j事件的级别。此属性的有效值为 trace, debug, info, warn, error, fatal”。
monitorInterval: 从文件配置后,Log4j能够自动检测对配置文件的更改并自行重新配置。以便仅在至少30秒之后检查配置文件的更改。默认为5秒。
4.2、Properties 标签
Properties 标签定义全局属性,name属性必须存在且唯一,允许使用${name}来引用该变量。
<Properties>
<Property name="LOG_HOME">../logs/xxx</Property>
</Properties>
4.3、Appenders 标签
4.3.1、日志输出到控制台(Console 标签)
有几个参数:
name:指定Appender的名字;
target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT;
PatternLayout:输出格式,不设置默认为:%m%n。
<!--Console:日志输出到控制台标准输出 -->
<Console name="Console" target="SYSTEM_OUT">
<!-- 添加过滤器,只接受程序中DEBUG级别的日志进行处理-->
<ThresholdFilter level="DEBUG" onMatch="A***EPT" onMismatch="DENY"/>
<!--pattern:日期,线程名,日志级别,日志名称,日志信息,换行 -->
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%L] - %msg%n" />
</Console>
4.3.2、日志输出到文件(File 标签)
有以下几个参数:
name:指定Appender的名字;
fileName:指定输出日志的目的文件带全路径的文件名;
append:是否追加,默认为
PatternLayout:输出格式,不设置默认为:%m%n。
<File name="log" fileName="log/test.log" append="false">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
</File>
4.3.3、滚动日志输出到文件(RollingFile 标签)
有以下几个参数:
name:指定Appender的名字。
fileName:指定输出日志的目的文件带全路径的文件名。
PatternLayout:输出格式,不设置默认为:%m%n。
filePattern:指定新建日志文件的名称格式。
Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志。
TimeBasedTriggeringPolicy:Policies 子节点,基于时间的滚动策略,interval 属性用来指定多久滚动一次,默认是 1 小时。modulate=true用来对备份日志的生成时间纠偏,纠偏以0为基准进行,"0+interval"决定启动后第一次备份时间;
SizeBasedTriggeringPolicy:Policies 子节点,基于指定文件大小的滚动策略,size 属性用来定义每个日志文件的大小;
DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过 max 属性)。
<!--RollingFile:日志输出到文件,下面的文件都使用相对路径 -->
<!--fileName:当前日志输出的文件名称 -->
<!--filePattern:备份日志文件名称,备份目录为logs下面以年月命名的目录,备份时使用gz格式压缩 -->
<RollingFile name="RollingFile" fileName="${LOG_HOME}/${FILE_NAME}.log"
filePattern="${LOG_HOME}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%L] - %msg%n" />
<!--Policies:触发策略决定何时执行备份 -->
<Policies>
<!--TimeBasedTriggeringPolicy:日志文件按照时间备份 -->
<!--interval:每1天生成一个新文件,时间单位需要结合filePattern时间%d{yyyy-MM-dd} -->
<!--同理,如果要每1小时生成一个新文件,则改成%d{yyyy-MM-ddHH} -->
<!--modulate:对备份日志的生成时间纠偏,纠偏以0为基准进行,"0+interval"决定启动后第一次备份时间 -->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<!--SizeBasedTriggeringPolicy:日志文件按照大小备份 -->
<!--size:指定日志文件最大为100MB,单位可以为KB、MB或GB -->
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<!-- DefaultRolloverStrategy:翻转策略决定如何执行备份 -->
<!--max:最多保存5个备份文件,结合时间使用后,在每个时间段内最多有5个备份,多出来的会被覆盖 -->
<!-- ***pressionLevel:配置日志压缩级别,范围0-9,0不压缩,1压缩速度最快,9压缩率最好,目前只对于zip压缩文件类型有效 -->
<DefaultRolloverStrategy max="5" ***pressionLevel="1">
<!--Delete: 删除匹配到的过期备份文件 -->
<!--maxDepth: 由于备份文件保存在${LOG_HOME}/$${date:yyyy-MM},所以目录深度设置为2 -->
<Delete basePath="${LOG_HOME}" maxDepth="2">
<!--IfFileName:匹配文件名称 -->
<!--glob:匹配2级目录深度下的以.log.gz结尾的备份文件 -->
<IfFileName glob="*/*.log.gz" />
<!--IfLastModified:匹配文件修改时间 -->
<!--age:匹配超过180天的文件,单位D、H、M、S分别表示天、小时、分钟、秒-->
<IfLastModified age="180D" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
4.4、loggers 节点
常见的有两种:Root 和 Logger。
4.4.1、root 标签
Root 节点用来指定项目的根日志,如果没有单独指定 Logger,那么就会默认使用该 Root 日志输出。
level:日志输出级别;
AppenderRef:Root 的子节点,用来指定该日志输出到哪个 Appender。
4.4.2、logger 标签
Logger 节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。
level:日志输出级别;
name:用来指定该 Logger 所适用的类或者类所在的包全路径,继承自Root节点;
AppenderRef:Logger 的子节点,用来指定该日志输出到哪个 Appender,如果没有指定,就会默认继承自 Root。如果指定了,那么会在指定的这个 Appender 和 Root 的 Appender 中都会输出,此时我们可以设置 Logger 的 additivity="false" 只在自定义的 Appender 中进行输出。
4.5、Filter 标签
允许在以下四个位置中指定过滤器:由全局到局部依次是 configuration,Logger ,Appender ,Appender Reference。注意:全局 Filter 标签 Filters 放在 properties 标签之后。
常用的 filter:
1)、***positeFilter : 组合模式,用以向外界提供统一的访问接口。
2)、ThresholdFilter : 这个Filter负责按照所配置的日志级别过滤日志,等于或超出所配置级别的日志将返回onMatch结果。
3)、 LevelRangeFilter : 这个Filter也是负责按照日志级别过滤日志,只是相比较于ThresholdFilter,它比较的是指定区间范围。这里有一个需要密切注意就是其两个参数minLevel,maxLevel的配置;如果想要只保留WARN到ERROR级别的日志,那么应该如下配置:
<!-- 危险级别高的等级配置 作为minLevel的值 -->
<LevelRangeFilter minLevel="ERROR" maxLevel="WARN" onMatch="A***EPT">
</LevelRangeFilter>
4)、 DynamicThresholdFilter :这个Filter允许依据ThreadContext中是否存在特定的某些值,以及日志级别来过滤LOG。
<Configuration status="TRACE" monitorInterval="5" packages="***.kanq.extend.cat.log4j2">
<Filters>
<!-- 全局级别Filter -->
<LevelRangeFilter minLevel="DEBUG" maxLevel="ERROR" onMatch="DENY"></LevelRangeFilter>
</Filters>
<Appenders>
<RollingFile name="RollingFile" fileName="logs/app.log"
filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
<!-- Appender级别的Filter -->
<BurstFilter level="INFO" rate="16" maxBurst="100"/>
<PatternLayout>
<pattern>%d %p %c{1.} [%t] %m%n</pattern>
</PatternLayout>
<TimeBasedTriggeringPolicy />
</RollingFile>
</Appenders>
<Loggers>
<!-- Logger级别的Filter -->
<Root level="error">
<MapFilter onMatch="A***EPT" onMismatch="NEUTRAL" operator="or">
<KeyValuePair key="eventId" value="Login"/>
<KeyValuePair key="eventId" value="Logout"/>
</MapFilter>
</Root>
<Logger name="TestJavaScriptFilter" level="trace" additivity="false">
<!-- AppenderRef级别的Filter -->
<AppenderRef ref="List">
<ScriptFilter onMatch="A***EPT" onMisMatch="DENY">
<ScriptRef ref="filter.js" />
</ScriptFilter>
</AppenderRef>
</Logger>
</Loggers>
</Configuration>
4.6、指定使用的激活环境
在某个 appender 上添加 SpringProfile 标签,设置使用当前 appender 的激活环境。
<SpringProfile name="dev | staging">
<Console name="Out">
<PatternLayout pattern="%m%n"/>
</Console>
</SpringProfile>
5、log4j2-spring.xml 文件
<?xml version="1.0" encoding="UTF-8" ?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="debug" monitorInterval="5">
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--变量配置-->
<Properties>
<!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
<!-- %logger{36} 表示 Logger 名字最长36个字符
%date{YYYY:MM:dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} %l - %msg%n -->
<property name="LOG_PATTERN" value="%date{YYYY:MM:dd HH:mm:ss.SSS} [%thread] %-5level %l -%M - %msg%n"/>
<!-- 定义日志存储的路径 -->
<property name="FILE_PATH" value="D:\logs"/>
</Properties>
<appenders>
<!--控制台日志输出-->
<console name="Console" target="SYSTEM_OUT">
<!--运行日志输入文件-->
<!--<ThresholdFilter level="info" onMatch="A***EPT" onMismatch="DENY"/>-->
<!--日志的格式-->
<PatternLayout pattern="${LOG_PATTERN}"/>
<!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<!--控制台输出日志格式-->
<!--<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>-->
</console>
<!--
debug 运行时异常日志信息
-->
<RollingFile name="debugJournal" fileName="${FILE_PATH}/堆栈日志.log"
filePattern="logs/$${date:yyyy-MM-dd}/debug-%d{yyyy-MM-dd}-%i.log">
<!--文件只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="error" onMatch="A***EPT" onMismatch="DENY"/>
<!--日志消息输出格式-->
<PatternLayout pattern="${LOG_PATTERN}"/>
<!--日志拆分规则-->
<Policies>
<!--在系统启动时,生成一个新的日志文件-->
<OnStartupTriggeringPolicy/>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="0.001"/>
<SizeBasedTriggeringPolicy size="10 Kb"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下10个文件开始覆盖-->
<DefaultRolloverStrategy max="30"/>
</RollingFile>
<RollingFile name="infoJournal" fileName="${FILE_PATH}/运行日志.log"
filePattern="logs/$${date:yyyy-MM-dd}/run-%d{yyyy-MM-dd}-%i.log">
<!--文件只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="fatal" onMatch="A***EPT" onMismatch="DENY"/>
<!--日志消息输出格式-->
<PatternLayout pattern="${LOG_PATTERN}"/>
<!--日志拆分规则-->
<Policies>
<!--在系统启动时,生成一个新的日志文件-->
<OnStartupTriggeringPolicy/>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="0.001"/>
<SizeBasedTriggeringPolicy size="10 KB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下10个文件开始覆盖-->
<DefaultRolloverStrategy max="30"/>
</RollingFile>
</appenders>
<!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
<!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<!--过滤掉spring和mybatis的一些无用的信息-->
<logger name="org.mybatis" level="info" additivity="false">
<AppenderRef ref="Console"/>
</logger>
<!--监控系统信息-->
<!--若是additivity设为false,则子Logger只会在自己的appender里输出,不会在父Logger里输出。-->
<Logger name="org.springframework" level="info" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<root level="info">
<appender-ref ref="Console"/>
<appender-ref ref="infoJournal"/>
<appender-ref ref="debugJournal"/>
</root>
</loggers>
</configuration>
6、日志配置信息的符号解释
-X号 # X信息输出时左对齐;
%p # 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,
%d # 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
%r # 输出自应用启动到输出该log信息耗费的毫秒数
%c # 输出日志信息所属的类目,通常就是所在类的全名
%t # 输出产生该日志事件的线程名
%l # 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main (TestLog4.java:10)
%x # 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%% # 输出一个"%"字符
%F # 输出日志消息产生时所在的文件名称
%L # 输出代码中的行号
%m # 输出代码中指定的消息,产生的日志具体信息
%n # 输出一个回车换行符,Windows平台为"/r/n",Unix平台为"/n"输出日志信息换行
可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:
1) %20c # 指定输出全类名最小的宽度是20,如果全类名小于20的话,默认的情况下右对齐。
2) %-20c # 指定输出全类名最小的宽度是20,如果全类名小于20的话,"-"号指定左对齐。
3) %.30c # 指定输出全类名最小的宽度是30,如果全类名大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。
4) %20.30c # 如果全类名小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边较远输出的字符截掉
总结:log4j2 日志框架是基于 log4j 和 logback 的升级,是当前应用最为广泛的一种框架,以上详解足以完成开发需求,更加详细配置请参考:Log4j – Configuring Log4j 2。
本人是一个从小白自学计算机技术,对运维、后端、各种中间件技术、大数据等有一定的学习心得,想获取自学总结资料(pdf版本)或者希望共同学习,关注微信公众号:it自学社团。后台回复相应技术名称/技术点即可获得。(本人学习宗旨:学会了就要免费分享)