零、前言
最近做课设想到要用日志来打印输出,因此我想到了log4j2这一个日志实现,虽然这个日志最近爆出了大漏洞。我用的是slf4j作为门面,log4j2作为日志实现。这篇文章只是我简单的学了一下后记录的笔记,如果有错误可以在评论区指出,我看到的话就会修改。
一、配置文件节点解析
来源:https://www.cnblogs.com/hafiz/p/6170702.html
根节点Configuration,有两个属性:
status属性:用来指定log4j本身的打印日志的级别。(也就是log4j自身能输出的日志的级别)- 日志级别排序:
<!-- 日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
- 日志级别排序:
monitorinterval属性:用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s。(这一属性我没用过)
根节点Configuration内有两个节点:
-
Appenders节点:-
我的理解是,通过设置一个
Appender节点,可以做到过滤,日志输出格式的工作,比如以下是我写的输出到控制台的一个Appender:-
<Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="[%highlight{%p}{error=red}] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" /> <!-- 注意, 这里的过滤不会影响到其它appender --> <Filters> <ThresholdFilter level="INFO" onMatch="ACCEPT " onMismatch="DENY" /> </Filters> </Console>
-
-
常见的有三种子节点:
Console、RollingFile、File。-
Console节点用来定义输出到控制台的Appender:-
name属性:指定Appender的名字。 -
target属性:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT。 -
PatternLayout节点:输出格式,不设置默认为:%m%n。- 以下来源https://blog.csdn.net/manmanxiaohui/article/details/79922546:
-
<!-- ========================== 自定义输出格式说明================================ --> <!-- %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL --> <!-- %r 输出自应用启动到输出该log信息耗费的毫秒数 --> <!-- %c 输出所属的类目,通常就是所在类的全名 --> <!-- %t 输出产生该日志事件的线程名 --> <!-- %m 表示要打印的日志信息 --> <!-- %n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n” --> <!-- %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921 --> <!-- %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlo4.main(TestLog4.java:10) --> <!-- ========================================================================== -->
-
-
File节点用来定义输出到指定位置的文件的Appender:name属性:指定Appender的名字。fileName属性:指定输出日志的目的文件带全路径的文件名。PatternLayout节点:输出格式,不设置默认为:%m%n。
-
RollingFile节点用来定义超过指定大小自动删除旧的创建新的的Appender(这个我暂时没用上):-
name属性:指定Appender的名字. -
fileName属性:指定输出日志的目的文件带全路径的文件名。 -
PatternLayout节点:输出格式,不设置默认为:%m%n。 -
filePattern属性:指定新建日志文件的名称格式。 -
Policies节点:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志-
TimeBasedTriggeringPolicy节点:Policies子节点,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am…而不是7am。 -
SizeBasedTriggeringPolicy节点:Policies子节点,基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小。
-
-
DefaultRolloverStrategy节点:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)。
-
-
-
-
Loggers节点:- 常见的有两种:
Root和Logger。 Root节点:- 用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出。
level属性:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF。AppenderRef节点:Root的子节点,用来指定该日志输出到哪个Appender。
Logger节点:- 用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。
level属性:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF。name属性:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点。AppenderRef节点:Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root。如果指定了,那么会在指定的这个Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity="false"只在自定义的Appender中进行输出。
- 常见的有两种:
二、日志过滤
-
日志级别:
<!-- ALL < TRANCE < DEBUG < INFO < WARN < ERROR < FATAL < OFF--><ThresholdFilter level="INFO" onMatch="" onMismatch=""/>- onMatch:意思是当前级别以及以上要怎么处理:ACCEPT 接收, NEUTRAL 往后走 DENY拒绝
- onMismatch:意思是当前级别(不包括当前级别)以下要怎么处理:ACCEPT 接收,NEUTRAL 往后走 DENY拒绝
- (总结:onMatch 是 >= 当前级别 onMismatch 是< 当前级别)
-
场景一:假如我们想要 INFO级别到ERROR级别之间的输出到控制台,其他的忽略,思路如下分析。
<!-- 经过分析也就是大于等于INFO级别的日志 往后走NEUTRAL进入下一个过滤器其他的拒绝 DENY。然后在下一个过滤器中,我让大于等于FATAL的拒绝DENY,小于的接受ACCEPT。-->
<Filters>
<ThresholdFilter level="INFO" onMatch="NEUTRAL " onMismatch="DENY"/>
<ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="ACCEPT"/>
</Filters>
第二种方式实现:让小于FATAL的往后走,其他的拒绝,然后进入下一个过滤器。在下一个过滤器中,让大于等于INFO的接受其他的拒绝。
<Filters>
<ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
- 场景二:我需要info之后的日志,忽略掉比info级别小的日志。
- 这个更简单,直接大于等于info的接受,小于的拒绝。
- 大于等于:onMath=“ACCEPT” 小于的 onMismatch=“DENY”
<ThresholdFilter level="FATAL" onMatch="ACCEPT" onMismatch="DENY"/>
只要不是截取一个日志级别范围一个过滤器就够了,不需要流动NEUTRAL到第二个过滤器。只有在截取日志级别大于某个级别小于某个级别的时候,才需要两个过滤器。实现方式就是场景一描述的那样。看了这篇文章相信你能彻底掌握。
-
总结一遍:不要刻意在意 ACCEPT NEUTRAL DENY这三个词的意思,理解的核心在于:onMatch 是匹配到当前级别以及大于当前级别的日志怎么怎么样。onMismatch是当前级别以下的日志不包含当前级别你要怎么处理。 无论是onMatch 还是onMismatch都有三个值。 是往后流动NEUTRAL 还是接受ACCEPT 或者是DENY。
-
最后,完整的使用是将其加入到
Appender下:-
<Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" /> <!-- 注意, 这里的过滤不会影响到其它appender --> <Filters> <ThresholdFilter level="INFO" onMatch="ACCEPT " onMismatch="DENY" /> </Filters> </Console>
-
三、关于日志级别
来源:https://www.cnblogs.com/hafiz/p/6170702.html
关于日志level。共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
- All:最低等级的,用于打开所有日志记录。
- Trace:是追踪,就是程序推进以下,你就可以写个trace输出,所以trace应该会特别多,不过没关系,我们可以设置最低日志级别不让他输出。
- Debug:指出细粒度信息事件对调试应用程序是非常有帮助的。
- Info:消息在粗粒度级别上突出强调应用程序的运行过程。
- Warn:输出警告及warn以下级别的日志。
- Error:输出错误信息日志。
- Fatal:输出每个严重的错误事件将会导致应用程序的退出的日志。
- OFF:最高等级的,用于关闭所有日志记录。
四、我的配置
- 我这里用了slf4j充当门面,然后用了log4j2作为实现:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.1</version>
<!-- <scope>test</scope> -->
</dependency>
- log4j的配置文件,我目前写的一个简单配置:
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!-- Configuration后面的status, 这个用于设置log4j2自身内部的信息输出, 可以不设置, 当设置成trace时, 你会看到log4j2内部各种详细输出 -->
<Configuration status="OFF">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" />
<!-- 注意, 这里的过滤不会影响到其它appender -->
<Filters>
<ThresholdFilter level="INFO" onMatch="ACCEPT " onMismatch="DENY" />
</Filters>
</Console>
<!-- 输出到fileName文件的一个appender -->
<File name="WarnFile" fileName="./src/main/java/com/jie/log/warn.log" append="true">
<PatternLayout pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" />
<!-- 只接受warn -->
<Filters>
<!-- WARN及以上的走下一个过滤器, 以下的全部禁掉 -->
<ThresholdFilter level="WARN" onMatch="NEUTRAL" onMismatch="DENY" />
<!-- ERROR及以上的全部禁掉, 以下的全部放行 -->
<ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="ACCEPT" />
</Filters>
</File>
<File name="ErrorFile" fileName="./src/main/java/com/jie/log/error.log" append="true">
<PatternLayout pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" />
<!-- 只接收error及以上 -->
<Filters>
<ThresholdFilter level="ERROR" onMatch="NEUTRAL" onMismatch="DENY" />
<ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="ACCEPT" />
</Filters>
</File>
</Appenders>
<Loggers>
<!-- 默认的root的logger -->
<!-- 这里的level是当前级别包括以上的用下面的appender -->
<Root level="all">
<!-- 输入到控制台的appender用下面这一个 -->
<AppenderRef ref="Console" />
<!-- 将warn输入到warn.log -->
<AppenderRef ref="WarnFile" />
<!-- 将error输入到error.log -->
<AppenderRef ref="ErrorFile" />
</Root>
</Loggers>
</Configuration>
- log4j2只支持
xml格式。(log4j倒是支持properties格式) - 别人的配置,来源:https://www.cnblogs.com/hafiz/p/6170702.html:
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="WARN" monitorInterval="30">
<!--先定义所有的appender-->
<appenders>
<!--这个输出控制台的配置-->
<console name="Console" target="SYSTEM_OUT">
<!--输出日志的格式-->
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
</console>
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用-->
<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>
<!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileInfo" fileName="${sys:user.home}/logs/info.log"
filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
<RollingFile name="RollingFileWarn" fileName="${sys:user.home}/logs/warn.log"
filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
<DefaultRolloverStrategy max="20"/>
</RollingFile>
<RollingFile name="RollingFileError" fileName="${sys:user.home}/logs/error.log"
filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
</appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
<logger name="org.springframework" level="INFO"></logger>
<logger name="org.mybatis" level="INFO"></logger>
<root level="all">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
</configuration>
五、getLogger(x.class)的原因
-
对于
public static final Logger logger = LoggerFactory.getLogger(x.class);,我的建议是只在x里用这个logger,因为假设我在y类里用了这个logger,那么如果我想屏蔽x类的日志,我会顺便屏蔽掉y类的日志。 -
比如如下例子:
-
public class ServerApplication { /** * 传入class是用于可以过滤这个类的日志 */ public static final Logger logger = LoggerFactory.getLogger(ServerApplication.class); public static void main(String[] args) { logger.info("服务器启动."); logger.info("服务器关闭."); } } -
public class Other { private static final Logger logger = LoggerFactory.getLogger(Other.class); private static final Logger logger1 = LoggerFactory.getLogger(ServerApplication.class); public static void main(String[] args) { ServerApplication.logger.warn("哈哈哈1"); logger1.warn("哈哈哈2"); logger.warn("哈哈哈3"); } } -
<Logger name="com.jie.server.ServerApplication" level="ERROR" additivity="false"> <AppenderRef ref="Console" /> </Logger>
-
-
运行
Other.main的结果:-
[WARN] [2021-12-30 23:17:45 下午]:com.jie.server.Other.main(Other.java:19) [message] 哈哈哈3
-
-
我只想屏蔽
ServerApplication类的日志的error级别以下的输出,但是运行Other.main后,发现只输出了哈哈哈3,把Other类使用的ServerApplication类的logger的日志输出屏蔽了,因此我不太建议用别的类的Logger。- 不过这种方式可能也有其他用处,需要结合实际使用。
本文详细介绍了如何使用SLF4J和Log4j2进行日志配置,包括日志级别、Appender配置(Console、File、RollingFile)、过滤器的使用以及日志过滤策略。通过示例展示了如何设置不同级别的日志输出到不同的文件,并解释了配置文件中各个属性的作用。同时,文章讨论了为什么在代码中使用`getLogger(x.class)`的原因,强调了类与日志关联的重要性。

1万+

被折叠的 条评论
为什么被折叠?



