拓扑
拓扑是把 "edge-prod-04 上一条 incident" 变成 "一条会带垮 payments、search、 email 的 incident" 的图。没有它,LLM 只能在单条触发 series 上推理。
ADR-025
当前的拓扑 BaseTool(expand_topology、find_topology_node)2026-05-18 落地。在那之前,LLM 拿到的是扁平的设备列表,没有走关系的办法;"什么依赖 X" 要靠运维自己先知道答案。
数据模型
四张表,全在 MySQL:
| 表 | 装什么 |
|---|---|
topology_nodes | 每个节点一行。有 type(device / service / cluster / ...)、name、自由形态的 props_json。 |
topology_node_types | 允许的 node.type 闭合集。 |
topology_relations | 有向边 src_node_id -> dst_node_id,带 type。 |
topology_relation_types | 闭合的边类型集,每个带 semantics 字段(hard_dep / runtime_dep / traffic / annotation / observation)。 |
semantics 标签是关键想法。带 hard_dep 的边传播故障(src 挂了 dst 受影响);带 annotation 的边不传。爆炸半径走图用它做过滤。
见 internal/manager/biz/topology/。
数据从哪儿来
分层的三种来源:
- 从 span 自动来 —— Tempo 的
service_graph处理器吐service_a -> service_b的边,带routes_tosemantics 标签。manager 按同步 tick 把 它们镜像到topology_relations。 - 从 edge 自动来 —— 每个注册的 edge 变成一个
type=device节点;节点 id 反链到host_devices.node_id列,这样expand_topology(device_id=X)能解到。 - 手动 —— 运维通过 SPA 的
/topology页加type=service/type=cluster节点和边。给那些想寻址但没被直接观测到的节点用(托管 数据库、第三方 API)。
工具
expand_topology
从一个节点向外走,返回每一个可达节点以及它怎么被走到的。默认 BFS 深度 2, 上限 5。默认方向 both(爆炸半径是对称的 —— 什么能搞挂这个,和这个能 搞挂什么)。
{
"node_id": 142,
"depth": 2,
"only_propagating": true,
"direction": "downstream"
}或者,从一个设备 id 起步:
{ "device_id": 17, "depth": 3 }工具会自动解 device_id → device.node_id。only_propagating=true(默认) 只走 hard_dep / runtime_dep / traffic 边;翻成 false 把 observation / annotation 边算进来(用于"给我看跟 X 有关的一切"场景)。
返回的命中带 LLM 推断影响时需要的 path 元数据:
{
"center": { "node_id": 142, "node_name": "payments-api", "node_type": "service", "hops": 0, "propagates_failure": false },
"max_hops": 2,
"reachable_count": 7,
"reachable": [
{ "node_id": 71, "node_name": "edge-prod-04", "node_type": "device", "hops": 1,
"relation_type": "deployed_on", "semantics_tag": "runtime_dep", "reached_via": "downstream",
"propagates_failure": true,
"via_node_id": 142, "via_node_name": "payments-api" }
]
}扁平列表(没有每邻居嵌套结构体)是故意的 —— 让 JSON 嵌进 prompt 里便宜。 见 expand_topology_basetool.go。
find_topology_node
"我有一个人类给的名字,帮我拿到 node_id" 的前置步骤。persona 在 prompt 里 出现按名字引用的服务 / 主机时,会先跑它再跑 expand_topology:
User: "what does loki-write depend on?"
Agent:
→ find_topology_node{ name: "loki-write" }
← { node_id: 219, node_type: "service", name: "loki-write" }
→ expand_topology{ node_id: 219, direction: "upstream" }
← { reachable_count: 4, ... }两者都注册为 ScopeManager BaseTool(没有 edge_id 参数)—— 拓扑 DB 住在 manager 侧。
爆炸半径走图实战
investigator persona 的 prompt 里含一条明确的 "找到触发服务后调 expand_topology 看还有什么受影响"。报告的 related_alerts 和"业务影响 / Business impact" 部分就是这么填出来的 —— Agent 从触发设备向上 / 向下走图, 交叉核对同一窗口里那些节点上还触发了哪些 incident。
相关代码路径:
correlate_incident返回指标 + 日志 + 链路摘要,加上 incident 的device_id。expand_topology { device_id, direction: both, depth: 2 }返回可达集。- Pass-2 抽取读 worker 的叙述,抽出
pinpointed_target(0 号病人)+related_alerts(级联)。