皛皛 發表於 2026-1-9 14:57:30

在Springboot中处理log4j2日志文件过程

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>简单介绍</li><ul class="second_class_ul"><li>日志切割</li><li>日志分离</li><li>日志清理</li></ul><li>如何在SpringBoot项目中配置使用</li><ul class="second_class_ul"></ul><li>实现原理</li><ul class="second_class_ul"><li>日志切割</li><li>日志的分离</li><li>日志清理</li></ul><li>总结</li><ul class="second_class_ul"></ul></ul></div><p class="maodian"></p><h2>简单介绍</h2>
<p class="maodian"></p><p class="maodian"></p><h3>日志切割</h3>
<p>日志切割指的是将一个持续增长的、庞大的日志文件,按照某种规则分割成多个较小的、易于管理的文件。(在本配置中我们将日志按天切割,同时限制了单个日志文件不能超过64MB)</p>
<p><strong>效果如图:</strong></p>
<p>切割策略有两个,每天零点会将昨天的日志文件加日期保存然后生成一个新的日志文件,当天如果单个日志文件超出规定(例如本配置的64MB),会自动将此日志文件加日期保存并生成一个新的日志文件</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010910261684.png" /></p>
<p class="maodian"></p><h3>日志分离</h3>
<p>日志分离指的是将不同种类、不同级别或来自不同模块的日志信息,输出到不同的、独立的日志文件中。</p>
<p><strong>效果如图:</strong></p>
<p>日志被根据不同级别分层保存</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010910261653.png" /></p>
<p class="maodian"></p><p class="maodian"></p><h3>日志清理</h3>
<p>日志清理指的是自动删除旧的、不再需要的日志归档文件,以防止日志文件无限制地占用磁盘空间,最终导致磁盘写满。</p>
<p>这是生产环境中至关重要的一环。(比如本配置的清理就是会删除超过N(比如Info30天,Warn60天,Error90天)天的日志归档文件以及每个类型的日志文件总大小不超过某个GB的大小(比如Info6GB,Warn3GB,Error2GB))</p>
<p class="maodian"></p><h2>如何在SpringBoot项目中配置使用</h2>
<p>第一步,导入如下依赖到pom.xml文件当中</p>
<div class="jb51code"><pre class="brush:xml;">      &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter&lt;/artifactId&gt;
            &lt;exclusions&gt;
                &lt;exclusion&gt;
                  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                  &lt;artifactId&gt;spring-boot-starter-logging&lt;/artifactId&gt;
                &lt;/exclusion&gt;
            &lt;/exclusions&gt;
      &lt;/dependency&gt;

      &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-log4j2&lt;/artifactId&gt;
      &lt;/dependency&gt;</pre></div>
<p>第二步,在yaml文件中添加如下配置</p>
<div class="jb51code"><pre class="brush:yaml;">logging:
config: classpath:log4j2.xml</pre></div>
<p>第三步,将xml文件放到resource目录下,下次启动项目,日志会自动被记录到logs目录(这个目录会在项目启动时自动生成)并分离清洗</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010910261684.png" /></p>
<p>xml文件名: log4j2.xml</p>
<p>文件代码:</p>
<div class="jb51code"><pre class="brush:xml;">&lt;Configuration status="WARN"&gt;
    &lt;Properties&gt;
      &lt;Property name="LOG_PATH"&gt;logs&lt;/Property&gt;
      &lt;Property name="APP_NAME"&gt;app&lt;/Property&gt;
      &lt;Property name="FILE_SIZE"&gt;64MB&lt;/Property&gt;
      &lt;Property name="LOG_PATTERN"&gt;%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p [%t] %c{1.} [%X{traceId:-}] - %m%n%ex&lt;/Property&gt;
    &lt;/Properties&gt;
    &lt;Appenders&gt;
      &lt;Console name="Console" target="SYSTEM_OUT"&gt;
            &lt;PatternLayout pattern="${LOG_PATTERN}"/&gt;
      &lt;/Console&gt;
      &lt;RollingFile name="InfoFile" fileName="${LOG_PATH}/${APP_NAME}-info.log" filePattern="${LOG_PATH}/$${date:yyyy-MM}/${APP_NAME}-info-%d{yyyy-MM-dd}-%i.log"&gt;
            &lt;Filters&gt;
                &lt;LevelMatchFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/&gt;
            &lt;/Filters&gt;
            &lt;PatternLayout pattern="${LOG_PATTERN}"/&gt;
            &lt;Policies&gt;
                &lt;TimeBasedTriggeringPolicy/&gt;
                &lt;SizeBasedTriggeringPolicy size="${FILE_SIZE}"/&gt;
            &lt;/Policies&gt;
            &lt;DefaultRolloverStrategy&gt;
                &lt;max&gt;64&lt;/max&gt;
                &lt;Delete basePath="${LOG_PATH}" maxDepth="2"&gt;
                  &lt;IfFileName glob="*/app-info*.log"/&gt;
                  &lt;IfLastModified age="30d"/&gt;
                &lt;/Delete&gt;
                &lt;Delete basePath="${LOG_PATH}" maxDepth="2"&gt;
                  &lt;IfFileName glob="*/app-info*.log"/&gt;
                  &lt;IfAccumulatedFileSize exceeds="6GB"/&gt;
                &lt;/Delete&gt;
            &lt;/DefaultRolloverStrategy&gt;
      &lt;/RollingFile&gt;
      &lt;RollingFile name="WarnFile" fileName="${LOG_PATH}/${APP_NAME}-warn.log" filePattern="${LOG_PATH}/$${date:yyyy-MM}/${APP_NAME}-warn-%d{yyyy-MM-dd}-%i.log"&gt;
            &lt;Filters&gt;
                &lt;LevelMatchFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/&gt;
            &lt;/Filters&gt;
            &lt;PatternLayout pattern="${LOG_PATTERN}"/&gt;
            &lt;Policies&gt;
                &lt;TimeBasedTriggeringPolicy/&gt;
                &lt;SizeBasedTriggeringPolicy size="${FILE_SIZE}"/&gt;
            &lt;/Policies&gt;
            &lt;DefaultRolloverStrategy&gt;
                &lt;max&gt;64&lt;/max&gt;
                &lt;Delete basePath="${LOG_PATH}" maxDepth="2"&gt;
                  &lt;IfFileName glob="*/app-warn*.log"/&gt;
                  &lt;IfLastModified age="60d"/&gt;
                &lt;/Delete&gt;
                &lt;Delete basePath="${LOG_PATH}" maxDepth="2"&gt;
                  &lt;IfFileName glob="*/app-warn*.log"/&gt;
                  &lt;IfAccumulatedFileSize exceeds="3GB"/&gt;
                &lt;/Delete&gt;
            &lt;/DefaultRolloverStrategy&gt;
      &lt;/RollingFile&gt;
      &lt;RollingFile name="ErrorFile" fileName="${LOG_PATH}/${APP_NAME}-error.log" filePattern="${LOG_PATH}/$${date:yyyy-MM}/${APP_NAME}-error-%d{yyyy-MM-dd}-%i.log"&gt;
            &lt;Filters&gt;
                &lt;LevelMatchFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/&gt;
            &lt;/Filters&gt;
            &lt;PatternLayout pattern="${LOG_PATTERN}"/&gt;
            &lt;Policies&gt;
                &lt;TimeBasedTriggeringPolicy/&gt;
                &lt;SizeBasedTriggeringPolicy size="${FILE_SIZE}"/&gt;
            &lt;/Policies&gt;
            &lt;DefaultRolloverStrategy&gt;
                &lt;max&gt;64&lt;/max&gt;
                &lt;Delete basePath="${LOG_PATH}" maxDepth="2"&gt;
                  &lt;IfFileName glob="*/app-error*.log"/&gt;
                  &lt;IfLastModified age="90d"/&gt;
                &lt;/Delete&gt;
                &lt;Delete basePath="${LOG_PATH}" maxDepth="2"&gt;
                  &lt;IfFileName glob="*/app-error*.log"/&gt;
                  &lt;IfAccumulatedFileSize exceeds="2GB"/&gt;
                &lt;/Delete&gt;
            &lt;/DefaultRolloverStrategy&gt;
      &lt;/RollingFile&gt;
      &lt;RollingFile name="DebugFile" fileName="${LOG_PATH}/${APP_NAME}-debug.log" filePattern="${LOG_PATH}/$${date:yyyy-MM}/${APP_NAME}-debug-%d{yyyy-MM-dd}-%i.log"&gt;
            &lt;Filters&gt;
                &lt;LevelMatchFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/&gt;
            &lt;/Filters&gt;
            &lt;PatternLayout pattern="${LOG_PATTERN}"/&gt;
            &lt;Policies&gt;
                &lt;TimeBasedTriggeringPolicy/&gt;
                &lt;SizeBasedTriggeringPolicy size="${FILE_SIZE}"/&gt;
            &lt;/Policies&gt;
            &lt;DefaultRolloverStrategy&gt;
                &lt;max&gt;64&lt;/max&gt;
                &lt;Delete basePath="${LOG_PATH}" maxDepth="2"&gt;
                  &lt;IfFileName glob="*/app-debug*.log"/&gt;
                  &lt;IfLastModified age="7d"/&gt;
                &lt;/Delete&gt;
                &lt;Delete basePath="${LOG_PATH}" maxDepth="2"&gt;
                  &lt;IfFileName glob="*/app-debug*.log"/&gt;
                  &lt;IfAccumulatedFileSize exceeds="5GB"/&gt;
                &lt;/Delete&gt;
            &lt;/DefaultRolloverStrategy&gt;
      &lt;/RollingFile&gt;
    &lt;/Appenders&gt;
    &lt;Loggers&gt;
      &lt;Logger name="org.springframework" level="info" additivity="false"&gt;
            &lt;AppenderRef ref="Console"/&gt;
            &lt;AppenderRef ref="InfoFile"/&gt;
            &lt;AppenderRef ref="WarnFile"/&gt;
            &lt;AppenderRef ref="ErrorFile"/&gt;
      &lt;/Logger&gt;
      &lt;Logger name="org.hibernate" level="warn"/&gt;
      &lt;Root level="info"&gt;
            &lt;AppenderRef ref="Console"/&gt;
            &lt;AppenderRef ref="InfoFile"/&gt;
            &lt;AppenderRef ref="WarnFile"/&gt;
            &lt;AppenderRef ref="ErrorFile"/&gt;
      &lt;/Root&gt;
    &lt;/Loggers&gt;
&lt;/Configuration&gt;</pre></div>
<p class="maodian"></p><h2>实现原理</h2>
<h3>日志切割</h3>
<p>Appender 就是日志的输出目的地。Appender 中的 <code>RollingFile</code>都设置了两种触发策略,它们之间是&ldquo;或&rdquo;的关系,只要满足任一条件,就会触发日志切割</p>
<ul><li><code>&lt;TimeBasedTriggeringPolicy/&gt;</code><strong> </strong>基于时间滚动,每天零点自动生成新的日志文件</li><li><code>&lt;SizeBasedTriggeringPolicy size=&quot;${FILE_SIZE}&quot;/&gt;</code><strong> </strong>基于文件大小的触发策略。</li></ul>
<p>参数 <code>${FILE_SIZE}</code>被定义为 <code>64MB</code>。</p>
<p>这意味着,即使在同一天内,只要当前正在写入的日志文件大小达到 64MB,也会立即触发切割,并生成一个新的日志文件 。</p>
<div class="jb51code"><pre class="brush:xml;">            &lt;Policies&gt;
                &lt;TimeBasedTriggeringPolicy/&gt;
                &lt;SizeBasedTriggeringPolicy size="${FILE_SIZE}"/&gt;
            &lt;/Policies&gt;</pre></div>
<p class="maodian"></p><h3>日志的分离</h3>
<p>可以看到,在Appenders中RollingFile被分为了四种,分别是Info,Warn,Error,Debug级别的文件</p>
<p>当日志文件被切割后,其归档文件的命名和存放位置由 <code>filePattern</code>属性精确控制:</p>
<div class="jb51code"><pre class="brush:xml;">filePattern="${LOG_PATH}/$${date:yyyy-MM}/${APP_NAME}-info-%d{yyyy-MM-dd}-%i.log.gz"</pre></div>
<p>这个配置实现了以下效果:</p>
<ul><li><strong>按月份归档</strong>:<code>$${date:yyyy-MM}</code>会在 <code>logs</code>目录下自动创建像 <code>2025-03</code>这样的子文件夹,将当月所有的归档日志文件放入其中,使目录结构非常清晰 。。</li><li><strong>索引区分</strong>:当同一天内因文件大小触发多次切割时,<code>%i</code>是一个从1开始递增的索引号,用于区分同一天产生的不同日志文件,例如会产生 <code>app-info-2025-03-18-1.log</code>,<code>app-info-2025-03-18-2.log</code>等文件。</li></ul>
<h3>日志清理</h3>
<p><strong>日志清理有三个策略</strong></p>
<p><code>&lt;max&gt;64&lt;/max&gt;</code>在这里表示:<strong>当天最多可以生成 64 个归档日志文件</strong>(例如 <code>app-info-2025-10-15-1.log.gz</code>到 <code>app-info-2025-10-15-64.log.gz</code>)。</p>
<p>当同一天内的第 65 次滚动触发时,最早的那个文件(如 <code>...-1.log.gz</code>)将会被删除 。</p>
<div class="jb51code"><pre class="brush:xml;">&lt;IfFileName glob="*/app-info*.log"/&gt;
&lt;IfLastModified age="30d"/&gt;</pre></div>
<p>这个代表如果超过30天会把info类型的最旧日志删除</p>
<div class="jb51code"><pre class="brush:xml;">&lt;IfFileName glob="*/app-info*.log"/&gt;
&lt;IfAccumulatedFileSize exceeds="6GB"/&gt;</pre></div>
<p>这个代表如果超过6GB会把info类型的最旧日志删除</p>
<div class="jb51code"><pre class="brush:xml;">            &lt;DefaultRolloverStrategy&gt;
                &lt;max&gt;64&lt;/max&gt;
                &lt;Delete basePath="${LOG_PATH}" maxDepth="2"&gt;
                  &lt;IfFileName glob="*/app-info*.log"/&gt;
                  &lt;IfLastModified age="30d"/&gt;
                &lt;/Delete&gt;
                &lt;Delete basePath="${LOG_PATH}" maxDepth="2"&gt;
                  &lt;IfFileName glob="*/app-info*.log"/&gt;
                  &lt;IfAccumulatedFileSize exceeds="6GB"/&gt;
                &lt;/Delete&gt;
            &lt;/DefaultRolloverStrategy&gt;</pre></div>
<p class="maodian"></p><h2>总结</h2>
<p>以上为个人经验,希望能给大家一个参考,也希望大家多多支持琼殿技术社区。</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>SpringBoot&nbsp;LogbackvsLog4j2配置与性能测试对比分析</li><li>SpringBoot项目使用Log4j2+SLF4J构建日志的方法步骤</li><li>一文带你搞定SpringBoot&nbsp;Log4j2日志配置文件</li><li>SpringBoot将logback替换成log4j2的操作步骤</li><li>SpringBoot使用log4j2将日志记录到文件及自定义数据库的配置方法</li><li>SpringBoot项目整合Log4j2实现自定义日志打印失效问题解决</li><li>SpringBoot整合Log4j2实现自定义日志打印失效的原因及解决</li><li>SpringBoot配置log4j2的实现示例</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: 在Springboot中处理log4j2日志文件过程