各位来宾,各位技术爱好者,大家好!
今天,我们齐聚一堂,探讨一个在软件开发领域既古老又前沿的话题:如何从失败中学习。但我们今天不仅仅是泛泛而谈“吸取教训”,而是要深入剖析一个具体且具有开创性的概念——“Chain-of-Hindsight”(CoH),即“回溯链”。
想象一下,如果我们的开发工具、我们的系统能够主动地将我们过去的失败,以一种结构化的、可对比的方式,呈现在我们当前的决策面前,那会是怎样一番景象?CoH正是旨在实现这一愿景。它不是一个简单的错误日志分析工具,而是一个将过去的“负面经验”转化为当前“决策智慧”的物理实现框架。
一、引言:从经验主义到系统化回溯
在软件开发的漫长历史中,我们一直依赖于“经验”。资深开发者凭借其丰富的项目经历,能够预判潜在的问题,规避常见的陷阱。然而,这种经验往往是个人化的、难以量化的,并且容易随着人员流动而流失。新手开发者则不得不反复跌入同样的坑,付出时间和精力的代价。
传统的错误日志、监控系统、乃至事后复盘(post-mortem),更多地停留在“记录”和“分析”层面。它们告诉我们“发生了什么”,甚至“为什么发生”,但它们往往缺乏一个关键的环节:如何将这些洞察,在实时或准实时的决策点上,与当前正在进行的任务关联起来,并作为对比负例来指导我们。
“Chain-of-Hindsight”正是为了填补这一空白而生。它的核心思想是:将过去的失败场景,以“快照”的形式结构化存储,并在新的决策或代码实现过程中,主动检索并呈现那些与当前上下文“相似”的失败快照,作为“请勿重蹈覆辙”的明确信号。这是一种主动的、系统化的负面经验学习机制,旨在将个人经验转化为团队乃至组织的集体智慧。
二、Chain-of-Hindsight的核心概念与价值
2.1 失败快照(Failure Snapshot):定义与构成
“失败快照”是CoH系统的基石。它不仅仅是一个错误堆栈,而是一个多维度、上下文丰富的失败记录。它旨在捕捉导致失败的完整环境和条件。
一个理想的失败快照应包含以下关键信息:
| 组成部分 | 描述 | 示例数据 ### 2.2 对比负例(Contrastive Negative Example):CoH的独特之处
CoH与其他错误分析系统最显著的区别,在于其对“对比负例”的运用。
- 传统分析: 倾向于独立分析每个错误,关注其根本原因。
- CoH: 在开发者或系统面临决策时,CoH会主动检索并呈现与当前决策上下文相似的过往失败案例。这些案例并非直接告诉你“应该怎么做”,而是明确地告诉你“如果这样做,可能会发生什么,或者过去就曾因为类似原因失败过”。
这种“负面教育”在人类学习中非常有效。我们不仅学习成功的模式,更会记住失败的教训。CoH将这种直觉转化为系统化的工具。
2.3 CoH的价值主张
- 加速学习曲线: 新手开发者能更快地了解常见的陷阱。
- 避免重复犯错: 组织层面的“集体失忆”得以缓解。
- 提升代码质量与系统稳定性: 潜在的缺陷在早期被发现和规避。
- 优化设计决策: 在架构或模块设计阶段,就能看到类似设计的历史遗留问题。
- 增强团队协作: 失败的经验被标准化、共享化。
三、Chain-of-Hindsight的物理实现:系统架构与核心组件
要将CoH从概念变为现实,我们需要构建一个涵盖数据采集、存储、分析、检索和集成的一体化系统。
3.1 总体架构概览
CoH系统可以被划分为以下主要功能模块:
+---------------------+ +--------------------------+ +---------------------+
| | | | | |
| 数据源 | | 数据采集与快照生成 | | 数据存储与索引 |
| (代码库, CI/CD, +---->+ (Snapshot Generation) +---->+ (Storage & Indexing) |
| 运行时系统, | | | | |
| 人工输入) | | | | |
+---------------------+ +--------------------------+ +---------------------+
|
V
+---------------------+ +--------------------------+ +---------------------+
| | | | | |
| 特征提取与分析 | | 相似度计算与匹配引擎 | | 决策支持与集成 |
| (Feature Extraction) |<---+ (Similarity Matching Engine) +---->+ (Decision Support & Integration) |
| | | | | |
+---------------------+ +--------------------------+ | |
^ | (IDE Plugin, |
| | CI/CD Hook, |
+---------------------+ PR Bot, Dashboard) |
| | |
+---------------------+---------------------+
|
V
+---------------------+
| |
| 反馈与优化 |
| (Feedback & Refinement) |
| |
+---------------------+
3.2 核心组件详解
3.2.1 数据采集与快照生成 (Data Ingestion & Snapshot Generation)
这是CoH系统的“眼睛”和“耳朵”,负责捕捉和结构化失败事件。
数据源:
- 代码库 (Version Control Systems – VCS):
- 失败代码上下文: 导致问题的具体代码段、文件路径、版本信息。
- 历史变更: 相关的提交信息、作者、代码审查记录。
- 静态分析结果: 代码质量工具(SonarQube, ESLint等)发现的潜在缺陷。
- 持续集成/持续部署 (CI/CD) 系统:
- 构建失败: 编译错误、依赖问题。
- 测试失败: 单元测试、集成测试、端到端测试的失败报告。
- 部署失败: 配置错误、环境不兼容。
- 流水线上下文: 触发构建的用户、分支、环境变量。
- 运行时系统 (Runtime Systems):
- 异常与错误日志: 堆栈跟踪、错误消息、日志上下文(请求ID、用户ID等)。
- 性能监控指标: 慢查询、高CPU/内存使用率、超时。
- 分布式追踪: 请求链路中的失败节点、延迟。
- 服务调用失败: API调用错误、网络分区。
- 人工输入 (Manual Input):
- 事后复盘报告 (Post-Mortem Reports): 详细的故障描述、根本原因分析、解决措施。
- 问题追踪系统 (Issue Trackers): Bug报告、重现步骤、解决方案。
- 经验分享: 开发人员主动提交的“我曾经在这里踩过坑”的经验。
快照生成机制:
这需要一套自动化工具链,在上述数据源中识别失败事件,并将其封装成统一的FailureSnapshot数据结构。
import datetime
from typing import Dict, List, Optional, Any
class FailureSnapshot:
"""
CoH系统中的失败快照数据模型。
尽可能全面地记录一次失败的上下文信息。
"""
def __init__(self,
snapshot_id: str,
timestamp: datetime.datetime,
failure_type: str, # e.g., "RuntimeError", "BuildFailure", "TestFailure"
root_cause_summary: str, # 人工或AI提取的根本原因概述
severity: str, # e.g., "Critical", "Major", "Minor"
project_name: str,
service_name: str,
component_name: Optional[str] = None,
version_control_info: Dict[str, str] = None, # Git commit hash, branch, repo URL
code_context: Dict[str, Any] = None, # 文件路径, 代码行号, 相关代码段AST/文本
error_details: Dict[str, Any] = None, # 堆栈跟踪, 错误消息, 异常类型
log_snippets: List[str] = None, # 关键日志片段
metrics_at_failure: Dict[str, float] = None, # 失败时的关键系统/应用指标
environment_info: Dict[str, str] = None, # OS, Runtime version, dependencies
ci_cd_context: Dict[str, str] = None, # CI/CD pipeline ID, job name, build URL
affected_users: Optional[int] = None,
resolution_steps: Optional[str] = None, # 解决步骤或补丁描述
tags: List[str] = None, # 自定义标签,如 "database", "network", "concurrency"
owner_team: Optional[str] = None,
related_success_snapshot_id: Optional[str] = None # 失败修复后的成功快照ID,用于对比学习
):
self.snapshot_id = snapshot_id
self.timestamp = timestamp
self.failure_type = failure_type
self.root_cause_summary = root_cause_summary
self.severity = severity
self.project_name = project_name
self.service_name = service_name
self.component_name = component_name
self.version_control_info = version_control_info or {}
self.code_context = code_context or {}
self.error_details = error_details or {}
self.log_snippets = log_snippets or []
self.metrics_at_failure = metrics_at_failure or {}
self.environment_info = environment_info or {}
self.ci_cd_context = ci_cd_context or {}
self.affected_users = affected_users
self.resolution_steps = resolution_steps
self.tags = tags or []
self.owner_team = owner_team
self.related_success_snapshot_id = related_success_snapshot_id
def to_dict(self):
"""将快照对象转换为字典,便于存储和序列化"""
return {
"snapshot_id": self.snapshot_id,
"timestamp": self.timestamp.isoformat(),
"failure_type": self.failure_type,
"root_cause_summary": self.root_cause_summary,
"severity": self.severity,
"project_name": self.project_name,
"service_name": self.service_name,
"component_name": self.component_name,
"version_control_info": self.version_control_info,
"code_context": self.code_context,
"error_details": self.error_details,
"log_snippets": self.log_snippets,
"metrics_at_failure": self.metrics_at_failure,
"environment_info": self.environment_info,
"ci_cd_context": self.ci_cd_context,
"affected_users": self.affected_users,
"resolution_steps": self.resolution_steps,
"tags": self.tags,
"owner_team": self.owner_team,
"related_success_snapshot_id": self.related_success_snapshot_id
}
# 示例:一个简单的运行时错误快照生成函数
def create_runtime_failure_snapshot(
exception: Exception,
code_file: str,
line_number: int,
function_name: str,
current_code_snippet: str,
project: str,
service: str,
log_buffer: List[str],
runtime_metrics: Dict[str, float]
) -> FailureSnapshot:
import traceback
snapshot_id = f"runtime-{datetime.datetime.now().isoformat()}-{hash(str(exception))}"
# 模拟从Git获取信息
vc_info = {
"commit_hash": "a1b2c3d4e5f6",
"branch": "main",
"repo_url": f"https://github.com/{project}/{service}"
}
return FailureSnapshot(
snapshot_id=snapshot_id,
timestamp=datetime.datetime.now(),
failure_type="RuntimeError",
root_cause_summary=f"Unhandled exception: {type(exception).__name__}",
severity="Major",
project_name=project,
service_name=service,
code_context={
"file": code_file,
"line": line_number,
"function": function_name,
"snippet": current_code_snippet
},
error_details={
"exception_type": type(exception).__name__,
"message": str(exception),
"stack_trace": traceback.format_exc()
},
log_snippets=log_buffer,
metrics_at_failure=runtime_metrics,
version_control_info=vc_info,
environment_info={"python_version": "3.9.7", "os": "Linux"}
)
# 在应用中捕获异常时调用
try:
# 模拟一个可能失败的操作
result = 1 / 0
except Exception as e:
current_log_buffer = ["INFO: Operation started", "ERROR: Division by zero attempted"]
current_metrics = {"cpu_usage": 0.5, "memory_usage": 0.7, "request_latency_ms": 100.0}
snapshot = create_runtime_failure_snapshot(
exception=e,
code_file="my_module.py",
line_number=15,
function_name="calculate_ratio",
current_code_snippet="result = numerator / denominator",
project="MyProject",
service="DataProcessor",
log_buffer=current_log_buffer,
runtime_metrics=current_metrics
)
# print(snapshot.to_dict()) # 将快照发送到存储层
3.2.2 数据存储与索引 (Data Storage & Indexing)
存储层需要支持海量快照的存储、高效检索和复杂查询。
- 技术选型:
- 文档数据库 (MongoDB, Elasticsearch): 适合存储非结构化或半结构化的快照数据,支持灵活的Schema和全文搜索。尤其是Elasticsearch,其强大的搜索和聚合能力使其成为理想选择。
- 时序数据库 (InfluxDB, Prometheus): 存储与快照关联的性能指标和日志时间序列。
- 图数据库 (Neo4j): 可用于存储代码依赖、服务调用关系等,以便进行更复杂的上下文关联分析。
- 索引策略:
- 基于快照的关键属性(
project_name,service_name,failure_type,tags,timestamp)创建索引。 - 对文本字段(
root_cause_summary,error_details.message,log_snippets,code_context.snippet)进行全文索引。 - 对代码上下文(文件路径、函数名)进行精确和模糊索引。
- 基于快照的关键属性(
3.2.3 特征提取与分析 (Feature Extraction & Analysis)
原始的快照数据是庞杂的,需要将其转化为可比较、可分析的“特征向量”。
- 文本特征:
- 错误消息/堆栈: 利用自然语言处理(NLP)技术(如TF-IDF, Word2Vec, BERT embeddings)提取语义特征,识别关键实体、动词和模式。
- 日志片段: 同样通过NLP进行模式识别,归一化日志模板。
- 代码片段: 抽象语法树(AST)分析,提取代码结构、变量使用、函数调用等特征。
- 结构化特征:
- 代码上下文: 文件路径、行号、函数名、类名、模块名。
- 版本控制信息: 提交作者、提交消息关键词、修改文件数量。
- 环境信息: 操作系统、运行时版本、依赖库版本。
- 指标数据: 失败时的资源使用率、请求量、延迟等统计特征。
- 人工标注: 允许人工为快照添加标签、归类、根本原因等,这些标注本身也是重要的特征。
import hashlib
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
# 简单的文本特征提取器 (用于错误消息和日志)
class TextFeatureExtractor:
def __init__(self):
self.vectorizer = TfidfVectorizer(stop_words='english', max_features=1000)
self.fitted = False
def fit(self, texts: List[str]):
if not self.fitted:
self.vectorizer.fit(texts)
self.fitted = True
def transform(self, texts: List[str]) -> np.ndarray:
return self.vectorizer.transform(texts).toarray()
# 示例:从快照中提取用于相似度匹配的特征
def extract_matching_features(snapshot: FailureSnapshot) -> Dict[str, Any]:
features = {
"failure_type": snapshot.failure_type,
"project_name": snapshot.project_name,
"service_name": snapshot.service_name,
"component_name": snapshot.component_name,
"code_path_hash": hashlib.md5(f"{snapshot.code_context.get('file', '')}:{snapshot.code_context.get('function', '')}".encode()).hexdigest(),
"error_message_text": snapshot.error_details.get("message", ""),
"root_cause_summary_text": snapshot.root_cause_summary,
"tags": snapshot.tags
}
# 可以添加更多结构化特征,如环境信息、关键指标范围等
return features
# 假设我们有一个预先训练好的TF-IDF vectorizer
# all_past_failure_messages = [s.error_details.get("message", "") for s in all_past_snapshots]
# text_extractor = TextFeatureExtractor()
# text_extractor.fit(all_past_failure_messages)
3.2.4 相似度计算与匹配引擎 (Similarity Matching Engine)
这是CoH系统的“大脑”,负责根据当前上下文,找出最相关的历史失败快照。
- 相似度算法:
- 文本相似度: 余弦相似度(Cosine Similarity)结合TF-IDF或词嵌入,用于比较错误消息、代码片段、日志。
- 结构化数据相似度: 欧氏距离、曼哈顿距离等,或基于规则的匹配(如完全匹配、前缀匹配)。
- 图相似度: 如果使用图数据库,可以进行子图匹配或图编辑距离计算,以比较代码结构或依赖关系。
- 混合模型: 综合多种特征和算法,赋予不同特征不同的权重。例如,如果文件路径和函数名完全匹配,则权重更高。
- 匹配流程:
- 接收查询: 当前代码上下文、错误信息、CI/CD任务信息等作为查询输入。
- 提取查询特征: 与快照存储时相同的特征提取器处理查询输入。
- 多维度匹配:
- 精确匹配: 服务名、项目名、文件路径、函数名。
- 模糊匹配: 错误消息(语义相似)、日志模式、代码结构。
- 标签匹配: 查找相同标签的失败。
- 排序与过滤: 根据相似度得分对匹配结果进行排序,并过滤掉不相关的快照。
# 假设我们有历史快照的特征向量和文本向量
# past_snapshot_features = [extract_matching_features(s) for s in all_past_snapshots]
# past_error_message_vectors = text_extractor.transform([s.error_details.get("message", "") for s in all_past_snapshots])
class SimilarityMatchingEngine:
def __init__(self, all_past_snapshots: List[FailureSnapshot], text_extractor: TextFeatureExtractor):
self.past_snapshots = all_past_snapshots
self.text_extractor = text_extractor
# 预计算所有历史快照的文本特征向量
past_error_messages = [s.error_details.get("message", "") for s in all_past_snapshots]
self.past_error_message_vectors = self.text_extractor.transform(past_error_messages)
# 预处理其他结构化特征,便于快速查找
self.indexed_structural_features = [extract_matching_features(s) for s in all_past_snapshots]
def find_similar_failures(self, current_context: Dict[str, Any], top_k: int = 5) -> List[Dict[str, Any]]:
"""
根据当前上下文查找相似的失败快照。
current_context 示例: {
"project_name": "MyProject",
"service_name": "DataProcessor",
"code_file": "my_module.py",
"function_name": "calculate_ratio",
"error_message": "division by zero" # 或者当前的代码片段,CI/CD 错误描述等
}
"""
query_error_message = current_context.get("error_message", "")
query_text_vector = self.text_extractor.transform([query_error_message])[0]
similarities = []
for i, past_snapshot in enumerate(self.past_snapshots):
# 1. 结构化特征匹配 (高权重)
structural_score = 0
if current_context.get("project_name") == past_snapshot.project_name:
structural_score += 0.3
if current_context.get("service_name") == past_snapshot.service_name:
structural_score += 0.3
if current_context.get("code_file") == past_snapshot.code_context.get("file"):
structural_score += 0.2
if current_context.get("function_name") == past_snapshot.code_context.get("function"):
structural_score += 0.1
# 2. 文本语义相似度 (中等权重)
text_score = 0
if query_error_message and self.past_error_message_vectors.shape[0] > 0:
past_vector = self.past_error_message_vectors[i].reshape(1, -1)
text_score = cosine_similarity(query_text_vector.reshape(1, -1), past_vector)[0][0] * 0.5 # 调整权重
# 3. 标签匹配 (可变权重)
tag_score = 0
current_tags = current_context.get("tags", [])
if current_tags and past_snapshot.tags:
common_tags = set(current_tags).intersection(set(past_snapshot.tags))
tag_score = len(common_tags) / max(len(current_tags), len(past_snapshot.tags)) * 0.1 # 调整权重
# 综合得分
total_score = structural_score + text_score + tag_score
similarities.append({"snapshot": past_snapshot, "score": total_score})
# 排序并返回前K个结果
similarities.sort(key=lambda x: x["score"], reverse=True)
# 过滤掉得分过低的结果
return [
{"snapshot_id": s["snapshot"].snapshot_id,
"score": s["score"],
"summary": s["snapshot"].root_cause_summary,
"error_message": s["snapshot"].error_details.get("message", ""),
"code_context": s["snapshot"].code_context
} for s in similarities if s["score"] > 0.1 # 设定一个阈值
][:top_k]
# 假设初始化
# all_past_snapshots = [...] # 从数据库加载所有历史快照
# messages = [s.error_details.get("message", "") for s in all_past_snapshots if s.error_details.get("message")]
# text_extractor = TextFeatureExtractor()
# if messages:
# text_extractor.fit(messages)
# else:
# # 处理没有历史消息的情况,例如使用一个空的vectorizer或者默认行为
# print("Warning: No historical error messages to fit TF-IDF vectorizer.")
# text_extractor.fitted = True # 标记为已初始化,避免后续错误
# matching_engine = SimilarityMatchingEngine(all_past_snapshots, text_extractor)
# # 示例查询
# current_query_context = {
# "project_name": "MyProject",
# "service_name": "DataProcessor",
# "code_file": "my_module.py",
# "function_name": "process_data", # 假设当前正在处理的函数
# "error_message": "null pointer dereference", # 假设开发者正在调试一个类似的错误
# "tags": ["data_processing", "null_safety"]
# }
# similar_failures = matching_engine.find_similar_failures(current_query_context)
# print("nSimilar past failures:")
# for sf in similar_failures:
# print(f" Score: {sf['score']:.2f}, ID: {sf['snapshot_id']}")
# print(f" Summary: {sf['summary']}")
# print(f" Error: {sf['error_message']}")
# print(f" Code: {sf['code_context'].get('file')}:{sf['code_context'].get('line')}")
3.2.5 决策支持与集成 (Decision Support & Integration)
CoH的最终目标是将这些洞察集成到开发者的日常工作流程中。
| 集成点 | 描述 | 用户交互 |
|---|
import datetime
from typing import List, Dict, Any, Optional
import hashlib
class CodeSnippet:
"""代表一个代码片段,包含其内容和相关元数据。"""
def __init__(self,
code: str,
file_path: str,
line_start: int,
line_end: int,
function_name: Optional[str] = None,
class_name: Optional[str] = None):
self.code = code
self.file_path = file_path
self.line_start = line_start
self.line_end = line_end
self.function_name = function_name
self.class_name = class_name
self.hash = hashlib.sha256(code.encode('utf-8')).hexdigest()
def to_dict(self):
return {
"code": self.code,
"file_path": self.file_path,
"line_start": self.line_start,
"line_end": self.line_end,
"function_name": self.function_name,
"class_name": self.class_name,
"hash": self.hash
}
class FailureSnapshot:
"""
Chain-of-Hindsight 系统中的失败快照数据模型。
尽可能全面地记录一次失败的上下文信息,特别是与代码和决策相关的。
"""
def __init__(self,
snapshot_id: str,
timestamp: datetime.datetime,
failure_type: str, # "RuntimeError", "BuildFailure", "TestFailure", "DeploymentFailure", "DesignFlaw"
severity: str, # "Critical", "Major", "Minor", "Warning"
project_name: str,
service_name: str,
component_name: Optional[str] = None, # 例如:某个模块、库名
version_control_info: Dict[str, str] = None, # Git commit hash, branch, repo URL, author
problematic_code_snippets: List[CodeSnippet] = None, # 导致失败的关键代码段
error_details: Dict[str, Any] = None, # 堆栈跟踪, 错误消息, 异常类型, 错误码
log_events: List[str] = None, # 关键日志事件,可能包含WARN/ERROR级别
metrics_at_failure: Dict[str, float] = None, # 失败时的关键系统/应用指标(CPU, Mem, Latency等)
environment_info: Dict[str, str] = None, # OS, Runtime version, dependencies versions
ci_cd_context: Dict[str, str] = None, # CI/CD pipeline ID, job name, build URL, test report summary
user_actions_context: List[str] = None, # 用户在失败前的操作序列 (对于前端或API失败)
root_cause_analysis: Optional[str] = None, # 对根本原因的详细文字描述
resolution_strategy: Optional[str] = None, # 解决该失败的策略或方法
fix_commit_hash: Optional[str] = None, # 修复该问题的提交哈希
tags: List[str] = None, # 自定义标签,如 "concurrency", "database_deadlock", "N+1_query", "memory_leak"
owner_team: Optional[str] = None,
affected_systems: List[str] = None, # 受影响的其他系统或服务
# 用于对比学习,记录失败修复后的成功快照ID,或者成功案例的ID
related_positive_example_id: Optional[str] = None
):
self.snapshot_id = snapshot_id
self.timestamp = timestamp
self.failure_type = failure_type
self.severity = severity
self.project_name = project_name
self.service_name = service_name
self.component_name = component_name
self.version_control_info = version_control_info or {}
self.problematic_code_snippets = problematic_code_snippets or []
self.error_details = error_details or {}
self.log_events = log_events or []
self.metrics_at_failure = metrics_at_failure or {}
self.environment_info = environment_info or {}
self.ci_cd_context = ci_cd_context or {}
self.user_actions_context = user_actions_context or []
self.root_cause_analysis = root_cause_analysis
self.resolution_strategy = resolution_strategy
self.fix_commit_hash = fix_commit_hash
self.tags = tags or []
self.owner_team = owner_team
self.affected_systems = affected_systems or []
self.related_positive_example_id = related_positive_example_id
def to_dict(self):
"""将快照对象转换为字典,便于存储和序列化"""
return {
"snapshot_id": self.snapshot_id,
"timestamp": self.timestamp.isoformat(),
"failure_type": self.failure_type,
"severity": self.severity,
"project_name": self.project_name,
"service_name": self.service_name,
"component_name": self.component_name,
"version_control_info": self.version_control_info,
"problematic_code_snippets": [s.to_dict() for s in self.problematic_code_snippets],
"error_details": self.error_details,
"log_events": self.log_events,
"metrics_at_failure": self.metrics_at_failure,
"environment_info": self.environment_info,
"ci_cd_context": self.ci_cd_context,
"user_actions_context": self.user_actions_context,
"root_cause_analysis": self.root_cause_analysis,
"resolution_strategy": self.resolution_strategy,
"fix_commit_hash": self.fix_commit_hash,
"tags": self.tags,
"owner_team": self.owner_team,
"affected_systems": self.affected_systems,
"related_positive_example_id": self.related_positive_example_id
}
@classmethod
def from_dict(cls, data: Dict[str, Any]):
"""从字典反序列化为FailureSnapshot对象"""
data['timestamp'] = datetime.datetime.fromisoformat(data['timestamp'])
data['problematic_code_snippets'] = [CodeSnippet(**cs) for cs in data['problematic_code_snippets']]
return cls(**data)
class SnapshotRepository:
"""模拟一个持久化存储失败快照的仓库"""
def __init__(self):
self._snapshots: Dict[str, FailureSnapshot] = {} # 内存存储,实际应是数据库
def save_snapshot(self, snapshot: FailureSnapshot):
self._snapshots[snapshot.snapshot_id] = snapshot
print(f"快照 {snapshot.snapshot_id} 已保存。")
def get_snapshot(self, snapshot_id: str) -> Optional[FailureSnapshot]:
return self._snapshots.get(snapshot_id)
def get_all_snapshots(self) -> List[FailureSnapshot]:
return list(self._snapshots.values())
def search_snapshots(self, query: Dict[str, Any]) -> List[FailureSnapshot]:
"""
模拟简单的搜索功能,实际会调用Elasticsearch等搜索引擎。
这里只做基于关键字段的模糊匹配。
"""
results = []
for snapshot in self._snapshots.values():
match = True
if query.get("project_name") and query["project_name"] != snapshot.project_name:
match = False
if query.get("service_name") and query["service_name"] != snapshot.service_name:
match = False
if query.get("failure_type") and query["failure_type"] != snapshot.failure_type:
match = False