前言:
当前管理的系统是由simens软件包进行二次开发的java系统,有些日志是我们不能控制的,而且这些日志都是在log文件中记录,整个系统涉及很多功能,虽然系统只是提供内部使用,访问量也不大,但是生成的日志是很大的。
一、大数据量文本
二、日志读取方式
三、读取效率分析
四、文本日志结构化
五、结构化数据入库
不说了,没啥好说的直接上代码了。 其中还有很多自定义类和方法没有引入,希望其中的思想可以帮助到你。如有问题可邮箱我:sunliguocumtb@163.com
private String logPath2Search = ConstClass.getConstMethod("logPath");
private long lastTimeFileSize = 0; //上次文件大小
private String fileName = "";
private static final Logger logger = LoggerFactory.getLogger(LoggerReaderImpl.class);
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
ScheduledExecutorService exec = Executors.newScheduledThreadPool(1);
@Override
public void realtimeShowLog() {
//启动一个线程每10秒读取新增的日志信息
exec.scheduleWithFixedDelay(new Runnable(){
@Override
public void run() {
String logPath = searchLatestModifyFile(logPath2Search);//指定读取文件路径,找到最新修改的文件,输出该文件的路径
//增加判断最新修改日期的文件是否改变:no->lastTimeFileSize=before;yes->lastTimeFileSize=0;
File logFile = new File(logPath);
//判断是否有新的日志文件产生
if(!fileName.equals(logFile.getName())) {
lastTimeFileSize = 0;
logger.info("*************************当前读取日志文件:"+logFile.getName()+"**原日志文件是:"+fileName+"*************************");
}
//获得变化部分
try {
long len = logFile.length();
if(len < lastTimeFileSize){
logger.info("Log file was reset. Restarting logging from start of file.");
lastTimeFileSize = 0;
}else{
RandomAccessFile randomFile= new RandomAccessFile(logFile,"rw");//指定文件可读可写
//获取RandomAccessFile对象文件指针的位置,初始位置是0
logger.info("RandomAccessFile文件指针的初始位置:"+lastTimeFileSize);
randomFile.seek(lastTimeFileSize);//移动文件指针位置
String tmp = "";
String date1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date());
int sum = 0;
while((tmp = randomFile.readLine()) != null) {
//匹配目标文本
String lineContent=new String(tmp.getBytes("ISO-8859-1"));
String regex = "com.polarion.platform.realm.PolarionRealm - Login failed: 达到了PRO许可证许可证";
if(lineContent.contains(regex)) {
//读取上一行文本内容:含有用户id信息
String lineContentOfUserId = "";
long nowPointer = randomFile.getFilePointer();
long tempPointer = nowPointer;
while(StringUtils.isBlank(lineContentOfUserId)){
tempPointer = tempPointer-1;
randomFile.seek(tempPointer);
String lineUserTemp = new String(randomFile.readLine().getBytes("ISO-8859-1"));
if(lineUserTemp.contains("- User")) {
lineContentOfUserId = lineUserTemp;
}
}
/*randomFile.seek(nowPointer-345L);
String lineContentOfUserId = new String(randomFile.readLine().getBytes("ISO-8859-1"));*/
logger.info("ALM许可证已满,该用户尝试登录未成功,详细信息如下:\n"+lineContentOfUserId+"\n"+lineContent);//打印日志
//获取关键信息并入库
keyInformation2DB(lineContentOfUserId,lineContent.substring(0, 18));
randomFile.seek(nowPointer);//回到原始位置,不影响循环遍历
}
sum=sum+1;
if((sum%10000)==0) {
logger.info("文本日志大小为:"+len+"字节;已读取:"+randomFile.getFilePointer()+"字节"+"。已完成:"+new DecimalFormat("0.0000").format((randomFile.getFilePointer()/(double)len)*100)+"%");//len不转变成double的话,int/int为零,结果为:0.00
}
}
String date2 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date());
logger.info("本次读取日志结束,用时:"+"start:"+date1+"_stop:"+date2);
//获取list<LoggerEntity>,insert2almDB(list);
lastTimeFileSize = randomFile.length();
fileName = logFile.getName();
randomFile.close();
}
} catch (Exception e) {
//实时读取日志异常,需要记录时间和lastTimeFileSize 以便后期手动补充
logger.error(dateFormat.format(new Date()) + " File read error, lastTimeFileSize: "+lastTimeFileSize);
} finally {
//将lastTimeFileSize 落地以便下次启动的时候,直接从指定位置获取
//可以将值存到指定位置的txt中
}
}
}, 0, 10, TimeUnit.SECONDS);
}