Files
张翔 08ea5fbe98 feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
2026-03-28 14:37:29 +08:00

583 lines
18 KiB
Python

"""
错误诊断模块
提供详细的错误分析、分类、归因和恢复建议
"""
import traceback
import re
from typing import Dict, Any, List, Optional, Tuple
from dataclasses import dataclass
from enum import Enum
import json
class ErrorCategory(Enum):
"""错误分类"""
NETWORK_ERROR = "network_error"
AUTH_ERROR = "auth_error"
VALIDATION_ERROR = "validation_error"
SERVER_ERROR = "server_error"
TIMEOUT_ERROR = "timeout_error"
DATA_ERROR = "data_error"
CONFIG_ERROR = "config_error"
UNKNOWN_ERROR = "unknown_error"
class ErrorSeverity(Enum):
"""错误严重程度"""
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
CRITICAL = "critical"
@dataclass
class ErrorAnalysis:
"""错误分析结果"""
error_type: str
error_category: ErrorCategory
error_severity: ErrorSeverity
error_message: str
stack_trace: str
context: Dict[str, Any]
possible_causes: List[str]
suggested_solutions: List[str]
recovery_actions: List[str]
related_tests: List[str]
class ErrorPattern:
"""错误模式"""
def __init__(self, pattern: str, category: ErrorCategory, severity: ErrorSeverity,
causes: List[str], solutions: List[str], recovery: List[str]):
"""
初始化错误模式
Args:
pattern: 错误模式(正则表达式)
category: 错误分类
severity: 错误严重程度
causes: 可能的原因
solutions: 建议的解决方案
recovery: 恢复操作
"""
self.pattern = re.compile(pattern, re.IGNORECASE)
self.category = category
self.severity = severity
self.causes = causes
self.solutions = solutions
self.recovery = recovery
def matches(self, error_message: str) -> bool:
"""
检查错误消息是否匹配此模式
Args:
error_message: 错误消息
Returns:
是否匹配
"""
return bool(self.pattern.search(error_message))
class ErrorDiagnoser:
"""错误诊断器"""
def __init__(self):
"""初始化错误诊断器"""
self.error_patterns = self._initialize_error_patterns()
self.error_history: List[ErrorAnalysis] = []
def _initialize_error_patterns(self) -> List[ErrorPattern]:
"""
初始化错误模式
Returns:
错误模式列表
"""
patterns = [
# 网络错误
ErrorPattern(
r"connection\s+(refused|timeout|reset|closed)",
ErrorCategory.NETWORK_ERROR,
ErrorSeverity.HIGH,
[
"网络连接被拒绝",
"服务器未启动或不可达",
"防火墙阻止连接",
"网络配置错误"
],
[
"检查服务器是否正在运行",
"验证网络连接",
"检查防火墙设置",
"确认服务器地址和端口正确"
],
[
"重启服务器",
"检查网络配置",
"重试连接"
]
),
ErrorPattern(
r"host\s+(unreachable|not\s+found)",
ErrorCategory.NETWORK_ERROR,
ErrorSeverity.HIGH,
[
"主机地址不存在",
"DNS解析失败",
"网络不可达"
],
[
"验证主机地址正确",
"检查DNS配置",
"确认网络连接"
],
[
"修正主机地址",
"重试连接"
]
),
# 认证错误
ErrorPattern(
r"(unauthorized|authentication\s+failed|invalid\s+(token|credentials))",
ErrorCategory.AUTH_ERROR,
ErrorSeverity.HIGH,
[
"认证令牌无效或过期",
"用户名或密码错误",
"权限不足"
],
[
"检查认证令牌",
"验证用户凭据",
"确认用户权限"
],
[
"重新登录",
"刷新认证令牌",
"联系管理员"
]
),
ErrorPattern(
r"(forbidden|access\s+denied)",
ErrorCategory.AUTH_ERROR,
ErrorSeverity.HIGH,
[
"访问被拒绝",
"权限不足",
"资源不存在"
],
[
"检查用户权限",
"验证资源是否存在",
"确认访问控制配置"
],
[
"联系管理员",
"申请相应权限"
]
),
# 验证错误
ErrorPattern(
r"(validation\s+failed|invalid\s+(parameter|input|data))",
ErrorCategory.VALIDATION_ERROR,
ErrorSeverity.MEDIUM,
[
"输入数据格式错误",
"参数验证失败",
"数据不符合要求"
],
[
"检查输入数据格式",
"验证参数类型和范围",
"参考API文档"
],
[
"修正输入数据",
"调整参数值"
]
),
ErrorPattern(
r"(required\s+field\s+missing|missing\s+required\s+parameter)",
ErrorCategory.VALIDATION_ERROR,
ErrorSeverity.MEDIUM,
[
"缺少必填字段",
"参数不完整"
],
[
"检查请求参数",
"确认必填字段",
"参考API文档"
],
[
"补充必填字段",
"修正请求参数"
]
),
# 服务器错误
ErrorPattern(
r"(internal\s+server\s+error|server\s+error)",
ErrorCategory.SERVER_ERROR,
ErrorSeverity.CRITICAL,
[
"服务器内部错误",
"服务器处理异常",
"服务器配置问题"
],
[
"检查服务器日志",
"验证服务器配置",
"检查数据库连接"
],
[
"联系技术支持",
"检查服务器状态",
"重启服务器"
]
),
ErrorPattern(
r"(database\s+(error|connection\s+failed|timeout))",
ErrorCategory.SERVER_ERROR,
ErrorSeverity.CRITICAL,
[
"数据库连接失败",
"数据库查询错误",
"数据库超时"
],
[
"检查数据库服务状态",
"验证数据库连接配置",
"检查SQL语句"
],
[
"重启数据库服务",
"修正连接配置",
"优化SQL查询"
]
),
# 超时错误
ErrorPattern(
r"(request\s+timeout|operation\s+timed\s+out)",
ErrorCategory.TIMEOUT_ERROR,
ErrorSeverity.MEDIUM,
[
"请求超时",
"服务器响应慢",
"网络延迟高"
],
[
"检查网络连接",
"增加超时时间",
"优化请求"
],
[
"重试请求",
"增加超时配置",
"优化网络环境"
]
),
# 数据错误
ErrorPattern(
r"(data\s+(not\s+found|does\s+not\s+exist)|record\s+not\s+found)",
ErrorCategory.DATA_ERROR,
ErrorSeverity.MEDIUM,
[
"数据不存在",
"记录未找到",
"数据已被删除"
],
[
"验证数据ID",
"检查数据是否存在",
"确认数据状态"
],
[
"使用正确的数据ID",
"重新创建数据"
]
),
ErrorPattern(
r"(duplicate\s+(key|entry|record)|constraint\s+violation)",
ErrorCategory.DATA_ERROR,
ErrorSeverity.MEDIUM,
[
"数据重复",
"唯一约束冲突",
"数据已存在"
],
[
"检查数据是否已存在",
"验证唯一字段",
"使用不同的值"
],
[
"删除重复数据",
"使用不同的值",
"更新现有数据"
]
),
# 配置错误
ErrorPattern(
r"(configuration\s+error|invalid\s+configuration|config\s+not\s+found)",
ErrorCategory.CONFIG_ERROR,
ErrorSeverity.HIGH,
[
"配置错误",
"配置文件缺失",
"配置参数无效"
],
[
"检查配置文件",
"验证配置参数",
"参考配置文档"
],
[
"修正配置文件",
"重置配置",
"重新加载配置"
]
)
]
return patterns
def diagnose_error(self, exception: Exception, context: Dict[str, Any] = None) -> ErrorAnalysis:
"""
诊断错误
Args:
exception: 异常对象
context: 上下文信息
Returns:
错误分析结果
"""
error_message = str(exception)
stack_trace = traceback.format_exc()
# 查找匹配的错误模式
matched_pattern = None
for pattern in self.error_patterns:
if pattern.matches(error_message):
matched_pattern = pattern
break
# 如果没有匹配的模式,使用默认分类
if matched_pattern is None:
matched_pattern = ErrorPattern(
r".*",
ErrorCategory.UNKNOWN_ERROR,
ErrorSeverity.MEDIUM,
["未知错误"],
["检查日志", "联系技术支持"],
["重试操作", "联系支持"]
)
# 分析上下文
context = context or {}
context.update({
"error_type": type(exception).__name__,
"error_message": error_message,
"timestamp": context.get("timestamp"),
"test_name": context.get("test_name"),
"url": context.get("url"),
"method": context.get("method")
})
# 创建错误分析结果
analysis = ErrorAnalysis(
error_type=type(exception).__name__,
error_category=matched_pattern.category,
error_severity=matched_pattern.severity,
error_message=error_message,
stack_trace=stack_trace,
context=context,
possible_causes=matched_pattern.causes,
suggested_solutions=matched_pattern.solutions,
recovery_actions=matched_pattern.recovery,
related_tests=self._find_related_tests(context)
)
# 记录错误历史
self.error_history.append(analysis)
return analysis
def _find_related_tests(self, context: Dict[str, Any]) -> List[str]:
"""
查找相关测试
Args:
context: 上下文信息
Returns:
相关测试列表
"""
related_tests = []
url = context.get("url", "")
method = context.get("method", "")
# 根据URL和方法查找相关测试
if "/auth/login" in url:
related_tests.extend(["用户登录", "认证测试", "权限测试"])
elif "/user/" in url:
related_tests.extend(["用户管理测试", "用户列表测试", "用户创建测试"])
elif "/role/" in url:
related_tests.extend(["角色管理测试", "角色列表测试", "角色创建测试"])
elif "/menu/" in url:
related_tests.extend(["菜单管理测试", "菜单列表测试"])
return related_tests
def get_error_statistics(self) -> Dict[str, Any]:
"""
获取错误统计信息
Returns:
错误统计信息
"""
if not self.error_history:
return {}
# 按分类统计
category_stats = {}
for analysis in self.error_history:
category = analysis.error_category.value
if category not in category_stats:
category_stats[category] = 0
category_stats[category] += 1
# 按严重程度统计
severity_stats = {}
for analysis in self.error_history:
severity = analysis.error_severity.value
if severity not in severity_stats:
severity_stats[severity] = 0
severity_stats[severity] += 1
# 按错误类型统计
type_stats = {}
for analysis in self.error_history:
error_type = analysis.error_type
if error_type not in type_stats:
type_stats[error_type] = 0
type_stats[error_type] += 1
return {
"total_errors": len(self.error_history),
"by_category": category_stats,
"by_severity": severity_stats,
"by_type": type_stats,
"most_common_errors": self._get_most_common_errors(5)
}
def _get_most_common_errors(self, limit: int = 5) -> List[Dict[str, Any]]:
"""
获取最常见的错误
Args:
limit: 返回数量限制
Returns:
最常见错误列表
"""
error_counts = {}
for analysis in self.error_history:
error_key = f"{analysis.error_type}: {analysis.error_message[:50]}"
if error_key not in error_counts:
error_counts[error_key] = 0
error_counts[error_key] += 1
sorted_errors = sorted(error_counts.items(), key=lambda x: x[1], reverse=True)
return [
{
"error": error[0],
"count": error[1]
}
for error in sorted_errors[:limit]
]
def generate_error_report(self, analysis: ErrorAnalysis) -> str:
"""
生成错误报告
Args:
analysis: 错误分析结果
Returns:
错误报告(Markdown格式)
"""
report = f"""# 错误诊断报告
## 错误信息
- **错误类型**: {analysis.error_type}
- **错误分类**: {analysis.error_category.value}
- **严重程度**: {analysis.error_severity.value}
- **错误消息**: {analysis.error_message}
## 错误堆栈
```
{analysis.stack_trace}
```
## 上下文信息
{self._format_context(analysis.context)}
## 可能的原因
{self._format_list(analysis.possible_causes)}
## 建议的解决方案
{self._format_list(analysis.suggested_solutions)}
## 恢复操作
{self._format_list(analysis.recovery_actions)}
## 相关测试
{self._format_list(analysis.related_tests)}
---
*报告生成时间: {self._get_current_timestamp()}*
"""
return report
def _format_context(self, context: Dict[str, Any]) -> str:
"""格式化上下文信息"""
lines = []
for key, value in context.items():
if value is not None:
lines.append(f"- **{key}**: {value}")
return "\n".join(lines)
def _format_list(self, items: List[str]) -> str:
"""格式化列表"""
return "\n".join([f"- {item}" for item in items])
def _get_current_timestamp(self) -> str:
"""获取当前时间戳"""
from datetime import datetime
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
def clear_history(self) -> None:
"""清空错误历史"""
self.error_history.clear()