搭建算法日志自检小系统

🥒 前言

目前演示的是一个工具,但如此,未来完成有潜力可以演变为一整套系统。

👑现场人员自检失败表计点位教程V2.0

NOTE: 如果没有logfiles-meter-tool“目录请联系我们进行提供

👇

进入<dist>目录

👇

【关键步骤一】、将我们需要分析的日志文件放到该目录中

👇

【关键步骤二】、配置<日志名称><任务ID>

config.ini配置文件内容和详细解析如下图:

@pararm:[logfile_path]是存放日志的路径,但由于与<应用程序>处于同目录下,所以相当于日志名,该日志包含您刚跑完测试的日志内容。
@pararm:[work_id] 是您任务的序号,如下图,Ftp图片路径下包含”task“/"Task"的字符串,也就是灰色框框住的那一串正式您此次任务的序号。

👇

【关键步骤三】、运行<应用程序>

👇

【异常如果出现下面的红框信息,是因为任务ID输入错了,没有匹配结果,根据提示操作。【如果有匹配结果,列出来的任务id后面会打√的。】

正常】正常运行终端结果

👇

自动生成自检报表meterLog_checking-<任务ID>.txt,位于<分析报告生成处>目录下

👇

里面部分关键内容如下:

👇

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

👇

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

👇

NOTE:如果出现无需现场人员自检的错误,需要提供一下日志文件,可能后续还需提供图片我们这边进行优化。

NOTE:如果点位出现多次,只会取最后一次也就是最新一次的结果。

🍉一些使用样例图: 

👑Code

# -*- 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 os
import re
import json
import configparserdef get_settings():   config = configparser.ConfigParser()config.read('./config.ini')log_file = config.get('settings', 'logfile_path')work_id = config.get('settings', 'work_id')return log_file, work_iddef extract_debug_segments(log_file):debug_segments = []with open(log_file, 'r', encoding='utf-8') as file:lines = file.readlines()start_line = Noneend_line = Nonesegment = []for i, line in enumerate(lines):if 'Debug' in line or '收到请求' in line or '数据库信息' in line:if start_line is None:start_line = isegment.append(line.strip())   elif '结果放入队列待发送' in line:if start_line is not None:end_line = isegment.append(line)debug_segments.append([segment, start_line, end_line])segment = []start_line = Noneend_line = Nonereturn 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_strdef get_pointList_length(json_str):pattern = r"'Position': '(\[.*?\])'"matches = re.search(pattern, json_str)if matches is None:return 0position_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_strjson_str = json_str.replace("'", "\"")sql_dict = json.loads(json_str)return sql_dictdef 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_dictdef contains_digit(string):pattern = r'\d'  # 正则表达式模式,匹配任意数字if re.search(pattern, string):return Trueelse:return Falsedef get_path_separator(path):if '/' in path:return '/'elif '\\' in path:return '\\'elif '\\' * 2 in path:return '\\\\'else:return Nonedef extract_work_path_tool(goal_str):split_str = get_path_separator(goal_str)pathIdx = -1splitPaths = goal_str.split(split_str)for idx, ss in enumerate(splitPaths):if ss == 'CCD':pathIdx = idxif pathIdx == -1:raise Exception("您的任务路径中没有CCD路径")work_path = splitPaths[pathIdx-1]return work_pathif __name__ == "__main__":print("---------------------------------------------------------------------")# 摄像机偏移严重+模糊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 = []# 画框与推理出来的油面表无匹配Error_withoutYmbMatch = []# OCR没有检测出数字Error_ocrRec = []# OCR没有检测出表盘Error_ocrDet = []# ===========================核# 获取命令行参数log_file, work_id =  get_settings()debug_segments = extract_debug_segments(log_file)error_num = 0# not_reading_num = 0# type_num = 0ymb_num, sxb_num, bj_num = 0, 0, 0ymb_errorNum, sxb_errorNum, bj_errorNum = 0, 0, 0# 过滤一遍只剩下最新的filter_schem = {}piNums_schem = {}not_del_ids = []# 任务计算workNUms_schem = {}for idx, segment in enumerate(debug_segments):strat_line = segment[1]end_line = segment[2]for line in segment[0]:if "收到请求" in line:# print('【请求信息】: ',end='')objectList_request_str = process_request(line)# 任务IDwork_path = extract_work_path_tool(objectList_request_str['imageUrlList'][0])if not work_path in workNUms_schem:workNUms_schem[work_path] = 1else:workNUms_schem[work_path] += 1if work_path != work_id:break#点位IDextract_objectId = objectList_request_str['objectId']if not extract_objectId in filter_schem.keys():# 新增filter_schem[extract_objectId] = idxpiNums_schem[extract_objectId] = 1else:# 更新filter_schem[extract_objectId] = idxpiNums_schem[extract_objectId] += 1not_del_ids.append(idx)breakprint('|任务id                                                        |数量')print("---------------------------------------------------------------------")for wnn in workNUms_schem:if work_id == wnn:print(wnn, '     |',workNUms_schem[wnn],end='   ✔\n')else:print(wnn, '     |',workNUms_schem[wnn])print('*********************************************************************')if not work_id in workNUms_schem:print("[告警]任务ID有误,本日志中无匹配任务。上方已列出所有任务ID以及他们的数量!请根据上面列出的任务ID,输入正确的任务ID。")print('*********************************************************************')work_id = input('[Input]:')print("[提示]此次任务ID已经修改为:<{}>".format(work_id))# 重置filter_schem = {}piNums_schem = {}not_del_ids = []for idx, segment in enumerate(debug_segments):strat_line = segment[1]end_line = segment[2]for line in segment[0]:if "收到请求" in line:objectList_request_str = process_request(line)# 任务IDwork_path = extract_work_path_tool(objectList_request_str['imageUrlList'][0])if work_path != work_id:break# 点位IDextract_objectId = objectList_request_str['objectId']if not extract_objectId in filter_schem.keys():# 新增filter_schem[extract_objectId] = idxpiNums_schem[extract_objectId] = 1else:# 更新filter_schem[extract_objectId] = idxpiNums_schem[extract_objectId] += 1not_del_ids.append(idx)breakprint('*********************************************************************')# print(piNums_schem)# 找到第一次出现重复点位的位置print("此次任务ID:<{}>中".format(work_id))idsNums_result1 = len({key: value for key, value in piNums_schem.items() if value == 1})print("点位 [=1] 的数量:",idsNums_result1) idsNums_result2 = len({key: value for key, value in piNums_schem.items() if value > 1})print("点位 [>1] 的数量:",idsNums_result2)  print('*********************************************************************')# print(filter_schem, len(filter_schem)) # ------------------过滤结束sumWorkNum, filter_workId_num, filter_objectId_num = 0, 0, 0for idx, segment in enumerate(debug_segments):# print(segment[0],'\n',len(segment[0]))error_flag = FalseftpLoad_flag = False# print('Start Line:', segment[1])# print('End Line:', segment[2])for line in segment[0]:if "收到请求" in line:# print('【请求信息】: ',end='')objectList_request_str = process_request(line)extract_objectId = objectList_request_str['objectId']# print(extract_objectId)# print(objectList_request_str['imageUrlList'][0], work_id)# 过滤掉【不同任务】if not work_id == extract_work_path_tool(objectList_request_str['imageUrlList'][0]):filter_workId_num += 1break# 过滤掉【同任务相同点位取最新】if ( piNums_schem[extract_objectId] > 1 ) and ( idx != filter_schem[extract_objectId] ):# print(idx, filter_schem[extract_objectId])filter_objectId_num += 1break# 这里才是没被break的真正点位数量sumWorkNum += 1elif '数据库信息' in line:# print(line)if line.split("【数据库信息】")[-1] == '{}':# 数据库信息为空# print('*pointList_length:0')# print('{}')Error_withoutId.append(extract_objectId)error_num += 1breakelse:# 数据库有信息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 += 1if meter_type == 'meter_ywj':ymb_num += 1if meter_type == 'paddleocr':sxb_num += 1if 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 = Trueelse: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)ftpLoad_flag = Trueerror_flag = Truebreakif result_schem['desc'] == '未识别到任何油面表!':error_flag = TrueError_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 = Trueif not 'sxb' in det_clsType and meter_type == 'paddleocr':Error_ocrDet.append(extract_objectId) error_flag = Trueif '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 = Trueelif '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 = Trueif "没识别出指针" in splitContent:Error_withoutPointer.append(extract_objectId)error_flag = True# 画框与推理出来的油面表无匹配if '画框与推理出来的油面表无匹配' in splitContent:Error_withoutYmbMatch.append(extract_objectId)error_flag = Trueif 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)continueif error_flag and not ftpLoad_flag: if meter_type == 'meter_v5':bj_errorNum += 1if meter_type == 'meter_ywj':ymb_errorNum += 1if meter_type == 'paddleocr':sxb_errorNum += 1error_num += 1elif error_flag and ftpLoad_flag:error_num += 1meter_type = ''print("错误总数比:【{}/{}】-> 即正确率:{}%".format(error_num,sumWorkNum,round((1-error_num/sumWorkNum)*100, 2)))# ===========================核# 写入# with open('meterLog_checking.txt', 'w') as output_file:saveLogFile_path = './分析报告生成处'if not os.path.exists(saveLogFile_path):os.makedirs(saveLogFile_path)with open(os.path.join(saveLogFile_path,'meterLog_checking-{}.txt'.format(work_id)), 'w', encoding='utf-8') as output_file:output_file.write('您这次序号为[{}]的任务:\n---------------------------------\n一共测试表计数量:[{}]个, 错误点位为:[{}]个, 未打点个数为:[{}]。\n<在此之中>\n,指针类表计成功占[{}/{}]个\n,油面表成功占[{}/{}]个\n,数显表成功占[{}/{}]个。'.format(work_id,sumWorkNum,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("-> 即正确率:{}%".format(error_num,sumWorkNum,round((1-error_num/sumWorkNum)*100, 2)))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(set(Error_withoutDetctor)))) + "\n")output_file.write("\n".join(set(Error_withoutDetctor)))output_file.write('\n')output_file.write("【错误】未识别出指针<数量:{}>:".format(str(len(set(Error_withoutPointer)))) + "\n") output_file.write("\n".join(set(Error_withoutPointer)))output_file.write('\n')output_file.write("【错误】读取ftp图失败<数量:{}>:".format(str(len(set(Error_loadftp)))) + "\n")output_file.write("\n".join(set(Error_loadftp)))output_file.write('\n')output_file.write("【错误】minIO无图<数量:{}>:".format(str(len(set(Error_withoutMinioImage)))) + "\n")output_file.write("\n".join(set(Error_withoutMinioImage)))output_file.write('\n')output_file.write("【错误】该点位没有录入<数量:{}>:".format(str(len(set(Error_withoutId)))) + "\n")output_file.write("\n".join(set(Error_withoutId)))output_file.write('\n')output_file.write("【错误】表计类型录入错误<数量:{}>:".format(str(len(set(Error_clsType)))) + "\n")output_file.write("\n".join(set(Error_clsType)))output_file.write('\n')output_file.write("【错误】最大最小值未设置<数量:{}>:".format(str(len(set(Error_withoutMinMax)))) + "\n")output_file.write("\n".join(set(Error_withoutMinMax)))output_file.write('\n')output_file.write("【错误】未打刻度点位<数量:{}>:".format(str(len(set(Error_withoutPointList)))) + "\n")output_file.write("\n".join(set(Error_withoutPointList)))output_file.write('\n')output_file.write("【错误】最大最小值设置错误<数量:{}>:".format(str(len(set(Error_minMaxSet)))) + "\n")output_file.write("\n".join(set(Error_minMaxSet)))output_file.write('\n')output_file.write("【错误】存在刻度打点错误(暂未启用)<数量:{}>:".format(str(len(set(Error_PointList)))) + "\n")output_file.write("\n".join(set(Error_PointList)))output_file.write('\n')for ey in Error_ymb:if ey in Error_withoutYmbMatch:Error_ymb.remove(ey)output_file.write("【错误】未识别到任何油面<数量:{}>:".format(str(len(set(Error_ymb)))) + "\n")output_file.write("\n".join(set(Error_ymb)))output_file.write('\n')output_file.write("【错误】画框与推理结果无匹配<数量:{}>:".format(str(len(set(Error_withoutYmbMatch)))) + "\n")output_file.write("\n".join(set(Error_withoutYmbMatch)))output_file.write('\n')output_file.write("【错误】OCR没有检测出数字<数量:{}>:".format(str(len(set(Error_ocrRec)))) + "\n")output_file.write("\n".join(set(Error_ocrRec)))output_file.write('\n')output_file.write("【错误】OCR没有检测出表盘<数量:{}>:".format(str(len(set(Error_ocrDet)))) + "\n")output_file.write("\n".join(set(Error_ocrDet)))output_file.write('\n')print('<*总共统计数量:{}>\n<*过滤掉的非此次任务ID数量:{}>\n<*过滤掉的重复的点位ID数量:{}>'.format(len(debug_segments),filter_workId_num, filter_objectId_num))print('*********************************************************************')input("Press any key to exit...")

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

构建基于RHEL7(CentOS7)的OpenSSH9.5p1的RPM包和升级回退方案

本文适用&#xff1a;RHEL7系列&#xff0c;或同类系统(CentOS7等) 文档形成时期&#xff1a;2023年 因软件世界之复杂和个人能力之限&#xff0c;难免疏漏和错误&#xff0c;欢迎指正。 文章目录 环境准备安装依赖openssh-9.5p1-el7.spec内容构建RPM包下载安装前注意事项开启t…

C语言用函数指针实现计算器

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>//实现目录函数&#xff1b; void menum() {//打印目录&#xff1b;printf("***********************************************\n");printf("***…

如何在“Microsoft Visual Studio”中使用OpenCV构建应用程序

我在这里描述的所有内容都将应用于 OpenCV 的界面。我首先假设您已经阅读并成功完成了 Windows 中的安装教程。因此&#xff0c;在进一步操作之前&#xff0c;请确保您有一个包含 OpenCV 头文件和二进制文件的 OpenCV 目录&#xff0c;并且您已按照此处所述设置环境变量 设置 O…

养猫家庭怎么挑选宠物空气净化器?猫用空气净化器推荐来了!

宠物空气净化器在近年来越来越受到关注&#xff0c;它们被宣传为解决宠物家庭空气质量问题的神器。然而&#xff0c;一些人认为宠物空气净化器只是商家们利用人们对宠物的爱而推出的一种所谓的“智商税”&#xff0c;那么作为一位养猫多年的铲屎官&#xff0c;我可以说宠物空气…

[windows]一种判断exe是32位还是64位程序简单方法

不用运行&#xff0c;直接查看 exe 文件的兼容性属性。 如果是 32 位的程序&#xff0c;“简化的颜色模式”和“用 640x480 屏幕分辨率运行”是可以勾选的&#xff0c;且兼容模式最低可以调到 Windows 95。 而 64 位的程序&#xff0c;“简化的颜色模式”和“用 640 x 480 屏…

在线项目实习分享:股票价格形态聚类与收益分析

01前置课程 数据挖掘基础数据探索数据预处理数据挖掘算法基础Python数据挖掘编程基础Matplotlib可视化Pyecharts绘图 02师傅带练 行业联动与轮动分析 通过分析申银万国行业交易指数的联动与轮动现象&#xff0c;获得有意义的行业轮动关联规则&#xff0c;并在此基础上设计量…

华云安攻击面发现及管理平台体验

省流&#xff1a; 无需【立即咨询】即可体验&#xff0c;开通即可查看演示数据&#xff0c;公开报价 界面&#xff1a; 界面简洁&#xff0c;要点清晰&#xff0c;可以清晰的看到暴露面及攻击面信息 功能&#xff1a; 资产发现&#xff1a;主域名发现、子域名发现、 IP 发现…

snmp协议配置

引言 SNMP&#xff08;Simple Network Management Protocol&#xff09;是一种网络管理协议&#xff0c;用于管理和监控网络设备、操作系统和应用程序。它提供了一组用于检索和修改网络设备配置、监视设备状态和性能的标准化方法。 SNMP 是一个客户端-服务器协议&#xff0c;…

性能监控软件选择攻略

随着企业对应用程序性能的关注度不断增加&#xff0c;选择适当的性能监控软件变得至关重要。性能监控软件能够帮助企业实时追踪应用程序的性能指标&#xff0c;识别潜在问题并提高系统的稳定性。在选择性能监控软件时&#xff0c;以下攻略将有助于确保您的选择符合业务需求并能…

制造知识普及--MES系统中的调度排产管理

要想弄清楚MES系统调度排产的管理机制&#xff0c;则要首先搞清楚车间调度排产是一套怎样的工作流程&#xff0c;它的难点在什么地方&#xff1f; 生产调度指的是具体组织实现生产作业计划的工作&#xff0c;是对执行生产作业计划过程中发生的问题和可能出现的问题&#xff0c…

代码随想录算法训练营第3天 | 203.移除链表元素 ,707.设计链表 , 206.反转链表

数组理论基础 文章链接&#xff1a;https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 203.移除链表元素 题目链接&#xff1a;https://leetcode.cn/problems/remove-linked-list-elements/ 这种情况下的移除操作&#xff0c;就是让…

【Docker】数据管理之数据卷的挂载

一、什么是数据卷 为了很好的实现数据保存和数据共享&#xff0c;Docker提出了Volume这个概念&#xff0c;简单的说就是绕过默认的联合 文件系统&#xff0c;而以正常的文件或者目录的形式存在于宿主机上。又被称作数据卷。数据卷提供了一些有用的特性&#xff1a; 数据卷可以在…