解析 ‘Chain-of-Hindsight’ 的物理实现:利用过去的失败快照作为当前决策的对比负例

各位来宾,各位技术爱好者,大家好!

今天,我们齐聚一堂,探讨一个在软件开发领域既古老又前沿的话题:如何从失败中学习。但我们今天不仅仅是泛泛而谈“吸取教训”,而是要深入剖析一个具体且具有开创性的概念——“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系统的“眼睛”和“耳朵”,负责捕捉和结构化失败事件。

数据源:

  1. 代码库 (Version Control Systems – VCS):
    • 失败代码上下文: 导致问题的具体代码段、文件路径、版本信息。
    • 历史变更: 相关的提交信息、作者、代码审查记录。
    • 静态分析结果: 代码质量工具(SonarQube, ESLint等)发现的潜在缺陷。
  2. 持续集成/持续部署 (CI/CD) 系统:
    • 构建失败: 编译错误、依赖问题。
    • 测试失败: 单元测试、集成测试、端到端测试的失败报告。
    • 部署失败: 配置错误、环境不兼容。
    • 流水线上下文: 触发构建的用户、分支、环境变量。
  3. 运行时系统 (Runtime Systems):
    • 异常与错误日志: 堆栈跟踪、错误消息、日志上下文(请求ID、用户ID等)。
    • 性能监控指标: 慢查询、高CPU/内存使用率、超时。
    • 分布式追踪: 请求链路中的失败节点、延迟。
    • 服务调用失败: API调用错误、网络分区。
  4. 人工输入 (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或词嵌入,用于比较错误消息、代码片段、日志。
    • 结构化数据相似度: 欧氏距离、曼哈顿距离等,或基于规则的匹配(如完全匹配、前缀匹配)。
    • 图相似度: 如果使用图数据库,可以进行子图匹配或图编辑距离计算,以比较代码结构或依赖关系。
    • 混合模型: 综合多种特征和算法,赋予不同特征不同的权重。例如,如果文件路径和函数名完全匹配,则权重更高。
  • 匹配流程:
    1. 接收查询: 当前代码上下文、错误信息、CI/CD任务信息等作为查询输入。
    2. 提取查询特征: 与快照存储时相同的特征提取器处理查询输入。
    3. 多维度匹配:
      • 精确匹配: 服务名、项目名、文件路径、函数名。
      • 模糊匹配: 错误消息(语义相似)、日志模式、代码结构。
      • 标签匹配: 查找相同标签的失败。
    4. 排序与过滤: 根据相似度得分对匹配结果进行排序,并过滤掉不相关的快照。
# 假设我们有历史快照的特征向量和文本向量
# 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

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注