Log4j2如何使用

什么是日志

日志(Log)是软件系统运行时记录的重要事件、状态信息和操作轨迹的机制。它是软件开发、测试和维护过程中不可或缺的工具,具有以下特点和作用:

  1. 问题诊断:当系统出现异常或错误时,日志提供了问题发生的上下文信息,帮助开发人员快速定位问题根源
  2. 行为追踪:记录用户操作和系统行为,便于审计和追踪业务流程
  3. 性能监控:通过记录关键操作的时间戳,可以分析系统性能瓶颈
  4. 安全审计:记录系统访问和敏感操作,满足合规性要求
  5. 运行状态记录:保存系统运行期间的重要状态变化,便于事后分析

日志通常分为不同级别,便于过滤和分类处理:

  1. FATAL/ERROR:错误,严重错误事件,可能导致系统崩溃或功能失效
  2. WARN:警告,输出警告的信息,潜在的有害情况,需要引起注意但不会立即影响系统运行
  3. INFO:信息,输出重要的运行时信息,记录系统正常运行状态
  4. DEBUG:调试,一般在开发中都设置的最低级别,详细的调试信息,用于开发阶段问题排查
  5. TRACE:追踪,最低的日志级别,最详细的跟踪信息,记录程序执行的详细路径

级别高的日志会自动屏蔽级别低的日志

日志的输出目的地指定了日志将会打印到控制台还是文件中,输出格式控制了日志信息的显示内容

Log4j2作为Java生态中最流行的日志框架之一,提供了强大的日志记录能力,能够满足上述所有日志需求。

简介

Log4j的1.x版本虽然已经被广泛使用于很多应用程序中,但由于出现内存泄漏等bug,代码难以维护,以及需要使用老版本的jdk等劣势,在2015年8月已经玩完。它的替代品,SLF4J,Logback,Log4j2对日志框架做了很多必要的改进。

历史上出现了很多的日记框架,如:

Log4j:Apache Log4j是一个基于Java的日志记录工具。它是由Ceki Gülcü首创的,现在则是Apache软件基金会的一个项目。 Log4j是几种Java日志框架之一。

Log4j2:Apache Log4j 2是apache开发的一款Log4j的升级产品。

Commons Logging:Apache基金会所属的项目,是一套Java日志接口,之前叫Jakarta Commons Logging,后更名为Commons Logging。

Slf4j:类似于Commons Logging,是一套简易Java日志门面,本身并无日志的实现。(Simple Logging Facade for Java,缩写Slf4j)。

Logback:一套日志组件的实现(Slf4j阵营)。

Jul(Java Util Logging):自Java1.4以来的官方日志实现。

安装

在开发中使用Log4j2日志记录框架需要引入的jar包如下:

1
2
log4j-api-2.13.0.jar
log4j-core-2.13.0.jar

maven中配置xml如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<properties>
<logging.log4j.version>2.13.0</logging.log4j.version>
</properties>

<dependencies>
<!-- Log4j2日志记录框架 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${logging.log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${logging.log4j.version}</version>
</dependency>
</dependencies>

配置文件

在项目的src根目录下,创建log4j2.xml配置文件。配置信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="UTF-8"?>
<!-- log4j2 配置文件 -->
<!-- 日志级别 trace<debug<info<warn<error<fatal -->
<configuration status="debug">
<!-- 自定义属性 -->
<Properties>
<!-- 日志格式(控制台) -->
<Property name="pattern1">[%-5p] %d %c - %m%n</Property>
<!-- 日志格式(文件) -->
<Property name="pattern2">
=========================================%n 日志级别:%p%n 日志时间:%d%n 所属类名:%c%n 所属线程:%t%n 日志信息:%m%n
</Property>
<!-- 日志文件路径 -->
<Property name="filePath">logs/myLog.log</Property>
</Properties>

<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${pattern1}"/>
</Console>
<RollingFile name="RollingFile" fileName="${filePath}"
filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="${pattern2}"/>
<SizeBasedTriggeringPolicy size="5 MB"/>
</RollingFile>
</appenders>
<loggers>
<root level="debug">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFile"/>
</root>
</loggers>
</configuration>

日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出。对于Loggers中level的定义同样适用。

下面是Appender配置,Appender可以理解为日志的输出目的地,这里配置了一个类型为Console的Appender,也就是输出到控制台。Console节点中的PatternLayout定义了输出日志时的格式。

Log4j提供的转换模式:

  • %m 输出代码中指定的消息。

  • %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL。

  • %r 输出自应用启动到输出该log信息耗费的毫秒数。

  • %c 输出所属的类目,通常就是所在类的全名。

  • %t 输出产生该日志事件的线程名。

  • %n 输出一个回车换行符,Windows平台为“”,Unix平台为“”。

  • %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,如:%d{dd MMM yyyy HH:mm:ss,SSS},输出类似:02 Nov 2012 14:34:02,781)。

  • %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数, 如:Testlog.main(TestLog.java:10)。

  • %F 输出日志消息产生时所在的文件名称。

  • %L 输出代码中的行号。

  • %x 输出和当前线程相关联的NDC(嵌套诊断环境),像java servlets多客户多线程的应用中。

  • %% 输出一个”%“字符。

最后是Logger的配置,这里只配置了一个Root Logger。

可以用如下代码测试

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args)
{
Logger logger = LogManager.getLogger(LogFunction.class);
logger.trace("trace level");
logger.debug("debug level");
logger.info("info level");
logger.warn("warn level");
logger.error("error level");
logger.fatal("fatal level");
}

Spring中整合Log4j2日志框架

Log4j2依赖导入

引入Log4j2的依赖

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>2.19.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.19.0</version>
</dependency>

在引入log4j2时,需要排除掉Logback日志框架的依赖即。

1
<artifactId>spring-boot-starter-logging</artifactId>

log4j2一般可以通过xml,json,yaml或者properties形式文件来实现,我们这边主要介绍xml文件格式。因为log4j 2.x版本不再支持像1.x中的.properties后缀的文件配置方式,2.x版本配置文件后缀名只能为”.xml”,“.json”或者”.jsn”。

系统选择配置文件的优先级(从先到后)如下:

(1).classpath下的名为log4j2-test.json 或者log4j2-test.jsn的文件。

(2).classpath下的名为log4j2-test.xml的文件。

(3).classpath下名为log4j2.json 或者log4j2.jsn的文件。

(4).classpath下名为log4j2.xml的文件。

我们一般默认使用log4j2.xml进行命名。如果本地要测试,可以把log4j2-test.xml放到classpath,而正式环境使用log4j2.xml,则在打包部署的时候不要打包log4j2-test.xml即可。

Log4j2的路径相关

默认路径

引入log4j2依赖后,默认在src/main/resources目录下加入log4j2.xml配置文件对日志进行配置即可,然后在application.yml中进行访问路径的配置。

示例如下:

  1. log4j2.xml部署位置 在代码工程中的src/main/resources目录下放入配置文件。
  2. yml配置
1
2
3
4
5
6
7
8
9
10
11
12
13
#日志配置 无特殊需求无需更改
logging:
config: classpath:log4j2.xml
level:
root: INFO
javax.activation: info
org.apache.catalina: INFO
org.apache.commons.beanutils.converters: INFO
org.apache.coyote.http11.Http11Processor: INFO
org.apache.http: INFO
org.apache.tomcat: INFO
org.springframework: INFO
com.chinamobile.cmss.bdpaas.resource.monitor: DEBUG

那么如何自定义部署位置

当然我们也可以在微服务部署的config/目录下放置,然后在application.yml中进行访问路径的配置。

举例:我们的micro-service01部署中配置的log4j2.xml路径。

  • log4j2.xml部署位置
1
2
3
4
5
6
[userA@linux01 config]$ pwd
/home/userA/SpringBoot/micro-service01/config
[userA@linux01 config]$ ll
total 24
-rwxr-xr-x 1 userA userA 5938 Sep 9 16:30 application.yml
-r-------- 1 userA userA 8342 Sep 8 16:33 log4j2.xml
  • yml配置
1
2
3
4
5
6
7
8
9
10
11
12
13
#日志配置 无特殊需求无需更改
logging:
config: /home/userA/SpringBoot/micro-service01/config/log4j2.xml
level:
root: INFO
javax.activation: info
org.apache.catalina: INFO
org.apache.commons.beanutils.converters: INFO
org.apache.coyote.http11.Http11Processor: INFO
org.apache.http: INFO
org.apache.tomcat: INFO
org.springframework: INFO
com.chinamobile.cmss.bdpaas.resource.monitor: DEBUG

Log4j2.xml配置详解

缺省默认配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>

解读:

全局配置

  • 仅输出 ERROR 及以上级别的日志(Root level="error")。
  • 使用名为 Console 的Appender(控制台输出)。

日志格式

1
14:25:30.456 [main] ERROR com.example.MyClass - This is an error message
  • %d{HH:mm:ss.SSS} → 时间(时:分:秒.毫秒)。
  • [%t] → 线程名(如 [main])。
  • %-5level → 左对齐的日志级别(如 ERROR)。
  • %logger{36} → 类名(长度限制为36字符)。
  • %msg%n → 日志内容 + 换行。

配置文件节点解析

  1. **根节点 <Configuration**>

    1
    <Configuration status="WARN">
    • 作用:整个配置文件的根节点。
    • 两个属性
      • status:用来指定log4j2本身的打印日志的级别,用于调试配置文件问题。可选值:TRACE, DEBUG, INFO, WARN, ERROR, FATAL
      • 其他可选属性:monitorInterval="30"用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s
    • 有两个子节点:AppendersLoggers(表明可以定义多个AppenderLogger)。
  2. 日志输出器Appenders节点,常见的有三种子节点:Console、RollingFile、File。

    1
    2
    3
    4
    5
    <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
    <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
    </Console>
    </Appenders>
    • 作用:定义日志输出的目的地(如控制台、文件等)。
    • 子节点类型
      • <Console>:定义输出到控制台的Appender
        • name:唯一标识符,指定Appender的名字。(后续通过 AppenderRef 引用)。
        • target:输出目标,可选 SYSTEM_OUT(标准输出)或 SYSTEM_ERR(标准错误)。一般只设置默认:SYSTEM_OUT。
        • PatternLayout:输出格式,不设置默认为:%m%n。
      • <File>:输出到文件(支持滚动日志)。用来定义输出到指定位置的文件的Appender
        • name:指定Appender的名字
        • fileName:指定输出日志的目的文件带全路径的文件名。
        • PatternLayout:输出格式,不设置默认为:%m%n。
      • <RollingFile>节点用来定义超过指定大小自动删除旧的创建新的的Appender
        • name:指定Appender的名字。
        • fileName:指定输出日志的目的文件带全路径的文件名。
        • PatternLayout:输出格式,不设置默认为:%m%n。
        • filePattern:指定新建日志文件的名称格式。
        • Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志。
        • TimeBasedTriggeringPolicyPolicies子节点,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am…而不是7am。
        • SizeBasedTriggeringPolicyPolicies子节点,基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小。
        • DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)。
      • 其他<Socket> <Kafka> <JDBC>
    • <PatternLayout>:定义日志格式。
      • pattern:格式模板,常用占位符:
        • %d:日期时间(可指定格式如 %d{yyyy-MM-dd HH:mm:ss})。
        • %t:线程名。
        • %-5level:左对齐的日志级别(长度5)。
        • %logger{36}:Logger名称(最大长度36)。
        • %msg:日志消息。
        • %n:换行符。
  3. 日志记录器<Loggers>

    1
    2
    3
    4
    5
    <Loggers>
    <Root level="error">
    <AppenderRef ref="Console" />
    </Root>
    </Loggers>
    • 作用:定义日志的采集规则(哪些级别的日志被记录,输出到哪些Appender)。常见的有两种:RootLogger
    • 核心节点
      • Root节点用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出
      • level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF。
      • AppenderRefRoot的子节点,用来指定该日志输出到哪个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中进行输出。
  4. 关于日志level

    共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF。

    • All:最低等级的,用于打开所有日志记录。
    • Trace:是追踪,就是程序推进以下,你就可以写个trace输出,所以trace应该会特别多,不过没关系,我们可以设置最低日志级别不让他输出。
    • Debug:指出细粒度信息事件对调试应用程序是非常有帮助的。
    • Info:消息在粗粒度级别上突出强调应用程序的运行过程。
    • Warn:输出警告及warn以下级别的日志。
    • Error:输出错误信息日志。
    • Fatal:输出每个严重的错误事件将会导致应用程序的退出的日志。
    • OFF:最高等级的,用于关闭所有日志记录。

    程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少

比较完整的log4j2.xml配置模板

配置模板1:

不同级别日志分离存储带日志滚动归档,历史日志分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?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{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%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>

配置模板2

基础控制台 + 文件日志(带滚动策略)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?xml version="1.0" encoding="UTF-8"?>
<!-- status="WARN" 表示 Log4j2 自身日志级别,调试时可设为 TRACE -->
<Configuration status="WARN" monitorInterval="30">
<Appenders>
<!-- 控制台输出 -->
<Console name="Console" target="SYSTEM_OUT">
<!-- 日志格式:时间 线程 级别 类名 - 消息 -->
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>

<!-- 滚动文件日志 (每天滚动,最多保留7天) -->
<RollingFile name="RollingFile"
fileName="logs/app.log"
filePattern="logs/app-%d{yyyy-MM-dd}-%i.log">
<PatternLayout>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</pattern>
</PatternLayout>
<Policies>
<!-- 每天午夜滚动日志 -->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<!-- 单个日志文件最大 100MB -->
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
<!-- 最多保留 7 天的日志 -->
<DefaultRolloverStrategy max="7"/>
</RollingFile>
</Appenders>

<Loggers>
<!-- Spring 框架日志控制 -->
<Logger name="org.springframework" level="WARN" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Logger>

<!-- Hibernate 日志控制 -->
<Logger name="org.hibernate" level="WARN" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Logger>

<!-- 项目代码日志 (包路径根据实际情况修改) -->
<Logger name="com.example" level="DEBUG" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Logger>

<!-- 根日志配置 -->
<Root level="INFO">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>

配置模板3

按环境区分配置(开发/生产)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Properties>
<!-- 通过环境变量切换配置 -->
<Property name="log.level">${sys:spring.profiles.active:-dev}</Property>
<Property name="logPath">logs</Property>
</Properties>

<Appenders>
<!-- 彩色控制台输出 -->
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%style{%d{yyyy-MM-dd HH:mm:ss.SSS}}{cyan} %highlight{%-5level} %logger{36} - %msg%n"/>
</Console>

<!-- 生产环境专用文件日志 -->
<RollingFile name="ProdFile"
fileName="${logPath}/prod.log"
filePattern="${logPath}/prod-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="500 MB"/>
</Policies>
<DefaultRolloverStrategy max="30"/>
</RollingFile>
</Appenders>

<Loggers>
<!-- 开发环境配置 -->
<If condition="${{log.level} == 'dev'}">
<Root level="DEBUG">
<AppenderRef ref="Console"/>
</Root>
</If>

<!-- 生产环境配置 -->
<If condition="${{log.level} == 'prod'}">
<Root level="WARN">
<AppenderRef ref="Console"/>
<AppenderRef ref="ProdFile"/>
</Root>
</If>
</Loggers>
</Configuration>

配置模板4

高性能异步日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<!-- 启用异步日志 -->
<AsyncLoggerConfig includeLocation="true" />

<Appenders>
<!-- 异步文件追加器 -->
<RollingRandomAccessFile name="AsyncFile"
fileName="logs/async.log"
filePattern="logs/async-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="%d{ISO8601} %-5level [%t] %logger{36} - %msg%n"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="200 MB"/>
</Policies>
<DefaultRolloverStrategy max="15"/>
</RollingRandomAccessFile>

<!-- 控制台快速输出 -->
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>

<Loggers>
<!-- 异步记录器配置 -->
<AsyncLogger name="com.example" level="INFO" includeLocation="true">
<AppenderRef ref="AsyncFile"/>
</AsyncLogger>

<!-- SQL 日志单独记录 -->
<Logger name="jdbc.sqlonly" level="DEBUG" additivity="false">
<AppenderRef ref="AsyncFile"/>
</Logger>

<Root level="WARN">
<AppenderRef ref="Console"/>
<AppenderRef ref="AsyncFile"/>
</Root>
</Loggers>
</Configuration>

模板5

JSON 格式日志(适用于 ELK 收集)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<JsonLayout compact="true" eventEol="true">
<KeyValuePair key="app" value="MySpringApp"/>
<KeyValuePair key="env" value="${sys:spring.profiles.active}"/>
</JsonLayout>
</Console>

<File name="JsonFile" fileName="logs/app.json">
<JsonLayout complete="false" compact="false">
<KeyValuePair key="timestamp" value="$${date:yyyy-MM-dd'T'HH:mm:ss.SSSZ}"/>
<KeyValuePair key="thread" value="%t"/>
<KeyValuePair key="level" value="%level"/>
<KeyValuePair key="logger" value="%logger"/>
<KeyValuePair key="message" value="%message"/>
<KeyValuePair key="exception" value="%ex{full}"/>
</JsonLayout>
</File>
</Appenders>

<Loggers>
<!-- 结构化日志专用配置 -->
<Logger name="com.example.api" level="DEBUG" additivity="false">
<AppenderRef ref="JsonFile"/>
</Logger>

<Root level="INFO">
<AppenderRef ref="Console"/>
<AppenderRef ref="JsonFile"/>
</Root>
</Loggers>
</Configuration>

自定义配置文件夹位置

log4j2默认在classpath下查找配置文件,可以修改配置文件的位置。在非web项目中:

1
2
3
4
5
6
7
8
9
public static void main(String[] args) throws IOException
{
File file = new File("D:/log4j2.xml");
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
final ConfigurationSource source = new ConfigurationSource(in);
Configurator.initialize(null, source);

Logger logger = LogManager.getLogger("mylog");
}

如果是web项目,在web.xml中添加:

1
2
3
4
5
6
7
8
<context-param>
<param-name>log4jConfiguration</param-name>
<param-value>/WEB-INF/conf/log4j2.xml</param-value>
</context-param>

<listener>
<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>

上述内容部分引用自 https://blog.csdn.net/pan_junbiao/article/details/104313938

推荐教程

推荐几篇我在网上找到的,写的很好的学习教程:

学习资料1:详解log4j2(上) - 从基础到实战

学习资料2:详解log4j2(下) - Async/MongoDB/Flume Appender 按日志级别区分文件输出

学习资料3:SpringBoot—整合log4j2入门和log4j2.xml配置详解

简单示例

在项目的src根目录下的resources文件夹创建如下log4j2.xml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="UTF-8"?>
<!-- log4j2 配置文件 -->
<!-- 日志级别 trace<debug<info<warn<error<fatal -->
<configuration status="debug">
<!-- 自定义属性 -->
<Properties>
<!-- 日志格式(控制台) -->
<Property name="pattern1">[%-5p] %d %c - %m%n</Property>
<!-- 日志格式(文件) -->
<Property name="pattern2">
=========================================%n 日志级别:%p%n 日志时间:%d%n 所属类名:%c%n 所属线程:%t%n 日志信息:%m%n
</Property>
<!-- 日志文件路径 -->
<Property name="filePath">logs/myLog.log</Property>
</Properties>

<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${pattern1}"/>
</Console>
<RollingFile name="RollingFile" fileName="${filePath}"
filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="${pattern2}"/>
<SizeBasedTriggeringPolicy size="5 MB"/>
</RollingFile>
</appenders>
<loggers>
<root level="debug">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFile"/>
</root>
</loggers>
</configuration>

日志功能测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class TestUser {

// 创建Logger
private Logger logger = LoggerFactory.getLogger(TestUser.class);

@Test
public void test() {
// 加载spring配置文件,对象创建
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");

// 获取创建的对象
User user = (User)context.getBean("user");
System.out.println("1:" + user); // 输出了对象的地址

// 使用对象调用方法完成测试
System.out.println("2:");
user.add();

// 手动写日志
logger.info("@执行调用成功");
// 追踪
logger.trace("trace level");
logger.debug("debug level");
logger.info("info level");
logger.warn("warn level");
logger.error("error level");
}

输出结果

image-20250416203626062
image-20250416203626062