log4j2 文件滚动扩展(基于行和时间的滚动)



目标:实现基于行和时间间隔的文件滚动

注:不是纯粹的行,而是log的次数,如果log一次是一行,就是行数(我log一次就是一行)。
例如:单个文件超过10行滚动文件,如果超过10秒还不到10行,也滚动文件。

mysql默认的组合策略达不到这个目标,他是两种策略的“或”,单一的行数到达限制,或者单一的时间间隔到达限制,都会滚动。在滚动后,两个策略单独重置,而不是一起都重置。

实现方法

通过实现一个TriggeringPlolicy即可达到这个目标。这个接口的isTriggeringEvent方法来控制滚动,如果该方法返回true,那么就滚动。
这里实现了一个LineBasedTriggeringPolicy ,需要实现TriggeringPlolicy,和一个工厂方法。该类和工厂方法都需要用Annotation标注。
上层对isTriggeringEvent的调用时同步的,我们这里不需额外的同步。

配置关键点解释:
1.configuration的packages:由于是基于Annotation开发,所以log4j需要扫描包,找到它的组件,如果没有这个属性,会找不到我们定义的Policy。
2. filePattern的日期格式:如果日志录入较快,文件滚动比较频繁,文件名重复的几率很大,这时是通过添加序号(pattern中的i)来解决的,RollingStrategy的max属性指示序号最大有几个,如果超过了最大个数,会再从头滚动,这样,我们前面的日志被覆盖,造成日志丢失。如果采用毫秒级的文件名,重复几率大大降低。(另外如果max的只很大,滚动会变得很慢,比如10万,我没有深究为什么。)
3. LineBasedTriggeringPolicy 就是我们的滚动策略。这里配置的是最多10行,最多10秒,就滚动。
4.类、工厂方法、工厂方法上的参数,都要有相应的Annotation。
5.configuration的statu属性:配置成debug可以查看log4j的装配过程,设置成OFF,即可关闭状态日志。

配置文件



	
		
			
				%m%n
			
			
			
		
	
	
		
			
		
	

自定义TriggeringPolicy

package org.apache.logging.log4j.core.appender.rolling;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttr;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.status.StatusLogger;

/**
 * zhmt
 */
@Plugin(name = "LineBasedTriggeringPolicy", type = "Core", printObject = true)
public class LineBasedTriggeringPolicy implements TriggeringPolicy {
	/**
	 * Allow subclasses access to the status logger without creating another
	 * instance.
	 */
	protected static final Logger LOGGER = StatusLogger.getLogger();
	private int counter = 0;
	private long lastUpdateTime = System.currentTimeMillis();

	/**
	 * Rollover threshold size in bytes.
	 */
	private static final long MAX_LINE_SIZE = 10 * 1024 * 2; // let 20k line
	private static final int MAX_ELAPSE_TIME = 24 * 60 * 60 * 1000; // 1day

	private final long maxLineSize;
	private final int maxElapsedTime; // in ms

	private RollingFileManager manager;

	/**
	 * Constructs a new instance.
	 */
	protected LineBasedTriggeringPolicy() {
		this.maxLineSize = MAX_LINE_SIZE;
		maxElapsedTime = MAX_ELAPSE_TIME;
	}

	/**
	 * Constructs a new instance.
	 * 
	 * @param maxFileSize
	 *            rollover threshold size in bytes.
	 */
	protected LineBasedTriggeringPolicy(final long maxFileSize,
			int maxElapsedTime) {
		this.maxLineSize = maxFileSize;
		this.maxElapsedTime = maxElapsedTime;
	}

	/**
	 * Initialize the TriggeringPolicy.
	 * 
	 * @param manager
	 *            The RollingFileManager.
	 */
	public void initialize(final RollingFileManager manager) {
		this.manager = manager;
	}

	/**
	 * Returns true if a rollover should occur.
	 * 
	 * @param event
	 *            A reference to the currently event.
	 * @return true if a rollover should take place, false otherwise.
	 */
	public boolean isTriggeringEvent(final LogEvent event) {
		counter++;
		int cur = counter;
		boolean ret = cur >= maxLineSize;
		if (!ret) {
			long time = System.currentTimeMillis() - lastUpdateTime;
			if (time > maxElapsedTime) {
				ret = true;
			}
		}

		if (ret) {
			counter = 0;
			lastUpdateTime = System.currentTimeMillis();
		}
		return ret;
	}

	@Override
	public String toString() {
		return "SizeBasedTriggeringPolicy(size=" + maxLineSize + ")";
	}

	/**
	 * Create a SizeBasedTriggeringPolicy.
	 * 
	 * @param size
	 *            The size of the file before rollover is required.
	 * @return A SizeBasedTriggeringPolicy.
	 */
	@PluginFactory
	public static LineBasedTriggeringPolicy createPolicy(@PluginAttr("size")
	final String size, @PluginAttr("maxElapsedTime")
	final String maxElapsedTime) {
		final long maxSize = size == null ? MAX_LINE_SIZE : Integer
				.valueOf(size);
		int time = maxElapsedTime == null ? MAX_ELAPSE_TIME / 1000 : Integer
				.valueOf(maxElapsedTime);
		return new LineBasedTriggeringPolicy(maxSize, time * 1000);
	}
}


你可能感兴趣的:(软件技术)