基于Log4j改进的日志存储应用研究
摘要:通过对Log4j提供的WriterAppender类的继承,利用管道通信机制处理来自Appender的日志输出,并将形成的日志对象缓存于一个基于观察者模式构建的缓存组件中。介绍了组件的结构和实现,结合Spring、Hibernate以及Quartz等开源组件可以应用在更广泛的信息系统日志记录和审计中。
关键词:Log4j;组件结构;管道通信;日志存储
Log4j 环境包括3个主要组件:①logger(日志记录器):控制要启用或禁用哪些日志记录语句。可以对日志记录器指定如下级别:ALL 、DEBUG 、INFO 、WARN 、ERROR , FATA 或OFF;②layout(布局):根据用户的愿望格式化日志记录请求;③appender:向目的地发送格式化的输出。
实现自定义输出的关键在于Appender,因为该类的实现定义了目的地的输出,同时它也决定了输出的性能问题,例如可以设置合适的缓冲区降低频繁的IO请求所造成的性能下降问题。扩展后的日志存储系统的基本结构如图1所示。
图1扩展后的日志存储系统的基本结构
在图1中,利用管道通信机制将一个日志处理器LogProcessor组件和一个Appender连接起来,这是系统的关键。同时,利用一个自定义的Cache缓存需要存储的日志对象,Job
的作用则是利用Quartz的定时特点定时将Cache中的日志对象取出保存到数据库中。
2关键实现
2.1Appender的设计
Appender的作用在于提供接收Logger传送的信息,实现向目的地发送需要处理的日志信息,可以通过继承org.apache.log4j.WriterAppender类。
public class MyAppender extends WriterAppender{
private String MessageRegex; //用于获得配置文件中定义的日志信息的分割模式
public String getMessageRegex() {
return MessageRegex;
}
public void setMessageRegex(String messageRegex) { MessageRegex = messageRegex;
}
}
2.2日志处理器的设计
日志处理器通过管道通信机制和Appender建立连接,输出到Appender的日志会通过管道送到日志处理器。
public final class LogProcessor extends Thread{
private boolean working=true;//线程工作状态
PipedReader reader;
LogProcessor processor;
private LogProcessor (PipedReader reader) {
}
public static LogProcessor getInstace(PipedReader reader){ if(processor ==null){
if(reader!=null){
processor =new LogProcessor (reader);
}
}
return processor;
}
public void run() {
Scanner scanner = new Scanner(reader);
while (scanner.hasNext()) {
//从管道中读取日志信息
String logInfoString = Line();
YourLoggerEvent evt=null;//声明一个自定义的日志对象
//这里插入对日志信息进行解析的代码,形成自定义的日志对象
LogCache.add(evt);//将日志存入缓冲区
}
}
}
这里将LogProcessor设计成为一个单态类的目的主要是为了保证系统只有一个日志处理线程,当然也可以根据自己的需要对此进行改造,实现不同的Appender对应不同的任务处理线程。
利用管道通信机制,可以将Appender接收的日志信息读取过来,解析后保存至日志缓冲区中。
2.3缓存组件
缓冲组件LogCache的作用在于保存待存储的日志对象。
public final class LogCache extends Observable{
int size; //缓冲的基本容量
private LinkedList<YourLoggerEvent> logInfoBuffer =
new LinkedList< YourLoggerEvent >();
private static LogCache cache;
private LogCache (int size) {
this. size = size;
}
public static LogCache getInstace(int size){
if(cache ==null){
cache =new LogCache(size);
}
return cache;
}
public void add(YourLoggerEvent evt) {
logInfoBuffer.add(evt);
if(logInfoBuffer.size()>=size&& countObservers()>0){
this.setChanged();
}
}
public List< YourLoggerEvent > get(){
//从链表中取出合适数量的对象构成需要批量存储的日志对象返回调用者
}
}log4j与log4j2
缓存组件也被设计为一个单态类,同时他也是一个被观察对象,可以拥有自己的观察者,一旦达到了约定的日志数量,就通知观察者开始处理缓存中的日志记录,同时也提供了另外的get()方法供直接进行调用获得日志对象集合。
2.4其他
定时器Job的设计相对简单,利用Quartz可以很容易地进

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。