토폴로지
토폴로지는 "edge-prod-04 호스트의 incident" 를 "payments 와 search 와 email 을 다운시키는 incident" 로 바꾸는 그래프 입니다. 없으면 LLM 은 단일 발화 시리즈에 대해서만 추론할 수 있습니다.
ADR-025
현재 토폴로지 BaseTool (expand_topology, find_topology_node) 은 2026-05-18 에 안착. 그 전에 LLM 은 flat 디바이스 리스트만 가졌고 관계를 워크할 방법이 없었습니다; "X 에 의존하는 것" 은 운영자가 이미 답을 알아야 했습니다.
데이터 모델
네 테이블, 모두 MySQL 에:
| Table | Holds |
|---|---|
topology_nodes | 노드당 한 행. 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/ 참고.
데이터 출처
세 소스, 계층화:
- Span 에서 자동 — Tempo 의
service_graph프로세서가routes_tosemantics 태그와 함께service_a -> service_b엣지를 배출. 매니저가 sync 틱에 이를topology_relations에 미러링. - Edge 에서 자동 — 등록된 모든 edge 가
type=device노드가 됨; 노드 id 는host_devices.node_id컬럼에 back-link 되므로expand_topology(device_id=X)가 해결됨. - 수동 — 운영자가 SPA 의
/topology페이지로type=service/type=cluster노드와 엣지를 추가. 주소 지정하고 싶지만 직접 관측되지 않는 노드 (관리형 데이터베이스, 서드파티 API) 에 사용.
도구
expand_topology
노드에서 외부로 워크하여 도달 가능한 모든 노드와 어떻게 도달했는지 반환. 기본 BFS 깊이 2, 상한 5. 기본 방향 both (영향 범위는 대칭 — 무엇이 이걸 깨뜨릴 수 있는지 AND 이게 무엇을 깨뜨리는지).
{
"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 이 영향에 대해 추론하는 데 필요한 경로 메타데이터를 운반:
{
"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" }
]
}Flat 리스트 (이웃별 중첩 구조 없음) 는 의도적 — JSON 을 prompt 에 임베드하기 저렴하게 유지. expand_topology_basetool.go 참고.
find_topology_node
"사람이 준 이름이 있다, node_id 를 줘" 사전 단계. Prompt 가 이름으로 서비스 / 호스트를 언급할 때마다 persona 는 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 는 매니저 측에 산다.
실무에서의 영향 범위 워크
Investigator persona 의 prompt 는 "발화 서비스를 식별한 후 무엇이 또 영향 받는지 보려면 expand_topology 를 호출하라" 는 명시적 지시 포함. 이것이 보고서의 related_alerts 와 "业务影响 / Business impact" 섹션이 채워지는 방법 — 에이전트가 발화 디바이스에서 위/아래로 그래프를 워크하고 그 노드들에서 같은 윈도우에 발화한 다른 incident 를 크로스 체크.
관련 코드 경로:
correlate_incident가 메트릭 + 로그 + 트레이스 요약과 incident 의device_id반환.expand_topology { device_id, direction: both, depth: 2 }가 도달 가능 셋 반환.- Pass-2 추출이 worker 의 내러티브를 읽고
pinpointed_target(zero patient) +related_alerts(캐스케이드) 를 풀.