生产事故调查最耗时的部分,往往不是查看某一张监控图,而是在日志、指标、链路追踪和部署记录之间反复切换,并把零散信号整理成可验证的故障假设。Expedia Group 推出的内部平台 STAR,尝试用结构化工作流和大模型缩短这一过程,同时保留工程师对结论的审核权。
根据公开摘要,STAR 使用 FastAPI、Datadog、Celery、Redis 和 Langfuse 构建。这个技术组合透露出一个重要设计方向:LLM 并不直接“盯着生产环境猜答案”,而是被放进一个可追踪、可排队、可审查的遥测分析流程中。
关键不是聊天框,而是结构化调查工作流
一次生产事故可能同时包含多类证据:
- 服务指标:错误率、延迟、吞吐量、资源饱和度;
- 日志:异常堆栈、超时、重试和依赖错误;
- 分布式追踪:慢调用、失败跨度和依赖传播路径;
- 变更信息:部署版本、配置调整和功能开关;
- 事故上下文:受影响服务、开始时间和用户症状。
如果直接把大量原始数据塞进提示词,通常会遇到上下文超限、噪声过多、成本失控和结论无法复现等问题。更稳妥的工作流是先缩小时间窗口和服务范围,再由确定性代码聚合遥测数据,最后让模型解释已经筛选过的证据。
一个典型流程可以拆成以下阶段:
- 接收事故编号、服务名和调查时间窗;
- 异步查询指标、日志与追踪数据;
- 计算基线偏差,提取异常事件和高频错误;
- 将证据整理成固定结构,再调用 LLM;
- 输出根因候选、证据引用、置信度与下一步验证动作;
- 由值班工程师确认、驳回或补充结论。
这种结构让 AI 承担信息压缩和假设生成,而不是替代事故指挥者作出最终判断。
这套组件分别解决什么问题
FastAPI 适合提供事故分析 API,并通过请求模型约束服务名、时间范围等输入。Celery 把耗时的遥测查询和模型调用移出 HTTP 请求,避免分析任务占满 Web 进程。Redis 可以承担任务队列或短期状态存储,让前端轮询调查进度。
Datadog 提供生产遥测数据。实际实现中,访问层应当限制查询窗口、数据量和允许访问的服务,避免一次调查拉取无边界日志。Langfuse 一类 LLM 可观测工具则可记录提示词版本、模型响应、延迟、费用和人工反馈,帮助团队判断某次根因分析为何产生了特定结论。
把这些组件组合起来后,平台本身也必须具备可观测性。至少应记录:
- 每个阶段的开始时间、结束时间和失败原因;
- 查询过的数据源、时间窗口与过滤条件;
- 提交给模型的证据摘要,而非无法核对的隐式上下文;
- 模型、提示词版本和采样参数;
- 工程师最终接受或否决了哪些判断。
可以这样实践:搭建最小调查任务 API
下面不是 STAR 的源码,而是基于摘要中技术栈整理的最小示例。它用 FastAPI 接收事故信息,用 Celery 和 Redis 执行异步分析,并用模拟遥测数据展示结构化输出。运行前需要安装 Docker 和 Python 3.11 以上版本。
创建 requirements.txt:
fastapi==0.115.6
uvicorn[standard]==0.34.0
celery[redis]==5.4.0
pydantic==2.10.4
创建 app.py:
from datetime import datetime
from typing import Literal
from celery import Celery
from fastapi import FastAPI
from pydantic import BaseModel, Field
celery = Celery(
"incident_analyzer",
broker="redis://localhost:6379/0",
backend="redis://localhost:6379/1",
)
app = FastAPI(title="Telemetry Incident Analyzer")
class InvestigationRequest(BaseModel):
incident_id: str = Field(min_length=1)
service: str = Field(min_length=1)
start: datetime
end: datetime
class InvestigationStatus(BaseModel):
task_id: str
state: str
result: dict | None = None
@celery.task(name="investigate")
def investigate(payload: dict) -> dict:
# 实际项目应在这里查询 Datadog,并对日志、指标和追踪进行聚合。
evidence = [
{
"type": "metric",
"signal": "http_5xx_rate",
"observation": "rose from 0.2% to 8.7%",
},
{
"type": "trace",
"signal": "payment-api latency",
"observation": "p95 increased to 4.8 seconds",
},
{
"type": "deployment",
"signal": "release",
"observation": "version 2025.03.08 deployed 6 minutes earlier",
},
]
# 生产版本可将 evidence 传给 LLM,但必须要求模型引用证据并声明不确定性。
return {
"incident_id": payload["incident_id"],
"service": payload["service"],
"assessment": {
"status": "needs_human_review",
"hypothesis": "The recent release may have increased downstream latency.",
"confidence": "medium",
"evidence_indexes": [0, 1, 2],
"next_actions": [
"Compare traces before and after the deployment",
"Check timeout configuration changes",
"Consider a controlled rollback",
],
},
"evidence": evidence,
}
@app.post("/investigations", status_code=202)
def create_investigation(request: InvestigationRequest) -> dict:
if request.end <= request.start:
return {"error": "end must be later than start"}
task = investigate.delay(request.model_dump(mode="json"))
return {"task_id": task.id, "state": "queued"}
@app.get("/investigations/{task_id}", response_model=InvestigationStatus)
def get_investigation(task_id: str) -> InvestigationStatus:
task = celery.AsyncResult(task_id)
result = task.result if task.successful() else None
return InvestigationStatus(task_id=task_id, state=task.state, result=result)
启动 Redis、Celery worker 和 API:
docker run --rm --name telemetry-redis -p 6379:6379 redis:7-alpine
在另外两个终端运行:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
celery -A app.celery worker --loglevel=INFO
source .venv/bin/activate
uvicorn app:app --reload --port 8000
提交调查任务:
curl -sS -X POST http://localhost:8000/investigations \
-H 'Content-Type: application/json' \
-d '{
"incident_id": "INC-1042",
"service": "checkout-api",
"start": "2025-03-08T10:00:00Z",
"end": "2025-03-08T10:30:00Z"
}'
响应中的 task_id 可用于查询结果:
curl -sS http://localhost:8000/investigations/替换为任务ID
接入真实 LLM 时,可以要求模型严格返回 JSON,并明确区分事实与推断。提示词可以这样设计:
You are assisting an on-call engineer with incident investigation.
Use only the supplied telemetry evidence.
Return JSON with:
- hypotheses: ranked root-cause candidates
- evidence_indexes: evidence supporting each candidate
- contradictions: evidence that weakens each candidate
- confidence: low, medium, or high
- next_actions: reversible validation steps
Do not claim causation from timing alone. If evidence is insufficient,
state that explicitly. Never invent logs, metrics, deployments, or traces.
人在环中不是装饰性审批
根因分析很容易把“同时发生”误写成“因果关系”。例如,某个版本上线后错误率升高,并不能单独证明该版本就是根因;流量变化、下游故障或配置漂移也可能发生在同一时间。平台应该主动展示反证,并要求工程师通过回滚、流量切换、配置对比或追踪采样验证假设。
同时需要防范遥测数据中的敏感信息。日志可能包含令牌、个人数据和业务字段,在发送给外部模型之前应执行脱敏、字段白名单、访问控制和保留期管理。对于高风险操作,模型只能建议,不能直接执行重启、扩容或回滚。
落地时从窄场景开始
引入类似 STAR 的能力时,可以先选择遥测质量较高、依赖关系清晰的一组服务,并限定为只读调查助手。上线前重点检查以下事项:
- 每项结论能否追溯到具体指标、日志或链路证据;
- 数据查询是否有服务范围、时间窗口和数量上限;
- 模型失败或超时时,值班人员能否继续使用原有工具;
- 是否记录提示词版本、成本、延迟和人工反馈;
- 是否用历史事故回放评估准确率,而不是只看演示效果;
- 是否明确禁止模型自动执行高风险生产操作。
这类平台的价值不在于给出一个听起来确定的答案,而在于更快组织证据、暴露未知项,并向工程师提供可验证的下一步动作。只有当调查过程能够审计、结论能够引用证据、人工能够推翻模型时,LLM 才真正适合进入生产事故响应链路。