现在大多情况下都使用日志组件,比如log4j、log4j2,这些组件的好处是比较通用,同时鉴于软件开发中的拿来主义,尽量用现成的代码减小工作任务,同时公用的框架能避免自己花大量时间去测试,因为大家都在测试;另一方面,使用日志组件比较简单,只要配置配置就好了。但是有的情况下,第三方组件不能满足日志需求,需要实现循环日志,或者想探究循环日志实现原理是什么,怎么去做呢
本文基于Jdk8,记录实现循环日志的基本原理和测试代码。主要分为三步:
-
对java.util.logging.Logger进行包装;
Logger自从JDK1.4添加,是JDK自带的Logger,对Logger进行包装主要可以从Logger命名、使用工厂模式进行构建等非功能性需求。 -
配置FileHandler
配置FileHandler主要配置循环日志目录以及文件命名,输出的日志格式,循环日志数目,每个循环日志文件的大小。关于循环日志输出的主要代码在FileHandler类中,以下方法是FileHandler中方法,主要用于日志文件重命名和新文件创建(PS,编辑器真不好用,是我不会用吗)。private synchronized void rotate() {
Level oldLevel = getLevel();
setLevel(Level.OFF);super.close(); for (int i = count-2; i >= 0; i--) { File f1 = files[i]; File f2 = files[i+1]; if (f1.exists()) { if (f2.exists()) { f2.delete(); } f1.renameTo(f2); } } try { open(files[0], false); } catch (IOException ix) { // We don't want to throw an exception here, but we // report the exception to any registered ErrorManager. reportError(null, ix, ErrorManager.OPEN_FAILURE); } setLevel(oldLevel);
}
-
配置MemoryHandler并绑定到Logger
MemoryHandler主要用于绑定FileHandler,指定缓存大小以及日志级别等,实现异步日志。
示例:
public class MyLogger {
private Logger logger;
protected MyLogger(String name) {
logger = Logger.getLogger(name);
}
public Boolean configureLogger(String filePattern, int count, int bufferSize, int limit, Formatter format) {
try {
FileHandler fileHandler = new FileHandler(filePattern, limit, count);
fileHandler.setFormatter(format);
MemoryHandler memHandler = new MemoryHandler(fileHandler, bufferSize, Level.INFO);
logger.addHandler(memHandler);
}
catch (SecurityException | IOException e) {
e.printStackTrace();
return false;
}
return true;
}
public void info(String msg) {
logger.info(msg);
}
public static class SimpleLogFormatter extends Formatter {
@Override
public String format(LogRecord record) {
return record.getMessage();
}
}
}
测试类:
public class TestLogger {
public static void main(String[] args) {
MyLogger myLogger = new MyLogger("test");
myLogger.configureLogger("/TEST/test.log", 3, 10, 10240, new MyLogger.SimpleLogFormatter());
for(int index=0; index<10000; index++) {
myLogger.info("test log" + index);
}
}
}
测试结果:
- 生成test.log.0,test.log.1, test.log.2文件
- 日志文件大小为10K(实际显示为11k)
- 日志循环输出