`

logback系列之三:输出日志到文件(滚动)

    博客分类:
  • java
阅读更多
logback系列之一:输出日志到控制台
logback系列之二:输出日志到文件
logback系列之三:输出日志到文件(滚动)
logback系列之四:输出日志到不同文件


实际生产中,每天都有大量的日志生成,单个文件(FileAppender)已经不能满足要求,RollingFileAppender继承了FileAppender,并提供了更多的功能:
  • 每天生成一个日志文件
  • 将前一天的日志重命名为包含日期的格式
  • 根据需要,删除过期历史日志

配置

logback系列之二:输出日志到文件类似,改动的地方:

1. logback[-test].xml文件:
<appender name="rollingAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>/logs/heuristic.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>/logs/heuristic-%d{yyyy-MM-dd}.log</fileNamePattern>
        <maxHistory>30</maxHistory>
    </rollingPolicy>
    <encoder><!-- 必须指定,否则不会往文件输出内容 -->
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n</pattern>
    </encoder>
    <append>false</append>
    <prudent>false</prudent>
</appender>

<root level="DEBUG">
    <appender-ref ref="rollingAppender" />
</root>


调用测试类的方法,生成heuristic-2013-11-16.log文件。


源码分析

a. 如果指定了file属性,当天的文件名为file属性值(/logs/heuristic.log):

ch.qos.logback.core.rolling.RollingFileAppender类
public void start() {
	...
	currentlyActiveFile = new File(getFile()); // 获取日志文件名
}

public String getFile() {
	return rollingPolicy.getActiveFileName(); // 从滚动策略获取
}


上面logback[-test].xml的rollingPolicy配置为
ch.qos.logback.core.rolling.TimeBasedRollingPolicy类

看下实现:
  public String getActiveFileName() {
    String parentsRawFileProperty = getParentsRawFileProperty();
    if (parentsRawFileProperty != null) { // logback.xml指定了file属性
      return parentsRawFileProperty; // 使用file值
    } else {
      return timeBasedFileNamingAndTriggeringPolicy
          .getCurrentPeriodsFileNameWithoutCompressionSuffix();
    }
  }

  public String getParentsRawFileProperty() {
    return parent.rawFileProperty();
  }


ch.qos.logback.core.FileAppender类
  final public String rawFileProperty() {
    return fileName;
  }


b. 必须指定TriggeringPolicy<E>和RollingPolicy,否则不会打印日志:

看下
ch.qos.logback.core.rolling.RollingFileAppender类
  public void start() {
    if (triggeringPolicy == null) {
      addWarn("No TriggeringPolicy was set for the RollingFileAppender named "
          + getName());
      addWarn("For more information, please visit "+CODES_URL+"#rfa_no_tp");
      return;
    }

    if (rollingPolicy == null) {
      addError("No RollingPolicy was set for the RollingFileAppender named "
          + getName());
      addError("For more information, please visit "+CODES_URL+"rfa_no_rp");
      return;
    }

TimeBasedRollingPolicy类实现了上面的两个接口,triggeringPolicy和rollingPolicy都指向TimeBasedRollingPolicy的实例对象。


c. 如果file指定,前一天的文件名改为fileNamePattern的值(/logs/heuristic-2013-11-15.log)。

通过设置TimeBasedRollingPolicy的maxHistory属性,可以控制已产生日志的数量。如果maxHistory设置为30,那么超过30天的log文件会被自动删除,这是通过RollingFileAppender的rollover()方法来实现的。

该方法会调用
ch.qos.logback.core.rolling.TimeBasedRollingPolicy类
的rollover方法:
  public void rollover() throws RolloverFailure {
    // 当此方法调用时,假定前一天日志文件已经关闭
    String elapsedPeriodsFileName = timeBasedFileNamingAndTriggeringPolicy
        .getElapsedPeriodsFileName();

    String elpasedPeriodStem = FileFilterUtil.afterLastSlash(elapsedPeriodsFileName);

    if (compressionMode == CompressionMode.NONE) {
      if (getParentsRawFileProperty() != null) {
        renameUtil.rename(getParentsRawFileProperty(), elapsedPeriodsFileName); // file指定,重命名为fileNamePattern格式。如果目标文件存在,则重命名失败
      } // else { nothing to do if CompressionMode == NONE and parentsRawFileProperty == null }
    } else {
      if (getParentsRawFileProperty() == null) {
        future = asyncCompress(elapsedPeriodsFileName, elapsedPeriodsFileName, elpasedPeriodStem); // file未指定,异步压缩
      } else {
        future = renamedRawAndAsyncCompress(elapsedPeriodsFileName, elpasedPeriodStem); // file指定,重命名并异步压缩
      }
    }

    if (archiveRemover != null) {
      archiveRemover.clean(new Date(timeBasedFileNamingAndTriggeringPolicy.getCurrentTime())); // 删除历史日志
    }
  }


默认的archiveRemover为ch.qos.logback.core.rolling.helper.DefaultArchiveRemover抽象类
  public void clean(Date now) {
    long nowInMillis = now.getTime();
    int periodsElapsed = computeElapsedPeriodsSinceLastClean(nowInMillis);
    lastHeartBeat = nowInMillis;
    if (periodsElapsed > 1) {
      addInfo("periodsElapsed = " + periodsElapsed);
    }
    // 从待删除日志的终止日期开始,每次回退一天,删除过期日志
    for (int i = 0; i < periodsElapsed; i++) {
      cleanByPeriodOffset(now, periodOffsetForDeletionTarget - i);
    }
  }

  public void setMaxHistory(int maxHistory) {
    // 待删除日志的终止日期:回退(maxHistory+1)天
    this.periodOffsetForDeletionTarget = -maxHistory - 1;
  }


cleanByPeriodOffset为抽象方法,这里交由
ch.qos.logback.core.rolling.helper.TimeBasedArchiveRemover子类实现:
  protected void cleanByPeriodOffset(Date now, int periodOffset) {
    Date date2delete = rc.getRelativeDate(now, periodOffset); // 计算需要删除日志的日期
    String filename = fileNamePattern.convert(date2delete);
    File file2Delete = new File(filename);
    if (file2Delete.exists() && file2Delete.isFile()) {
      file2Delete.delete(); // 删除文件
      addInfo("deleting " + file2Delete);
      if (parentClean) {
        removeFolderIfEmpty(file2Delete.getParentFile());
      }
    }
  }


d. 如果要启用压缩,需要将fileNamePattern的后缀名设置为压缩格式,如:/logs/heuristic-%d{yyyy-MM-dd}.zip。

看下ch.qos.logback.core.rolling.RollingPolicyBase类相关的代码:
  protected void determineCompressionMode() {
    if (fileNamePatternStr.endsWith(".gz")) {
      addInfo("Will use gz compression");
      compressionMode = CompressionMode.GZ;
    } else if (fileNamePatternStr.endsWith(".zip")) {
      addInfo("Will use zip compression");
      compressionMode = CompressionMode.ZIP;
    } else { // 如果后缀名不是.gz或.zip,不会启用压缩
      addInfo("No compression will be used");
      compressionMode = CompressionMode.NONE;
    }
  }


e. RollingFileAppender保证append的值为true,这样当天先写入的日志内容就不会丢失

ch.qos.logback.core.rolling.RollingFileAppender类的start()方法:
    if (!append) { // append为false时
      addWarn("Append mode is mandatory for RollingFileAppender");
      append = true; // 改成true
    }


f. prudent模式不支持file设定;如果启用了压缩,logback将不会记录日志

ch.qos.logback.core.rolling.RollingFileAppender类
的start()方法:
    if (isPrudent()) { // 安全模式,但效率低
      if (rawFileProperty() != null) {
        addWarn("Setting \"File\" property to null on account of prudent mode");
        setFile(null); // 取消file属性设置
      }
      if (rollingPolicy.getCompressionMode() != CompressionMode.NONE) { // 启用了压缩
        addError("Compression is not supported in prudent mode. Aborting");
        return; // 返回,不会进行后面的记录日志操作
      }
    }
分享到:
评论
4 楼 xunux 2016-04-01  
如何按日期分目录,按小时和文件大小滚动策略? 我下面的配置无效, 不按日期分目录就有效。

该如何实现呢?


<appender name="downloadLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
		<file>${log.dir}/downloadLog.log</file>
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.dir}/%d{yyyy-MM-dd}/downloadLog-%d{yyyy-MM-dd_HH}.%i.log</fileNamePattern>
            <maxHistory>365</maxHistory>
			<timeBasedFileNamingAndTriggeringPolicy	class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
				<MaxFileSize>5MB</MaxFileSize>
			</timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
		<encoder charset="UTF-8">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} - %msg%n</pattern>
        </encoder>
	</appender>
3 楼 PlunderColor 2015-12-16  
很好的文章
把前一天的log日志压缩的时间是什么时候呢, 第二天开始打log的时候吗?
2 楼 czj4451 2014-11-12  
在世界的中心呼喚愛 写道
不错的文章。
这里删除过期的日志,通过编码实现?

不好意思没写清楚,logback已经实现了,只需要在logback[-test].xml文件中配置maxHistory属性就可以了。
1 楼 在世界的中心呼喚愛 2014-11-10  
不错的文章。
这里删除过期的日志,通过编码实现?

相关推荐

    Logback配置文件根据 LEVEL级别将日志分类保存到不同文件.docx

    Logback提供了多种文件滚动策略,例如`SizeAndTimeBasedRollingPolicy`,可以根据文件大小和时间进行滚动。在上面的配置中,当单个日志文件达到100MB时,系统会自动创建新的文件,并将旧文件按日期压缩保存,最多...

    shiro简单登录+logback日志记录

    Logback提供了按日期滚动、按大小滚动等多种日志文件滚动策略,确保日志不会无限增长占用磁盘空间。 7. **MDC(Mapped Diagnostic Context)** MDC是Logback提供的一种特性,允许我们在代码中存储一些诊断信息,...

    采用slf4j+logback输出日志

    Logback支持更复杂的配置,如文件输出、日志滚动、异步日志记录、过滤器和自定义编码器等。例如,可以配置一个将日志写入文件的Appender: ```xml &lt;appender name="FILE" class="ch.qos.logback.core....

    Logback类库含logback.xml配置文件

    学习 Logback 包括理解如何配置 `logback.xml` 文件以满足项目需求,如何在代码中使用 SLF4J API 来记录日志,以及如何管理和优化日志输出,比如控制日志文件大小、滚动策略等。对于 Java 开发者来说,熟练掌握 ...

    Logback框架需要的3个jar包和logback.xml文件

    - **大小滚动策略(SizeBasedTriggeringPolicy)**:当日志文件达到一定大小时,会自动创建新的日志文件并保留旧文件。 - **时间滚动策略(TimeBasedTriggeringPolicy)**:根据时间(如每天、每小时)滚动日志...

    日志文件配置,logback

    Logback 配置文件的灵活性使得它能够满足各种日志需求,包括控制日志级别、定制日志格式、设置日志输出位置以及管理日志文件大小。SLF4J 的使用则简化了与日志框架的交互,提供了良好的可移植性。正确配置和使用 ...

    logback日志配置

    1. **属性定义**:通过 `&lt;property&gt;` 标签定义日志文件存储路径。 2. **控制台输出配置**: - `&lt;appender&gt;`:定义了一个名为 `console` 的控制台输出 Appender。 - `&lt;layout&gt;`:定义了输出格式,包括日期、日志...

    Grails3配置logback日志.pdf

    rollingPolicy用于定义日志文件滚动的策略,本文中展示了基于时间的滚动策略TimeBasedRollingPolicy,并且设置了日志文件名的模式以及日志文件保留的时间长度。 在配置文件中,还演示了如何设置日志文件滚动的触发...

    Tomcat日志catalina.out过大解决方案--使用logback按日轮转.rar

    这个配置中,`RollingFileAppender`定义了日志写入到`logs/catalina.log`文件,并使用`TimeBasedRollingPolicy`按日期进行滚动,每天生成一个新的日志文件,最多保留30天的历史日志。`encoder`部分则设置了日志的...

    Logback 实例,log4,slf4,logback日志输出 demo

    Logback提供了日志归档策略,如`TimeBasedRollingPolicy`,可以按时间(每天、每小时等)滚动日志文件,防止单个文件过大。此外,还可以设置最大文件数量、压缩旧日志等策略,以优化存储空间的使用。 **总结** ...

    logback-spring.xml日志打印demo

    可以通过`FileAppender`或`RollingFileAppender`实现日志文件的滚动,例如: ```xml &lt;appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"&gt; &lt;file&gt;logs/app.log ...

    logbackーslf4j-配置文件实例 难得

    Logback允许配置日志文件的归档策略,例如按日期、大小等条件滚动。这有助于管理日志文件的大小和数量,防止存储空间被过度占用。 ### 9. 性能优化 Logback提供了多种性能优化选项,例如预编译日志模式、日志缓存...

    logback做日志(代码演示和文档)

    3. **日志归档**:通过TimeBasedRollingPolicy,logback 可以定期滚动和归档日志文件。 4. **MDC(Mapped Diagnostic Context)**:用于存储与线程相关的诊断信息,便于追踪问题。 5. **SiftingAppender**:允许为...

    logback日志文件

    例如,我们可以设置每天生成一个新的日志文件,并且当文件大小达到一定值时自动归档: ```xml &lt;appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"&gt; &lt;file&gt;logs/app.log ...

    springboot整合logback保存日志到文件

    这样配置后,日志文件将按照日期自动滚动,并且当单个文件大小达到10MB时,触发滚动。 5. **自定义日志处理器** 如果需要对日志进行特殊处理,比如发送邮件、存入数据库等,可以通过定义自定义Appender实现。 6....

    LogBack日志的使用

    日志归档是LogBack的另一大特色,通过`TimeBasedRollingPolicy`可以设置日志文件按日期滚动,避免单个日志文件过大。同时,`SizeAndTimeBasedFNATP`策略允许在文件大小达到一定限制时进行滚动。 在分布式系统中,...

    logback jar包和logback.xml配置文件打包下载 小白新手学Java

    `appender-ref`指定了`STDOUT`appender,意味着所有日志都会输出到控制台。 学习和理解SLF4J与Logback的使用,对于Java开发者来说非常重要,它们能够帮助我们有效地管理和监控应用程序的运行状况。通过配置`logback...

    日志框架+Logback的jar包和配置文件

    Logback支持多种高级特性,例如日志文件大小限制、自动滚动、异步日志记录等。例如,你可以添加一个File Appender来将日志写入文件,并配置文件大小和保留策略: ```xml &lt;appender name="FILE" class="ch.qos....

    logback所需jar包

    Logback还支持日志文件的滚动和清理策略。例如,可以配置每天创建一个新的日志文件,保留最近30天的文件: ```xml &lt;appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"&gt; &lt;file&gt;logs/...

    Logback中文手册

    3. **RollingFileAppender**:按日期或文件大小自动滚动日志文件,避免单个文件过大。 4. **SMTPAppender**:当发生严重错误时,通过电子邮件发送报警。 四、过滤器与触发策略 1. **过滤器**:允许根据特定条件过滤...

Global site tag (gtag.js) - Google Analytics