Spring Boot 配置 log4j2

发布时间 2024-01-07 18:15:06作者: 每天七点半

Spring Boot 配置 log4j2

引入依赖

SpringBoot 的 starter 自带的是 logback 日志,若要使用 log4j2 日志,需要引入对应依赖。

logback 日志和 log4j2 日志都是对 slf4j 门面的实现,只能存在一个,且必须存在一个,不存在或者存在多个都会出错。

因此,在使用 log4j2 日志时,必须要在依赖中把 logback 给 exclude 掉。 并且,使用 log4j2 日志还需要适配器 log4j-slf4j-impl,它跟 SpringBoot 的 starter 自带的 log4j-to-slf4j 是相互冲突的,因此还需要将 log4j-to-slf4j 也 exclude 掉。

因为 SpringBoot 的 starter 中已经带有 slf4j 门面了,因此无需再引入 slf4j 依赖。

<dependencies>
  <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
  <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-slf4j-impl</artifactId>
      <version>2.17.1</version>
      <scope>test</scope>
  </dependency>
  <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
  <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
      <version>2.17.1</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
  <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>2.17.1</version>
  </dependency>
</dependencies>

定义日志文件 log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!-- Configuration 后面的 status 用于设置 log4j2 自身内部的信息输出,可以不设置,当设置成 trace 时,可以看到 log4j2 内部各种详细输出-->
<configuration status="INFO">
    <!--先定义所有的 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>
    </appenders>
    <!--然后定义 logger,只有定义了 logger 并引入的 appender,appender 才会生效-->
    <!--root:用于指定项目的根日志,如果没有单独指定 Logger,则会使用 root 作为默认的日志输出-->
    <loggers>
        <root level="info">
            <appender-ref ref="Console"/>
        </root>
    </loggers>
</configuration>

SpringBoot 配置文件中配置

在 SpringBoot 的 application.properties (或者 ymal 格式的 application.yaml) 中指明日志配置文件

logging:
  config: classpath:log4j2.xml

log4j2 配置文件

log4j2 配置文件中主要包含以下配置项:

配置项 说明
Configuration 用于指定 Log4j2 的配置信息,包括日志级别、日志存储位置、日志格式等
Appenders 用于指定日志输出的目的地,包括文件、控制台、数据库等,每个 Appender 都需要指定一个 layout(日志格式)
Loggers 用于指定每个日志记录器的日志级别和 Appender。可以通过指定 Logger 的名称、级别,以及添加的 Appender,来控制日志的输出
filters 用于指定针对特定 Logger、Appender 或 LogEvent 的过滤器,如正则表达式过滤、阈值过滤等
properties 用于指定 Log4j2 的全局变量,可以在 Log4j2 配置文件中使用这些变量来配置一些参数
script 用于指定 JavaScript 脚本,允许通过脚本来动态地生成日志信息
Custom Levels 用于定义自定义日志级别
Include 用于引入其他 XML 配置文件,允许将多个配置文件合并为一个配置

<Configuration>是配置文件的根元素

Log4j2.xml 的 Configuration 属性包括:

属性 说明
status 指定日志记录器的状态,可以是“trace”、“debug”、“info”、“warn”或“error”
monitorInterval 配置文件监视间隔,单位是毫秒
verbose 是否在启动时显示详细的日志记录信息
name 指定日志配置文件的名称,可以为空
packages 指定需要自动配置的日志包
shutdownHook 指定是否使用 JVM Shutdown Hook 关闭日志记录器
strict 是否启用严格模式,如果启用则会强制要求所有配置项必须正确配置
schema 指定 XML 配置文件的模式
advertiser 指定广告器的类名,广告器用于将日志记录发送到远程或者本地的其他进程或应用

Properties 变量

log4j2.xml 文件中的 Properties 元素定义了一组键值对,可以在日志记录中使用。这些属性可以在配置文件中定义,也可以通过环境变量或其他方式在运行时指定。

<Properties>
   <Property name="appName">myApp</Property>
   <Property name="logDir">/var/log/myApp</Property>
</Properties>

....

<File name="File" fileName="${logDir}/myApp.log">
   <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p ${appName} - %m%n"/>
</File>

在这个例子中,通过使用\({appName}和\){logDir}在日志记录模板中使用了定义的属性。这将会被解析为实际的值,如 myApp 和/var/log/myApp。

Appender 附加器

Log4j2 的 Appender 是用于将日志消息输出到指定目的地的组件。Log4j2 提供了多种 Appender,包括但不限于:

附加器类型 说明
ConsoleAppender 将日志消息输出到控制台
FileAppender 将日志消息输出到文件
RollingFileAppender 将日志消息输出到文件,并支持日志轮换
SocketAppender 将日志消息发送到远程服务器的 Socket 端口
JMSAppender 将日志消息发送到 JMS 队列或主题
SMTPAppender 将日志作为电子邮件发送
SyslogAppender 将日志输出到 Syslog 服务器
JDBCAppender 将日志写入数据库
KafkaAppender 将日志消息发送到 Kafka 主题
  • ConsoleAppender
<Appenders>
  <Console name="Console" target="SYSTEM_OUT">
    <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
  </Console>
</Appenders>

以下是一些常用的 ConsoleAppender 参数:

参数 说明
name 指定日志输出器的名称
target 指定输出目标,例如 System.out 或 System.err,默认为 System.out
follow 指定是否跟踪 stdout 或 stderr 的变化(仅适用于 Windows 平台)
encoding 指定字符编码,用于控制台输出
immediateFlush 指定是否立即将日志消息刷新到控制台,默认为 True
  • FileAppender
<Appenders>
  <File name="FileAppender" fileName="logs/myapp.log">
    <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
  </File>
</Appenders>

Log4j2 的 FileAppender 有以下参数:

参数 说明
name 指定 Appender 的名称
fileName 日志文件的保存路径和名称。可以使用相对路径和绝对路径,也可以使用变量(${})
append 是否在原有的日志文件中追加日志,默认为 true
bufferedIo 是否开启缓存写入,默认为 true
bufferSize 缓冲区的大小,默认为 8192
immediateFlush 是否立即写入日志文件,默认为 true
layout 指定日志文件的输出格式
filePermissions 指定日志文件的权限。可以是 UNIX 风格的数字权限(如 0644)或者文件权限符号(如 rwxr-xr–)
fileOwner 指定日志文件的拥有者
fileGroup 指定日志文件的所属组
  • RollingFileAppender

RollingFileAppender 是 Log4j2 中用于将日志输出到文件的一种 appender,它可以实现日志文件的滚动和压缩,以支持更长时间的日志存储。

<Appenders>
  <RollingFile name="RollingFileAppender" fileName="logs/myapp.log"
               filePattern="logs/myapp-%d{yyyy-MM-dd}-%i.log.gz">
    <PatternLayout pattern="%d %p %C{1.} [%t] %m%n"/>
    <Policies>
      <TimeBasedTriggeringPolicy />
      <SizeBasedTriggeringPolicy size="100 MB" />
    </Policies>
    <DefaultRolloverStrategy max="10"/>
  </RollingFile>
</Appenders>

在这个配置中,我们定义了一个 RollingFileAppender 来处理日志。它的名称是“RollingFileAppender”,它的文件名是“logs/myapp.log”,并且它的文件模式是“logs/myapp-%d{yyyy-MM-dd}-%i.log.gz”。这将导致日志文件以日期和索引进行轮换,并使用 gzip 进行压缩。

在 RollingFileAppender 中,我们使用了 PatternLayout 来指定日志的格式。我们还添加了两个策略,一个是 TimeBasedTriggeringPolicy,它基于时间触发轮换,另一个是 SizeBasedTriggeringPolicy,它基于文件大小触发轮换。我们还指定了一个 DefaultRolloverStrategy 来定义轮换的最大文件数。

RollingFileAppender 的参数如下:

参数 说明
name 指定 Appender 的名称
fileName 日志文件的保存路径和名称。可以使用相对路径和绝对路径,也可以使用变量(${})
filePattern 日志文件的文件名模式,支持日期格式化。例如:logs/myapp-%d{yyyy-MM-dd}-%i.log,表示按日期划分日志文件,并使用索引号区分不同的日志文件
append 是否在原有的日志文件中追加日志,默认为 true
bufferedIo 是否开启缓存写入,默认为 true
bufferSize 缓冲区的大小,默认为 8192
immediateFlush 是否立即写入日志文件,默认为 true
layout 指定日志文件的输出格式
policy 滚动策略,支持基于时间、文件大小等方式滚动,默认为 DefaultRolloverStrategy
strategy 日志消息的格式化方式,需指定一个 Layout 实例
filter 日志过滤器,需指定一个 Filter 实例
ignoreExceptions 是否忽略错误,当写入日志文件发生错误时是否抛出异常,默认为 true
  • SMTPAppender

SMTPAppender 是 log4j2 中的一个 appender,它允许将日志信息通过电子邮件发送。以下是一个示例 log4j2.xml 配置文件中 SMTPAppender 发送 html 格式的邮件:

<Appenders>
  <SMTP name="smtpAppender" subject="Log4j2 Test Mail" to="youremail@mail.com"
        from="fromemail@mail.com" smtpHost="smtp.gmail.com" smtpPort="587" smtpUsername="yourusername"
        smtpPassword="yourpassword" smtpProtocol="smtp" smtpDebug="true"
        htmlMsgLayout="${htmlMsgLayout}">
    <ThresholdFilter level="WARN"/>
  </SMTP>
</Appenders>
<Layouts>
  <HtmlLayout title="Log4j2 Test Mail">
    <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
  </HtmlLayout>
</Layouts>

在这个配置文件中,我们使用 SMTPAppender 来发送邮件。其中,我们设置了 SMTP 服务器的主机名、端口、用户名和密码等信息,并指定了发送的邮件内容为 html 格式。我们还定义了一个 HtmlLayout 来格式化邮件内容,它将普通的日志信息格式化为 html 形式。

在实际使用中,只需将 to 和 from 设置为你的邮箱地址,以及填写正确的 smtpHost、smtpPort、smtpUsername 和 smtpPassword 即可成功发送一封带有 html 格式的邮件。

以下是 SMTPAppender 的属性:

参数 说明
name Appender 的名称
to 指定邮件接收者的电子邮件地址
cc 指定邮件抄送者的电子邮件地址
bcc 指定邮件密送者的电子邮件地址
from 指定邮件发送者的电子邮件地址
smtpHost SMTP 服务器的主机名或 IP 地址
smtpPort SMTP 服务器的端口号,默认为 25
smtpUsername SMTP 服务器的用户名
smtpPassword SMTP 服务器的密码
smtpProtocol SMTP 服务器的协议,默认为 smtp
bufferSize 缓冲区大小,默认为 512
subject 邮件主题,默认为 Log4j Log Message
layout 指定日志信息的格式
filter 指定日志信息的过滤器
ignoreExceptions 是否忽略异常,默认为 true。如果设置为 false,则发生异常时邮件发送将会失败。

Loggers 日志记录器

log4j2.xml 文件中的 loggers 元素定义了日志记录器的配置。它包含一个或多个 logger 元素,每个 logger 元素代表一个具体的日志记录器。每个 logger 元素可以指定日志级别、日志输出目标(appender)、日志过滤器(filter)等。

<Loggers>
    <Logger name="com.example" level="info" additivity="false">
        <AppenderRef ref="CONSOLE" />
        <AppenderRef ref="FILE" />
    </Logger>
    <Root level="error">
        <AppenderRef ref="CONSOLE" />
        <AppenderRef ref="FILE" />
    </Root>
</Loggers>

在上面的示例中,有两个 logger 元素。第一个 logger 元素的 name 属性为“com.example”,表示这是一个名为“com.example”的日志记录器。它的 level 属性为“info”,指定日志级别为“info”级别。additivity 属性为“false”,表示在这个日志记录器中,日志不会被发送到它的父级日志记录器中。

第二个 logger 元素是 root 元素,表示所有未被明确指定日志记录器的日志都会被记录到这个 root 记录器中。它的 level 属性为“error”级别。

两个 logger 元素都引用了两个 appender(CONSOLE 和 FILE),这表示日志会被输出到控制台和文件中。

Filters 过滤器

log4j2.xml 中的 Filters 指的是过滤器,可以帮助我们过滤掉不需要的日志。Filters 可以被配置在 Logger、Appender、Layout 等组件中。常用的 Filters 有以下几种:

过滤器 说明
ThresholdFilter 根据日志级别过滤,比如只输出 ERROR 级别及以上的日志
RegexFilter 根据正则表达式过滤,比如只输出满足特定正则表达式的日志
MapFilter 根据键值对过滤,比如只输出包含特定键值对的日志
StructuredDataFilter 根据结构化数据过滤,比如只输出带有指定结构化数据的日志

Filters 可以被链式组合起来,以实现更复杂的过滤逻辑。例如,可以使用 ThreadContextMapFilter 过滤指定键值对,然后再使用 ThresholdFilter 过滤指定级别的日志事件。

可以在 log4j2.xml 文件中通标签中添加一个或多个 Filters。例如:

<Appenders>
  <Console name="ConsoleAppender" target="SYSTEM_OUT">
    <ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
    <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
  </Console>
</Appenders>

该配置文件将所有级别为 WARN 及以上的日志事件过滤掉,并将其输出到控制台。其中,onMatch 和 onMismatch 表示匹配和不匹配时的处理方式,可以取值为 DENY(拒绝)、NEUTRAL(中立)和 ACCEPT(接受)。

Layout 输出格式

Log4j2 的 Layout 是用于指定日志消息输出格式的组件。它定义了日志事件的消息格式,以便它可以被写入到指定的输出目标中。

Log4j2 提供了多种 Layout 实现,包括:

LayoutType 说明
PatternLayout 通过指定一个格式化字符串来输出日志消息。
HtmlLayout 用 HTML 标记格式化日志消息,使其在网页上更容易查看。
XmlLayout 以 XML 格式输出日志事件。
CsvLayout 以逗号分隔的格式输出日志消息,方便导入到 Excel 等表格软件中。
JsonLayout 以 JSON 格式输出日志事件。

用户可以根据需要选择合适的 Layout 实现,并根据自己的需求进行配置和定制化。例如,可以通过设置 Layout 的属性来控制时间和日期格式、输出日志级别等信息。

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

<?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>