算法日志的存在核心在于搭建自检系统

news2025/1/8 5:42:15

        "相信每一个人执行与日志有关的任务都会遇到这样难题吧?长达几万行的日志,如果我们单纯用肉眼去一个个排查,那么恐怕所耗费的时间是以天为计量单位了。当然这是一种比较夸张的情况,根据我的项目经验,正常情况是十几个站点的人可能每天需要花费3-4个小时去排查日志或者与日志有关却能被日志替代的内容。如果我们能搭建一个智能化的系统,使得这个系统可以智能的读取日志中我们关键的信息,那么会发生什么呢?"

        有些人问,我就想用肉眼看,不行嘛?其实,"不是肉眼看不起,而是智能化日志更有性价比!"没错,如果我们搭建这样一个智能化日志自检系统,N个站n*m个团体每天都能节省n*m*k个工时去干别的事情。

NOTE:本文只是介绍一种思想,所以不会有过多的具体代码讲解,但是可以给上一个成功的案例手册,仅供参考。
———————————————————————————————————————————华丽的分割线

现场人员自检失败表计点位教程

NOTE: 如果没有meterPoint_Self-Checking_sys.py“脚本的请联系我们进行提供

👇

运行该脚本,参考运行命令如下(请确保此时您的工作目录处于meter/log)

#这是一条参考运行命令,请您根据您实际的情况修改-p和-t参数的具体内容
python3 meterPoint_Self-Checking_sys.py -p meterlog -t 30M00000036658634_task1703485183168_20231225141946
# @pararm:-p 是存放日志的路径,该日志包含您刚跑完测试的日志内容。
# @pararm:-t 是您任务的序号,如下图,Ftp图片路径下包含”task“的字符串,也就是灰色框框住的那一串正式您此次任务的序号,输入30M00000036658634_task1703485183168_20231225141946

👇

自动生成自检报表meterlog_checking.txt

里面部分关键内容如下:

👇

接下来大家请对照这张表,找到【需要现场人员自检】【错误】进行搜索排查,有多个,可以从上往下慢慢来。

👇

以【通用类】<序号7>"该点位没有录入"作为例子,打开自检文本meterlog_checking.txt

👇

👇

如果出现无需现场人员自检的错误,需要截图一下日志中有关内容,可能后续还需提供图片我们这边进行优化

一些使用样例图: 

# -*- coding: utf-8 -*-
'''
参考diamagnetic:
# 兰江
python3 meterPoint_Self-Checking_sys.py -p meterlog -t 30M00000036658634_task1703485183168_20231225141946
# 金鼎
python3 meterPoint_Self-Checking_sys.py -p meterlog -t 30M00000036658634_task1703485183168_20231225141947
'''
import re
import json
import argparse

# 创建命令行参数解析器
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--log_file', help='log文件路径')
parser.add_argument('-t', '--task_id', help='任务ID')
args = parser.parse_args()

def extract_debug_segments(log_file):
    debug_segments = []
    with open(log_file, 'r') as file:
        lines = file.readlines()
        start_line = None
        end_line = None
        segment = []

        for i, line in enumerate(lines):
            if 'Debug' in line or '收到请求' in line or '数据库信息' in line:
                if start_line is None:
                    start_line = i
                segment.append(line.strip())   

            elif '结果放入队列待发送' in line:
                if start_line is not None:
                    end_line = i
                    segment.append(line)
                    debug_segments.append([segment, start_line, end_line])
                    segment = []
                    start_line = None
                    end_line = None

    return debug_segments
def process_request(request_str):
    target_index = request_str.index("{")
    # 按照":"分割字符串
    split_str = request_str[target_index:]
    # 获取分割后数组中最后一个索引所保存的信息
    json_str = split_str.strip().replace("—", "-").replace("'", "\"")

    objectList_request_str = json.loads(json_str)['objectList'][0]
    # for k in objectList_request_str:
    #     print(k)
    return objectList_request_str

def get_pointList_length(json_str):
    
    pattern = r"'Position': '(\[.*?\])'"
    matches = re.search(pattern, json_str)
    if matches is None:
        return 0
    position_list = json.loads(matches.group(1))
    # print("position_list:", position_list)
    return len(position_list)

def process_sql(json_str):

    json_str = json_str[json_str.index("MinValue"):]
    json_str = "{'" + json_str
    json_str = json_str.replace("'", "\"")
    sql_dict = json.loads(json_str)
    return sql_dict

def process_result(json_str):

    json_str = json_str[json_str.index("code"):-5]
    json_str = "{'" + json_str
    # print(json_str)
    json_str = json_str.replace("'", "\"")
    json_str = json_str.replace("None", "null")
    sql_dict = json.loads(json_str)
    return sql_dict

def contains_digit(string):
    pattern = r'\d'  # 正则表达式模式,匹配任意数字
    if re.search(pattern, string):
        return True
    else:
        return False

if __name__ == "__main__":
    # 摄像机偏移严重+模糊
    Error_withoutDetctor = []
    # 未识别出指针
    Error_withoutPointer = []
    # 读取ftp图失败
    Error_loadftp = []
    # minIO无图
    Error_withoutMinioImage = []
    # minIO错图
    Error_minioErrorImage = []
    # 点位未录入
    Error_withoutId = []
    # 表计类型录入错误
    Error_clsType = []
    # 最大最小值设置错误
    Error_minMaxSet = []
    # 最大最小值未设置
    Error_withoutMinMax = []
    # 未打刻度点位
    Error_withoutPointList = []
    # 刻度打点错误
    Error_PointList = []
    # 未识别到任何油面表!
    Error_ymb = []
    # OCR没有检测出数字
    Error_ocrRec = []
    # OCR没有检测出表盘
    Error_ocrDet = []
    # ===========================核
    # 获取命令行参数
    log_file = args.log_file
    work_id = args.task_id
    debug_segments = extract_debug_segments(log_file)
    error_num = 0
    # not_reading_num = 0
    # type_num = 0
    ymb_num, sxb_num, bj_num = 0, 0, 0
    ymb_errorNum, sxb_errorNum, bj_errorNum = 0, 0, 0
    for segment in debug_segments:
        error_flag = False
        # print('Start Line:', segment[1])
        # print('End Line:', segment[2])
        for line in segment[0]:
            # print(line)
            if "收到请求" in line:
                # print('【请求信息】: ',end='')
                objectList_request_str = process_request(line)
                extract_objectId = objectList_request_str['objectId']
                # print(objectList_request_str['imageUrlList'][0], work_id)
                if not work_id in objectList_request_str['imageUrlList'][0]:
                    break

            elif '数据库信息' in line:
                if line.split("【数据库信息】")[-1] == '{}':
                    # 数据库信息为空
                    # print('*pointList_length:0')
                    # print('{}')
                    Error_withoutId.append(extract_objectId)
                    error_flag = True
                    break
                else:
                    # 数据库有信息
                    pointList_length = get_pointList_length(line)
                    sql_schem = process_sql(line)
                    MinValue = sql_schem['MinValue']
                    MaxValue = sql_schem['MaxValue']
                    meter_type = sql_schem['AlgorithmType']
                    ImagePath = sql_schem['ImagePath']

                    if meter_type == 'meter_v5':
                        bj_num += 1
                    if meter_type == 'meter_ywj':
                        ymb_num += 1
                    if meter_type == 'paddleocr':
                        sxb_num += 1

                    if meter_type == 'meter_v5':
                        if len(MinValue)== 0 or len(MaxValue) == 0:
                            Error_withoutMinMax.append(extract_objectId)
                            MinValue = float(0)
                            MaxValue = float(100)
                            error_flag = True
                        else:
                            MinValue = float(MinValue)
                            MaxValue = float(MaxValue)

                    # 表计类型录入错误(如果打点了,但表计类型不是meter_v5)
                    if meter_type == 'meter_v5' and pointList_length == 0:
                        Error_clsType.append(extract_objectId)
                        error_flag = True
                    # 未打刻度点位
                    if meter_type == 'meter_v5' and pointList_length == 0:
                        Error_withoutPointList.append(extract_objectId)
                        error_flag = True

                    # print(sql_schem, end=',')
                    # print("*pointList_length:", pointList_length)
            
            elif '结果放入队列待发送' in line:
                result_schem = process_result(line)
                # print('【结果队列信息】:',end='')
                # print(result_schem)
                if result_schem['code'] == '2001':
                    Error_loadftp.append(extract_objectId)
                    error_flag = True
                if result_schem['desc'] == '未识别到任何油面表!':
                    error_flag = True
                    Error_ymb.append(extract_objectId)
            else:
                splitContent = line.split("【Debug】")[-1]
                if "成功检测到表盘!表盘信息是" in splitContent:
                    det_clsType = splitContent.split(":")[-1].strip().strip("").strip("[]").strip()
                    if splitContent.split(":")[-1].strip().strip("") == "[]":
                        Error_withoutDetctor.append(extract_objectId)
                        error_flag = True

                    if not 'sxb' in det_clsType and meter_type == 'paddleocr':
                        Error_ocrDet.append(extract_objectId) 
                        error_flag = True

                    if 'ywb' in det_clsType:
                        ywb_minMax = [
                            [-20, 140],
                            [0, 160]
                        ]
                        iter_minMax = [MinValue, MaxValue]
                        if not iter_minMax in ywb_minMax:
                            Error_minMaxSet.append(extract_objectId)
                            error_flag = True
                            
                    elif 'xldlb' in det_clsType:
                        xldlb_minMax = [
                            [0, 3.0],
                            [0, 10],
                            [0, 9],
                            [0, 1]
                        ]
                        iter_minMax = [MinValue, MaxValue]
                        if not iter_minMax in xldlb_minMax:
                            Error_minMaxSet.append(extract_objectId)
                            error_flag = True
                # if '动作次数' in splitContent:
                #     print(splitContent)
                # if '泄漏电流值' in splitContent:
                #     print(splitContent)
                if 'OCR没有检测出数字' in splitContent:
                    Error_ocrRec.append(extract_objectId)
                    error_flag = True

                if "没识别出指针" in splitContent:
                    Error_withoutPointer.append(extract_objectId)
                    error_flag = True

                if len(ImagePath) == 0 or "MinIo中缺失该点位基准图" in splitContent:
                    Error_withoutMinioImage.append(extract_objectId)
                    error_flag = True

                # 用于验证
                if '读数结果' in splitContent and not contains_digit(splitContent):
                    # not_reading_num +=1
                    # 验证后 无读数个数和错误个数基本一致->代表验证成功
                    # print(not_reading_num)
                    continue
        if error_flag:
            if meter_type == 'meter_v5':
                bj_errorNum += 1
            if meter_type == 'meter_ywj':
                ymb_errorNum += 1
            if meter_type == 'paddleocr':
                sxb_errorNum += 1
            error_num += 1
    print("错误总数比:【{}/{}】".format(error_num,len(debug_segments)))
    # ===========================核
    # 写入
    with open('meterlog_checking.txt', 'w') as output_file:
        output_file.write('您这次序号为[{}]的任务:\n---------------------------------\n一共测试表计数量:[{}]个, 错误点位为:[{}]个, 未打点个数为:[{}]。\n<在此之中>\n,指针类表计成功占[{}/{}]个\n,油面表成功占[{}/{}]个\n,数显表成功占[{}/{}]个。'.format(work_id,len(debug_segments),error_num,len(Error_withoutId),bj_num - bj_errorNum, bj_num,ymb_num - ymb_errorNum, ymb_num, sxb_num - sxb_errorNum, sxb_num))

        output_file.write('\n')
        output_file.write('---------------------------------\n')
        output_file.write('NOTE:接下来,请您根据所需要查询的错误名称,使用<ctrl+F>的方式进行查询。\n')
        output_file.write('---------------------------------\n')
        output_file.write("【错误】可能存在摄像机偏移严重/模糊<数量:{}>:".format(str(len(Error_withoutDetctor))) + "\n")
        output_file.write("\n".join(Error_withoutDetctor))
        output_file.write('\n')

        output_file.write("【错误】未识别出指针<数量:{}>:".format(str(len(Error_withoutPointer))) + "\n") 
        output_file.write("\n".join(Error_withoutPointer))
        output_file.write('\n')

        output_file.write("【错误】读取ftp图失败<数量:{}>:".format(str(len(Error_loadftp))) + "\n")
        output_file.write("\n".join(Error_loadftp))
        output_file.write('\n')

        output_file.write("【错误】minIO无图<数量:{}>:".format(str(len(Error_withoutMinioImage))) + "\n")
        output_file.write("\n".join(Error_withoutMinioImage))
        output_file.write('\n')
        
        output_file.write("【错误】该点位没有录入<数量:{}>:".format(str(len(Error_withoutId))) + "\n")
        output_file.write("\n".join(Error_withoutId))
        output_file.write('\n')

        output_file.write("【错误】表计类型录入错误<数量:{}>:".format(str(len(Error_clsType))) + "\n")
        output_file.write("\n".join(set(Error_clsType)))
        output_file.write('\n')

        output_file.write("【错误】最大最小值未设置<数量:{}>:".format(str(len(Error_withoutMinMax))) + "\n")
        output_file.write("\n".join(Error_withoutMinMax))
        output_file.write('\n')

        output_file.write("【错误】未打刻度点位<数量:{}>:".format(str(len(Error_withoutPointList))) + "\n")
        output_file.write("\n".join(Error_withoutPointList))
        output_file.write('\n')

        output_file.write("【错误】最大最小值设置错误<数量:{}>:".format(str(len(Error_minMaxSet))) + "\n")
        output_file.write("\n".join(Error_minMaxSet))
        output_file.write('\n')

        output_file.write("【错误】存在刻度打点错误(暂未启用)<数量:{}>:".format(str(len(Error_PointList))) + "\n")
        output_file.write("\n".join(Error_PointList))
        output_file.write('\n')

        output_file.write("【错误】未识别到任何油面表<数量:{}>:".format(str(len(Error_ymb))) + "\n")
        output_file.write("\n".join(Error_ymb))
        output_file.write('\n')

        output_file.write("【错误】OCR没有检测出数字<数量:{}>:".format(str(len(Error_ocrRec))) + "\n")
        output_file.write("\n".join(Error_ocrRec))
        output_file.write('\n')

        output_file.write("【错误】OCR没有检测出表盘<数量:{}>:".format(str(len(Error_ocrDet))) + "\n")
        output_file.write("\n".join(Error_ocrDet))
        output_file.write('\n')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1362282.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【langchain】在单个文档知识源的上下文中使用langchain对GPT4All运行查询

In the previous post, Running GPT4All On a Mac Using Python langchain in a Jupyter Notebook, 我发布了一个简单的演练&#xff0c;让GPT4All使用langchain在2015年年中的16GB Macbook Pro上本地运行。在这篇文章中&#xff0c;我将提供一个简单的食谱&#xff0c;展示我们…

GeoServe本地部署结合内网穿透实现远程访问Web管理界面

文章目录 前言1.安装GeoServer2. windows 安装 cpolar3. 创建公网访问地址4. 公网访问Geo Servcer服务5. 固定公网HTTP地址 前言 GeoServer是OGC Web服务器规范的J2EE实现&#xff0c;利用GeoServer可以方便地发布地图数据&#xff0c;允许用户对要素数据进行更新、删除、插入…

STM32的在线升级(IAP)实现方法:BOOT+APP原理详解

0 工具准备 Keil uVision5 Cortex M3权威指南&#xff08;中文&#xff09; STM32参考手册 1 在线升级&#xff08;IAP&#xff09;设计思路 为了实现STM32的在线升级&#xff08;IAP&#xff09;功能&#xff0c;通常会将STM32的FLASH划分为BOOT和APP两个部分&#xff0c;BOO…

Vue组件封装

组件封装 一个封装好的组件可以在项目的任意地方使用&#xff0c;甚至我们可以直接从npm仓库下载别人封装好的组件来进行使用&#xff0c;比如iview、element-ui这一类的组件库。但是每个公司的需求是不一样的&#xff0c;我们可以封装自己的组件库并发布到npm上去&#xff0c…

【ONE·MySQL || 基本查询(CRUD)】

总言 主要内容&#xff1a;表的增删查改&#xff08;DML操作&#xff09;。insert插入&#xff08;包含插入更新、插入查询&#xff09;&#xff0c;replace替换。select查询&#xff08;包含列别名、distinct去重、where条件筛选、order排序、limit子句、group by子句、having…

【2023年度总结】多变的2023 | 成长的2023 | 蜕变的2023

文章目录 2023年&#x1f4cc;&#xff0c;对我来说2023年&#xff0c;是多变的一年&#x1f393;2023年&#xff0c;是挑战的一年&#x1f38a;2023年&#xff0c;是惊喜的一年&#x1f389;2023年&#xff0c;是好多第一次的一年&#x1f3a8; 2024年&#xff0c;是新的开始2…

计算机组成原理-进位计数制(进制表示 进制转换 真值和机器树)

文章目录 现代计算机的结构总览最古老的计数方法十进制计数法推广&#xff1a;r进制计数法任意进制->十进制二进制<--->八进制&#xff0c;十六进制 各种进制常见的书写方式十进制->任意进制整数部分小数部分 十进制->二进制&#xff08;拼凑法&#xff09;真值…

一起学docker(六)| docker网络

Docker网络 不启动docker&#xff0c;网络情况&#xff1a; 启动docker&#xff0c;网络情况&#xff1a; 作用 容器间的互联和通信以及端口映射容器IP变动时候可以通过服务名直接网络通信而不受影响 常用命令 docker network --help 查看docker网络相关命令docker network…

Elasticsearch:结合 ELSER 和 BM25 文本查询的相关搜索

Elastic Learned Spare EncodeR (ELSER) 允许你执行语义搜索以获得更相关的搜索结果。 然而&#xff0c;有时&#xff0c;将语义搜索结果与常规关键字搜索结果相结合以获得最佳结果会更有用。 问题是&#xff0c;如何结合文本和语义搜索结果&#xff1f; 首先&#xff0c;让我…

大数据 MapReduce如何让数据完成一次旅行?

专栏上一期我们聊到MapReduce编程模型将大数据计算过程切分为Map和Reduce两个阶段&#xff0c;先复习一下&#xff0c;在Map阶段为每个数据块分配一个Map计算任务&#xff0c;然后将所有map输出的Key进行合并&#xff0c;相同的Key及其对应的Value发送给同一个Reduce任务去处理…

1_开闭原则(Open Closed Principle)

开闭原则(Open Closed Principle) 1.概念 开闭原则&#xff08;Open-Closed Principle&#xff09;是指一个软件实体如类、模块和函数应该对扩展开放&#xff0c; 对修改关闭。所谓的开闭&#xff0c;也正是对扩展和修改两个行为的一个原则。强调的是用抽象构建框架&#xff…

“TypeError: Cannot read properties of null (reading ‘getContext‘)“

目录 一、报错截图 二、使用场景 三、代码截图 四、报错原因 五、解决办法 一、报错截图 二、使用场景 第一次在vue项目种使用canvas&#xff0c;跟着网上教程做&#xff0c;标签canvas写好了&#xff0c;dom元素获取了&#xff0c;简单“画”了一下&#xff0c;运行之后报…

基于Rangenet Lib的自动驾驶LiDAR点云语义分割与可视化

这段代码是一个C程序&#xff0c;用于处理来自KITTI数据集的激光雷达&#xff08;LiDAR&#xff09;扫描数据。程序主要实现以下功能&#xff1a; 1. **读取和解析命令行参数**&#xff1a;使用Boost库中的program_options模块来定义和解析命令行参数。这包括扫描文件路径、模型…

程序员副业之无人直播助眠

介绍和概览 大家好&#xff0c;我是小黑&#xff0c;本文给大家介绍一个比较轻松简单的副业&#xff0c;无人直播助眠副业。 这个项目的核心就是通过直播一些助眠素材来赚钱。比如你可以放一些舒缓的雨声之类的&#xff0c;吸引观众进来。然后&#xff0c;咱们可以挂个小程序…

K8Spod组件

一个pod能包含几个容器 一个pause容器(基础容器/父容器/根容器&#xff09; 一个或者多个应用容器(业务容器) 通常一个Pod最好只包含一个应用容器&#xff0c;一个应用容器最好也只运行一个业务进程。 同一个Pod里的容器都是运行在同一个node节点上的&#xff0c;并且共享 net、…

深度学习中的知识蒸馏

一.概念 知识蒸馏&#xff08;Knowledge Distillation&#xff09;是一种深度学习中的模型压缩技术&#xff0c;旨在通过从一个教师模型&#xff08;teacher model&#xff09;向一个学生模型&#xff08;student model&#xff09;传递知识来减小模型的规模&#xff0c;同时保…

了解Web 基础与 HTTP 协议

本章内容 了解静态网页与动态网页 理解 HTTP 协议的 GET 和 POST 方法 理解 HTTP 协议请求流程 随着互联网的高速发展&#xff0c;企业信息化应用大部分已采用网页的形式构建&#xff0c;掌握网页 的相关知识和 HTTP 的请求流程&#xff0c;是掌握互联网技术的第一步&#x…

分析C++软件问题的常用分析工具及案例集锦详解

目录 1、库依赖关系查看工具Dependency Walker 2、GDI对象查看工具GDIview 3、PE信息查看工具PeViewer/MiTeC EXE Explorer 4、进程信息查看工具Process Explorer 5、进程监控工具Process Monitor 6、API函数调用监测工具API Monitor C软件异常排查从入门到精通系列教程&…

聚道云软件连接器助力某半导体行业公司实现访客管理自动化

客户介绍&#xff1a; 某半导体行业公司是一家全球领先的半导体公司&#xff0c;在全球拥有众多研发中心和生产基地。该公司每天都有大量的访客来访&#xff0c;需要严格的访客管理制度。 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 客户痛点&#…