# -*- 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': '未知错误' }