Log4j 4种日志文件生成方式

参考了某位兄弟的代码, 但是使用了之后,回过头来写博客忘记原地址,勿怪。

Log4j  4种日志文件生成方式

方式1 : 按天生成日志  org.apache.log4j.DailyRollingFileAppender (log4j.jar 自带)

方式2 : 按大小生成日志   org.apache.log4j.RollingFileAppender (log4j.jar  自带)

方式3 : 支持每日创建新的日志文件的同时,又限制日志文件的大小、个数 Log4JDateAndSizeSplit  (自定义,见下面的类代码)

方式4 :每日创建新的日志文件的同时,又限制日志文件的个数 Log4jDateSplitAndCountControl (自定义,见下面的类代码)

Log4JDateAndSizeSplit  代码如下

package com.sino.lgdd.utils;

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

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

/**
 * 支持每日创建新的日志文件的同时,又限制日志文件的大小、个数
 * MaxBackupIndex=-1 的时候表示不限制个数
 */
public class Log4JDateAndSizeSplit extends FileAppender {
	static final int TOP_OF_TROUBLE = -1;
	static final int TOP_OF_MINUTE = 0;
	static final int TOP_OF_HOUR = 1;
	static final int HALF_DAY = 2;
	static final int TOP_OF_DAY = 3;
	static final int TOP_OF_WEEK = 4;
	static final int TOP_OF_MONTH = 5;

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

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

	/** 
	 * The date pattern. By default, the pattern is set to "'.'yyyy-MM-dd" 
	 * meaning daily rollover. 
	 */
	private String datePattern = "'.'yyyy-MM-dd";

	/** 
	 * The log file will be renamed to the value of the scheduledFilename 
	 * variable when the next interval is entered. For example, if the rollover 
	 * period is one hour, the log file will be renamed to the value of 
	 * "scheduledFilename" at the beginning of the next hour. 
	 *  
	 * The precise time when a rollover occurs depends on logging activity. 
	 */
	private String scheduledFilename;

	/** 
	 * The next time we estimate a rollover should occur. 
	 */
	private long nextCheck = System.currentTimeMillis() - 1;

	Date now = new Date();

	SimpleDateFormat sdf;

	RollingCalendar rc = new RollingCalendar();

	int checkPeriod = TOP_OF_TROUBLE;

	// The gmtTimeZone is used only in computeCheckPeriod() method.  
	static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");

	/** 
	 * The default constructor does nothing. 
	 */
	public Log4JDateAndSizeSplit() {
	}

	/** 
	 * Instantiate a <code>Log4JDateAndSizeSplit</code> and open the file 
	 * designated by <code>filename</code>. The opened filename will become the 
	 * ouput destination for this appender. 
	 */
	public Log4JDateAndSizeSplit(Layout layout, String filename, String datePattern) throws IOException {
		super(layout, filename, true);
		this.datePattern = datePattern;
		activateOptions();
	}

	/** 
	 * 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;
	}

	/** 
	 * 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);
	}

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

	/** 
	 * 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;
	}

	/** 
	 * The <b>DatePattern</b> takes a string in the same format as expected by 
	 * {@link SimpleDateFormat}. This options determines the rollover schedule. 
	 */
	public void setDatePattern(String pattern) {
		datePattern = pattern;
	}

	/** Returns the value of the <b>DatePattern</b> option. */
	public String getDatePattern() {
		return datePattern;
	}

	public void activateOptions() {
		super.activateOptions();
		if (datePattern != null && fileName != null) {
			now.setTime(System.currentTimeMillis());
			sdf = new SimpleDateFormat(datePattern);
			int type = computeCheckPeriod();
			printPeriodicity(type);
			rc.setType(type);
			File file = new File(fileName);
			scheduledFilename = fileName + sdf.format(new Date(file.lastModified()));

		} else {
			LogLog.error("Either File or DatePattern options are not set for appender [" + name + "].");
		}
	}

	void printPeriodicity(int type) {
		switch (type) {
		case TOP_OF_MINUTE:
			LogLog.debug("Appender [" + name + "] to be rolled every minute.");
			break;
		case TOP_OF_HOUR:
			LogLog.debug("Appender [" + name + "] to be rolled on top of every hour.");
			break;
		case HALF_DAY:
			LogLog.debug("Appender [" + name + "] to be rolled at midday and midnight.");
			break;
		case TOP_OF_DAY:
			LogLog.debug("Appender [" + name + "] to be rolled at midnight.");
			break;
		case TOP_OF_WEEK:
			LogLog.debug("Appender [" + name + "] to be rolled at start of week.");
			break;
		case TOP_OF_MONTH:
			LogLog.debug("Appender [" + name + "] to be rolled at start of every month.");
			break;
		default:
			LogLog.warn("Unknown periodicity for appender [" + name + "].");
		}
	}

	// This method computes the roll over period by looping over the  
	// periods, starting with the shortest, and stopping when the r0 is  
	// different from from r1, where r0 is the epoch formatted according  
	// the datePattern (supplied by the user) and r1 is the  
	// epoch+nextMillis(i) formatted according to datePattern. All date  
	// formatting is done in GMT and not local format because the test  
	// logic is based on comparisons relative to 1970-01-01 00:00:00  
	// GMT (the epoch).  

	int computeCheckPeriod() {
		RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone, Locale.ENGLISH);
		// set sate to 1970-01-01 00:00:00 GMT  
		Date epoch = new Date(0);
		if (datePattern != null) {
			for (int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {
				SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
				simpleDateFormat.setTimeZone(gmtTimeZone); // do all date  
															// formatting in GMT  
				String r0 = simpleDateFormat.format(epoch);
				rollingCalendar.setType(i);
				Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
				String r1 = simpleDateFormat.format(next);
				// System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);  
				if (r0 != null && r1 != null && !r0.equals(r1)) {
					return i;
				}
			}
		}
		return TOP_OF_TROUBLE; // Deliberately head for trouble...  
	}

	/** 
	 * 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  
	void sizeRollOver() {
		File target;
		File file;

		LogLog.debug("rolling over count=" + ((CountingQuietWriter) qw).getCount());
		LogLog.debug("maxBackupIndex=" + maxBackupIndex);

		String datedFilename = fileName + sdf.format(now);

		if (maxBackupIndex > 0) {
			// Delete the oldest file, to keep Windows happy.  
			file = new File(datedFilename + '.' + maxBackupIndex);
			if (file.exists())
				file.delete();

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

			// Rename fileName to datedFilename.1  
			target = new File(datedFilename + "." + 1);

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

			file = new File(fileName);
			LogLog.debug("Renaming file " + file + " to " + target);
			file.renameTo(target);
		} else if (maxBackupIndex < 0) {//infinite number of files   
			//find the max backup index  
			for (int i = 1; i < Integer.MAX_VALUE; i++) {
				target = new File(datedFilename + "." + i);
				if (!target.exists()) {//Rename fileName to datedFilename.i  
					this.closeFile();
					file = new File(fileName);
					file.renameTo(target);
					LogLog.debug("Renaming file " + file + " to " + target);
					break;
				}
			}
		}

		try {
			// This will also close the file. This is OK since multiple  
			// close operations are safe.  
			this.setFile(fileName, false, bufferedIO, bufferSize);
		} catch (IOException e) {
			LogLog.error("setFile(" + fileName + ", false) call failed.", e);
		}
		scheduledFilename = datedFilename;
	}

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

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

	/** 
	 * Rollover the current file to a new file. 
	 */
	void timeRollOver() throws IOException {

		/* Compute filename, but only if datePattern is specified */
		if (datePattern == null) {
			errorHandler.error("Missing DatePattern option in rollOver().");
			return;
		}

		String datedFilename = fileName + sdf.format(now);
		// It is too early to roll over because we are still within the  
		// bounds of the current interval. Rollover will occur once the  
		// next interval is reached.  
		if (scheduledFilename.equals(datedFilename)) {
			return;
		}

		// close current file, and rename it to datedFilename  
		this.closeFile();

		File target = new File(scheduledFilename);
		if (target.exists()) {
			target.delete();
		}

		File file = new File(fileName);
		boolean result = file.renameTo(target);
		if (result) {
			LogLog.debug(fileName + " -> " + scheduledFilename);
		} else {
			LogLog.error("Failed to rename [" + fileName + "] to [" + scheduledFilename + "].");
		}

		try {
			// This will also close the file. This is OK since multiple  
			// close operations are safe.  
			super.setFile(fileName, false, this.bufferedIO, this.bufferSize);
		} catch (IOException e) {
			errorHandler.error("setFile(" + fileName + ", false) call failed.");
		}
		scheduledFilename = datedFilename;
	}

	/** 
	 * This method differentiates Log4JDateAndSizeSplit from its super class. 
	 *  
	 * <p> 
	 * Before actually logging, this method will check whether it is time to do 
	 * a rollover. If it is, it will schedule the next rollover time and then 
	 * rollover. 
	 * */
	protected void subAppend(LoggingEvent event) {
		long n = System.currentTimeMillis();

		if (n >= nextCheck) {
			now.setTime(n);
			nextCheck = rc.getNextCheckMillis(now);
			try {
				timeRollOver();
			} catch (IOException ioe) {
				LogLog.error("rollOver() failed.", ioe);
			}
		} else if ((fileName != null) && ((CountingQuietWriter) qw).getCount() >= maxFileSize) {
			sizeRollOver();
		}
		super.subAppend(event);

	}
}

/** 
* RollingCalendar is a helper class to Log4JDateAndSizeSplit. Given a 
* periodicity type and the current time, it computes the start of the next 
* interval. 
* */
class RollingCalendar extends GregorianCalendar {

	int type = Log4JDateAndSizeSplit.TOP_OF_TROUBLE;

	RollingCalendar() {
		super();
	}

	RollingCalendar(TimeZone tz, Locale locale) {
		super(tz, locale);
	}

	void setType(int type) {
		this.type = type;
	}

	public long getNextCheckMillis(Date now) {
		return getNextCheckDate(now).getTime();
	}

	public Date getNextCheckDate(Date now) {
		this.setTime(now);

		switch (type) {
		case Log4JDateAndSizeSplit.TOP_OF_MINUTE:
			this.set(Calendar.SECOND, 0);
			this.set(Calendar.MILLISECOND, 0);
			this.add(Calendar.MINUTE, 1);
			break;
		case Log4JDateAndSizeSplit.TOP_OF_HOUR:
			this.set(Calendar.MINUTE, 0);
			this.set(Calendar.SECOND, 0);
			this.set(Calendar.MILLISECOND, 0);
			this.add(Calendar.HOUR_OF_DAY, 1);
			break;
		case Log4JDateAndSizeSplit.HALF_DAY:
			this.set(Calendar.MINUTE, 0);
			this.set(Calendar.SECOND, 0);
			this.set(Calendar.MILLISECOND, 0);
			int hour = get(Calendar.HOUR_OF_DAY);
			if (hour < 12) {
				this.set(Calendar.HOUR_OF_DAY, 12);
			} else {
				this.set(Calendar.HOUR_OF_DAY, 0);
				this.add(Calendar.DAY_OF_MONTH, 1);
			}
			break;
		case Log4JDateAndSizeSplit.TOP_OF_DAY:
			this.set(Calendar.HOUR_OF_DAY, 0);
			this.set(Calendar.MINUTE, 0);
			this.set(Calendar.SECOND, 0);
			this.set(Calendar.MILLISECOND, 0);
			this.add(Calendar.DATE, 1);
			break;
		case Log4JDateAndSizeSplit.TOP_OF_WEEK:
			this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());
			this.set(Calendar.HOUR_OF_DAY, 0);
			this.set(Calendar.SECOND, 0);
			this.set(Calendar.MILLISECOND, 0);
			this.add(Calendar.WEEK_OF_YEAR, 1);
			break;
		case Log4JDateAndSizeSplit.TOP_OF_MONTH:
			this.set(Calendar.DATE, 1);
			this.set(Calendar.HOUR_OF_DAY, 0);
			this.set(Calendar.SECOND, 0);
			this.set(Calendar.MILLISECOND, 0);
			this.add(Calendar.MONTH, 1);
			break;
		default:
			throw new IllegalStateException("Unknown periodicity type.");
		}
		return getTime();
	}
}

Log4jDateSplitAndCountControl 代码如下 :

/*
 * Copyright 1999-2005 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.sino.lgdd.utils;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.log4j.FileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.LoggingEvent;

/**
 * 支持每日创建新的日志文件的同时,又限制日志文件的个数(比如限制保存3个月内的日志)
 * 不支持文件大小
 */
public class Log4jDateSplitAndCountControl extends FileAppender {
	// The code assumes that the following constants are in a increasing
	// sequence.
	static final int TOP_OF_TROUBLE = -1;
	static final int TOP_OF_MINUTE = 0;
	static final int TOP_OF_HOUR = 1;
	static final int HALF_DAY = 2;
	static final int TOP_OF_DAY = 3;
	static final int TOP_OF_WEEK = 4;
	static final int TOP_OF_MONTH = 5;

	/**
	   The date pattern. By default, the pattern is set to
	   "'.'yyyy-MM-dd" meaning daily rollover.
	 */
	private String datePattern = "'.'yyyy-MM-dd";

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

	/**
	   The log file will be renamed to the value of the
	   scheduledFilename variable when the next interval is entered. For
	   example, if the rollover period is one hour, the log file will be
	   renamed to the value of "scheduledFilename" at the beginning of
	   the next hour.

	   The precise time when a rollover occurs depends on logging
	   activity.
	*/
	private String scheduledFilename;

	/**
	   The next time we estimate a rollover should occur. */
	private long nextCheck = System.currentTimeMillis() - 1;

	Date now = new Date();

	SimpleDateFormat sdf;

	RollingPastCalendar rpc = new RollingPastCalendar();

	int checkPeriod = TOP_OF_TROUBLE;

	// The gmtTimeZone is used only in computeCheckPeriod() method.
	static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");

	/**
	   The default constructor does nothing. */
	public Log4jDateSplitAndCountControl() {
	}

	/**
	  Instantiate a <code>Log4jDateSplitAndCountControl</code> and open the
	  file designated by <code>filename</code>. The opened filename will
	  become the ouput destination for this appender.

	  */
	public Log4jDateSplitAndCountControl(Layout layout, String filename, String datePattern) throws IOException {
		super(layout, filename, true);
		this.datePattern = datePattern;
		activateOptions();
	}

	/**
	   The <b>DatePattern</b> takes a string in the same format as
	   expected by {@link SimpleDateFormat}. This options determines the
	   rollover schedule.
	 */
	public void setDatePattern(String pattern) {
		datePattern = pattern;
	}

	/** Returns the value of the <b>DatePattern</b> option. */
	public String getDatePattern() {
		return datePattern;
	}

	/**
	   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 renamed to the value of the
	   scheduledFilename variable when the next interval is entered.
	 */
	public void setMaxBackupIndex(int maxBackups) {
		this.maxBackupIndex = maxBackups;
	}

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

	public void activateOptions() {
		super.activateOptions();

		LogLog.debug("Max backup file kept: " + maxBackupIndex + ".");

		if (datePattern != null && fileName != null) {
			now.setTime(System.currentTimeMillis());
			sdf = new SimpleDateFormat(datePattern);
			int type = computeCheckPeriod();
			printPeriodicity(type);
			rpc.setType(type);
			File file = new File(fileName);
			scheduledFilename = fileName + sdf.format(new Date(file.lastModified()));
		} else {
			LogLog.error("Either File or DatePattern options are not set for appender [" + name + "].");
		}
	}

	void printPeriodicity(int type) {
		switch (type) {
		case TOP_OF_MINUTE:
			LogLog.debug("Appender [[+name+]] to be rolled every minute.");
			break;
		case TOP_OF_HOUR:
			LogLog.debug("Appender [" + name + "] to be rolled on top of every hour.");
			break;
		case HALF_DAY:
			LogLog.debug("Appender [" + name + "] to be rolled at midday and midnight.");
			break;
		case TOP_OF_DAY:
			LogLog.debug("Appender [" + name + "] to be rolled at midnight.");
			break;
		case TOP_OF_WEEK:
			LogLog.debug("Appender [" + name + "] to be rolled at start of week.");
			break;
		case TOP_OF_MONTH:
			LogLog.debug("Appender [" + name + "] to be rolled at start of every month.");
			break;
		default:
			LogLog.warn("Unknown periodicity for appender [[+name+]].");
		}
	}

	// This method computes the roll over period by looping over the
	// periods, starting with the shortest, and stopping when the r0 is
	// different from from r1, where r0 is the epoch formatted according
	// the datePattern (supplied by the user) and r1 is the
	// epoch+nextMillis(i) formatted according to datePattern. All date
	// formatting is done in GMT and not local format because the test
	// logic is based on comparisons relative to 1970-01-01 00:00:00
	// GMT (the epoch).

	int computeCheckPeriod() {
		RollingPastCalendar rollingPastCalendar = new RollingPastCalendar(gmtTimeZone, Locale.ENGLISH);
		// set sate to 1970-01-01 00:00:00 GMT
		Date epoch = new Date(0);
		if (datePattern != null) {
			for (int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {
				SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
				simpleDateFormat.setTimeZone(gmtTimeZone); // do all date formatting in GMT
				String r0 = simpleDateFormat.format(epoch);
				rollingPastCalendar.setType(i);
				Date next = new Date(rollingPastCalendar.getNextCheckMillis(epoch));
				String r1 = simpleDateFormat.format(next);

				//System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);
				if (r0 != null && r1 != null && !r0.equals(r1)) {
					return i;
				}
			}
		}

		return TOP_OF_TROUBLE; // Deliberately head for trouble...
	}

	/**
	   Rollover the current file to a new file.
	*/
	void rollOver() throws IOException {
		/* Compute filename, but only if datePattern is specified */
		if (datePattern == null) {
			errorHandler.error("Missing DatePattern option in rollOver().");
			return;
		}

		String datedFilename = fileName + sdf.format(now);
		// It is too early to roll over because we are still within the
		// bounds of the current interval. Rollover will occur once the
		// next interval is reached.
		if (scheduledFilename.equals(datedFilename)) {
			return;
		}

		// close current file, and rename it to datedFilename
		this.closeFile();

		File target = new File(scheduledFilename);
		if (target.exists()) {
			target.delete();
		}

		File file = new File(fileName);
		boolean result = file.renameTo(target);
		if (result) {
			LogLog.debug(fileName + " -> " + scheduledFilename);

			// 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 + dateBefore());

				if (file.exists())
					file.delete();
			}
		} else {
			LogLog.error("Failed to rename [[+fileName+]] to [[+scheduledFilename+]].");
		}

		try {
			// This will also close the file. This is OK since multiple
			// close operations are safe.
			this.setFile(fileName, false, this.bufferedIO, this.bufferSize);
		} catch (IOException e) {
			errorHandler.error("setFile(" + fileName + ", false) call failed.");
		}
		scheduledFilename = datedFilename;
	}

	private String dateBefore() {
		String dataAnte = "";

		if (datePattern != null) {
			SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);

			dataAnte = simpleDateFormat.format(new Date(rpc.getPastCheckMillis(new Date(), maxBackupIndex)));
		}

		return dataAnte;
	}

	/**
	 * This method differentiates Log4jDateSplitAndCountControl from its
	 * super class.
	 *
	 * <p>Before actually logging, this method will check whether it is
	 * time to do a rollover. If it is, it will schedule the next
	 * rollover time and then rollover.
	 * */
	protected void subAppend(LoggingEvent event) {
		long n = System.currentTimeMillis();

		if (n >= nextCheck) {
			now.setTime(n);
			nextCheck = rpc.getNextCheckMillis(now);

			try {
				rollOver();
			} catch (IOException ioe) {
				LogLog.error("rollOver() failed.", ioe);
			}
		}

		super.subAppend(event);
	}

	/*
	 * DEBUG
	*/
	public static void main(String args[]) {
		Log4jDateSplitAndCountControl dmrfa = new Log4jDateSplitAndCountControl();

		dmrfa.setDatePattern("'.'yyyy-MM-dd-HH-mm");

		dmrfa.setFile("prova");

		System.out.println("dmrfa.getMaxBackupIndex():" + dmrfa.getMaxBackupIndex());

		dmrfa.activateOptions();

		for (int i = 0; i < 5; i++) {
			dmrfa.subAppend(null);

			try {
				Thread.sleep(60000);
			} catch (InterruptedException ex) {
			}

			System.out.println("Fine attesa");
		}
	}
}

/**
 *  RollingPastCalendar is a helper class to DailyMaxRollingFileAppender.
 *  Given a periodicity type and the current time, it computes the
 *  past maxBackupIndex date.
 * */
class RollingPastCalendar extends RollingCalendar {
	private static final long serialVersionUID = 1L;

	RollingPastCalendar() {
		super();
	}

	RollingPastCalendar(TimeZone tz, Locale locale) {
		super(tz, locale);
	}

	public long getPastCheckMillis(Date now, int maxBackupIndex) {
		return getPastDate(now, maxBackupIndex).getTime();
	}

	public Date getPastDate(Date now, int maxBackupIndex) {
		this.setTime(now);

		switch (type) {
		case Log4jDateSplitAndCountControl.TOP_OF_MINUTE:
			this.set(Calendar.SECOND, this.get(Calendar.SECOND));
			this.set(Calendar.MILLISECOND, this.get(Calendar.MILLISECOND));
			this.set(Calendar.MINUTE, this.get(Calendar.MINUTE) - maxBackupIndex);
			break;

		case Log4jDateSplitAndCountControl.TOP_OF_HOUR:
			this.set(Calendar.MINUTE, this.get(Calendar.MINUTE));
			this.set(Calendar.SECOND, this.get(Calendar.SECOND));
			this.set(Calendar.MILLISECOND, this.get(Calendar.MILLISECOND));
			this.set(Calendar.HOUR_OF_DAY, this.get(Calendar.HOUR_OF_DAY) - maxBackupIndex);
			break;

		case Log4jDateSplitAndCountControl.HALF_DAY:
			this.set(Calendar.MINUTE, this.get(Calendar.MINUTE));
			this.set(Calendar.SECOND, this.get(Calendar.SECOND));
			this.set(Calendar.MILLISECOND, this.get(Calendar.MILLISECOND));
			int hour = get(Calendar.HOUR_OF_DAY);
			if (hour < 12) {
				this.set(Calendar.HOUR_OF_DAY, 12);
			} else {
				this.set(Calendar.HOUR_OF_DAY, 0);
			}
			this.set(Calendar.DAY_OF_MONTH, this.get(Calendar.DAY_OF_MONTH) - maxBackupIndex);

			break;

		case Log4jDateSplitAndCountControl.TOP_OF_DAY:
			this.set(Calendar.HOUR_OF_DAY, this.get(Calendar.HOUR_OF_DAY));
			this.set(Calendar.MINUTE, this.get(Calendar.MINUTE));
			this.set(Calendar.SECOND, this.get(Calendar.SECOND));
			this.set(Calendar.MILLISECOND, this.get(Calendar.MILLISECOND));
			this.set(Calendar.DATE, this.get(Calendar.DATE) - maxBackupIndex);
			break;

		case Log4jDateSplitAndCountControl.TOP_OF_WEEK:
			this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());
			this.set(Calendar.HOUR_OF_DAY, this.get(Calendar.HOUR_OF_DAY));
			this.set(Calendar.MINUTE, this.get(Calendar.MINUTE));
			this.set(Calendar.SECOND, this.get(Calendar.SECOND));
			this.set(Calendar.MILLISECOND, this.get(Calendar.MILLISECOND));
			this.set(Calendar.WEEK_OF_YEAR, this.get(Calendar.WEEK_OF_YEAR) - maxBackupIndex);
			break;

		case Log4jDateSplitAndCountControl.TOP_OF_MONTH:
			this.set(Calendar.DATE, this.get(Calendar.DATE));
			this.set(Calendar.HOUR_OF_DAY, this.get(Calendar.HOUR_OF_DAY));
			this.set(Calendar.MINUTE, this.get(Calendar.MINUTE));
			this.set(Calendar.SECOND, this.get(Calendar.SECOND));
			this.set(Calendar.MILLISECOND, this.get(Calendar.MILLISECOND));
			this.set(Calendar.MONTH, this.get(Calendar.MONTH) - maxBackupIndex);
			break;

		default:
			throw new IllegalStateException("Unknown periodicity type.");
		}

		return getTime();
	}
}


猜你喜欢

转载自blog.csdn.net/xubo_ob/article/details/71172550