最近做了一个查看服务器新增日志将日志实时显示到前端页面的功能,采用的websocket通信,由于项目比较复杂(web 和server进行连接,server 和多个节点建立连接,节点下有很多个服务器,监听的是这个服务器文件)我就不过多地介绍websocket的连接方式什么的了,就介绍下实时监听日志文件的和关闭监听
下面是我的日志查看者类
package com.monitor.socket.handle;
import com.air.utils.SocketSessionUtil;
import com.alibaba.fastjson.JSONObject;
import javax.websocket.Session;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class LogWatcher {
//储存已启动定时查看的类
public static ConcurrentHashMap<String,LogWatcher> logWatcherMap=new ConcurrentHashMap<>();
//编码格式
public static final String ISO="ISO8859-1";
//上次文件读取的位置
private long lastTimeFileSize;
//是否为第一次读取 第一次读取读取的是之前所有的日志,只要新增的,不要之前的
private boolean first =true;
private RandomAccessFile randomFile =null;
//节点下的项目里log文件的相对路径
private final String PATH = File.separator + "log" + File.separator + "sys" + File.separator + "SystemLog.log";
//启动一个线程每1秒钟读取新增的日志信息
private ScheduledExecutorService exec =
Executors.newScheduledThreadPool(1);
//启动定时将新增的日志发送出去
public void realtimeShowLog(Session session, JSONObject jsonObject) throws IOException {
String projectPath= (String) jsonObject.get("projectPath");
File file=new File(projectPath+PATH);
//指定文件可读可写
randomFile = new RandomAccessFile(file,"rw");
exec.scheduleWithFixedDelay(new Runnable(){
public void run() {
try {
//只获取新增部分的
if(first){
lastTimeFileSize=randomFile.length();
first=false;
return;
}
//没有变化不发送
if(lastTimeFileSize==randomFile.length()){
return;
}
//日志文件被替换了,从0开始读取
if(lastTimeFileSize>randomFile.length()){
lastTimeFileSize=0;
}
randomFile.seek(lastTimeFileSize);
StringBuffer sbf = new StringBuffer();
String tmp = "";
while( (tmp = randomFile.readLine())!= null) {
sbf.append(new String(tmp.getBytes(ISO)));
sbf.append("\r\n");
}
System.err.println(sbf.toString());
jsonObject.put("content",sbf.toString());
lastTimeFileSize = randomFile.length();
SocketSessionUtil.send(session,jsonObject.toJSONString());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}, 0, 1, TimeUnit.SECONDS);
}
//停止定时任务
public void close() throws IOException {
if(randomFile!=null){
randomFile.close();
}
exec.shutdown();
}
}
SocketSessionUtil.send(session,jsonObject.toJSONString());Session是websocket发送数据不用太在乎我的,根据自己的情况去做处理
sbf.toString()就是我们每次获取的新增的日志数据,我这里设置的是一秒获取一次
因为我的业务需求我是以token作为key,进行销毁
logWatcherMap是协助我们对实时监控进行销毁,同时也可以从里面查看有多少正在进行
这是启动代码:
LogWatcher logWatcher=new LogWatcher();
logWatcher.realtimeShowLog(session,object);
LogWatcher.logWatcherMap.put(token,logWatcher);
这是销毁代码
LogWatcher logWatcher=LogWatcher.logWatcherMap.get(token);
logWatcher.close();
LogWatcher.logWatcherMap.remove(token);
最后最重要的一点:
