SigNoz에서 앱에 무슨 일이 일어났는지 물어보는 에이전트를 만들었습니다
요약
SigNoz의 관측성 데이터를 활용하여 시스템 장애 원인을 스스로 조사하는 'Why Did It Break' 에이전트를 소개합니다. 사용자의 자연어 질문에 따라 모델이 도구를 선택해 트레이스 및 통계를 분석하며, 조사 과정을 투명하게 공개합니다.
핵심 포인트
- SigNoz API를 활용한 자율적 장애 조사 에이전트 구현
- 6개의 도구를 사용하여 서비스 통계부터 상세 트레이스까지 심층 분석
- 에이전트의 도구 호출 기록을 UI에 출력하여 신뢰성 확보
- 트레이스 기반 알림 규칙과 연동하여 능동적인 장애 대응 가능
SigNoz Agents 해커톤을 위해 제작됨, 2026년 7월.
새벽 2시에 운영 환경(production)이 중단될 때, 증거는 이미 존재합니다. 시스템이 처리한 모든 요청, 모든 데이터베이스 호출, 모든 타임아웃(timeout)과 재시도(retry)는 관측성 스택(observability stack)에 기록된 채 남아 있습니다. 문제는 그것을 읽는 것입니다. 쿼리 빌더(query builder), 아키텍처에 대한 정신적 지도, 그리고 당직자에게는 없는 약 40분 정도의 시간이 필요합니다.
그래서 저는 Why Did It Break을 만들었습니다. 이것은 SigNoz 상에서 동작하는 조사 에이전트(investigation agent)입니다. 당신은 동료에게 묻는 것처럼 질문을 던지면(
하드코딩된 쿼리 시퀀스는 없습니다. 모델은 6개의 도구(tools)를 부여받고 스스로 경로를 선택합니다. 일반적으로 서비스별 통계(per-service stats)로 시작하여, 의심되는 가장 느린 스팬(spans)을 심층 조사하고, 부모-자식 타이밍(parent-child timing)을 확인하기 위해 특정 ID로 하나의 트레이스(trace)를 가져온 뒤, 충분한 정보가 모이면 멈춥니다. UI는 모든 답변 아래에 전체 도구 호출 기록(tool-call trail)을 출력하므로, 에이전트가 어떤 쿼리를 선택했는지 확인할 수 있습니다. 이 기록이 신뢰 메커니즘입니다... 에이전트는 자신의 작업 과정을 보여주어야 합니다.
SigNoz의 활용 방식
SigNoz는 데이터 플레인(data plane), 트리거(trigger), 그리고 증거(proof) 역할을 합니다.
설치는 'one-config-one-command' 경로인 Foundry를 통해 진행되었습니다. casting.yaml과 생성된 casting.yaml.lock 파일이 리포지토리에 포함되어 있습니다. 호스팅된 데모를 위해, 저는 Foundry에서 생성된 compose 매니페스트(manifests)를 프라이빗 네트워킹(private networking)을 사용하는 Railway 서비스로 변환하여 전체 스택(ClickHouse, ClickHouse Keeper, Postgres, otel-collector, SigNoz 서버)을 Railway 상에 재구축했습니다. 이 패키지는 deploy/railway/ 아래에 커밋되어 있습니다.
v5 query_range API는 에이전트의 전체 도구 세트입니다. 6개의 모든 도구는 viewer 역할의 서비스 계정 키(service-account key)를 사용하여 POST /api/v5/query_range를 호출합니다:
- 트레이스(traces)에 대한 raw builder 쿼리:
duration_nano순으로 정렬된 가장 느린 스팬(spans),status_message가 포함된 최근의has_error = true스팬, 그리고trace_id = '...'또는service.name = 'x' AND duration_nano > 1000000000와 같은 필터 표현식을 사용한 심층 조사(drill-downs) service.name별로 그룹화된 스칼라 집계(scalar aggregations),count()및p99(duration_nano)를 통해 에이전트는 누가 느린지, 누가 실패하고 있는지에 대한 첫 번째 정보를 얻습니다.- 오프셋 윈도우(offset window)를 적용한 동일한 집계로,
그리고 알림(alerts)이 있습니다. 질문을 던지는 것이 반응적인(reactive) 절반이라면, 나머지 능동적인(proactive) 절반은 트레이스 기반의 알림 규칙(trace-based alert rule)입니다. (예: Redis 드라이버-룩업 경로에서 임계값을 초과하는 에러 횟수) 이 규칙은 제 앱을 가리키는 웹훅(webhook) 알림 채널에 연결되어 있습니다. SigNoz가 알림을 발생시키면, 에이전트가 스스로 조사하며, 그 결과는 누군가 대시보드를 열기도 전에 인시던트 피드(incident feed)에 기록됩니다. 이는 해커톤 기간 동안 실제로 발생했습니다. 라이브 트래픽이 에러율을 임계값 위로 밀어 올렸고, SigNoz의 평가기(evaluator)가 작동했으며, 웹훅이 전달되었습니다. 에이전트는 알림의 임계값인 10% 대비 18.5%의 에러율을 측정했습니다. 그리고 에이전트는 원시 스팬(raw spans)을 대조하여 알림 자체의 주장이 맞는지 확인했습니다.
모든 증거 항목은 SigNoz의 트레이스 뷰(trace view)로 딥링크(deep-link)됩니다. 에이전트가 "MySQL SELECT가 1.6초의 디스패치(dispatch) 중 1.19초를 차지합니다"라고 말하는 것과, 직접 플레임 그래프(flame graph)를 클릭하여 정확히 해당 스팬 계층 구조(span hierarchy)를 확인하는 것은 차원이 다른 문제입니다. 후자가 바로 사용자가 에이전트를 신뢰하게 만드는 핵심입니다.
개발 과정에서 발생한 문제들
에이전트가 통제 불능 상태가 된 적이 있습니다. 개발 초기, SigNoz에 접속할 수 없는 상황에서 제 프롬프트는 "도구가 실패할 때 적응하라"고 지시했습니다. 모델은 적응했고, 무려 50번 연속으로 호출을 시도하며, 결코 성공할 수 없는 조사를 위해 실제 API 크레딧을 낭비했습니다. 저는 이를 단계별로 해결했습니다. 조사당 하드웨어 요청 예산(hard request budget)을 설정하고, 동일한 실패가 두 번 반복되면 중단하는 규칙을 만들었으며, 백엔드가 다운되었을 때 즉각적으로 응답하며 비용을 전혀 쓰지 않는 사전 점검(preflight health check) 기능을 추가했습니다.
빈 로그 쿼리(log queries)는 에이전트를 헛된 탐색으로 몰아넣었습니다. get_logs가 아무것도 반환하지 않을 때, 에이전트는 최대 100,000분의 조회 기간까지 점점 더 넓은 윈도우를 적용하며 9번이나 재시도했습니다. 프롬프트 수준의 조언으로는 이를 막을 수 없었습니다. 해결책은 도구(tool) 자체가 "이 시스템은 로그를 전송하지 않으므로, 다시 호출하지 마십시오"라는 메시지를 반환하도록 만드는 것이었습니다.
HotROD는 gRPC 포트인 4317번 포트로 HTTP를 통해 OTLP를 내보냈습니다. ClickHouse의 행(row) 수가 0인 동안, 모든 스팬은 "전송 연결 끊김(transport connection broken)" 에러와 함께 사라졌습니다. 15분 동안 콜렉터(collector) 로그를 뚫어지게 쳐다본 경험은 그 어떤 튜토리얼보다 OTLP에 대해 더 많은 것을 가르쳐 주었습니다. 4317은 gRPC이고, 4318은 HTTP이며, 에러 메시지가 당신이 무엇을 틀렸는지 알려준다는 사실 말입니다.
그리고 마감 당일에 유료 API 크레딧을 완전히 다 써버렸습니다. 저는 OpenRouter 카탈로그에서 실제 도구 호출 (tool-calling) 기능을 지원하는 무료 모델들을 필터링하여, 에이전트를 무료 550B 모델로 교체했습니다. 이 모델은 조사는 정확하게 수행하지만, 구조화된 증거 배열 (structured evidence array) 대신 산문 형태의 텍스트에 트레이스 ID (trace id)를 인용하는 것을 좋아합니다. 그래서 모델이 언급하는 모든 트레이스 ID를 클릭 가능한 증거 카드 (evidence card)로 가져오는 백필 (backfill) 작업을 추가했습니다.
현재 상태
이제 이 모든 것은 클라우드에서 실행됩니다. 5개의 서비스에 걸친 SigNoz, 지속적인 부하를 받는 데모 앱, 그리고 에이전트가 그것입니다. 에이전트에게 "왜 차량 배차가 느린가요?"라고 물으면, 에이전트는 스스로 선택한 몇 가지 쿼리를 통해 정확하게 답변합니다. 예를 들어, 배차 호출은 고객 서비스 뒤에 있는 느린 MySQL SELECT 문이 지배적이며, 여기에 Redis 드라이버 조회 (driver-lookup) 에러가 추가되어 재시도 (retries)가 발생한다는 식입니다. 각 주장에는 클릭하여 확인할 수 있는 트레이스 링크가 포함되어 있습니다.
데이터는 항상 그곳에 있었습니다. 이제 누구나 데이터에 질문을 던질 수 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기