问题背景
1、现有日志生成规则:debug到error四种级别,按照日期每天生成新的日志文件。
2、项目中日志打印不规范,部分日志没有唯一区分标识(例如流水号),在查找日志时,多个客户端的请求混在一起,难以分析。
3、客户希望能够根据客户端设备号进行分类输出日志。
log4j的执行流程分析
1、初始化配置文件流程
(1)调用:FileAppender类中的setFile(String fileName)方法设置this.fileName文件名(文件名来自配置文件)。
(2)调用:FileAppender类中的activateOptions方法,该方法中调用了setFile(fileName, fileAppend, bufferedIO, bufferSize) 里面包含了创建日志文件的方法。
2、每次调用写日志方法
调用WriterAppender类的subAppend(LoggingEvent event)方法。
解决方法
继承FileAppender,重写subAppend(LoggingEvent event)方法, 在里面调用setFile(fileName, fileAppend, bufferedIO, bufferSize),每次写日志时重新指定输出文件。
1、代码
public class MyFileAppender extends FileAppender {
private Logger logger = Logger.getLogger(this.getClass());
private void switchFilename(String datedFilename) throws IOException {
try {
setFile(datedFilename, getAppend(), getBufferedIO(), getBufferSize());
} catch (IOException ex) {
this.errorHandler.error("setFile(" + datedFilename + ", false) call failed.");
}
this.fileName = datedFilename;
}
protected void subAppend(LoggingEvent event) {
String msg = (String) event.getMessage();
// 如果日志中包含a,则重新指定生成文件;实际改为匹配
if(msg.indexOf("a") != -1){
try {
switchFilename("E:/a.log");
} catch (IOException e) {
e.printStackTrace();
}
}
super.subAppend(event);
}
}
2、配置文件
<appender name="debugLog" class="test_log4j.MyFileAppender">
<param name="File" value="E:/debug.log" />
<param name="Append" value="true" />
<param name="Encoding" value="UTF-8" />
<param name="DatePattern" value=".yyyy-MM-dd" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%-5p] %c [%t] - %m%n" />
</layout>
</appender>
总结
1、最好的方法是规范日志输出,延用平时的方法记录日志,在记录日志的时候加上流水号,后期可利用代码或管理员直接在命令下操作提取分析日志信息。
2、并不是每个请求都会带设备号,如果是新项目的话,直接封装前端请求的公共方法进行统一处理;对于该项目,由于设备都处于内网,且固定IP,可根据IP进行区分。
3、只适用于设备量不是很多的情况下,如果设备量过多,又要考虑日志文件的存放问题,比如根据设备编号每1000个设备一个目录等。