`
kimmking
  • 浏览: 546866 次
  • 性别: Icon_minigender_1
  • 来自: 中华大丈夫学院
社区版块
存档分类
最新评论

log4j定时轮换文件

    博客分类:
  • java
阅读更多

网友 zhangyang6380006在帖子

http://www.iteye.com/topic/1006088

主题:求一个log文件定时生成功能

 

正好做过,就丢出来献丑了。

 -------------------------------------------------------------------------------

同步异步

Foxswily 写道
不知道有没有考虑用slf4j+logback,log4j的作者已经转到把精力完全放倒这上边了,据说性能有提升。

另外log4j是异步输出,服务停止的瞬间不保证能输出所有的log,如果是精确度高的业务也许不合适


http://www.iteye.com/topic/900845
log4j内置的三种 输出方式

flush=true 直接输出到文件,同步不缓存
bufferedIO 按一定字节大小缓存,同步缓存
AsynFileAppender  按一定的条数缓存,异步输出

  -------------------------------------------------------------------------------

仓库与自定义配置

 

说到log4j,大家最常见的用法就是 配置一个log4j.xml或properties,放在classpath的根目录下。

在里面配置上多个Appender,多个package对应的Logger或是Category,然后在代码里,直接用Class获取logger。

 

其实还有两点可以提一提:

1、使用命名logger,而不是class

// <logger  name="ASYNC_LOGGER">
Logger logger = Logger.getLogger("ASYNC_LOGGER");

 

2、使用仓库配置多个不同的log4j配置文件

 

       		LoggerRepository loggerRepository1 =  new Hierarchy(new RootCategory(Level.DEBUG));
		String path = new File("log4j_1.xml").getAbsolutePath();
		new DOMConfigurator().doConfigure(path,loggerRepository1);
		Logger log_1 = loggerRepository1.getLogger("TEST_LOGGER_1");
		
		LoggerRepository loggerRepository2 =  new Hierarchy(new RootCategory(Level.DEBUG));
		path = new File("log4j_2.xml").getAbsolutePath();
		new DOMConfigurator().doConfigure(path,loggerRepository2);
		Logger log_2 = loggerRepository2.getLogger("TEST_LOGGER_2");

 

 

 -------------------------------------------------------------------------------

轮换文件

 

  log4j可以按大小轮换文件(FileAppender, fileSize), 按天轮换文件 (DailyRollingFileAppender )

在我的某个应用场景中,使用log4j做数据落地,就是把每条日志数据格式化后,写入本地日志文件。

然后通过一个进程来读取所有轮换后的文件,分析每一条数据,入库(mongodb)。

做了如下的修改

1、除了使用文件大小来做轮换规则外,添加一个rollTime属性,表示需要轮换的时间s。

如果文件一直为0,不轮换,创建文件时记录下时间戳,定时与当前时间比较,超过rollTime,强制轮换。

2、同时修改轮换文件名称规则,默认的是.1,.2...这种形式。修改为.时间戳的形式。

其实还自定义了一个简单的Layout序列化数据。这个不是必须的。

 

使用方法,在log4j.xml中,

 

<appender
  class="xxx.log.TimeRollingFileAppender"
  name="ROLLING_FILE">
  <param name="MaxBackupIndex" value="1024" />
  <param name="Encoding" value="UTF-8" />
  <param name="File" value="esb.log" />
  <!--
   <param name="BufferSize" value="8192" />
   <param name="BufferedIO" value="true" />
  -->
  <param name="ImmediateFlush" value="true" />
  <param name="RollTime" value="60" />
  <param name="MaxFileSize" value="100MB" />

   ......

 

import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.Writer;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.log4j.FileAppender;
import org.apache.log4j.helpers.CountingQuietWriter;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.spi.LoggingEvent;

/**
 * TODO 根据时间和大小轮换文件
 *
 * @author kimmking (mailto:qinjw@primeton.com)
 */
public class TimeRollingFileAppender extends FileAppender {

	/**
	 * The default maximum file size is 10MB.
	 */
	protected long maxFileSize = 10 * 1024 * 1024;

	/**
	 * There is one backup file by default.
	 */
	protected int maxBackupIndex = 1;

	private long nextRollover = 0;

	protected int rollTime = 60; // seconds

	long fileTimeStamp = 0;

	Timer timer = null;

	private TimerTask getTask() {

		return new TimerTask() {

			@Override
			public void run() {

				// 时间戳
				long result = System.currentTimeMillis() - fileTimeStamp - getRollTime() * 1000;
				if (result > 0)
					if (new File(fileName).length() > 0)
						rollOver();

			}
		};
	}

	/**
	 * The default constructor simply calls its
	 * {@link FileAppender#FileAppender parents constructor}.
	 */
	public TimeRollingFileAppender() {
		super();

		timer = new Timer("TimeRollingFileAppender", true);

		long period = rollTime * 1000;

		TimerTask task = getTask();
		timer.schedule(task, period, 1l); // 从一个轮换时间间隔以后,每秒检查一次

	}

	/**
	 * Returns the value of the <b>MaxBackupIndex</b> option.
	 */
	public int getMaxBackupIndex() {
		return maxBackupIndex;
	}

	/**
	 * Get the maximum size that the output file is allowed to reach before
	 * being rolled over to backup files.
	 *
	 * @since 1.1
	 */
	public long getMaximumFileSize() {
		return maxFileSize;
	}

	/**
	 * Implements the usual roll over behaviour.
	 *
	 * <p>
	 * If <code>MaxBackupIndex</code> is positive, then files {
	 * <code>File.1</code>, ..., <code>File.MaxBackupIndex -1</code> are
	 * renamed to {<code>File.2</code>, ...,
	 * <code>File.MaxBackupIndex</code> . Moreover, <code>File</code> is
	 * renamed <code>File.1</code> and closed. A new <code>File</code> is
	 * created to receive further log output.
	 *
	 * <p>
	 * If <code>MaxBackupIndex</code> is equal to zero, then the
	 * <code>File</code> is truncated with no backup files created.
	 */
	public// synchronization not necessary since doAppend is alreasy synched
	synchronized void rollOver() {
		File target;
		File file;

		if (qw != null) {
			long size = ((CountingQuietWriter) qw).getCount();
			LogLog.debug("rolling over count=" + size);
			// if operation fails, do not roll again until
			// maxFileSize more bytes are written
			nextRollover = size + maxFileSize;
		}
		// LogLog.debug("maxBackupIndex=" + maxBackupIndex);
		long timestamp = System.currentTimeMillis();

		boolean renameSucceeded = true;
		// If maxBackups <= 0, then there is no file renaming to be done.
		// if (maxBackupIndex > 0) {
		// // Delete the oldest file, to keep Windows happy.
		// file = new File(fileName + '.' + maxBackupIndex);
		// if (file.exists())
		// renameSucceeded = file.delete();

		// // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3,
		// // 2}
		// for (int i = maxBackupIndex - 1; i >= 1 && renameSucceeded; i--) {
		// file = new File(fileName + "." + i);
		// if (file.exists()) {
		// target = new File(fileName + '.' + (i + 1));
		// LogLog.debug("Renaming file " + file + " to " + target);
		// renameSucceeded = file.renameTo(target);
		// }
		// }
		//
		// if (renameSucceeded) {
		// Rename fileName to fileName.1
		target = new File(fileName + "." + timestamp);

		this.closeFile(); // keep windows happy.

		file = new File(fileName);
		LogLog.debug("Renaming file " + file + " to " + target);
		renameSucceeded = file.renameTo(target);
		//
		// if file rename failed, reopen file with append = true
		//
		if (!renameSucceeded) {
			try {
				this.setFile(fileName, true, bufferedIO, bufferSize);
			} catch (IOException e) {
				if (e instanceof InterruptedIOException) {
					Thread.currentThread().interrupt();
				}
				LogLog.error("setFile(" + fileName + ", true) call failed.", e);
			}
		}
		// }
		// }

		//
		// if all renames were successful, then
		//
		if (renameSucceeded) {
			try {
				// This will also close the file. This is OK since multiple
				// close operations are safe.
				this.setFile(fileName, false, bufferedIO, bufferSize);
				nextRollover = 0;
			} catch (IOException e) {
				if (e instanceof InterruptedIOException) {
					Thread.currentThread().interrupt();
				}
				LogLog.error("setFile(" + fileName + ", false) call failed.", e);
			}
		}
	}

	public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize) throws IOException {
		File file = new File(fileName).getParentFile();
		if (!file.exists())
			file.mkdirs();
		super.setFile(fileName, append, this.bufferedIO, this.bufferSize);
		if (append) {
			File f = new File(fileName);
			((CountingQuietWriter) qw).setCount(f.length());
		}

		fileTimeStamp = System.currentTimeMillis();
	}

	public void setRollTime(int rollTime) {

		if (this.rollTime == rollTime)
			return;

		this.rollTime = rollTime;

		// if (this.timer != null) {
		// this.timer.cancel();
		// }
		// this.timer = new Timer("TimeRollingFileAppender", true);
		//
		// if (rollTime > 0) {
		// long period = rollTime * 1000;
		// this.timer.schedule(getTask(), period, period);
		// }
	}

	public final int getRollTime() {
		return this.rollTime;
	}

	/**
	 * Set the maximum number of backup files to keep around.
	 *
	 * <p>
	 * The <b>MaxBackupIndex</b> option determines how many backup files are
	 * kept before the oldest is erased. This option takes a positive integer
	 * value. If set to zero, then there will be no backup files and the log
	 * file will be truncated when it reaches <code>MaxFileSize</code>.
	 */
	public void setMaxBackupIndex(int maxBackups) {
		this.maxBackupIndex = maxBackups;
	}

	/**
	 * Set the maximum size that the output file is allowed to reach before
	 * being rolled over to backup files.
	 *
	 * <p>
	 * This method is equivalent to {@link #setMaxFileSize} except that it is
	 * required for differentiating the setter taking a <code>long</code>
	 * argument from the setter taking a <code>String</code> argument by the
	 * JavaBeans {@link java.beans.Introspector Introspector}.
	 *
	 * @see #setMaxFileSize(String)
	 */
	public void setMaximumFileSize(long maxFileSize) {
		this.maxFileSize = maxFileSize;
	}

	/**
	 * Set the maximum size that the output file is allowed to reach before
	 * being rolled over to backup files.
	 *
	 * <p>
	 * In configuration files, the <b>MaxFileSize</b> option takes an long
	 * integer in the range 0 - 2^63. You can specify the value with the
	 * suffixes "KB", "MB" or "GB" so that the integer is interpreted being
	 * expressed respectively in kilobytes, megabytes or gigabytes. For example,
	 * the value "10KB" will be interpreted as 10240.
	 */
	public void setMaxFileSize(String value) {
		maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1);
	}

	protected void setQWForFiles(Writer writer) {
		this.qw = new CountingQuietWriter(writer, errorHandler);
	}

	/**
	 * This method differentiates RollingFileAppender from its super class.
	 *
	 * @since 0.9.0
	 */
	protected void subAppend(LoggingEvent event) {
		super.subAppend(event);
		if (fileName != null && qw != null) {
			long size = ((CountingQuietWriter) qw).getCount();
			if (size >= maxFileSize && size >= nextRollover) {
				rollOver();
			}
		}
	}
}

 

 

 

分享到:
评论
8 楼 leeaee 2011-04-18  
我和楼主有相同的需求,正准备自己写一个的~楼主可以把轮询的时间可配,1s 毕竟不能慢足大家的需求的,明天来帮楼主也再测试下~
7 楼 kimmking 2011-04-18  
ctoeye 写道
引用
  log4j可以按大小轮换文件(FileAppender, fileSize), 按天轮换文件 (DailyRollingFileAppender )

在我的某个应用场景中,使用log4j做数据落地,就是把每条日志数据格式化后,写入本地日志文件。

然后通过一个进程来读取所有轮换后的文件,分析每一条数据,入库(mongodb)。

做了如下的修改

1、除了使用文件大小来做轮换规则外,添加一个rollTime属性,表示需要轮换的时间s。

如果文件一直为0,不轮换,创建文件时记录下时间戳,定时与当前时间比较,超过rollTime,强制轮换。

2、同时修改轮换文件名称规则,默认的是.1,.2...这种形式。修改为.时间戳的形式。

其实还自定义了一个简单的Layout序列化数据。这个不是必须的。


log4j本来就支持这种行为,不知道为什么还要写代码?
而且这种错误日志还需要入库吗?除非是业务相关的日记。


默认实现不支持的。
6 楼 kimmking 2011-04-18  
kakaluyi 写道

1 this.closeFile(); // keep windows happy.后面注释是log4j作者写的吗,真有闲情逸致啊
2 overwrite原先的FileAppender,是很好的实践,看了下代码,其他没有什么问题



我现在的项目用着呢。
我机器上测试每秒写8000笔 3.5k大小日志没什么问题。
5 楼 cady36 2011-04-18  
mark 以后有用估计
4 楼 kakaluyi 2011-04-18  

1 this.closeFile(); // keep windows happy.后面注释是log4j作者写的吗,真有闲情逸致啊
2 overwrite原先的FileAppender,是很好的实践,看了下代码,其他没有什么问题
3 楼 ctoeye 2011-04-18  
引用
  log4j可以按大小轮换文件(FileAppender, fileSize), 按天轮换文件 (DailyRollingFileAppender )

在我的某个应用场景中,使用log4j做数据落地,就是把每条日志数据格式化后,写入本地日志文件。

然后通过一个进程来读取所有轮换后的文件,分析每一条数据,入库(mongodb)。

做了如下的修改

1、除了使用文件大小来做轮换规则外,添加一个rollTime属性,表示需要轮换的时间s。

如果文件一直为0,不轮换,创建文件时记录下时间戳,定时与当前时间比较,超过rollTime,强制轮换。

2、同时修改轮换文件名称规则,默认的是.1,.2...这种形式。修改为.时间戳的形式。

其实还自定义了一个简单的Layout序列化数据。这个不是必须的。


log4j本来就支持这种行为,不知道为什么还要写代码?
而且这种错误日志还需要入库吗?除非是业务相关的日记。
2 楼 liuyes 2011-04-18  
不错,有机会也用一下
1 楼 key_hua 2011-04-18  
很有用哦,借用学习了

相关推荐

    log4j.jar包,和log4j.properties配置文件下载

    在"Log4j.jar包,和log4j.properties属性文件打包下载"中,我们有两个关键组成部分: 1. **Log4j.jar**:这是Log4j的主要库文件,包含了所有必需的类和方法,使得程序员能够方便地在代码中插入日志语句。它提供了...

    log4j多文件输出打印

    本话题将深入探讨如何使用Log4j实现多文件输出打印,以及自定义日志的配置。 首先,我们要理解Log4j的基本工作原理。Log4j的核心组件包括Logger、Appender和Layout。Logger负责生成日志事件,Appender则负责接收...

    log4j-1.2.17的jar包以及依赖包,还有一份log4j的配置文件,输出到控制台和文件夹两种配置

    1. **log4j-1.2.17.jar**: 这是Log4j的主要库文件,包含了所有Log4j的类和接口。通过这个库,开发者可以方便地在代码中插入日志语句,记录程序运行时的信息、警告、错误等。 2. **commons-logging-1.2.jar**: 这是...

    老生常谈Log4j和Log4j2的区别(推荐)

    下面我们将从配置文件类型、核心JAR包、文件渲染和Log调用四个方面来比较Log4j和Log4j2的区别。 配置文件类型 Log4j通过一个.properties文件作为主配置文件,而Log4j2则弃用了这种方式,采用的是.xml、.json或者....

    Log4J_全能配置文件.pdf

    ### Log4J 全能配置文件详解 #### 一、概述 Log4J是一款非常流行的Java日志框架,被广泛应用于各种规模的应用程序中。它提供了灵活的日志记录机制,可以将日志输出到不同的目的地,如控制台、文件、数据库等,并且...

    log4j.properties配置文件

    ### log4j.properties配置文件详解 #### 一、概述 `log4j.properties`是Apache Log4j框架中用于配置日志记录行为的核心文件之一。通过这个文件,开发者可以定义日志消息的输出方式(例如控制台或文件)、日志级别...

    log4j及配置文件

    《深入理解Log4j及其配置文件》 在Java开发领域,日志管理是不可或缺的一部分,它可以帮助开发者跟踪程序运行状态,排查错误,优化性能。Log4j,作为Apache的一个开源项目,是Java中最广泛使用的日志框架之一。本文...

    log4j.CustomLogAppender 限制log4j文件保存天数

    每天生成一个log4j日志文件,如果只需要将最近一段时间内的日志文件保留,以前或更早的文件不用保留。例如只保留最近一周的日志,日志文件保留3天等等这些。。。通过这个jar包就可以实现。 log4j.properties文件在...

    log4j2配置文件

    log4j2配置,文件分割,自动清除等相关配置。

    若依框架使用的log4j2.16.0,修复log4j漏洞log4j2下载最新log4j2.16.0下载

    在提供的压缩包文件列表中,"log4j2.16.0"可能包含了Log4j2库的更新JAR文件或其他相关资源。用户应当解压这个文件,然后根据项目的具体依赖管理方式,将新的JAR添加到若依框架的类路径中,或者更新Maven或Gradle的...

    log4j.properties文件放置在其它目录下

    log4j.properties 文件放置在其它目录下 在 Tomcat 中,log4j.properties 文件通常被放在 src 目录下,这样系统自动会找到该文件的路径是在 WEB-INF/classes 文件下,该目录在 classpath 下,所以直接就能找到。...

    log4j使用jar包和log4j.properties配置文件

    本文将详细探讨Log4j的使用,主要关注1.2.17版本的jar包以及配置文件`log4j.properties`。 ### 1. Log4j简介 Log4j是一个开源的日志组件,支持多种输出格式,如控制台、文件、数据库等。它的核心概念包括Logger、...

    log4j需要的jar以及properties文件

    例如,`log4j.appender.Console=org.apache.log4j.ConsoleAppender`配置了一个控制台Appender,而`log4j.appender.File=org.apache.log4j.DailyRollingFileAppender`则配置了一个每天滚动的日志文件Appender。...

    使用log4j写日志文件

    在Java应用中使用Log4j进行日志记录的第一步,是创建并配置log4j的属性文件(log4j.properties)。这个文件定义了日志的级别、输出目的地以及日志的格式。以下是一个典型的log4j配置示例: ```properties # 设置根...

    SSM整合中的Log4j日志的配置详情

    四、在 Maven 项目中引入 Log4j 依赖 在 Maven 项目中,需要引入 Log4j 依赖项,以便使用 Log4j。下面是一个基本的 Maven 依赖项配置: ``` &lt;groupId&gt;log4j &lt;artifactId&gt;log4j &lt;version&gt;1.2.16 ``` 这个配置...

    Log4j2简介及与Log4j效率对比

    - **日志文件写入速度**:Log4j2通过优化的布局(Layout)和过滤器(Filter),实现了更快的日志文件写入速度。这对于大数据量的日志记录尤为重要。 综上所述,Log4j2在效率方面较Log4j 1.x有了显著提升,这主要得益...

    log4j日志配置以及配置文件详解

    本文将深入探讨log4j的配置以及配置文件的详解。** 首先,我们要理解什么是`log4j.properties`文件。这是log4j框架的配置文件,使用Java Properties格式,用于定义日志输出的行为。主要包括以下几个核心部分: 1. ...

    log4j的配置文件.zip

    `log4j.properties`文件是Log4j的核心配置文件,它定义了日志输出的行为,包括日志级别、输出目的地、格式以及过滤规则等。 在`log4j.properties`文件中,有以下几个关键知识点: 1. **日志级别(Logging Levels)...

    log4j2-core和log4j2-api和log4j2文档文件

    这是做日志分析的最新log4j2所必需的文件和包

    log4j使用jar文件

    使用Log4j时,你需要在项目的类路径下包含`log4j.jar`文件,这是Log4j的基本运行库。然后,创建一个`log4j.properties`或`log4j.xml`配置文件,定义Logger、Appender和Layout的具体设置。例如: ```properties # ...

Global site tag (gtag.js) - Google Analytics