JRT仪器Trace准备

JRT仪器Trace准备

码农世界 2024-05-23 后端 65 次浏览 0个评论

QC的试验告一段落,现在准备开发仪器监控和仪器控制,最终把QC传输数据采用接口传。前期准备好了监听程序和TCP设备的基础程序,现在需要做仪器数据监控界面。对于连设备有个说重要也不重要,说不重要缺了又很难受的功能,就是传入日志记录(Trace)。

这个信息的特点是:

1.数据量大

2.没必要长久保存

3.没必要大量保存

4.要能查最近的

所以这数据用表存储就太浪费空间了。用表存储固定数量、多了删也会因为数据量大产生大量表日志。所以表不太合适。那么为了这东西引入Radis环境也不值得,所以基于Queue定制了可本地化的队列来给Trace用。

先实现Trace对象

package JRT.Core.Debug;
import JRT.Core.MultiPlatform.JRTContext;
import java.io.*;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
/**
 * 供仪器等调试用的日志队列,仪器日志数据存数据库太多了,也没有必要,存内存队列又没有持久化,封装定时持久化的TraceQueue给仪器做Trace用
 */
public class TraceQueue {
    /**
     * 跟踪队列
     */
    private ConcurrentLinkedDeque traceQueue = new ConcurrentLinkedDeque();
    /**
     * 唯一标识
     */
    private String key;
    /**
     * 本地名称
     */
    private String localName;
    /**
     * 最大数量
     */
    public int MaxSize = 50000;
    /**
     * 构造函数
     *
     * @param queueKey 唯一键
     * @param maxSize  最大大小
     * @throws Exception
     */
    public TraceQueue(String queueKey, int maxSize) throws Exception {
        key = queueKey;
        String fileName = Paths.get(JRTContext.WebBasePath, "trace").toString();
        File dir = new File(fileName);
        if (!dir.exists()) {
            dir.mkdir();
        }
        fileName = Paths.get(fileName, key + ".queue").toString();
        localName = fileName;
        File localFile = new File(localName);
        //从本地加载数据
        if (localFile.exists()) {
            traceQueue = DeserializeDeque(localName);
        }
    }
    /**
     * 往队列尾部加入数据
     *
     * @param str
     */
    public void AddLast(String str) {
        traceQueue.addLast(str);
        //数量大于最大就丢弃之前的
        if (traceQueue.size() > MaxSize) {
            traceQueue.poll();
        }
    }
    /**
     * 清空队列
     */
    public void Clear() {
        traceQueue.clear();
    }
    /**
     * 保存到本地
     */
    public void Save() throws Exception {
        SerializeDeque(traceQueue, localName);
    }
    /**
     * 序列化队列到本地文件
     *
     * @param deque    队列
     * @param fileName 文件名称
     * @throws IOException
     */
    private void SerializeDeque(ConcurrentLinkedDeque deque, String fileName) throws IOException {
        //将Deque内容转换为ArrayList以便序列化
        ArrayList list = new ArrayList<>(deque);
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName))) {
            oos.writeObject(list);
        }
    }
    /**
     * 从本地文件反序列化文件到队列
     *
     * @param fileName
     * @return 队列
     * @throws IOException
     * @throws ClassNotFoundException
     */
    private ConcurrentLinkedDeque DeserializeDeque(String fileName) throws IOException, ClassNotFoundException {
        // 从文件反序列化ArrayList
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName))) {
            @SuppressWarnings("unchecked")
            ArrayList list = (ArrayList) ois.readObject();
            //将ArrayList内容转换回Deque
            ConcurrentLinkedDeque deque = new ConcurrentLinkedDeque<>(list);
            return deque;
        }
    }
}

再提供Manager

package JRT.Core.Debug;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import JRT.Core.Debug.TraceQueue;
/**
 * 跟踪管理器,仪器Trace通过GetTraceHandler得到Trace句柄,定时器通过SaveAllTraceQueue定时写文件,网站结束时候写文件
 */
public class TraceManager {
    /**
     * 所有的日志队列
     */
    private static ConcurrentHashMap allTrace = new ConcurrentHashMap<>();
    /**
     * 得到Trace句柄
     *
     * @param key     唯一键
     * @param maxSize 最大大小
     * @return Trace句柄
     */
    public static TraceQueue GetTraceHandler(String key, int maxSize) throws Exception {
        if (allTrace.containsKey(key)) {
            return allTrace.get(key);
        } else {
            TraceQueue one = new TraceQueue(key, maxSize);
            allTrace.put(key, one);
            return one;
        }
    }
    /**
     * 保存所有的跟踪队列
     */
    public static void SaveAllTraceQueue() {
        Iterator> iterator = allTrace.entrySet().iterator();
        while (iterator.hasNext()) {
            ConcurrentHashMap.Entry entry = iterator.next();
            try {
                entry.getValue().Save();
            } catch (Exception ex) {
                JRT.Core.Util.LogUtils.WriteExceptionLog("保存TraceQueue异常", ex);
            }
        }
    }
}

使用方式

JRT仪器Trace准备

测试Trace

import JRT.Core.Debug.TraceManager;
import JRT.Core.Debug.TraceQueue;
import JRTBLLBase.BaseHttpHandlerNoSession;
import JRTBLLBase.Helper;
/**
 * 测试Trace
 */
public class ashTraceTest extends BaseHttpHandlerNoSession {
    /**
     * 测试
     * @return
     */
    public String Test() throws Exception
    {
        //得到Trace句柄
        TraceQueue trace= TraceManager.GetTraceHandler("1-trace",2000);
        for(int i=0;i<1;i++) {
            trace.AddLast("M->H:"+Helper.GetNowTimeStr()+" 第"+(i+1)+"条日志");
            //Thread.currentThread().sleep(200);
        }
        //trace.Clear();
        trace.Save();
        return "共"+trace.GetTraceDataSize()+"条日志,"+Helper.Object2Json(trace.GetTraceData());
    }
}

JRT仪器Trace准备

可以准备开始仪器数据监控了

转载请注明来自码农世界,本文标题:《JRT仪器Trace准备》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,65人围观)参与讨论

还没有评论,来说两句吧...

Top