OpenTelemetry v1
OpenTelemetry v1
OpenTelemetry는 CNCF(Cloud Native Computing Foundation)의 관측성(observability) 표준이에요. Jaeger, Zipkin, Datadog, New Relic, Traceloop, Levo AI 등 어떤 관측성 도구와도 연결할 수 있어요.

전체 요청 추적을 찾고 계신가요?
LiteLLM Proxy에는 더 새롭고 선택(opt-in) 방식의 OpenTelemetry v2 통합이 있어요. 요청 하나당 하나의 추적(HTTP → 인증(auth) → 가드레일(guardrails) → LLM 호출 → DB 쓰기)을 만들어 내고, 공식 GenAI 시맨틱 컨벤션을 따르며, Arize·Phoenix·Langfuse·Weave 등을 위한 프리셋이 포함돼 있어요. LITELLM_OTEL_V2=true로 활성화할 수 있어요. 자세한 내용은 OpenTelemetry v2 문서를 참고해 주세요.
v1.81.0 변경 사항
v1.81.0부터 요청/응답이 기본적으로 부모 스팬 Received Proxy Server Request에 속성(attribute)으로 설정되고, 별도의 litellm_request 스팬은 옵트 인하지 않는 한 만들어지지 않아요. 중첩된 litellm_request 스팬을 복원하려면 USE_OTEL_LITELLM_REQUEST_SPAN=true를 설정하면 돼요. 전체 구조는 Span 계층 구조를, 언제 플래그를 바꿔야 하는지는 왜 litellm_request 스팬이 안 보이나요를 참고해 주세요.
출처: 문서
본문
시작하기 (Getting Started)
OpenTelemetry SDK를 설치해요.
uv add opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp
환경 변수를 설정해요 (프로바이더마다 필요한 변수가 달라요).
Traceloop Cloud에 로그
OTEL_EXPORTER="otlp_http"
OTEL_ENDPOINT="https://api.traceloop.com"
OTEL_HEADERS="Authorization=Bearer%20<your-api-key>"
OTEL HTTP Collector에 로그
OTEL_EXPORTER_OTLP_ENDPOINT="http://0.0.0.0:4318"
OTEL_EXPORTER_OTLP_PROTOCOL=http/json
OTEL_EXPORTER_OTLP_HEADERS="api-key=key,other-config-value=value"
OTEL GRPC Collector에 로그
참고: OTLP gRPC는 grpcio가 필요해요. uv add "litellm[grpc]"(또는 grpcio)로 설치해요.
OTEL_EXPORTER_OTLP_ENDPOINT="http://0.0.0.0:4318"
OTEL_EXPORTER_OTLP_PROTOCOL=grpc
OTEL_EXPORTER_OTLP_HEADERS="api-key=key,other-config-value=value"
Laminar에 로그
참고: OTLP gRPC는 grpcio가 필요해요. uv add "litellm[grpc]"(또는 grpcio)로 설치해요.
OTEL_EXPORTER="otlp_grpc"
OTEL_ENDPOINT="https://api.lmnr.ai:8443"
OTEL_HEADERS="authorization=Bearer <project-api-key>"
Splunk Observability Cloud
OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.<realm>.observability.splunkcloud.com/v2/trace/otlp"
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_HEADERS="X-SF-Token=<your-ingest-access-token>"
OTEL_SERVICE_NAME="litellm-proxy"
LiteLLM Proxy 설정, 인제스트 토큰 패턴, 추적 검증에 대해서는 Splunk Observability Cloud (OpenTelemetry) 문서를 참고해 주세요.
SDK에서 한 줄만으로 모든 프로바이더의 LLM 응답을 OpenTelemetry로 기록할 수 있어요.
litellm.callbacks = ["otel"]
Span 계층 구조 (Span Hierarchy)
LiteLLM Proxy가 처리하는 모든 LLM 요청은 Received Proxy Server Request를 루트로 하는 스팬 트리를 만들어 내요. 아래의 조건부 스팬들은 제어 플래그가 설정되었거나 해당 기능이 사용될 때만 생성됩니다.
Received Proxy Server Request (SpanKind.SERVER, root)
│
├── litellm_request (INTERNAL, only when USE_OTEL_LITELLM_REQUEST_SPAN=true)
│ ├── raw_gen_ai_request (INTERNAL — provider request/response, content-capture-gated)
│ └── guardrail (INTERNAL — one per executed guardrail)
│
├── raw_gen_ai_request (INTERNAL — when litellm_request is collapsed into the root)
├── guardrail (INTERNAL — when litellm_request is collapsed into the root)
│
├── auth, router, self, proxy_pre_call, (INTERNAL — service-hook spans, see below)
│ redis, postgres, batch_write_to_db
│
└── Failed Proxy Server Request (INTERNAL — only on exception)
semconv 모드(OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental)에서는 LLM 호출 스팬이 생성될 때 이름이 {operation} {model}(예: chat gpt-5.6-terra)이 되고 SpanKind.CLIENT가 되며, raw_gen_ai_request는 억제됩니다. 스팬이 생성될지 여부는 동일한 USE_OTEL_LITELLM_REQUEST_SPAN 게이팅으로 결정돼요. 자세한 내용은 최신 GenAI 시맨틱 컨벤션 옵트 인을 참고하세요.
SDK(프록시 없이) 사용 시 부모 컨텍스트가 없으면 litellm_request가 루트가 되고, 순수 SDK 사용에서는 Received Proxy Server Request 스팬이 생성되지 않아요.
Span 이름 참조 (Span name reference)
| Span | Kind | 생성 조건 / 비고 |
|---|---|---|
Received Proxy Server Request |
SERVER |
루트. traceparent 컨텍스트와 연계 |
litellm_request |
INTERNAL |
USE_OTEL_LITELLM_REQUEST_SPAN=true 일 때 |
{operation} {model} (예: litellm.completion) |
INTERNAL/실제 |
LLM 호출 스팬 |
raw_gen_ai_request |
INTERNAL |
litellm_request 하위 또는 루트에 병합 |
llm.{provider}.* |
인프라 | 프로바이더 호출 |
guardrail |
INTERNAL |
실행된 가드레일마다 하나 |
Failed Proxy Server Request |
INTERNAL |
예외 발생 시에만 |
{route} (/user/info, /key/info) |
INTERNAL |
라우트별 |
auth, router, self, proxy_pre_call, redis, postgres, batch_write_to_db, reset_budget_job, pod_lock_manager |
INTERNAL |
인프라 스팬 |
서비스 훅 스팬 (Service-hook spans, 일명 인프라 스팬)
async_service_success_hook, async_service_failure_hook이 방출하는 ServiceTypes에는 auth, router, self, proxy_pre_call, redis, postgres 등이 있고, 타입 정의는 litellm/types/services.py에 있어요. 예를 들어 self는 make_openai_chat_completion_request, router는 async_get_available_deployment, acompletion 같은 작업(call_type)과 "router", "redis" 같은 서비스 이름으로 식별됩니다.
litellm_request 스팬 제어
기본값(USE_OTEL_LITELLM_REQUEST_SPAN=false)에서는 요청/응답 관련 gen_ai.* 속성과 name이 루트 Received Proxy Server Request에 직접 부착돼요. USE_OTEL_LITELLM_REQUEST_SPAN=true로 설정하면 litellm.completion 같은 litellm_request 스팬과 그 하위 raw_gen_ai_request, guardrail 스팬이 다시 생성됩니다.
추적할 때 부모 SpanId를 litellm_request가 아닌 루트 Received Proxy Server Request에 맞추고 싶다면 metadata.litellm_parent_otel_span에 traceparent를 넣어 위임할 수도 있어요. OTEL_IGNORE_CONTEXT_PROPAGATION=true를 설정하면 TraceContextTextMapPropagator 기반 컨텍스트 전파를 무시할 수 있어요.
여러 OpenTelemetry 핸들러 실행하기 (Running Multiple OpenTelemetry Handlers)
핸들러를 여러 개 실행하려면 기본값 외 핸들러에 skip_set_global=True를 지정해 자체 TracerProvider, MeterProvider, LoggerProvider를 갖게 해요.
import litellm
from litellm.integrations.opentelemetry import OpenTelemetry, OpenTelemetryConfig
# Primary handler. Claims the global TracerProvider.
primary = OpenTelemetry(config=OpenTelemetryConfig(
exporter="otlp_http",
endpoint="https://your-collector/v1/traces",
))
# Secondary handler. Has its own private providers.
secondary = OpenTelemetry(config=OpenTelemetryConfig(
exporter="otlp_http",
endpoint="https://second-collector/v1/traces",
skip_set_global=True,
))
litellm.callbacks = [primary, secondary]
크로스 콜렉터 동작 (예: Langsmith + 일반 OTEL)
otel 콜백은 traceparent를 통해 부모 스팬(Received Proxy Server Request)과 연결돼요. skip_set_global=True로 둔 핸들러도 trace_id는 공유되지만 litellm_request, raw_gen_ai_request, guardrail 스팬의 소유권은 나눠 가질 수 있어요.
메시지 콘텐츠 캡처 (Capturing Message Content)
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT 환경 변수로 콘텐츠 캡처 정책을 정할 수 있어요.
# Do not capture message content
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=NO_CONTENT
# Capture content on span attributes only
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=SPAN_ONLY
# Capture content on event attributes only
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=EVENT_ONLY
# Capture content on both spans and events
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=SPAN_AND_EVENT
기본값은 콘텐츠를 캡처하는 true/EVENT_ONLY이고, false는 NO_CONTENT와 같아요.
핸들러별 콘텐츠 정책 (Per-handler content policy)
OpenTelemetryConfig.capture_message_content로 핸들러마다 정책을 다르게 둘 수 있어요.
import litellm
from litellm.integrations.opentelemetry import OpenTelemetry, OpenTelemetryConfig
stripped = OpenTelemetry(config=OpenTelemetryConfig(
exporter="otlp_http",
endpoint="https://compliance-collector/v1/traces",
capture_message_content="NO_CONTENT",
))
verbose = OpenTelemetry(config=OpenTelemetryConfig(
exporter="otlp_http",
endpoint="https://debug-collector/v1/traces",
capture_message_content="SPAN_AND_EVENT",
skip_set_global=True,
))
litellm.callbacks = [stripped, verbose]
전역으로 litellm.turn_off_message_logging=True를 켜면 모든 캡처가 꺼지고, 이때는 OpenTelemetryConfig.capture_message_content/OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT가 NO_CONTENT를 우선합니다. message_logging이 True이면 SPAN_AND_EVENT로 간주돼요.
최신 GenAI 시맨틱 컨벤션 옵트 인 (Opt-In to Latest GenAI Semantic Conventions)
OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental을 설정하면 OpenTelemetry GenAI 스팬 시맨틱 컨벤션을 따르는 스팬 형태로 전환돼요. 이 모드에서는 raw_gen_ai_request가 억제되고, gen_ai.provider.name, gen_ai.system, gen_ai.client.inference.operation.details 등이 사용돼요. OpenTelemetryConfig.semconv_stability로도 설정할 수 있어요.
OpenTelemetry 로그에서 메시지·응답 콘텐츠 숨기기 (Redacting Messages/Response)
모든 OpenTelemetry 로그에서 숨기기
litellm.turn_off_message_logging=True
특정 OpenTelemetry 로그에서 숨기기
# 예: mask_input / mask_output / update_trace_keys 사용
mask_input=True, mask_output=True를 설정하고 update_trace_keys에 input, output을 지정하면 콘텐츠를 마스킹할 수 있어요.
문제 해결 (Troubleshooting)
litellm_request스팬이 안 보여요: v1.81.0부터 기본값은USE_OTEL_LITELLM_REQUEST_SPAN=false여서litellm_request가 루트에 병합돼요. 중첩 스팬을 원하면USE_OTEL_LITELLM_REQUEST_SPAN=true를 설정해요. semconv 모드에서는 이름이{operation} {model}(예:chat gpt-5.6-terra)가 되고gen_ai.system등의 속성이 붙어요.- 인프라 스팬이 안 보여요:
router,auth,redis,proxy_pre_call,raw_gen_ai_request,guardrail스팬은litellm_request가 루트에 병합될 때 억제될 수 있어요. 콜백이litellm.callbacks또는litellm_settings.callbacks의"otel"로 등록되어 있는지,/chat/completions(모델 요청)나/key/info,/user/info(메타데이터)에서gen_ai.*속성이 확인되는지 점검해 보세요. - 콘텐츠가 기록되길 원치 않아요:
litellm.turn_off_message_logging=true또는mask_input/mask_output을 사용해요. - 실패 요청에 user/key/org/team 정보를 추적하고 싶어요:
metadata.user_api_key_*속성을 확인해요. 디버그 추적 예시는 otel_debug_trace 이미지를 참고해 주세요.
추적이 통합에 안 보이는 경우 (Not Seeing Traces Land on Integration)
디버그 로깅을 켜요.
export OTEL_DEBUG="True"
OTEL_EXPORTER_OTLP_ENDPOINT의 프로토콜이 grpc인지 http인지, OTEL_HEADERS가 올바른지 확인해요. gRPC를 쓴다면 grpcio가 설치되어 있는지 확인해요(없으면 uv add "litellm[grpc]").
Span이 잘리거나 버려지는 경우 (Spans Getting Truncated/Dropped)
gen_ai.input.messages, gen_ai.output.messages가 너무 커서 잘릴 수 있어요. litellm.turn_off_message_logging=true로 콘텐츠를 끄거나, metadata.cold_storage_object_key를 쓰거나, max_attribute_value_length, max_recv_msg_size_mib를 조정해요.
메트릭 속성 카디널리티 제어 (Control Metric Attribute Cardinality)
gen_ai.client.*, hidden_params, metadata.* 같은 고카디널리티 속성이 메트릭 태그를 과도하게 만들 수 있어요. callback_settings.otel.attributes의 include_list/exclude_list로 제어할 수 있어요.
고카디널리티 속성 버리기 (exclude_list)
litellm_settings:
callbacks: ["otel"]
callback_settings:
otel:
attributes:
exclude_list:
- hidden_params
- metadata.requester_metadata
- metadata.requester_ip_address
- metadata.spend_logs_metadata
- metadata.mcp_tool_call_metadata
- metadata.vector_store_request_metadata
- metadata.prompt_management_metadata
명시적 집합만 내보내기 (include_list)
litellm_settings:
callbacks: ["otel"]
callback_settings:
otel:
attributes:
include_list:
- gen_ai.operation.name
- gen_ai.system
- gen_ai.request.model
- gen_ai.framework
- metadata.user_api_key_team_id
- metadata.user_api_key_org_id
유효한 속성 이름 (Valid Attribute Names)
반드시 gen_ai.*, hidden_params, metadata.* 중 하나여야 해요. 예: gen_ai.operation.name, gen_ai.system, gen_ai.request.model, gen_ai.framework, hidden_params, metadata.user_api_key_hash, metadata.user_api_key_alias, metadata.user_api_key_team_id, metadata.user_api_key_org_id, metadata.user_api_key_user_id, metadata.user_api_key_team_alias, metadata.user_api_key_user_email, metadata.user_api_key_end_user_id, metadata.spend_logs_metadata, metadata.requester_ip_address, metadata.requester_metadata, metadata.prompt_management_metadata, metadata.applied_guardrails, metadata.mcp_tool_call_metadata, metadata.vector_store_request_metadata.
설정 참조 (Configuration Reference)
Exporter & Resource
| 변수 | 기본값 | 설명 |
|---|---|---|
OTEL_EXPORTER / OTEL_EXPORTER_OTLP_PROTOCOL |
console |
console, otlp_http, otlp_grpc; 프로토콜은 http/json, http/protobuf, grpc |
OTEL_ENDPOINT / OTEL_EXPORTER_OTLP_ENDPOINT |
— | OTEL 수집 엔드포인트 |
OTEL_HEADERS / OTEL_EXPORTER_OTLP_HEADERS |
— | key=value,key2=value2 형식의 헤더 |
OTEL_SERVICE_NAME |
litellm |
service.name 리소스 속성 |
OTEL_ENVIRONMENT_NAME |
production |
deployment.environment |
OTEL_MODEL_ID |
OTEL_SERVICE_NAME |
model_id 리소스 속성 |
OTEL_TRACER_NAME / LITELLM_METER_NAME / LITELLM_LOGGER_NAME |
litellm |
트레이서·미터·로거 이름 |
OTEL_LOGS_EXPORTER |
console |
console, otlp_http |
SSL_CERT_FILE / litellm_settings.ssl_verify |
false |
TLS 인증서 설정 |
OTEL_EXPORTER_OTLP_CERTIFICATE |
— | gRPC용 인증서 |
Span·Metric·Event 토글
| 변수 | 기본값 | 설명 |
|---|---|---|
USE_OTEL_LITELLM_REQUEST_SPAN |
false |
중첩 litellm_request 스팬 생성 여부 |
OTEL_SEMCONV_STABILITY_OPT_IN |
— | gen_ai_latest_experimental로 최신 GenAI 컨벤션 활성화 |
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT |
message_logging(True → SPAN_AND_EVENT) |
NO_CONTENT, SPAN_ONLY, EVENT_ONLY, SPAN_AND_EVENT |
LITELLM_OTEL_INTEGRATION_ENABLE_METRICS |
false |
메트릭 활성화 (gen_ai.content.prompt, gen_ai.content.completion, gen_ai.client.inference.operation.details 등) |
LITELLM_OTEL_INTEGRATION_ENABLE_EVENTS |
false |
이벤트 활성화 |
OTEL_IGNORE_CONTEXT_PROPAGATION |
false |
traceparent 컨텍스트 전파 무시 |
OTEL_DEBUG / DEBUG_OTEL |
false |
디버그 로깅 |
litellm.turn_off_message_logging / litellm_settings.turn_off_message_logging |
false |
콘텐츠 로깅 끄기 (llm.{provider}.*, gen_ai.input.messages, gen_ai.output.messages, gen_ai.content.* 영향) |
capture_message_content 관련 메타데이터는 metadata 아래에서 확인할 수 있어요.