Java 学习笔记 - 日志体系 SLF4J + Log4j2

Posted 笑虾

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 学习笔记 - 日志体系 SLF4J + Log4j2相关的知识,希望对你有一定的参考价值。

SLF4J

Simple Logging Facade for Java (SLF4J) 充当各种日志框架(例如 java.util.logging、logback、log4j)的简单外观或抽象(外观模式),允许最终用户在部署时插入所需的日志框架。(啥叫面向接口编程,这就是吧。)
SLF4J的出现是为了干掉上一个想一统江湖,却又力不从心的JCL(Jakarta Commons Logging)

  • 首先slf4j依赖。引入后,我们就可以嗨皮了…
<dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-api</artifactId>
   <version>2.0.0-alpha5</version>
</dependency>

官方 HelloWorld

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld 
  public static void main(String[] args) 
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  

到了具体部署时,我们再选择使用哪个日志框架,只需要引用一个依赖,就可以实现将SLF4J与目标日志框架进行绑定

Log4j2

  • 输出规则:
    • 门槛越高,输出越少。
    • 门槛比较低,那么比它严重的都会打印出来。比如设置了WARN,那么除了WARN,比它更严重的ERROR,FATAL都会打印出来。
  • 日志级别(门槛):共8个,从高到低:
Standard LevelintLevel说明
OFF0【最高冷】不打印任何日志
FATAL100崩溃
ERROR200报错
WARN300警告
INFO400
DEBUG500打印 SQL 执行语句
TRACE600打印 SQL 结果
ALLInteger.MAX_VALUE【最低】打印所有日志

添加适配器依赖

绑定log4j2实现:

		<!-- 绑定实现:slf4j 绑定到 log4j2  -->
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-slf4j-impl</artifactId>
			<version>$log4j.version</version>
		</dependency>
		<!-- log4j2 应用于 web 项目时,解决资源释放问题  -->
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-web</artifactId>
			<version>$log4j.version</version>
			<scope>runtime</scope>
		</dependency>

web.xml 配置

SpringMVC项目 src/main/webapp/WEB-INF/web.xml

    <!-- 这个是默认的只可以省  -->
	<context-param>
		<param-name>log4jConfiguration</param-name>
		<param-value>classpath:log4j2.xml</param-value>
	</context-param>
	
	<!-- log4j2-begin -->
	<listener>
		<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
	</listener>
	<filter>
		<filter-name>log4jServletFilter</filter-name>
		<filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>log4jServletFilter</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>REQUEST</dispatcher>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>INCLUDE</dispatcher>
		<dispatcher>ERROR</dispatcher>
	</filter-mapping>
	<!-- log4j2-end -->

如果是log4jlog4j2记得清理垃圾。去掉log4j的配置

<context-param>
	<param-name>log4jConfigLocation</param-name>
	<param-value>classpath:properties/log4j.properties</param-value>
</context-param>

log4j2.xml

  • 添加配置文件 :src/main/resources/log4j2.xml
  • 输出
    • 控制台:打印 DEBUG 和比它更严重的日志。
    • all.log:和控制台一样,写到日志文件,备份。(这个有点猛,硬盘抗不住)
    • error.log:单独记录所有错误日志。
    • mybatis.log:单独记录mybatis执行的SQL和结果
<?xml version="1.0" encoding="UTF-8"?>
<!-- 
status 日志级别。当设置成trace时,你会看到log4j2内部各种详细输出。
monitorInterval:自动检测修改配置,设置间隔秒数。
    %d: 表示日期
    %level:表示日志级别,%-5level,表示5个占位符
    %C: 包名 (%F: 类文件名,这里没加)
    %t: 方法名
    %L: 行号
    %m: 消息体(即我们填的信息)
    详见:本文底部:log4j2 官方文档 - log4j - PatternLayout
-->
<configuration status="error" monitorInterval="30">
    <properties>
        <!-- 存log文件的根目录。 $log4j.logFileBasePath 是 pom.xml 中定义的环境变量 -->
        <property name="LOG_HOME">$log4j.logFileBasePath</property>
        <!-- 日志内容格式化 -->
        <property name="PATTERN_LAYOUT">%-5level %dyyyy-MM-dd HH:mm:ss.SSSGMT+8 %class36 %L %M - %msg%xEx%n</property>
        <!-- RollingFile 备份位置 -->
        <property name="errorBakPattern">$log4j.logFileBasePath/error/$$date:yyyy-MM/error-%dyyyy-MM-dd-%i.log.gz</property>
        <property name="mybatisBakPattern">$log4j.logFileBasePath/mybatis/$$date:yyyy-MM/mybatis-%dyyyy-MM-dd-%i.log.gz</property>
    </properties>

    <!--先定义所有的 appender-->
    <appenders>
        <!--【控制台】-->
        <Console name="Console" target="SYSTEM_OUT">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
            <!--这个都知道是输出日志的格式-->
            <PatternLayout pattern="$PATTERN_LAYOUT"/>
        </Console>
        
        <!--【完整日志】-->
        <File name="ALL" fileName="$LOG_HOME/all.log" append="false">
            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY" />
            <PatternLayout charset="UTF-8" pattern="$PATTERN_LAYOUT"/>
        </File>
        
        <!--【错误日志】-->
        <RollingFile name="ERROR" fileName="$LOG_HOME/error.log" filePattern="$errorBakPattern">
            <PatternLayout charset="UTF-8" pattern="$PATTERN_LAYOUT"/>
            <!--输出error及以上级别的日志-->
            <Filters>
                <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <!--单个文件大小,超过后按filePattern重命名并压缩归档-->
            <SizeBasedTriggeringPolicy size="50MB"/>
            <!-- 同一文件夹下最多几个文件,默认7个 -->
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>
        
        <!--【Mybatis日志】-->
        <RollingFile name="Mybatis" fileName="$LOG_HOME/mybatis.log" filePattern="$mybatisBakPattern">
            <PatternLayout charset="UTF-8" pattern="$PATTERN_LAYOUT"/>
            <Filters>
                <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <SizeBasedTriggeringPolicy size="50MB"/>
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>
    </appenders>
    <!--定义logger,不指定 appender-ref 会从父级向上找-->
    <loggers>
        <!--
        	mybatis 日志(好像不支持通配符,以后一定把Dao放在一块555)
        	additivity="false" 不向父级传递,因为不想父级再打一遍,
        	那样就与 <logger name="com.jerry" /> 重复了。
        -->
        <logger name="com.jerry.event.node.dao" level="trace" additivity="false">
            <appender-ref ref="Mybatis"/>
        </logger>
        <logger name="com.jerry.event.info.dao" level="trace" additivity="false">
            <appender-ref ref="Mybatis"/>
        </logger>
        <logger name="com.jerry.event.flow.dao" level="trace" additivity="false">
            <appender-ref ref="Mybatis"/>
        </logger>
        <logger name="com.jerry.event.extension.dao" level="trace" additivity="false">
            <appender-ref ref="Mybatis"/>
        </logger>
        <logger name="com.jerry.event.eventoutsize.dao" level="trace" additivity="false">
            <appender-ref ref="Mybatis"/>
        </logger>
        <logger name="com.jerry.event.mapper" level="trace" additivity="false">
            <appender-ref ref="Mybatis"/>
        </logger>
        <!--为当前项目项目定义 logger-->
        <logger name="com.jerry" />
        <!--root的logger-->
        <root level="debug">
            <appender-ref ref="Console"/>
            <appender-ref ref="ALL"/>
            <appender-ref ref="ERROR"/>
        </root>
    </loggers>
</configuration> 

参考资料

log4j2 核弹大锅,顺便学习 SLF4J 与 log4j2 各日志框架关系

log4j2 官方文档 - log4j - PatternLayout
Mybatis 官方文档 - 日志

java日志发展史 log4j slf4j log4j2 jul jcl 日志和各种桥接包的关系
聊一聊log4j2配置文件log4j2.xml

以上是关于Java 学习笔记 - 日志体系 SLF4J + Log4j2的主要内容,如果未能解决你的问题,请参考以下文章

Java 日志体系jcl 和 slf4j

Java日志体系 —— slf4j

Java日志体系 —— 日志框架切换

Java日志体系最佳实践

[springboot]Slf4j日志框架的体系结构

Java日志体系 —— 那些年那些事,那些日志的历史