トポロジー
トポロジーは「ホスト edge-prod-04 のインシデント」を「payments と search と email を巻き込むインシデント」に変える グラフ です。 これがないと LLM は単一の発火系列についてしか推論できません。
ADR-025
現行のトポロジー BaseTool(expand_topology、find_topology_node)は 2026-05-18 にランディングしました。それ以前は LLM はフラットなデバイス リストしか持たず関係を walk する手段がなく、「何が X に依存するか」は operator が答えをすでに知っている必要がありました。
データモデル
4 つのテーブル、すべて MySQL:
| テーブル | 何を保持するか |
|---|---|
topology_nodes | ノードごとに 1 行。type(device / service / cluster / ...)、name、自由形式の props_json を持つ。 |
topology_node_types | 許容される node.type 値のクローズドセット。 |
topology_relations | type を持つ有向エッジ src_node_id -> dst_node_id。 |
topology_relation_types | エッジタイプのクローズドセット。各々が semantics フィールド(hard_dep / runtime_dep / traffic / annotation / observation)でタグ付け。 |
semantics タグが鍵となるアイデアです。hard_dep タグのエッジは障害を 伝播します(src が死ねば dst が影響を受ける)、annotation タグの エッジはしません。ブラスト半径ウォークはこれでフィルタします。
internal/manager/biz/topology/ 参照。
データの出所
3 つのソース、層をなして:
- スパンからの自動 —— Tempo の
service_graphプロセッサがroutes_tosemantics タグ付きのservice_a -> service_bエッジを emit します。manager は同期 tick でこれらをtopology_relationsに ミラーします。 - edge からの自動 —— 登録された各 edge は
type=deviceノードに なり、ノード id はhost_devices.node_idカラムに back-link される ので、expand_topology(device_id=X)が解決します。 - 手動 —— operator は SPA の
/topologyページでtype=service/type=clusterノードとエッジを追加します。アドレスしたいが直接観測 されないノード(マネージドデータベース、サードパーティ API)に 使います。
ツール
expand_topology
ノードから外側に walk し、到達可能なすべてのノードと到達経路を返します。 デフォルトの 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 エッジのみを walk します。observation / annotation エッジを 含めるには false に反転します(「X に関連するすべてを見せて」のケースに 便利)。
返ってきたヒットは LLM が影響を推論するのに必要なパスメタデータを持ち ます:
{
"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 のコストを抑えます。 expand_topology_basetool.go 参照。
find_topology_node
「人間が与えた名前があるので node_id をくれ」の前段ステップ。ペルソナは プロンプトがサービス / ホストを名前で言及するたび、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 ペルソナのプロンプトには明示的に「発火サービスを特定したら、 他に何が影響を受けるか見るため expand_topology を呼べ」と入っています。 これがレポートの related_alerts と「业务影响 / Business impact」セクション が埋まる仕組みです —— エージェントが発火デバイスから上流 / 下流にグラフを walk し、それらのノード上で同じウィンドウに他のどのインシデントが発火した かを相互チェックします。
関連コードパス:
correlate_incidentがメトリクス + ログ + トレース要約と インシデントのdevice_idを返す。expand_topology { device_id, direction: both, depth: 2 }が到達可能 集合を返す。- Pass-2 抽出が worker の物語を読み、
pinpointed_target(0 号病人)とrelated_alerts(カスケード)を引き出す。