> 文章列表 > log4j2日志简单使用

log4j2日志简单使用

log4j2日志简单使用

log4j2日志使用

1、log4j2介绍

Apache Log4j2是对Log4j的升级版,
log4j2借鉴了logback的一些优秀的设计,并且修复了一些问题,因此带来了一些重大的提升,主要有:
1、异常处理:在logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异常处理机制。
2、性能提升:log4j2相较于log4j 1和logback都具有很明显的性能提升,在异步配置下是logback的10倍左右。
3、自动重载配置:参考了logback的设计,提供自动刷新参数配置,可以动态的修改日志的级别而不需要重启应用。
4、无垃圾机制,log4j2在大部分情况下,都可以使用其设计的一套无垃圾机制,避免频繁的日志收集导致的jvm gc。

详情可参考其官方文档:http://logging.apache.org/log4j/2.x/manual/configuration.html

log4j2既可以作为日志实现,也可以作为日志门面来使用,不过在日常开发中,习惯于将log4j2作为日志实现,slf4j作为日志门面来结合使用。

2、实践

2.1 pom依赖

  1. 若为本地maven工程的测试:

    在2.9之后,新增了对进程号的显示格式: %processId

    log4j2作为日志门面和 实现****所需导入如下依赖:

    <dependencies><!--log4j依赖:api和core--><!--log4j日志门面--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.13.3</version></dependency><!--log4j日志实现--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.13.3</version></dependency>
    </dependencies>

    slf4j作为日志门面,log4j2作为日志实现所需导入依赖:

    <dependencies><!--使用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-core</artifactId><version>2.13.3 </version></dependency>
    </dependencies>
    
  2. 若为Springboot工程,则需要引用如下依赖:

    如项目中有导入spring-boot-starter-web依赖包, 记得去掉spring自带的日志依赖spring-boot-starter-logging,如下:

    <dependencies><!--springboot工程需要使用的log4j2的依赖--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency><!--如果引用由web的依赖,需要排除掉spring自带的logging日志依赖-->   <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency>
    </dependencies>    

2.2 配置文件

添加上述依赖后,需要添加配置文件log4j2.xml,放置在resources目录下:

<?xml version="1.0" encoding="UTF-8"?>
<!-- status表示设置的日志级别,高于该级别的日志显示,monitorInterval配置成一个正整数,则每隔指定的时间(秒),log4j2会刷新一次配置。如果不配置则不会动态刷新 -->
<configuration status="info" monitorInterval="600" ><properties><property name="LOG_HOME">./logs</property><!--info日志的标准输出文件名字--><property name="FILE_NAME_INFO">std</property><!--error日志的标准输出文件名字--><property name="FILE_NAME_ERROR">error</property><!--日志输出的格式--><!--日期时间|日志级别|所属类的全类名|线程名|进程号|方法名|日志信息--><property name="PATTERN_LAYOUT">%d{yyyy-MM-dd HH:mm:ss}|%-5level|%c{5}|%t|%processId|%M|%m%n</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><!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用 --><!--append为true表示消息追加到指定文件中,false表示消息覆盖指定的文件内容,默认值是true --><RollingRandomAccessFile   name="info" fileName="${LOG_HOME}/${FILE_NAME_INFO}.log" append="true"filePattern="${LOG_HOME}/${FILE_NAME_INFO}.log.%d{yyyy-MM-dd}"><Policies><!--TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件, modulate="true" : 产生文件是否以0点偏移时间--><TimeBasedTriggeringPolicy/></Policies><!--       日志输出格式     --><PatternLayout pattern="${PATTERN_LAYOUT}"/></RollingRandomAccessFile  ><!--添加过滤器Filters,可以有选择的输出某个级别以上的类别  onMatch="ACCEPT" onMismatch="DENY"意思是匹配就接受,否则直接拒绝  --><RollingRandomAccessFile   name="error" fileName="${LOG_HOME}/${FILE_NAME_ERROR}.log"filePattern="${LOG_HOME}/${FILE_NAME_ERROR}.log.%d{yyyy-MM-dd}"><Policies><!--TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件, modulate="true" : 产生文件是否以0点偏移时间--><TimeBasedTriggeringPolicy/></Policies><Filters><!--记录error级别信息 --><ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/></Filters><!--输出日志的格式 --><PatternLayout pattern="${PATTERN_LAYOUT}"/></RollingRandomAccessFile  ></Appenders><!--然后定义logger,只有定义了logger并引入的appender,appender才会生效 --><loggers><root level="info"><appender-ref ref="Console"/><appender-ref ref="error" /><appender-ref ref="info"/></root><!--向root上报这个包下的debug级别的日志--><logger name = "com.kevin" level="debug" /></loggers>
</configuration>

2.3 测试代码

package com.kevin.log4j;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Test;/*** @Author Kevin* @Date 22:04 2023/4/18* @Description*/
public class Log4j2Demo {private static  Logger log = LogManager.getLogger();@Testpublic void log4j2DemoTest1(){System.out.println("===========显示打印Debug日志信息=============");log.debug("log level is DEBUG:{}","this is DEBUG log...");System.out.println("===========显示打印Info日志信息=============");log.info("log level is INFO:{}","this is INFO log...");System.out.println("===========显示打印Warn日志信息=============");log.warn("log level is WARN:{}","this is WARN log...");System.out.println("===========显示打印Error日志信息=============");log.error("log level is ERROR:{}","this is ERROR log...");}
}

在这里插入图片描述

控制台输出结果:
在这里插入图片描述

日志文件中的结果:
在这里插入图片描述

配置文件的格式: log2j配置文件可以是xml格式的,也可以是json格式的,
配置文件的位置: log4j2默认会在classpath目录下寻找log4j2.xml、log4j.json、log4j.jsn等名称的文件,如果都没有找到,则会按默认配置输出,也就是输出到控制台,也可以对配置文件自定义位置(需要在web.xml中配置),一般放置在src/main/resources根目录下即可

配置文件的名称: 必须为log4j2字样

个人踩坑: 将log4j2.xml配置成了log4j.xml,结果log4j2没有找到对应的xml配置,按照默认配置输出到控制台上:只显示error级别的日志信息:
在这里插入图片描述

2.4 配置文件详解

log4j2.xml文件的配置大致如下:

  • Configuration
    • properties
    • Appenders
      • Console
        • PatternLayout
      • File
      • RollingRandomAccessFile
      • Async
    • Loggers
      • Logger
      • Root
        • AppenderRef

1、Configuration: 为根节点,有status和monitorInterval等多个属性

  • status:用于表示控制log4j2的日志级别,其值的级别从小到大依次有: “trace”, “debug”, “info”, “warn”, “error” and “fatal”,只会显示高于status值级别的日志会显示。
  • monitorInterval:每隔多长时间重新读取配置文件,可以不重启应用的情况下修改配置,时间单位:秒;

2、 Appenders: 输出源,用于定义日志输出的地方
log4j2支持的输出源有很多,有控制台Console、文件File、RollingRandomAccessFile、MongoDB、Flume 等

  • Console: 控制台输出源,是将日志打印到控制台上,开发的时候一般都会配置,以便进行调试

  • File: 文件输出源,将日志写入到指定的文件,需要配置输入到哪个位置(例如:./app/logs)

  • RollingRandomAccessFile: 该输出源也是写入到文件,不同的是比File更加强大,可以指定当文件达到一定大小(如20MB)时,另起一个文件继续写入日志,另起一个文件就涉及到新文件的名字命名规则,因此需要配置文件命名规则;这种方式更加实用,因为你不可能一直往一个文件中写,如果一直写,文件过大,打开就会卡死,也不便于查找日志。

    RollingRandomAccseeFile:中有如下常用属性:

    • fileName 指定当前日志文件的位置和文件名称
    • filePattern 指定当发生Rolling时,文件的转移和重命名规则,大多用.log.时间进rolling:filePattern="${LOG_HOME}/${FILE_NAME_INFO}.log.%d{yyyy-MM-dd}">
    • SizeBasedTriggeringPolicy 指定当文件体积大于size指定的值时,触发Rolling
    • DefaultRolloverStrategy 指定最多保存的文件个数
    • TimeBasedTriggeringPolicy 这个配置需要和filePattern结合使用,注意filePattern中配置的文件重命名规则是${FILE_NAME}-%d{yyyy-MM-dd HH-mm}-%i,最小的时间粒度是mm,即分钟;若指定的size是1,结合起来就是每1分钟生成一个新文件。如果改成%d{yyyy-MM-dd HH},则最小粒度为小时,就会每一个小时生成一个文件

3、PatternLayout: 日志输出的格式

  • 控制台或文件输出源(Console、File、RollingRandomAccessFile)都必须包含一个PatternLayout节点,用于指定输出文件的格式(如 日志输出的时间 文件 方法 行数 等格式)

  • 例如 %d{yyyy-MM-dd HH:mm:ss}|%-5level|%c{5}|%t|%processId|%M|%m%n

  • 日期时间|日志级别|所属类的全类名|线程名|进程号|方法名|日志信息

    # 日志常用的显示格式含义:
    %c 输出所属类的全名,可写为 %c{Num} ,Num类名输出的范围 如:"com.kevin.study.DemoClass",%C{2}将使日志输出输出范围为:study.DemoClass
    %d 输出日志时间其格式为 可指定格式 如 %d{yyyy-MM-dd HH:mm:ss}等
    %l 输出日志事件发生位置,包括类目名、发生线程,在代码中的行数
    %n 换行符
    %m输出代码指定信息,如info(“message”),输出message 一般输出:%m%n放在最后
    %msg 显示日志文本
    %-5level 输出日志级别,-5表示左对齐并且固定输出5个字符,如果不足在右边补0
    %-5p 输出日志的优先级,即 FATAL ,ERROR 等; 与-5level效果一样
    %r 输出从启动到显示该条日志信息所耗费的时间(毫秒数)
    %t 输出产生该日志事件的线程名
    %processId 输出进程号,2.9之后新增
    %M 显示方法名
    

4、Loggers: 日志器

日志器分为:根日志器Root和自定义日志器,当根据日志名字获取不到指定的日志器时,就使用Root作为默认的日志器,自定义时需要指定每个Logger的名称name(对于命名可以以包名作为日志的名字,不同的包配置不同的级别等),日志级别level,相加性additivity(是否继承下面配置的日志器), 对于一般的日志器(如Console、File、RollingRandomAccessFile)一般需要配置一个或多个输出源AppenderRef;

每个logger可以指定一个level(TRACE, DEBUG, INFO, WARN, ERROR, ALL or OFF),不指定时level默认为ERROR

additivity指定是否同时输出log到父类的appender,缺省为true。

5、properties: 属性
使用来定义常量,以便在其他配置的时候引用,该配置是可选的,譬如:

  • 定义日志的存放位置 ,当前目录下的logs文件夹下:<property name="LOG_HOME">./logs</property>
  • 定义日志的输出格式:<property name="PATTERN_LAYOUT">%d{yyyy-MM-dd HH:mm:ss}|%5p|%c{5}|%t|%processId|%M|%m%n</properties>