AI 코딩 어시스턴트를 위한 통합 로컬 관측성 (Observability)
AI Observer는 Claude Code, Gemini CLI, OpenAI Codex CLI와 같은 로컬 AI 코딩 도구를 모니터링하기 위해 특별히 설계된, 셀프 호스팅(self-hosted)이 가능한 단일 바이너리 형태의 OpenTelemetry 호환 관측성 백엔드(observability backend)입니다.
실시간 업데이트와 외부 의존성 제로를 통해, 모든 AI 코딩 어시스턴트의 토큰 사용량, 비용, API 지연 시간 (latency), 에러율 및 세션 활동을 하나의 통합된 대시보드에서 추적하세요.
AI 코딩 어시스턴트는 필수적인 개발 도구가 되고 있지만, 그 동작 방식과 비용을 이해하는 것은 여전히 과제로 남아 있습니다:
가시성 (Visibility): 세션 전반에 걸쳐 AI 도구가 어떻게 작동하는지 정확히 확인
비용 추적 (Cost tracking): 토큰 사용량과 API 호출을 모니터링하여 지출 파악
디버깅 (Debugging): 에러 및 느린 응답을 특정 상호작용으로 추적
개인정보 보호 (Privacy): 텔레메트리 (telemetry) 데이터를 로컬에 유지 — 제3자 서비스가 필요 없음
멀티 도구 지원 (Multi-tool support) — Claude Code, Gemini CLI, OpenAI Codex CLI와 연동 가능
실시간 대시보드 (Real-time dashboard) — 텔레메트리가 도착함에 따라 WebSocket을 통해 라이브 업데이트 제공
커스터마이징 가능한 위젯 (Customizable widgets) — 다양한 위젯 유형을 갖춘 드래그 앤 드롭 대시보드 빌더
이력 가져오기 (Historical import) — 비용 계산 기능과 함께 로컬 JSONL/JSON 파일에서 과거 세션 가져오기
비용 추적 (Cost tracking) — Claude, Codex, Gemini 전반에 걸친 67개 이상의 모델에 대한 내장 가격 데이터 포함
빠른 분석 (Fast analytics) — 대규모 데이터셋에 대한 즉각적인 쿼리를 위해 DuckDB 기반 저장소 사용
단일 바이너리 (Single binary) — 프론트엔드가 내장된 약 54MB의 실행 파일 하나로 구성 — 외부 의존성 없음
멀티 아키텍처 Docker (Multi-arch Docker) — linux/amd64 및 linux/arm64를 위한 즉시 실행 가능한 약 97MB 이미지
OTLP 네이티브 (OTLP-native) — 표준 OpenTelemetry 프로토콜 (OTLP) 수집 (HTTP/JSON 및 HTTP/Protobuf)
- Import 명령 — 로컬 AI 도구 파일에서 과거 세션 데이터 가져오기
- Export 명령 — 아카이빙 및 공유를 위해 텔레메트리 데이터를 Parquet 파일로 내보내기
- 가격 시스템 (Pricing System) — Claude, Codex 및 Gemini 모델에 대한 비용 계산
docker run -d \
-p 8080:8080 \
-p 4318:4318 \
...
대시보드: http://localhost:8080
데이터 영속성 (Data Persistence)을 위한 로컬 디렉토리 사용:
# 로컬 데이터 디렉토리 생성
mkdir -p ./ai-observer-data
# 로컬 볼륨 마운트와 함께 실행
...
이렇게 하면 DuckDB 데이터베이스가 로컬의 ./ai-observer-data 디렉토리에 저장되어, 백업하거나 검사하기가 용이해집니다.
brew tap tobilg/ai-observer
brew install ai-observer
ai-observer
Releases에서 사용 중인 플랫폼에 맞는 최신 릴리스를 다운로드한 후, 다음을 실행하세요:
./ai-observer
git clone https://github.com/tobilg/ai-observer.git
cd ai-observer
make setup # 의존성 설치
...
| 변수 (Variable) | 기본값 (Default) | 설명 (Description) |
|---|
AI_OBSERVER_API_PORT | 8080 | HTTP 서버 포트 (대시보드 + API) |
AI_OBSERVER_OTLP_PORT | 4318 | OTLP 수집 (Ingestion) 포트 |
AI_OBSERVER_DATABASE_PATH | ./data/ai-observer.duckdb (binary) 또는 /app/data/ai-observer.duckdb (Docker) | DuckDB 데이터베이스 파일 경로 |
AI_OBSERVER_FRONTEND_URL | http://localhost:5173 | 허용된 CORS 오리진 (개발 모드) |
AI_OBSERVER_LOG_LEVEL | INFO | 로그 레벨: DEBUG, INFO, WARN, ERROR |
CORS 및 WebSocket 오리진은 AI_OBSERVER_FRONTEND_URL과 더불어 http://localhost:5173 및 http://localhost:8080을 허용합니다. 커스텀 UI 오리진을 제공할 때는 AI_OBSERVER_FRONTEND_URL을 설정하세요.
ai-observer [command] [options]
명령어 (Commands):
| 명령어 (Command) | 설명 (Description) |
|---|
import | AI 도구 파일로부터 로컬 세션 가져오기 |
export | 텔레메트리 (Telemetry) 데이터를 Parquet 파일로 내보내기 |
delete | 데이터베이스에서 텔레메트리 데이터 삭제 |
setup | AI 도구들을 위한 설정 안내 표시 |
serve | OTLP 서버 시작 (명령어가 없을 경우 기본값) |
글로벌 옵션 (Global Options):
| 옵션 (Option) | 설명 (Description) |
|---|
-h, --help | 도움말 메시지를 표시하고 종료 |
-v, --version | 버전 정보를 표시하고 종료 |
예시 (Examples):
# 서버 시작 (기본값, 명령어 불필요)
ai-observer
# 버전 표시
...
로컬 AI 코딩 도구 파일로부터 과거 세션 데이터를 AI Observer로 가져옵니다.
ai-observer import [claude-code|codex|gemini|all] [options]
| 옵션 | 설명 |
|---|
--from DATE | DATE (YYYY-MM-DD) 이후의 세션만 가져옵니다 |
--to DATE | DATE (YYYY-MM-DD) 이전의 세션만 가져옵니다 |
--force | 이미 가져온 파일들을 다시 가져옵니다 |
--dry-run | 변경 사항을 적용하지 않고 무엇이 가져와질지 보여줍니다 |
--skip-confirm | 확인 프롬프트를 건너뜁니다 |
--purge | 가져오기 전에 해당 기간 내의 기존 데이터를 삭제합니다 |
--pricing-mode MODE | Claude를 위한 비용 계산 모드: auto (기본값), calculate, display |
--verbose | 상세한 진행 과정을 보여줍니다 |
파일 위치:
| 도구 | 기본 위치 |
|---|
| Claude Code | ~/.claude/projects/**/*.jsonl |
| ... | |
환경 변수로 재정의할 수 있습니다: AI_OBSERVER_CLAUDE_PATH, AI_OBSERVER_CODEX_PATH, AI_OBSERVER_GEMINI_PATH | |
예시:
# 모든 도구로부터 가져오기
ai-observer import all
# 특정 날짜 범위에서 Claude 데이터 가져오기
...
상세한 문서는 docs/import.md를, 비용 계산에 대한 자세한 내용은 docs/pricing.md를 참조하세요.
텔레메트리 (Telemetry) 데이터를 선택 사항인 DuckDB 뷰 (Views) 데이터베이스가 포함된 휴대 가능한 Parquet 파일로 내보냅니다.
ai-observer export [claude-code|codex|gemini|all] --output <directory> [options]
| 옵션 | 설명 |
|---|
--output DIR | 출력 디렉토리 (필수) |
--from DATE | 시작 날짜 필터 (YYYY-MM-DD) |
--to DATE | 종료 날짜 필터 (YYYY-MM-DD) |
--from-files | 데이터베이스 대신 원시 JSON/JSONL 파일에서 읽어옵니다 |
--zip | 내보낸 파일들을 하나의 ZIP 아카이브로 생성합니다 |
--dry-run | 무엇이 내보내질지 미리 보여줍니다 |
--verbose | 상세한 진행 과정을 보여줍니다 |
--yes | 확인 프롬프트를 건너뜁니다 |
출력 파일:
traces.parquet — 모든 트레이스 (Trace)/스팬 (Span) 데이터
logs.parquet — 모든 로그 (Log) 레코드
metrics.parquet — 모든 메트릭 (Metric) 데이터 포인트
ai-observer-export-{SOURCE}-{RANGE}.duckdb — 상대 경로가 포함된 뷰 (Views) 데이터베이스
예시:
# 데이터베이스에서 모든 데이터 내보내기
ai-observer export all --output ./export
# 날짜 필터를 사용하여 Claude 데이터 내보내기
...
상세한 문서는 docs/export.md를 참조하세요.
시간 범위를 지정하여 데이터베이스에서 텔레메트리 (Telemetry) 데이터를 삭제합니다.
ai-observer delete [logs|metrics|traces|all] --from DATE --to DATE [options]
| 옵션 | 설명 |
|---|
--from DATE | 시작 날짜 (YYYY-MM-DD, 필수) |
--to DATE | 종료 날짜 (YYYY-MM-DD, 필수) |
--service NAME | 특정 서비스의 데이터만 삭제 |
--yes | 확인 프롬프트 건너뛰기 |
예시:
# 지정된 날짜 범위 내의 모든 데이터 삭제
ai-observer delete all --from 2025-01-01 --to 2025-01-31
# 지정된 날짜 범위 내의 로그만 삭제
...
Claude Code
다음 환경 변수 (Environment Variables)를 설정하세요:
# 텔레메트리 활성화 (필수)
export CLAUDE_CODE_ENABLE_TELEMETRY=1
# 익스포터 (Exporters) 설정
...
세션 간에 설정을 유지하려면 이를 ~/.bashrc, ~/.zshrc 또는 셸 프로필 (Shell Profile)에 추가하세요.
설정 후 Claude Code는 메트릭 (Metrics)과 이벤트 (Events)를 AI Observer로 자동 전송합니다.
Gemini CLI
OTLP 발행과 관련된 버그가 이전 모든 버전에서 발생했으므로, 최소 v0.34.0 버전 이상의 Gemini CLI를 사용 중이라고 가정합니다.
~/.gemini/settings.json에 다음을 추가하세요:
{
"telemetry": {
"enabled": true,
...
필수 환경 변수 (Gemini CLI의 타이밍 이슈에 대한 해결책):
export OTEL_METRIC_EXPORT_TIMEOUT=10000
export OTEL_LOGS_EXPORT_TIMEOUT=5000
OpenAI Codex CLI
~/.codex/config.toml에 다음을 추가하세요:
[otel]
log_user_prompt = true
exporter = { otlp-http = { endpoint = "http://localhost:4318/v1/logs", protocol = "binary" } }
...
참고: Codex CLI는 로그 (Logs)와 트레이스 (Traces)를 내보내지만, 메트릭 (Metrics)은 내보내지 않습니다. trace_exporter 옵션은 문서화되어 있지는 않지만 사용 가능하며, 생략할 경우 트레이스는 로그와 동일한 엔드포인트 (Endpoint)로 전송됩니다.
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Claude Code │ │ Gemini CLI │ │ Codex CLI │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
...
기술 스택 (Tech Stack):
백엔드 (Backend): Go 1.24+, chi router, DuckDB, gorilla/websocket
프론트엔드 (Frontend): React 19, TypeScript, Vite, Tailwind CSS v4, Zustand, Recharts
AI Observer는 두 개의 HTTP 서버를 노출합니다:
텔레메트리 (Telemetry) 데이터를 수신하기 위한 표준 OpenTelemetry Protocol (OTLP) 엔드포인트.
- 전송 방식은 HTTP/1.1 + h2c입니다 (gRPC 리스너는 노출되지 않음).
- 압축된 페이로드 (Payload)를 위해
Content-Encoding: gzip을 지원합니다.
| 메서드 (Method) | 엔드포인트 (Endpoint) | 설명 |
|---|
POST | /v1/traces | 트레이스 스팬 (Trace spans) 수집 (protobuf 또는 JSON) |
POST | /v1/metrics | 메트릭 (Metrics) 수집 (protobuf 또는 JSON) |
POST | /v1/logs | 로그 (Logs) 수집 (protobuf 또는 JSON) |
GET | /health | 상태 확인 (Health check) |
저장된 텔레메트리 데이터를 쿼리하기 위한 REST API. 별도로 지정하지 않는 한, from 및 to는 기본적으로 지난 24시간으로 설정됩니다.
트레이스 (Traces)
| 메서드 (Method) | 엔드포인트 (Endpoint) | 설명 |
|---|
GET | /api/traces | 필터링 및 페이지네이션 (Pagination)을 포함한 트레이스 목록 조회 |
GET | /api/traces/recent | 가장 최근의 트레이스 조회 |
GET | /api/traces/{traceId} | 특정 트레이스 조회 |
GET | /api/traces/{traceId}/spans | 특정 트레이스의 모든 스팬 (Spans) 조회 |
/api/traces를 위한 쿼리 파라미터 (Query parameters):
service — 서비스 이름으로 필터링
search — 전체 텍스트 검색
from, to — 시간 범위 (ISO 8601)
limit, offset — 페이지네이션
메트릭 (Metrics)
| 메서드 (Method) | 엔드포인트 (Endpoint) | 설명 |
|---|
GET | /api/metrics | 필터링을 포함한 메트릭 목록 조회 |
GET | /api/metrics/names | 모든 메트릭 이름 목록 조회 |
GET | /api/metrics/series | 메트릭에 대한 시계열 (Time series) 데이터 조회 |
POST | /api/metrics/batch-series | 한 번의 요청으로 여러 시계열 데이터 조회 |
/api/metrics/series를 위한 쿼리 파라미터 (Query parameters):
name — 메트릭 이름 (필수)
service — 서비스로 필터링
from, to — 시간 범위 (ISO 8601)
interval — 집계 간격 (예: 1 minute, 1 hour)
aggregate — 모든 시계열을 하나로 집계 (기본값: false)
배치 시계열 (Batch series) (POST /api/metrics/batch-series) 요청 본문 (Request body):
- 각 쿼리는
id와 name이 필요하며, service, aggregate, interval은 선택 사항입니다.
- 요청당 최대 50개의 쿼리가 가능합니다.
- 본문의
from/to 역시 생략될 경우 기본적으로 지난 24시간으로 설정됩니다.
로그 (Logs)
| 메서드 (Method) | 엔드포인트 (Endpoint) | 설명 |
|---|
GET | /api/logs | 필터링 및 페이지네이션 (Pagination)을 포함한 로그 목록 조회 |
GET | /api/logs/levels | 심각도 레벨 (Severity level)별 로그 수 조회 |
/api/logs를 위한 쿼리 파라미터 (Query parameters):
service
— 서비스 이름으로 필터링
severity
— 심각도로 필터링 (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)
traceId
— 특정 트레이스 (Trace)와 연결된 로그 필터링
search
— 전체 텍스트 검색 (Full-text search)
from , to
— 시간 범위 (ISO 8601)
limit , offset
— 페이지네이션 (Pagination)
대시보드 (Dashboards)
| 메서드 (Method) | 엔드포인트 (Endpoint) | 설명 |
|---|
GET | /api/dashboards | 모든 대시보드 목록 조회 |
POST | /api/dashboards | 새 대시보드 생성 |
GET | /api/dashboards/default | 위젯 (Widgets)이 포함된 기본 대시보드 조회 |
GET | /api/dashboards/{id} | ID로 대시보드 조회 |
PUT | /api/dashboards/{id} | 대시보드 업데이트 |
DELETE | /api/dashboards/{id} | 대시보드 삭제 |
PUT | /api/dashboards/{id}/default | 기본 대시보드로 설정 |
POST | /api/dashboards/{id}/widgets | 위젯 추가 |
PUT | /api/dashboards/{id}/widgets/positions | 위젯 위치 업데이트 |
PUT | /api/dashboards/{id}/widgets/{widgetId} | 위젯 업데이트 |
DELETE | /api/dashboards/{id}/widgets/{widgetId} | 위젯 삭제 |
기타 (Other)
| 메서드 (Method) | 엔드포인트 (Endpoint) | 설명 |
|---|
GET | /api/services | 텔레메트리 (Telemetry)를 전송하는 모든 서비스 목록 조회 |
GET | /api/stats | 집계 통계 (Aggregate statistics) 조회 |
GET | /ws | 실시간 업데이트를 위한 웹소켓 (WebSocket) |
GET | /health | 상태 확인 (Health check) |
AI Observer는 표준 OpenTelemetry 데이터를 수신합니다:
| 시그널 (Signal) | 설명 | 데이터 예시 |
|---|
| 트레이스 (Traces) | 분산 트레이싱 스팬 (Distributed tracing spans) | API 호출, 도구 실행, 세션 타임라인 |
| 메트릭 (Metrics) | 수치 측정값 | 토큰 수, 지연 시간 히스토그램 (Latency histograms), 요청률 |
| 로그 (Logs) | 구조화된 로그 레코드 | 에러, 프롬프트 (활성화된 경우), 시스템 이벤트 |
모든 데이터는 DuckDB에 로컬로 저장됩니다. 외부 서비스로 전송되는 것은 아무것도 없습니다.
각 AI 코딩 도구는 서로 다른 텔레메트리 (Telemetry) 신호를 내보냅니다. 관찰할 수 있는 항목은 다음과 같습니다:
Claude Code 메트릭 (Metrics) 및 이벤트 (Events)