Claude Code 사용량·성능 모니터링
Claude Code 사용량·성능 모니터링 (OpenTelemetry)
Claude Code 세션이 OpenTelemetry 표준으로 내보내는 메트릭·추적·로그를 활용해 사용량과 성능을 모니터링하는 방법을 다루는 페이지입니다. 데이터는 OTLP(HTTP/gRPC), Prometheus, 콘솔로 내보낼 수 있습니다. 텔레메트리는 기본 꺼져 있으며, CLAUDE_CODE_ENABLE_TELEMETRY=1로 켭니다. 이렇게 수집한 데이터를 멀티팀 조직에서 팀별·비용센터별로 집계할 수도 있습니다.
출처: 공식문서
본문
개요
텔레메트리는 세션 중 발생하는 요청·내부 이벤트·하드웨어 사용률 데이터를 수집해 내보냅니다. 스키마의 비안정(beta) 필드는 세부 구성 요소 이름이 바뀔 수 있습니다. 데이터는 네 가지 신호로 나뉩니다:
- Metrics (카운터·게이지): 호출 로그 기반 카운터와 상시 측정 게이지
- Traces + Spans: 전체 세션 트레이스와 그 안의 span
- Logs: 특정 이벤트와 리소스 사용률 로그
내보낼 수 있는 것
| 신호 | 지표 | 내보내기 | 세부 정보 |
|---|---|---|---|
| Metrics | claude_code.session.active (게이지) |
OTLP, Prometheus, 콘솔, 파일 | 항상 캡처 |
| Metrics | claude_code.session.count (카운터) |
OTLP, Prometheus, 콘솔, 파일 | 항상 캡처 |
| Logs/Events | 요청 & 내부 이벤트 | OTLP 로그 (otel), 콘솔 |
A·D 베타 클래스만, 명시적 옵트인 |
| Traces + Spans | 세션 & 완료된 요청 | OTLP 트레이스 | 베타, 명시적 옵트인 |
기본 꺼짐: 모든 내보내기는 CLAUDE_CODE_ENABLE_TELEMETRY=1이 필요한 옵트인입니다. 로그 스키마는 아직 불안정하여 기본 로깅은 필터링됩니다.
시작하기 (Quick start)
로그로 텔레메트리를 켜고 확인하는 가장 빠른 경로:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_LOGS_EXPORTER=console
claude
claude -p "hello"
claude가 켜지면 콘솔 로그로 내보냅니다. claude -p "hello" 같은 일회성 세션은 명령이 끝나면 정리되므로 로그가 아예 안 나올 수 있습니다 — 세션을 켜둔 채 몇 초간 /status로 확인하세요.
조직에서 시그널 → 엔드포인트(Otel Collector 등) → 백엔드(Jaeger·Grafana Cloud·New Relic 등) 파이프라인이 흔히 쓰입니다. 외부 공급자는 OpenTelemetry Collector 또는 Langfuse의 @langfuse/vercel-ai SDK로 그릴 수 있습니다. 내부 개발은 Claude Code SDK languageModel 훅과 통합합니다.
[OTLP 엔드포인트 설정] 주 배출구인 OTLP는 환경변수 3개로 구성합니다. 기본값: OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318, OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 # 기본값
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf # 기본값
export OTEL_METRICS_EXPORTER=otlp
로그만으로 검증
무언가가 안 들어온다면 먼저 로그만 켭니다:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_LOGS_EXPORTER=console
claude
세션이 완료되면 콘솔에 이벤트가 나타납니다. 로그가 보이면 텔레메트리는 동작 중이라는 뜻 — 메트릭·추적이 안 보이는 것은 로그 스키마가 아닌 내보내기 구성 문제일 가능성이 높습니다.
OTLP gRPC 예시
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_TRACES_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
시그널별 내보내기
커스텀 백엔드 구성을 위해 시그널별 내보내기·엔드포인트를 설정할 수 있습니다. OTEL_TRACES_EXPORTER, OTEL_METRICS_EXPORTER, OTEL_LOGS_EXPORTER로 시그널별 exporter를, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT·OTEL_EXPORTER_OTLP_METRICS_ENDPOINT·OTEL_EXPORTER_OTLP_LOGS_ENDPOINT로 시그널별 엔드포인트를 지정합니다(메트릭·로그 기본값 http://localhost:4318/v1/metrics·/v1/logs, 트레이스 http://localhost:4318/v1/traces).
메트릭과 커스텀 속성
핵심 메트릭
| 메트릭 | 유형 | 설명 |
|---|---|---|
claude_code.session.active |
Gauge | 현재 활성 세션 수 (시작에서 종료까지) |
claude_code.session.count |
Counter | 새 세션 시작 수 |
커스텀 속성 (다중 팀)
OTEL_RESOURCE_ATTRIBUTES로 팀·부서·비용센터를 구분하는 사용자 지정 속성을 추가할 수 있습니다:
export OTEL_RESOURCE_ATTRIBUTES="department=engineering,team.id=platform,cost_center=eng-123"
이 속성은 모든 메트릭·이벤트 측정점에 포함되어 팀별 필터·비용센터별 비용 추적·팀별 대시보드·알림에 씁니다. 커스텀 키는 vcs.* 저장소 속성을 제외하면 user.id·session.id 같은 표준 속성을 덮어쓰지 않습니다(키가 겹치면 내장 값 유지). 커스텀 키가 모든 시리즈 라벨이 되므로 고카디널리티 값은 백엔드 저장 비용이 늘어납니다. 리소스 블록에만 보내고 측정점 라벨에서 빼려면 OTEL_METRICS_INCLUDE_RESOURCE_ATTRIBUTES=false.
⚠️
OTEL_RESOURCE_ATTRIBUTES는 쉼표 구분key=value쌍을 엄격히 요구합니다: 값에 공백 불가, US-ASCII만, 제어문자·공백·큰따옴표·쉼표·세미콜론·백슬래시 제외, 특수문자는 퍼센트 인코딩. 공백이 필요하면_나 camelCase 사용. 값 인용부호는 이스케이프하지 않습니다(org.name="My Company"는 따옴표까지 리터럴 값).
트레이스: 트레이스·스팬·이벤트
트레이스와 스팬
기본 트레이스에서 세션 시작~종료 Span, 각 세션당 요청 서브스팬(토큰 수.count·duration.ms 속성 포함)을 배출합니다. 베타 추적에서 claude.code.execution 등 추가 스팬이 나옵니다.
| 스팬 | 유형 | 설명 |
|---|---|---|
claude_code.session |
Root | 세션 전체 지속 시간 |
claude_code.request |
Child | 세션당 완료된 요청 (하나 이상) |
claude.code.execution (베타) |
Nested | 요청을 세분화한 하위 스팬 |
컨텍스트 속성
컨텍스트 속성은 에이전트 학습·대시보드·비교에 쓰입니다. 예: 프로젝트 메타데이터 claude_code.project.directory·claude_code.project.repository.name, 세션 메타데이터 claude_code.session.id·claude_code.session.mode·claude_code.session.optout(프라이버시 설정 적용 여부), 요청 메타데이터 claude_code.request.agent·claude_code.request.cost_estimate_min·claude_code.request.cost_estimate_max·claude_code.request.total_cost_usd(0=계산 안 되거나 무료 플랜)·claude_code.request.url_override, 모델 및 토큰 claude_code.request.model·claude_code.request.tokens.in·claude_code.request.tokens.out·claude_code.request.tokens.cache_write·claude_code.request.tokens.cache_read·claude_code.request.stop_reason.
스팬 속성 (베타)
베타 추적으로 배출되는 추가 속성(불안정 스키마): claude.code.event.context_management.ratio·.allowed_fraction, claude.code.request.duration, claude.code.request.stop_reason, claude.code.request.status, claude.code.request.tokens_in.total, claude.code.zoom.base_tokens, claude.code.zoom.actual_tokens. claude.code.message.usage.input_tokens·claude.code.message.usage.output_tokens·claude.code.message.usage.cache_creation_input_tokens·claude.code.message.usage.cache_read_input_tokens 등 사용량 스팬도 있습니다. 콘텐츠 포함 속성(new_context, system_prompt_preview, user_system_prompt, tool_input, response.model_output)은 상세 베타 추적 중에만 배출되며 안정 스키마가 아닙니다. user_system_prompt는 추가로 OTEL_LOG_USER_PROMPTS=1이 필요하고, SDK systemPrompt 옵션 또는 --system-prompt·--append-system-prompt 플래그로 준 시스템 프롬프트만 담으며(기본 60KB 제한), 세션당 한 번 배출됩니다.
동적 헤더
동적 인증이 필요한 엔터프라이즈 환경은 헤더를 생성하는 스크립트를 구성할 수 있습니다. 동적 헤더는 http/protobuf·http/json 프로토콜에만 적용되고, grpc는 정적 헤더 변수(OTEL_EXPORTER_OTLP_HEADERS 및 시그널별 변형)만 씁니다. .claude/settings.json에:
{
"otelHeadersHelper": "/path/to/generate-otel-headers.sh"
}
값은 실행 파일 경로(공백 포함 가능) 또는 인자가 있는 셸 명령줄. Windows는 항상 셸을 거치므로 JSON 값 안의 공백 경로를 인용하세요. 스크립트는 HTTP 헤더를 나타내는 문자열 key-value의 유효한 JSON을 출력해야 합니다:
#!/bin/bash
echo "{\"Authorization\": \"Bearer $(get-token.sh)\", \"X-API-Key\": \"$(get-api-key.sh)\"}"
실패하거나 형식이 맞지 않으면 /status 출력, --debug·/debug 시 디버그 로그, -p 비대화형 세션의 stderr에 보고됩니다. 헬퍼는 시작 시·주기적으로 실행돼(기본 29분 간격, CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS로 조정) 토큰 갱신을 지원합니다.
예시 구성
claude 실행 전에 환경변수를 설정하세요. 적용 확인은 세션 시작 후 백엔드에서 claude_code.session.count 메트릭을 봅니다.
1초 간격 콘솔 디버깅:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=console
export OTEL_METRIC_EXPORT_INTERVAL=1000
gRPC OTLP:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
Prometheus (http://localhost:9464/metrics 스크레이프):
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=prometheus
다중 exporter:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=console,otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/json
메트릭·로그를 서로 다른 엔드포인트로:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://metrics.example.com:4318
export OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://logs.example.com:4317
트레이스·스팬 활성화 (베타)
베타 추적을 켜려면 CLAUDE_CODE_ENABLE_TELEMETRY=1 위에 OTEL_TRACES_EXPORTER=otlp와 트레이스 엔드포인트를 설정합니다. 베타는 스키마 변경 가능성이 있으며, 대규모가 아닌 소규모 배포에 적합합니다. 구조: 루트 스팬 claude_code.session(세션 지속), 자식 claude_code.request(완료 요청), claude.code.execution 베타 하위 스팬(요청 세분화). 자세한 못지 않은 span 세부사항은 비안정 스키마입니다.
mTLS (베타)
OTLP 엔드포인트에 대한 상호 TLS(mTLS)를 베타로 지원합니다. .claude/settings.json에:
{
"otelMtlsClientCert": "/path/to/client.crt",
"otelMtlsClientKey": "/path/to/client.key",
"otelMtlsServerCert": "/path/to/server-ca.crt"
}
두 인증서(클라이언트 cert를 줄 때 클라이언트 key)는 함께 지정해야 합니다. 환경변수로도 설정 가능합니다: CLAUDE_CODE_OTEL_MTLS_CLIENT_CERT, CLAUDE_CODE_OTEL_MTLS_CLIENT_KEY, CLAUDE_CODE_OTEL_MTLS_SERVER_CERT. mTLS는 자동으로 특정 OTLP 내보내기에만 적용되며 설정을 쓰려면 재시작이 필요할 수 있습니다. 클라이언트 인증서는 시스템 인증서 저장소에서 로드됩니다.
이벤트 (로그 / 베타)
상세 로깅은 베타이며 명시적 옵트인이 필요합니다. A 클래스(OBSERVABILITY_ENABLED_MS·OBSERVABILITY_PROMPT·CLAUDE_CODE_ENABLE_DEBUG_OUTPUT·클래스 A 로그를 허용하는 --verbose)와 D 클래스(앱 로그, --debug)만 로그 스키마로 우선 배출됩니다. 로그 기반 추적 지표는 호출 로그에서 파생됩니다. 기본 오픈텔레메트리 로그 스키마를 넘어 일반 로그를 위해선 OTEL_LOGS_EXPORTER 구성과 베타 옵션이 필요합니다.
저장소 속성
vcs.* 속성이 저장소 메타데이터를 운반합니다. 일부는 OTLP 리소스 블록에서만 나오고, 일부는 user.id·session.id처럼 리소스 및 데이터포인트/이벤트 속성으로 나옵니다. 각 저장소 이름은 리포지토리 원격 URL에서 파생됩니다. 사용자 지정 속성과 달리 vcs.* 속성은 여러 저장소를 동시에 작업할 때 데이터 포인트마다 값이 달라, 신중하게 사용해 카디널리티를 피하세요.
알려진 제한 사항
Konfig 시그널은 그리기 어려울 수 있고, 선택한 사용자 지정 속성은 리소스 블록으로 그룹화되며 청구·지출 요약에 포함되지 않을 수 있습니다.