搭建算法日志自检小系统

2024-01-12 13:04

本文主要是介绍搭建算法日志自检小系统,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

🥒 前言

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

👑现场人员自检失败表计点位教程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.chinasem.cn/article/597949

相关文章

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创

Spring Boot整合log4j2日志配置的详细教程

《SpringBoot整合log4j2日志配置的详细教程》:本文主要介绍SpringBoot项目中整合Log4j2日志框架的步骤和配置,包括常用日志框架的比较、配置参数介绍、Log4j2配置详解... 目录前言一、常用日志框架二、配置参数介绍1. 日志级别2. 输出形式3. 日志格式3.1 PatternL

CentOS系统Maven安装教程分享

《CentOS系统Maven安装教程分享》本文介绍了如何在CentOS系统中安装Maven,并提供了一个简单的实际应用案例,安装Maven需要先安装Java和设置环境变量,Maven可以自动管理项目的... 目录准备工作下载并安装Maven常见问题及解决方法实际应用案例总结Maven是一个流行的项目管理工具

本地搭建DeepSeek-R1、WebUI的完整过程及访问

《本地搭建DeepSeek-R1、WebUI的完整过程及访问》:本文主要介绍本地搭建DeepSeek-R1、WebUI的完整过程及访问的相关资料,DeepSeek-R1是一个开源的人工智能平台,主... 目录背景       搭建准备基础概念搭建过程访问对话测试总结背景       最近几年,人工智能技术

开启mysql的binlog日志步骤详解

《开启mysql的binlog日志步骤详解》:本文主要介绍MySQL5.7版本中二进制日志(bin_log)的配置和使用,文中通过图文及代码介绍的非常详细,需要的朋友可以参考下... 目录1.查看是否开启bin_log2.数据库会把日志放进logs目录中3.查看log日志总结 mysql版本5.71.查看

5分钟获取deepseek api并搭建简易问答应用

《5分钟获取deepseekapi并搭建简易问答应用》本文主要介绍了5分钟获取deepseekapi并搭建简易问答应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需... 目录1、获取api2、获取base_url和chat_model3、配置模型参数方法一:终端中临时将加

C#实现系统信息监控与获取功能

《C#实现系统信息监控与获取功能》在C#开发的众多应用场景中,获取系统信息以及监控用户操作有着广泛的用途,比如在系统性能优化工具中,需要实时读取CPU、GPU资源信息,本文将详细介绍如何使用C#来实现... 目录前言一、C# 监控键盘1. 原理与实现思路2. 代码实现二、读取 CPU、GPU 资源信息1.

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

2.1/5.1和7.1声道系统有什么区别? 音频声道的专业知识科普

《2.1/5.1和7.1声道系统有什么区别?音频声道的专业知识科普》当设置环绕声系统时,会遇到2.1、5.1、7.1、7.1.2、9.1等数字,当一遍又一遍地看到它们时,可能想知道它们是什... 想要把智能电视自带的音响升级成专业级的家庭影院系统吗?那么你将面临一个重要的选择——使用 2.1、5.1 还是