631 lines
20 KiB
Python
631 lines
20 KiB
Python
# -*- coding: utf-8 -*-
|
||
|
||
"""
|
||
错误代码映射配置
|
||
用于为不同类型的错误分配固定的告警代码
|
||
"""
|
||
|
||
from typing import Dict, List, Tuple
|
||
import re
|
||
|
||
class ErrorCodeMapping:
|
||
"""错误代码映射管理器"""
|
||
|
||
# 基础告警代码范围定义
|
||
BASE_RANGES = {
|
||
'system': (5400, 5499), # 系统相关错误 5400-5499
|
||
'task': (5500, 5699), # 任务相关错误 5500-5699
|
||
'robot': (5700, 5799), # 机器人相关错误 5700-5799
|
||
'database': (5800, 5849), # 数据库相关错误 5800-5849
|
||
'network': (5850, 5899), # 网络相关错误 5850-5899
|
||
'auth': (5900, 5949), # 认证相关错误 5900-5949
|
||
'validation': (5950, 5999), # 验证相关错误 5950-5999
|
||
}
|
||
|
||
# 错误类型和关键词映射
|
||
ERROR_TYPE_PATTERNS = {
|
||
# 任务相关错误
|
||
'task_execution_failed': {
|
||
'patterns': [
|
||
r'任务执行失败',
|
||
r'task execution failed',
|
||
r'execute.*failed',
|
||
r'执行.*失败',
|
||
],
|
||
'code': 5500,
|
||
'category': 'task'
|
||
},
|
||
'task_execution_timeout': {
|
||
'patterns': [
|
||
r'任务执行超时',
|
||
r'task execution timeout',
|
||
r'execute.*timeout',
|
||
r'执行.*超时',
|
||
],
|
||
'code': 5501,
|
||
'category': 'task'
|
||
},
|
||
'task_scheduling_failed': {
|
||
'patterns': [
|
||
r'任务调度失败',
|
||
r'task scheduling failed',
|
||
r'调度.*失败',
|
||
r'scheduling.*failed',
|
||
],
|
||
'code': 5502,
|
||
'category': 'task'
|
||
},
|
||
'task_not_found': {
|
||
'patterns': [
|
||
r'任务.*不存在',
|
||
r'task.*not found',
|
||
r'找不到.*任务',
|
||
r'任务.*未找到',
|
||
],
|
||
'code': 5503,
|
||
'category': 'task'
|
||
},
|
||
'task_params_invalid': {
|
||
'patterns': [
|
||
r'任务参数.*无效',
|
||
r'task parameters invalid',
|
||
r'参数.*错误',
|
||
r'invalid.*parameters',
|
||
],
|
||
'code': 5504,
|
||
'category': 'task'
|
||
},
|
||
'task_status_error': {
|
||
'patterns': [
|
||
r'任务状态.*错误',
|
||
r'task status error',
|
||
r'状态.*异常',
|
||
r'status.*error',
|
||
],
|
||
'code': 5505,
|
||
'category': 'task'
|
||
},
|
||
'task_block_execution_failed': {
|
||
'patterns': [
|
||
r'块.*执行.*失败',
|
||
r'block.*execution.*failed',
|
||
r'任务块.*失败',
|
||
r'block.*failed',
|
||
],
|
||
'code': 5506,
|
||
'category': 'task'
|
||
},
|
||
'task_template_error': {
|
||
'patterns': [
|
||
r'任务模板.*错误',
|
||
r'task template error',
|
||
r'模板.*异常',
|
||
r'template.*error',
|
||
],
|
||
'code': 5507,
|
||
'category': 'task'
|
||
},
|
||
'task_sync_failed': {
|
||
'patterns': [
|
||
r'同步任务.*失败',
|
||
r'sync.*task.*failed',
|
||
r'同步任务到.*系统.*失败',
|
||
r'任务同步.*失败',
|
||
],
|
||
'code': 5508,
|
||
'category': 'task'
|
||
},
|
||
'task_start_failed': {
|
||
'patterns': [
|
||
r'启动任务失败',
|
||
r'start.*task.*failed',
|
||
r'任务启动.*失败',
|
||
r'task.*startup.*failed',
|
||
],
|
||
'code': 5509,
|
||
'category': 'task'
|
||
},
|
||
'task_run_failed': {
|
||
'patterns': [
|
||
r'运行任务失败',
|
||
r'run.*task.*failed',
|
||
r'任务运行.*失败',
|
||
r'task.*execution.*failed',
|
||
],
|
||
'code': 5510,
|
||
'category': 'task'
|
||
},
|
||
'task_scene_id_not_exist': {
|
||
'patterns': [
|
||
r'此场景id不存在',
|
||
r'场景.*不存在',
|
||
r'scene.*id.*not.*exist',
|
||
r'scene.*not.*found',
|
||
],
|
||
'code': 5511,
|
||
'category': 'task'
|
||
},
|
||
'task_child_block_failed': {
|
||
'patterns': [
|
||
r'子块.*执行失败',
|
||
r'child.*block.*failed',
|
||
r'子块.*失败',
|
||
r'child.*execution.*failed',
|
||
],
|
||
'code': 5512,
|
||
'category': 'task'
|
||
},
|
||
|
||
# 机器人相关错误
|
||
'robot_connection_failed': {
|
||
'patterns': [
|
||
r'机器人.*连接.*失败',
|
||
r'robot.*connection.*failed',
|
||
r'AGV.*连接.*失败',
|
||
r'vehicle.*connection.*failed',
|
||
],
|
||
'code': 5700,
|
||
'category': 'robot'
|
||
},
|
||
'robot_battery_low': {
|
||
'patterns': [
|
||
r'机器人.*电池.*低',
|
||
r'robot.*battery.*low',
|
||
r'AGV.*电量.*低',
|
||
r'电池.*不足',
|
||
],
|
||
'code': 5701,
|
||
'category': 'robot'
|
||
},
|
||
'robot_navigation_failed': {
|
||
'patterns': [
|
||
r'机器人.*导航.*失败',
|
||
r'robot.*navigation.*failed',
|
||
r'AGV.*导航.*失败',
|
||
r'导航.*异常',
|
||
],
|
||
'code': 5702,
|
||
'category': 'robot'
|
||
},
|
||
'robot_task_failed': {
|
||
'patterns': [
|
||
r'机器人.*任务.*失败',
|
||
r'robot.*task.*failed',
|
||
r'AGV.*任务.*失败',
|
||
r'机器人.*执行.*失败',
|
||
],
|
||
'code': 5703,
|
||
'category': 'robot'
|
||
},
|
||
'robot_select_amr_failed': {
|
||
'patterns': [
|
||
r'为任务选择AMR失败',
|
||
r'选择.*AMR.*失败',
|
||
r'select.*amr.*failed',
|
||
r'amr.*selection.*failed',
|
||
],
|
||
'code': 5704,
|
||
'category': 'robot'
|
||
},
|
||
'robot_select_execution_failed': {
|
||
'patterns': [
|
||
r'选择执行机器人失败',
|
||
r'选择.*机器人.*失败',
|
||
r'robot.*selection.*failed',
|
||
r'select.*execution.*robot.*failed',
|
||
],
|
||
'code': 5705,
|
||
'category': 'robot'
|
||
},
|
||
'robot_tianfeng_task_id_not_exist': {
|
||
'patterns': [
|
||
r'此天风任务id不存在',
|
||
r'天风任务.*不存在',
|
||
r'tianfeng.*task.*id.*not.*exist',
|
||
r'tianfeng.*task.*not.*found',
|
||
],
|
||
'code': 5706,
|
||
'category': 'robot'
|
||
},
|
||
'robot_block_action_detail_failed': {
|
||
'patterns': [
|
||
r'调用获取任务块动作详情接口失败',
|
||
r'获取任务块动作.*详情.*失败',
|
||
r'task.*block.*action.*detail.*failed',
|
||
r'get.*task.*block.*action.*failed',
|
||
],
|
||
'code': 5707,
|
||
'category': 'robot'
|
||
},
|
||
'robot_block_detail_failed': {
|
||
'patterns': [
|
||
r'调用获取任务块详情接口失败',
|
||
r'获取任务块.*详情.*失败',
|
||
r'task.*block.*detail.*failed',
|
||
r'get.*task.*block.*failed',
|
||
],
|
||
'code': 5708,
|
||
'category': 'robot'
|
||
},
|
||
|
||
# 数据库相关错误
|
||
'database_connection_failed': {
|
||
'patterns': [
|
||
r'数据库.*连接.*失败',
|
||
r'database.*connection.*failed',
|
||
r'DB.*连接.*失败',
|
||
r'连接.*数据库.*失败',
|
||
],
|
||
'code': 5800,
|
||
'category': 'database'
|
||
},
|
||
'database_query_failed': {
|
||
'patterns': [
|
||
r'数据库.*查询.*失败',
|
||
r'database.*query.*failed',
|
||
r'SQL.*执行.*失败',
|
||
r'查询.*失败',
|
||
],
|
||
'code': 5801,
|
||
'category': 'database'
|
||
},
|
||
'database_transaction_failed': {
|
||
'patterns': [
|
||
r'数据库.*事务.*失败',
|
||
r'database.*transaction.*failed',
|
||
r'事务.*回滚',
|
||
r'transaction.*rollback',
|
||
],
|
||
'code': 5802,
|
||
'category': 'database'
|
||
},
|
||
|
||
# 网络相关错误
|
||
'network_connection_failed': {
|
||
'patterns': [
|
||
r'网络.*连接.*失败',
|
||
r'network.*connection.*failed',
|
||
r'连接.*超时',
|
||
r'connection.*timeout',
|
||
],
|
||
'code': 5850,
|
||
'category': 'network'
|
||
},
|
||
'network_request_failed': {
|
||
'patterns': [
|
||
r'网络.*请求.*失败',
|
||
r'network.*request.*failed',
|
||
r'HTTP.*请求.*失败',
|
||
r'request.*failed',
|
||
],
|
||
'code': 5851,
|
||
'category': 'network'
|
||
},
|
||
'network_timeout': {
|
||
'patterns': [
|
||
r'网络.*超时',
|
||
r'network.*timeout',
|
||
r'请求.*超时',
|
||
r'request.*timeout',
|
||
r'TimeoutError',
|
||
r'CancelledError',
|
||
],
|
||
'code': 5852,
|
||
'category': 'network'
|
||
},
|
||
'network_connect_refused': {
|
||
'patterns': [
|
||
r'ConnectionRefusedError',
|
||
r'Connect call failed',
|
||
r'Cannot connect to host',
|
||
r'连接.*被拒绝',
|
||
r'connection.*refused',
|
||
],
|
||
'code': 5853,
|
||
'category': 'network'
|
||
},
|
||
'network_api_call_failed': {
|
||
'patterns': [
|
||
r'调用.*接口失败',
|
||
r'调用.*API.*失败',
|
||
r'api.*call.*failed',
|
||
r'interface.*call.*failed',
|
||
r'调用系统任务创建任务接口失败',
|
||
],
|
||
'code': 5854,
|
||
'category': 'network'
|
||
},
|
||
|
||
# 系统相关错误
|
||
'system_resource_exhausted': {
|
||
'patterns': [
|
||
r'系统.*资源.*耗尽',
|
||
r'system.*resource.*exhausted',
|
||
r'内存.*不足',
|
||
r'memory.*insufficient',
|
||
],
|
||
'code': 5400,
|
||
'category': 'system'
|
||
},
|
||
'system_configuration_error': {
|
||
'patterns': [
|
||
r'系统.*配置.*错误',
|
||
r'system.*configuration.*error',
|
||
r'配置.*异常',
|
||
r'configuration.*error',
|
||
],
|
||
'code': 5401,
|
||
'category': 'system'
|
||
},
|
||
'system_service_unavailable': {
|
||
'patterns': [
|
||
r'系统.*服务.*不可用',
|
||
r'system.*service.*unavailable',
|
||
r'服务.*不可用',
|
||
r'service.*unavailable',
|
||
],
|
||
'code': 5402,
|
||
'category': 'system'
|
||
},
|
||
|
||
# 认证相关错误
|
||
'auth_token_invalid': {
|
||
'patterns': [
|
||
r'认证.*令牌.*无效',
|
||
r'auth.*token.*invalid',
|
||
r'token.*过期',
|
||
r'token.*expired',
|
||
],
|
||
'code': 5900,
|
||
'category': 'auth'
|
||
},
|
||
'auth_permission_denied': {
|
||
'patterns': [
|
||
r'权限.*拒绝',
|
||
r'permission.*denied',
|
||
r'访问.*被拒绝',
|
||
r'access.*denied',
|
||
],
|
||
'code': 5901,
|
||
'category': 'auth'
|
||
},
|
||
|
||
# 验证相关错误
|
||
'validation_parameter_invalid': {
|
||
'patterns': [
|
||
r'参数.*验证.*失败',
|
||
r'parameter.*validation.*failed',
|
||
r'参数.*无效',
|
||
r'invalid.*parameter',
|
||
],
|
||
'code': 5950,
|
||
'category': 'validation'
|
||
},
|
||
'validation_data_format_error': {
|
||
'patterns': [
|
||
r'数据.*格式.*错误',
|
||
r'data.*format.*error',
|
||
r'格式.*不正确',
|
||
r'format.*invalid',
|
||
],
|
||
'code': 5951,
|
||
'category': 'validation'
|
||
},
|
||
|
||
# 程序错误相关
|
||
'program_attribute_error': {
|
||
'patterns': [
|
||
r'AttributeError',
|
||
r'\'.*\' object has no attribute \'.*\'',
|
||
r'属性.*错误',
|
||
r'attribute.*error',
|
||
r'\'NoneType\' object has no attribute \'get\'',
|
||
],
|
||
'code': 5952,
|
||
'category': 'validation'
|
||
},
|
||
'program_type_error': {
|
||
'patterns': [
|
||
r'TypeError',
|
||
r'类型.*错误',
|
||
r'type.*error',
|
||
r'NoneType.*object',
|
||
],
|
||
'code': 5953,
|
||
'category': 'validation'
|
||
},
|
||
'program_runtime_error': {
|
||
'patterns': [
|
||
r'RuntimeError',
|
||
r'运行时.*错误',
|
||
r'runtime.*error',
|
||
r'执行时.*错误',
|
||
],
|
||
'code': 5954,
|
||
'category': 'validation'
|
||
},
|
||
}
|
||
|
||
# 模块特定的错误代码偏移
|
||
MODULE_OFFSETS = {
|
||
'services.task_service': 0,
|
||
'services.task_execution': 5,
|
||
'services.task_scheduler': 10,
|
||
'services.enhanced_scheduler.task_scheduler': 15,
|
||
'services.task_edit_service': 20,
|
||
'services.sync_service': 25,
|
||
'services.robot_scheduler': 30,
|
||
'services.calldevice_service': 35,
|
||
'services.modbus_config_service': 40,
|
||
'services.script_service': 45,
|
||
'services.execution.block_executor': 50,
|
||
'services.execution.task_executor': 55,
|
||
'routes.task_api': 60,
|
||
'routes.task_edit_api': 65,
|
||
'routes.calldevice_api': 70,
|
||
'routes.modbus_config_api': 75,
|
||
'app.task_edit_api': 80,
|
||
'middlewares.error_handlers': 85,
|
||
'middleware.request_logger': 90,
|
||
'utils.alert_sync': 95,
|
||
'data.models': 100,
|
||
'data.session': 105,
|
||
'core.intelligence': 110,
|
||
}
|
||
|
||
@classmethod
|
||
def get_error_code(cls, logger_name: str, message: str) -> int:
|
||
"""
|
||
根据logger名称和消息内容获取错误代码
|
||
|
||
Args:
|
||
logger_name: logger名称
|
||
message: 错误消息
|
||
|
||
Returns:
|
||
错误代码
|
||
"""
|
||
# 首先尝试匹配错误类型
|
||
error_type = cls._match_error_type(message)
|
||
|
||
if error_type:
|
||
# 获取基础代码
|
||
base_code = cls.ERROR_TYPE_PATTERNS[error_type]['code']
|
||
|
||
# 根据模块添加偏移量
|
||
module_offset = cls._get_module_offset(logger_name)
|
||
|
||
# 确保代码在合理范围内
|
||
final_code = base_code + module_offset
|
||
|
||
# 确保不超过最大值
|
||
if final_code > 9999:
|
||
final_code = base_code
|
||
|
||
return final_code
|
||
|
||
# 如果没有匹配的错误类型,使用通用代码生成
|
||
return cls._generate_fallback_code(logger_name, message)
|
||
|
||
@classmethod
|
||
def _match_error_type(cls, message: str) -> str:
|
||
"""
|
||
匹配错误类型
|
||
|
||
Args:
|
||
message: 错误消息
|
||
|
||
Returns:
|
||
错误类型名称,如果没有匹配则返回None
|
||
"""
|
||
message_lower = message.lower()
|
||
|
||
for error_type, config in cls.ERROR_TYPE_PATTERNS.items():
|
||
for pattern in config['patterns']:
|
||
if re.search(pattern, message_lower, re.IGNORECASE):
|
||
return error_type
|
||
|
||
return None
|
||
|
||
@classmethod
|
||
def _get_module_offset(cls, logger_name: str) -> int:
|
||
"""
|
||
获取模块的偏移量
|
||
|
||
Args:
|
||
logger_name: logger名称
|
||
|
||
Returns:
|
||
偏移量
|
||
"""
|
||
# 尝试精确匹配
|
||
if logger_name in cls.MODULE_OFFSETS:
|
||
return cls.MODULE_OFFSETS[logger_name]
|
||
|
||
# 尝试部分匹配
|
||
for module, offset in cls.MODULE_OFFSETS.items():
|
||
if logger_name.startswith(module):
|
||
return offset
|
||
|
||
return 0
|
||
|
||
@classmethod
|
||
def _generate_fallback_code(cls, logger_name: str, message: str) -> int:
|
||
"""
|
||
生成备用错误代码(用于无法匹配的错误)
|
||
|
||
Args:
|
||
logger_name: logger名称
|
||
message: 错误消息
|
||
|
||
Returns:
|
||
错误代码
|
||
"""
|
||
import hashlib
|
||
|
||
# 使用简化的消息内容生成代码
|
||
simplified_message = cls._simplify_message(message)
|
||
hash_input = f"{logger_name}:{simplified_message}"
|
||
hash_value = hashlib.md5(hash_input.encode()).hexdigest()
|
||
|
||
# 生成在6000-6999范围内的代码(未分类错误)
|
||
code = int(hash_value[:4], 16) % 1000 + 6000
|
||
return code
|
||
|
||
@classmethod
|
||
def _simplify_message(cls, message: str) -> str:
|
||
"""
|
||
简化错误消息,去除变量部分
|
||
|
||
Args:
|
||
message: 原始错误消息
|
||
|
||
Returns:
|
||
简化后的消息
|
||
"""
|
||
# 移除常见的变量部分
|
||
simplified = re.sub(r'\d+', '[NUMBER]', message) # 替换数字
|
||
simplified = re.sub(r'[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}', '[UUID]', simplified) # 替换UUID
|
||
simplified = re.sub(r'/[^/\s]+', '[PATH]', simplified) # 替换路径
|
||
simplified = re.sub(r'[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}', '[IP]', simplified) # 替换IP地址
|
||
simplified = re.sub(r'\s+', ' ', simplified).strip() # 清理空白字符
|
||
|
||
return simplified
|
||
|
||
@classmethod
|
||
def get_error_info(cls, error_code: int) -> Dict:
|
||
"""
|
||
根据错误代码获取错误信息
|
||
|
||
Args:
|
||
error_code: 错误代码
|
||
|
||
Returns:
|
||
错误信息字典
|
||
"""
|
||
# 查找匹配的错误类型
|
||
for error_type, config in cls.ERROR_TYPE_PATTERNS.items():
|
||
if config['code'] <= error_code < config['code'] + 200: # 允许偏移量
|
||
return {
|
||
'error_type': error_type,
|
||
'category': config['category'],
|
||
'base_code': config['code'],
|
||
'description': f"{config['category']}相关错误: {error_type}"
|
||
}
|
||
|
||
# 根据代码范围确定类别
|
||
for category, (start, end) in cls.BASE_RANGES.items():
|
||
if start <= error_code <= end:
|
||
return {
|
||
'error_type': 'unknown',
|
||
'category': category,
|
||
'base_code': start,
|
||
'description': f"{category}相关错误"
|
||
}
|
||
|
||
return {
|
||
'error_type': 'unknown',
|
||
'category': 'unknown',
|
||
'base_code': error_code,
|
||
'description': '未知错误'
|
||
} |