Skip to content

RCA (근본 원인)

알림 발화 시 Ongrid 는 incident-investigator persona 에 대해 그래프 커널 기반 ReAct 에이전트를 구동하는 LLM worker 를 스폰하고, 증거 수집을 위해 도구를 호출하며, 구조화된 보고서를 investigation_reports 에 다시 씁니다.

보고서는 SPA 의 /alerts/incidents/:id 페이지에 발화 시리즈 옆에 렌더링됩니다 — 인간 SRE 는 "빈 prompt 에서" 시작할 필요가 없습니다.

HLD-013

현재 파이프라인은 HLD-013 의 Phase 1+2 인과 모델을 안착합니다. 단순한 "무엇이 발화했는지 요약" 접근 (PR-2) 은 운영자가 알람 텍스트 요약이 아닌 zero patient — 캐스케이드를 시작한 특정 프로세스 / 컨테이너 / 라인 — 을 원한다는 것이 명확해진 후 교체되었습니다.

생명주기

text
incident.fire (isNew=true)
    └─ alert.Usecase.RecordFiring
        └─ Investigator.InvestigateAsync(incident)
            └─ Enqueue → Gate 1-3 (severity, inflight, semaphore)
                └─ repo.Create(pending row)   ← UI shows "investigating…"
                └─ go run(reportID, incident, dedupKey, locale)
                    ├─ spawner.SpawnWorker(incident-investigator persona)
                    ├─ worker drives the ReAct loop with tools
                    ├─ Pass-2 structured extraction (cheap model)
                    └─ repo.MarkReady(report fields)  ← UI shows ready

InvestigateAsync 는 alert.Usecase 가 호출하는 공개 seam — usecase.go:301 참고.

게이트

worker 가 스폰되기 전 세 게이트가 필터링. 각 거부는 status=skipped 행으로 영속화되어 SPA 가 운영자에게 "절대 시작 안 됨" 대신 이유를 보여 줍니다.

Gate기본Miss 시 동작
Severity floor (Config.MinSeverity)warning조용한 skip, 행 미작성
In-process inflight (incident_id 별)항상 on조용한 병합
동시성 상한 (Config.MaxConcurrent)5skipped: concurrency limit reached (N workers in flight)

동시성 상한은 LLM provider rate-limit 을 방어하고 한 번에 100 incident 가 발화할 때 RAM 을 제한. 상한 초과 호출자는 큐가 아닌 명시적 skipped 행을 받음.

Worker

런타임이 chatruntime.SpawnRequest 로 worker 스폰:

go
// internal/manager/biz/alert/investigator/usecase.go:571
worker, err := uc.spawner.SpawnWorker(ctx, chatruntime.SpawnRequest{
    AgentName:   uc.cfg.AgentName, // "incident-investigator"
    Prompt:      prompt,
    Background:  false,
    SessionKind: "investigation",
})

prompt 는 renderAlertPrompt 가 렌더링하며 포함:

  • Incident 메타데이터 (규칙, 심각도, device_id, 값, 임계값, 요약).
  • 명시적 시작 지시: Start with correlate_incident to pull metrics + logs + traces + topology around the fire window.
  • 하드 예산: 최대 10 도구 호출, 호출 #7 까지 보고서 작성 시작해야 함. 이 예산은 사용자 메시지에 있는 이유 — 비 frontier 모델 (GLM, DeepSeek) 이 system 메시지 제약보다 사용자 메시지 제약을 더 신뢰성 있게 따르기 때문. 없으면 eino MaxStep 상한이 매번 다른 실행 마다 도달했습니다.
  • 운영자의 UI 로케일로 persona 의 암묵적 언어를 오버라이드하는 locale 지시 (로케일이 어떻게 전파되는지는 Models / Routing 참고).

도구 예산 + salvage

eino ReAct 그래프가 총 단계를 상한. worker 가 최종 답 작성 없이 상한을 소진하면 investigator 는 부분 흔적을 salvage:

  1. MessageReader.ListMessages(sessionID, limit=100) 가 모든 턴을 풀.
  2. Assistant + 도구 메시지가 합성 "우리가 찾은 것" markdown 으로 연결.
  3. Salvage 는 같은 Pass-2 추출기를 통해 공급.
  4. 보고서는 낮은 신뢰도 노트가 prepend 된 ready 로 표시: 工作器超出最大步数预算(exceeds max steps);以下为根据已收集工具结果的局部分析,置信度偏低。

Salvage 없이는 운영자가 유용한 데이터 없이 status=failed 를 봤습니다 — worker 가 보통 10+ 도구를 호출하고 답을 모았지만 합성 턴을 절대 작성하지 않았습니다.

구조화 추출 (Pass 2)

Worker 의 최종 assistant 메시지는 markdown — SPA 는 구조화 필드가 필요. 두 번째, 저렴한 LLM 호출이 추출:

  • root_cause — 한 문단 TL;DR.
  • affected_window — 증상 span 이 언제 시작 / 정지.
  • pinpointed_target — 변경된 특정 프로세스 / 컨테이너 / 파일.
  • related_alerts — 공동 발화 incident (RelatedAlertQuerier 경유).
  • evidence — 불릿 소스 인용 (PromQL 출력, 로그 라인 등).
  • suggested_actions — 운영자 실행 가능한 다음 단계.
  • confidence + confidence_factors.
  • tool_call_countchat_messages 에서 다시 읽어 UI 가 worker 가 실제로 호출한 도구 수를 표시 (하드코딩 0 아님).

Config.SummarizerProvider / Config.SummarizerModel 로 구성 가능한 모델 + provider. 기본 30 초 타임아웃 (짧은 prompt, 짧은 답, 도구 루프 없음).

추출기가 미배선이거나 에러일 때 폴백은 root_cause 채우기를 위해 worker 의 markdown 위에 firstParagraphOneLine 을 사용하고 전체 markdown 을 그대로 findings_md 로 출하.

Bold 헤더 함정

firstParagraphOneLine (usecase.go:846) 은 순수 markdown scaffolding (헤딩, 구분선, 완전 bold 섹션 제목) 을 건너뛰어 root_cause**현상** 이 아닌 문장으로 읽히게 합니다. 이전 버그는 선행 ** 만 제거하고 후행 쌍을 남겼습니다 — 같은 함수에서 수정됨.

수동 재트리거

http
POST /v1/alerts/incidents/{id}/investigation
Accept-Language: en

ForceEnqueue 가 수동 경로 실행:

  1. 이 incident 에 대해 현재 실행 중인 worker 중지 (best-effort — 재시작 후 worker_id 가 만료되어 있으면 경고하고 계속).
  2. 이전 investigation_reports 행 하드 삭제 (이전 force-enqueue 에서 soft 삭제된 행을 커버하여 고유 incident_id 인덱스가 다음 Create 를 거부하지 않도록).
  3. inflight 가드 해제.
  4. Accept-Language 에서 파싱된 locale 로 EnqueueWith 호출하여 재생성된 보고서가 운영자의 UI 언어로 돌아오게.

Severity floor 는 여전히 적용 — info 레벨 incident 에 대한 수동 트리거는 severity below floor 에러를 반환.

부팅 시점 백필

신규 설치는 닭과 달걀 문제를 만남: 구조화 RCA 체인은 최소 하나의 LLM provider 가 구성되어야 배선되지만 incident 는 운영자가 provider 를 추가하기 전에 발화할 수 있습니다. BackfillUnstartedIncidents 는 부팅 시 실행되어 ListIncidentsWithoutReport(since, limit) 를 워크하고 윈도우에서 발화한 모든 것을 재 enqueue. 일반 게이트는 여전히 적용되어 해결된 incident 와 floor 초과 incident 는 건너뜀.

배선은 cmd/ongrid/main.go 참고 — 24 시간 윈도우로 시작 시 실행.

같이 보기

  • 알림 — 무엇이 발화하나.
  • 토폴로지expand_topology 가 investigator 의 영향 범위 워크에 노출하는 것.
  • 기능correlate_incident, get_incident_detail, query_promql, search_logs: worker 가 호출하는 도구.
  • Models / Routing — investigation 별 로케일 + provider 가 어떻게 해석되는지.
  • Models / Budget — investigation 비용을 제한하는 전역 일일 토큰 상한.