官网使用手册:https://logging.apache.org/log4j/2.x/manual/

使用

Log4j2 的 Maven 依赖:

  1. <dependency>
  2. <groupId>org.apache.logging.log4j</groupId>
  3. <artifactId>log4j-core</artifactId>
  4. <version>2.14.0</version>
  5. </dependency>

Maven 依赖的名称还是叫 log4j,只是在 version 中体现出了新版本。依赖关系如下:
image.png
我们写一个示例:

  1. public class Log4j2Test {
  2. private static final Logger LOGGER = LogManager.getLogger(Log4j2Test.class);
  3. public static void main(String[] args) {
  4. LOGGER.trace("Hello trace Log4j2!");
  5. LOGGER.debug("Hello debug Log4j2!");
  6. LOGGER.info("Hello info Log4j2!");
  7. LOGGER.warn("Hello warn Log4j2!");
  8. LOGGER.error("Hello error Log4j2!");
  9. }
  10. }

应用启动时 Log4j2 会去寻找 4 种类型的配置文件,后缀分别是 propertiesyamljsonxml。前缀是 log4j2-test 或者 log4j2。通常我们使用名为 log4j2.xml 的配置文件。

如果是配合 Slf4j 的 API 使用也是可以的,只需要做好适配即可。不过如果是新系统的话,建议直接使用 Log4j2 的 API,因为可以享受所有 Log4j2 的功能,如果使用 Slf4j 在 API 上会有语法限制。

配置文件

Log4j2 的配置文件格式和 Logback 有点相似,基本的结构为 元素,其内部包含了 0 或多个 元素,以及 0 或多个 元素,Loggers 内部最多只能存在一个 元素。
image.png

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Configuration xmlns:xi="http://www.w3.org/2001/XInclude"
  3. status="warn" name="XInclude">
  4. <Appenders>
  5. <RollingFile name="File" fileName="logs/app.log" filePattern="logs/archives/app-%d{yyyy-MM-dd}-%i.log.gz">
  6. <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%t] %-40.40c{1.} : %m%n"/>
  7. <Policies>
  8. <TimeBasedTriggeringPolicy />
  9. <!-- 一天内大于size就单独分隔 -->
  10. <SizeBasedTriggeringPolicy size="1 GB"/>
  11. </Policies>
  12. </RollingFile>
  13. </Appenders>
  14. <Loggers>
  15. <Root level="INFO">
  16. <AppenderRef ref="File"/>
  17. </Root>
  18. </Loggers>
  19. </Configuration>

1. Appenders

Appenders 就是配置日志的输出目的地,内部可以包含多个不同的输出地。与 Logback 不同的是,它是通过标签名来确定要输出的目的地的,这样语法上更加简洁。

  1. <Console name="Console">
  2. <RollingFile name="File">
  3. <!-- 等同于logback中的 -->
  4. <appender name = "Console" class= "ch.qos.logback.core.ConsoleAppender">
  5. <appender name = "File" class= "ch.qos.logback.core.rolling.RollingFileAppender">

2. 自动重载配置

Logback 支持自动重载配置,Log4j2 当然也支持,想要启用这个功能也非常简单,只需要在 Configuration 元素上添加 monitorInterval 属性即可。

  1. <Configuration monitorInterval="30">
  2. ...
  3. </Configuration>

注意:最小间隔为 5 秒,上例中的意思是每隔 30 秒检查配置文件中的配置是否更改。

3. 异步输出

与 Log4j 相比,Log4j2 的异步输出日志性能非常强劲,但在具体使用时我们需要了解不同配置的含义:

全异步模式:
可通过如下系统配置开启全异步(all async)模式:

  1. -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

这样,所有日志记录器都是异步的,在 XML 配置文件中只需要使用普通的 即可。由于其底层依赖 Disruptor 库,需要注意依赖版本。

混合异步模式:
通过在 XML 配置文件中使用 来开启混合异步模式,其中,同步和异步日志记录器可以混合使用。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Configuration status="WARN">
  3. <Appenders>
  4. <!-- Async Loggers will auto-flush in batches, so switch off immediateFlush. -->
  5. <RandomAccessFile name="RandomAccessFile" fileName="asyncWithLocation.log"
  6. immediateFlush="false" append="false">
  7. <PatternLayout>
  8. <Pattern>%d %p %class{1.} [%t] %location %m %ex%n</Pattern>
  9. </PatternLayout>
  10. </RandomAccessFile>
  11. </Appenders>
  12. <Loggers>
  13. <!-- pattern layout actually uses location, so we need to include it -->
  14. <AsyncLogger name="com.foo.Bar" level="trace" includeLocation="true">
  15. <AppenderRef ref="RandomAccessFile"/>
  16. </AsyncLogger>
  17. <Root level="info" includeLocation="true">
  18. <AppenderRef ref="RandomAccessFile"/>
  19. </Root>
  20. </Loggers>
  21. </Configuration>

4. 滚动更新策略

RollingFileAppender 是 Log4j2 中的一种能够实现日志文件滚动更新的 Appender。滚动的意思是当满足一定条件(如文件达到指定大小,达到指定的时间)后就重命名原日志文件进行归档,并生成新的日志文件用于 log 写入。如果还设置了一定时间内允许归档的日志文件的最大数量,将对过旧的日志文件进行删除操作。

RollingFile 实现日志文件滚动更新,依赖于 TriggeringPolicyRolloverStrategy。前者为触发策略,其决定了何时触发日志文件的滚动,即 When;后者为滚动更新策略,其决定了当触发了日志文件的滚动时,如何进行文件的滚动更新,即 How。

Log4j2 提供了默认的滚动策略:DefaultRolloverStrategy。一般情况下,采用默认的过渡策略即可,因为它已经足够强大。下面通过一个 log4j2.xml 文件示例来简单了解 RollingFile 的配置:

  1. <RollingFile name="RollingFileWarn" fileName="logs/app.log"
  2. filePattern="logs/app.%d{yyyy-MM-dd}-%i.log">
  3. <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY" />
  4. <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd} [%t] %-5level %l %msg%n" />
  5. <Policies>
  6. <TimeBasedTriggeringPolicy interval="1"/>
  7. <SizeBasedTriggeringPolicy size="100MB" />
  8. </Policies>
  9. <DefaultRolloverStrategy max="20" />
  10. </RollingFile>
  • fileName 指定日志文件的位置和文件名称(如果文件或文件所在的目录不存在,会创建文件)
  • filePattern 指定触发滚动更新时,文件的重命名规则

上述配置文件中配置了一个 RollingFile,日志写入 logs/app.log 文件中,每经过 1 天或者当文件大小到达 250M 时,按照 app.2021-08-01-1.log 的格式对 app.log 进行重命名、归档,并生成新文件用于写日志。

下面我们重点分析下触发策略,Log4j2 提供的触发策略主要包含:

  • 基于 cron 表达式的 CronTriggeringPolicy
  • 基于文件大小的 SizeBasedTriggeringPolicy
  • 基于时间的 TimeBasedTriggeringPolicy
  • 混合多个触发策略的 CompositeTriggeringPolicy,比如同时基于文件大小和时间
  • 默认提供的 DefaultRolloverStrategy

4.1 SizeBasedTriggeringPolicy

规定了当日志文件达到了指定的 size 时,触发滚动更新操作。size 参数可以用 KB、MB、GB 等做后缀来指定具体的字节数,如 20MB。

  1. <SizeBasedTriggeringPolicy size="250MB"/>

4.2 TimeBasedTriggeringPolicy

规定了当日志文件名中的 date/time pattern 不再符合 filePattern 中的 date/time pattern 时,触发滚动更新操作。比如,filePattern 指定文件重命名规则为 app-%d{yyyy-MM-dd HH}.log,文件名为 app-2017-08-25 11.log,当时间达到 2017 年 8 月 25 日中午 12 点(2017-08-25 12)时将触发滚动更新操作。
image.png

4.3 CompositeTriggeringPolicy

将多个 TriggeringPolicy 放到 Policies 标签中以表示使用复合策略:

  1. <Policies>
  2. <TimeBasedTriggeringPolicy />
  3. <SizeBasedTriggeringPolicy size="250 MB"/>
  4. </Policies>

如上,同时使用了 TimeBasedTriggeringPolicy 和 SizeBasedTriggeringPolicy,只要有其中一个条件满足,就会触发滚动更新。

4.4 DefaultRolloverStrategy

DefaultRolloverStrategy 是 Log4j2 提供的默认的 rollover 策略,即使没有在 log4j2.xml 中显式指明。该策略提供了一个 max 参数用于指定计数器的最大值。一旦计数器达到了最大值,过旧的日志文件将被删除。max 参数要与 filePattern 中的计数器 %i 配合起作用,具体作用方式与 filePattern 的配置密切相关。

  1. 如果 filePattern 中仅含有 date/time pattern,每次 rollover 时,将用当前的日期和时间替换文件中的日期格式对文件进行重命名。max 参数此时不起作用。

  2. 如果 filePattern 中仅含有整数计数器(即 %i),每次 rollover 时,文件重命名时的计数器将每次加 1(初始值为 1),若达到 max 的值,将删除旧的文件。

  3. 如果 filePattern 中既含有 date/time pattern,又含有 %i,每次 rollover 时,计数器将每次加 1,若达到 max 的值将删除旧的文件,直到 data/time pattern 不再符合,被替换为当前的日期和时间,计数器再从 1 开始计数。

    5. 配置总览

    本配置文件的目标是将不同级别的日志输出到不同文件,最大 100MB 一个文件,文件数据达到最大值时,旧数据会被压缩并放进指定文件夹,最多存放 20 个文件。

    1. <!-- status:用于设置log4j2自身内部的信息输出,可以不设置 -->
    2. <?xml version="1.0" encoding="UTF-8"?>
    3. <!-- status : 这个用于设置log4j2自身内部的信息输出,可以不设置-->
    4. <Configuration status="error">
    5. <!-- 配置日志文件输出目录,此配置将日志输出到根目录下的指定文件夹 -->
    6. <Properties>
    7. <Property name="fileDir">/logs/log4j2</Property>
    8. <Property name="fileHistory">/logs/log4j2/history</Property>
    9. </Properties>
    10. <Appenders>
    11. <!-- 优先级从高到低分别是 OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL -->
    12. <!-- 单词解释:Match:匹配 DENY:拒绝 Mismatch:不匹配 ACCEPT:接受 -->
    13. <!-- DENY,日志将立即被抛弃不再经过其他过滤器;NEUTRAL,有序列表里的下个过滤器过接着处理日志;ACCEPT,日志会被立即处理,不再经过剩余过滤器。 -->
    14. <!-- 输出日志的格式
    15. %d{yyyy-MM-dd HH:mm:ss, SSS} : 日志生产时间
    16. %t 输出当前线程名称
    17. %-5level 输出日志级别,-5表示左对齐并且固定输出5个字符,如果不足在右边补0
    18. %logger 输出logger名称,因为Root Logger没有名称,所以没有输出
    19. %msg 日志文本
    20. %n 换行
    21. 其他常用的占位符有:
    22. %F 输出所在的类文件名,如Client.java
    23. %L 输出行号
    24. %M 输出所在方法名
    25. %l 输出语句所在的行数, 包括类名、方法名、文件名、行数
    26. -->
    27. <!--这个输出控制台的配置,这里输出all信息到System.out -->
    28. <console name="Console" target="SYSTEM_OUT">
    29. <!-- 输出日志的格式 -->
    30. <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %l %msg%n" />
    31. </console>
    32. <!--这个输出文件的配置,这里输出info信息到junbao_info.log -->
    33. <RollingFile name="RollingFileInfo" fileName="${fileDir}/info.log" filePattern="${fileHistory}/info/%d{yyyy-MM-dd}-%i.log">
    34. <!-- 此Filter意思是,只输出info级别的数据 DENY,日志将立即被抛弃不再经过其他过滤器;NEUTRAL,有序列表里的下个过滤器过接着处理日志;
    35. ACCEPT,日志会被立即处理,不再经过剩余过滤器。 -->
    36. <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" />
    37. <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %l %msg%n" />
    38. <Policies>
    39. <!-- 如果启用此配置,则日志会按文件名生成新文件, 即如果filePattern配置的日期格式为 %d{yyyy-MM-dd HH}
    40. ,则每小时生成一个压缩文件, 如果filePattern配置的日期格式为 %d{yyyy-MM-dd} ,则天生成一个压缩文件,默认为1 -->
    41. <TimeBasedTriggeringPolicy />
    42. <!-- 每个日志文件最大100MB,超过100MB生产新的文件 ; -->
    43. <SizeBasedTriggeringPolicy size="100MB" />
    44. </Policies>
    45. <!--文件夹下最多的文件个数-->
    46. <DefaultRolloverStrategy max="20" />
    47. </RollingFile>
    48. <RollingFile name="RollingFileWarn" fileName="${fileDir}/warn.log" filePattern="${fileHistory}/warn/%d{yyyy-MM-dd}-%i.log">
    49. <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY" />
    50. <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %l %msg%n" />
    51. <Policies>
    52. <TimeBasedTriggeringPolicy />
    53. <SizeBasedTriggeringPolicy size="100MB" />
    54. </Policies>
    55. <DefaultRolloverStrategy max="20" />
    56. </RollingFile>
    57. <RollingFile name="RollingFileError" fileName="${fileDir}/error.log" filePattern="${fileHistory}/error/%d{yyyy-MM-dd}-%i.log">
    58. <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY" />
    59. <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %l %msg%n" />
    60. <Policies>
    61. <TimeBasedTriggeringPolicy />
    62. <SizeBasedTriggeringPolicy size="100MB" />
    63. </Policies>
    64. <DefaultRolloverStrategy max="20" />
    65. </RollingFile>
    66. </Appenders>
    67. <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
    68. <Loggers>
    69. <!--同步输出info级以上的日志信息-->
    70. <!-- <root level="info" includeLocation="true">
    71. <appender-ref ref="Console" />
    72. </root> -->
    73. <!--全异步输出info级以上的日志信息-->
    74. <asyncRoot level="info" includeLocation="true">
    75. <appender-ref ref="Console" />
    76. <appender-ref ref="RollingFileInfo" />
    77. </asyncRoot>
    78. </Loggers>
    79. </Configuration>