OpenTelemetry
OpenTelemetry
Confident AI의 OTEL 서버가 트레이스를 어떻게 수집하는지, 그리고 그것이 이해하는 gen_ai, confident, OpenInference, OpenLLMetry 관례를 알아봐요.
OpenTelemetry(OTEL)은 트레이스, 메트릭, 로그를 위한 오픈·벤더 중립 표준이에요. Confident AI의 LLM 트레이싱은 OpenTelemetry 네이티브예요: confident-trace, 서드파티 인스트루먼터, 또는 원시 OpenTelemetry SDK 어디서 왔든 모든 트레이스가 OTLP로 도착해요.
출처: 문서
본문
개요
Confident AI의 OpenTelemetry 서버(OTEL 서버)는 모든 트레이싱 데이터의 OTLP/HTTP 수집 엔드포인트로, https://(eu.)otel.confident-ai.com에 호스팅돼요. 모든 스팬은 이 엔드포인트로 들어와요 — confident-trace SDK, 서드파티 통합, 클라우드 런타임, 또는 OpenTelemetry Collector 어디서 만들어졌든요.
OTEL 서버를
confident-trace와 혼동하지 마세요. 둘 다 OpenTelemetry 관례를 따르지만,confident-trace는 애플리케이션을 인스트루먼트하고(25개 이상 내장 통합) OTEL 서버 로 스팬을 내보내는 클라이언트예요. OTEL 서버는 수신자입니다.
OTEL 서버는 표준 OTLP를 받아들이므로 confident-trace가 필수는 아니에요. 하지만 Google ADK, Pydantic AI, AgentCore 같은 OTel 네이티브 프레임워크를 쓰더라도 confident-trace를 여전히 강력히 권장해요. 25개 이상의 AI 프로바이더, 프레임워크, 게이트웨이를 한 번에 네이티브로 통합하기 때문이에요.
OpenTelemetry 스팬을 이미 내보내는 무엇이든 그 exporter를 OTEL 서버로 지정하면 트레이스가 Confident AI에, 타입이 붙고 평가 준비된 채로 나타나요:
- 관리형 클라우드 런타임 — Amazon Bedrock AgentCore, Microsoft Foundry, Google Gemini Enterprise. 여기서는
OTEL_EXPORTER_OTLP_*환경 변수만 설정할 수 있어요- 기존 OpenTelemetry 인스트루먼터 — OpenInference, OpenLLMetry, Google ADK, 또는
gen_ai.*속성을 내보내는 어떤 프레임워크든- Confident AI SDK 없는 언어 — 수동 인스트루먼테이션을 통한 Go, Ruby, C#, Java, Rust
- 기존 관측성 파이프라인 — OpenTelemetry Collector에
otlphttpexporter 하나를 더 추가(trace broadcasting)이 소스들의 스팬은 모델, 토큰 사용량, 비용, 메시지가 채워진 LLM·tool·agent·retriever 스팬으로 렌더링되고,
confident-trace트레이스처럼 온라인 평가, 스레드, 트레이스 포워딩으로 흘러가요.
OTEL 서버
flowchart LR
subgraph App["Your application"]
direction TB
A[confident-trace<br/>25+ auto-instrumentations]
B[OpenInference / OpenLLMetry<br/>instrumentors]
C[Raw OpenTelemetry SDK<br/>Go, Ruby, C#, Java...]
D[Cloud runtime<br/>AgentCore, Foundry, Gemini Enterprise]
end
subgraph Export["Export (OTLP/HTTP)"]
direction TB
X[OTLP exporter<br/>in-process]
Y[OpenTelemetry Collector<br/>optional, fan-out to other backends]
end
A --> X
B --> X
C --> X
D --> X
X -.-> Y
X --> S
Y --> S
S[Confident AI OTEL server<br/>otel.confident-ai.com] --> O[Confident AI]
O --> E[Online evals]
O --> T[Trace forwarding]
스팬은 두 가지 방법 중 하나로 Confident AI에 도달해요:
- 프로세스에서 직접. SDK의 OTLP exporter(
confident-trace가 구성해 주는 것)가 스팬을 배치로 묶어x-confident-api-key헤더에 프로젝트 API 키를 실어 POST해요. - OpenTelemetry Collector를 통해. 서비스가 여러분이 운영하는 Collector로 내보내고, 그
otlphttpexporter가 다른 백엔드와 함께 Confident AI에 사본을 보내요. trace broadcasting을 보세요.
수신 시 Confident AI는 요청을 인증하고, 이해하는 모든 네임스페이스에서 속성을 읽고, OpenTelemetry trace_id와 부모 스팬 ID로 트레이스를 재구성해요. 따라서 서로 다른 서비스·언어의 스팬은 W3C 트레이스 컨텍스트만 공유하면 같은 트레이스에 들어가요 — 분산 트레이싱의 기반이죠.
리전과 엔드포인트
| Region | Base endpoint | Traces endpoint | API key prefix |
|---|---|---|---|
| US (default) | https://otel.confident-ai.com |
https://otel.confident-ai.com/v1/traces |
confident_us_ |
| EU | https://eu.otel.confident-ai.com |
https://eu.otel.confident-ai.com/v1/traces |
confident_eu_ |
| Self-hosted | Your own otel. host |
https://otel.<your-domain>/v1/traces |
Deployment-issued |
OTEL_EXPORTER_OTLP_ENDPOINT에는 베이스 엔드포인트를(SDK가 /v1/traces를 붙여요), OTEL_EXPORTER_OTLP_TRACES_ENDPOINT나 CONFIDENT_OTEL_ENDPOINT에는 트레이스 엔드포인트를 써요. 데이터 레지던시와 셀프호스팅을 보세요.
프로토콜 지원
| Capability | Supported |
|---|---|
| OTLP/HTTP protobuf | Yes — recommended (Content-Type: application/x-protobuf) |
| OTLP/HTTP JSON | Yes (Content-Type: application/json) |
| OTLP/gRPC | No — use otlphttp in the Collector and the *-proto-http exporter in SDKs |
| Metrics / logs signals | Not yet — accepted and dropped so mixed pipelines don't error |
| Gzip request bodies | Yes |
| Authentication | x-confident-api-key: *** api key> header |
| Batch size | Up to 4 MB per request |
여러 OpenTelemetry SDK에서 gRPC가 기본값이에요. 연결 리셋이나 HTTP 415 오류는 거의 항상 gRPC로 내보내고 있다는 뜻이에요 — HTTP/protobuf exporter로 전환하세요. 언어별 올바른 exporter 패키지는 문제 해결을 보세요.
confident-trace가 어떻게 동작하나요
confident-trace는 exporter를 붙인 독점 SDK가 아니라 Confident AI용으로 미리 구성된 OpenTelemetry SDK예요. 그것이 만드는 모든 스팬 — 자동 통합, Python의 @span 데코레이터나 span() 컨텍스트 매니저, TypeScript의 withSpan() — 은 여러분이 손으로 설정할 것과 같은 gen_ai.*와 confident.* 속성을 담는 진짜 OpenTelemetry 스팬이에요.
init()은 시작 시 한 번 다음을 해요:
| Step | What init() does |
OpenTelemetry equivalent |
|---|---|---|
| Provider | Creates a global TracerProvider, or attaches to the one passed via init(tracer_provider=...) |
TracerProvider, trace.set_tracer_provider() |
| Exporter | Configures an OTLP/HTTP exporter to the OTEL server using CONFIDENT_API_KEY and, optionally, CONFIDENT_OTEL_ENDPOINT |
OTLPSpanExporter + BatchSpanProcessor |
| Instrumentation | Detects and instruments installed SDKs — OpenAI, LangChain, LangGraph, LlamaIndex, Pydantic AI, Vercel AI SDK, and 20+ more | opentelemetry-instrumentation-* packages |
| Sampling | Applies CONFIDENT_SAMPLE_RATE or init(sample_rate=...) |
TraceIdRatioBased sampler |
| Environment | Stamps traces with CONFIDENT_ENVIRONMENT or init(environment=...) |
Resource attribute |
그 헬퍼들이 confident.* 속성을 써 주므로 속성 이름을 직접 건드릴 필요가 없어요:
| Helper | Sets |
|---|---|
@span / span() / withSpan() |
confident.span.type, span name, and type-specific fields such as model, provider |
update_span() / updateSpan() |
Span input, output, metadata, and test-case fields |
update_trace() / updateTrace() |
Trace name, tags, metadata, user, customer, thread, and trace-level input/output |
trace_context() / traceContext() |
The same trace-level fields, scoped to a block |
turn() |
Thread ID and per-turn input/output for multi-turn conversations |
밑바닥이 평범한 OpenTelemetry이기 때문에:
tracer.start_as_current_span(...)와confident-trace의 스팬이 접착 코드 없이 같은 트레이스에 중첩돼요.- 기존
TracerProvider를 재사용할 수 있어요 — Python의init(tracer_provider=provider), TypeScript의confident-trace/otel의createSpanProcessor(). 기존 OpenTelemetry 프로바이더를 보세요. OTEL_RESOURCE_ATTRIBUTES,OTEL_SERVICE_NAME, W3C 전파가 변함없이 적용돼요.
Python이나 TypeScript에서 손으로 쓴 스팬에도
confident-trace를 쓰세요:init()이 exporter를 처리하고,init(instrumentations=())/init({ instrumentations: [] })가 자동 인스트루먼테이션을 끕니다.
GenAI 시맨틱 컨벤션
OpenTelemetry GenAI 시맨틱 컨벤션이 모델 호출, 툴 실행, 에이전트 호출을 위한 gen_ai.* 어휘를 정의해요. Confident AI는 그것을 기준으로 채택하므로, 순응하는 어떤 인스트루먼터도 Confident 특정 속성 없이 타입 붙은 트레이스를 만들어요.
스팬 타입
confident.span.type이 없을 때 스팬 타입은 gen_ai.operation.name에서 추론돼요:
gen_ai.operation.name |
Span type | Notes |
|---|---|---|
chat, text_completion, generate_content |
llm |
Model, tokens, and messages read from gen_ai.* |
embeddings |
llm |
No output messages |
execute_tool |
tool |
Name from gen_ai.tool.name, arguments from gen_ai.tool.call.arguments |
invoke_agent, create_agent |
agent |
Name from gen_ai.agent.name |
| (no standard retrieval op) | retriever |
Set confident.span.type: retriever or use an OpenInference RETRIEVER span |
| (anything else) | custom |
속성
| Concept | gen_ai.* attribute(s) |
Where it shows up |
|---|---|---|
| Provider | gen_ai.provider.name (legacy gen_ai.system) |
LLM span header, cost lookup |
| Model | gen_ai.request.model, gen_ai.response.model |
LLM span header, cost |
| Token usage | gen_ai.usage.input_tokens, gen_ai.usage.output_tokens |
Token usage and cost |
| Cached / reasoning | gen_ai.usage.cache_read.input_tokens, gen_ai.usage.reasoning.output_tokens |
Token breakdown |
| Request params | gen_ai.request.temperature, gen_ai.request.max_tokens, gen_ai.request.top_p |
Span metadata |
| Messages | gen_ai.input.messages, gen_ai.output.messages, gen_ai.system_instructions |
LLM span input/output |
| Tool | gen_ai.tool.name, gen_ai.tool.call.arguments, gen_ai.tool.call.result |
Tool span name, input, output |
| Agent | gen_ai.agent.name, gen_ai.agent.description |
Agent span name and metadata |
| Conversation | gen_ai.conversation.id |
Thread ID |
| Finish reason | gen_ai.response.finish_reasons |
Span metadata |
메시지 콘텐츠는 컨벤션이 사용한 모든 형태로 받아들여지므로, 오래된 인스트루먼터도 계속 동작해요:
- 스팬 속성 (현재) — JSON 배열로 된
gen_ai.input.messages/gen_ai.output.messages - 스팬 이벤트 (레거시) —
gen_ai.content.prompt,gen_ai.content.completion, 메시지별gen_ai.*.message이벤트 - 인덱스 속성 (OpenLLMetry 스타일) —
gen_ai.prompt.{n}.*/gen_ai.completion.{n}.*
GenAI 컨벤션은 아직 development 상태이고 파괴적인 이름 변경이 있었어요(예:
gen_ai.system→gen_ai.provider.name). Confident AI는 폐기된 이름도 읽지만, 현재 것을 선호하세요.
지원되는 속성 네임스페이스
gen_ai.* 외에도 OTEL 서버는 가장 흔한 LLM 인스트루먼테이션 생태계의 어휘를 인식해요. 이 중 어떤 것의 스팬도 입력, 출력, 모델, 토큰 사용량이 채워진 타입 붙은 스팬으로 렌더링돼요.
| Namespace | Origin | Typical producers | Support |
|---|---|---|---|
confident.* |
Confident AI | confident-trace, manual instrumentation, Agent Skills |
Full — the only namespace that sets every field in the data model |
gen_ai.* |
OpenTelemetry GenAI semconv | confident-trace, Google ADK, Strands, Bedrock AgentCore, Microsoft Foundry, official opentelemetry-instrumentation-* packages |
Full |
openinference.*, llm.*, input.*, output.*, retrieval.*, tool.* |
OpenInference (Arize) | openinference-instrumentation-*, @arizeai/openinference-instrumentation-*, Arize Phoenix pipelines |
Full — see OpenInference |
traceloop.*, llm.* |
OpenLLMetry (Traceloop) | traceloop-sdk, Traceloop's opentelemetry-instrumentation-* forks |
Full |
ai.* |
Vercel AI SDK telemetry | experimental_telemetry |
Full — see Vercel AI SDK |
mastra.*, agent.* |
Framework-specific | Mastra, Claude Agent SDK | Mapped onto agent and tool spans |
| Everything else | — | Any OpenTelemetry-instrumented service | Preserved as span metadata, not typed |
OpenInference
| OpenInference | Confident AI |
|---|---|
openinference.span.kind = LLM |
llm span |
openinference.span.kind = TOOL |
tool span, name from tool.name |
openinference.span.kind = AGENT |
agent span |
openinference.span.kind = RETRIEVER |
retriever span, retrieval.documents.*.document.content → retrieval context |
openinference.span.kind = CHAIN, EMBEDDING, others |
custom span |
llm.model_name, llm.provider, llm.system |
Model and provider |
llm.token_count.prompt, llm.token_count.completion |
Input / output tokens |
llm.input_messages.*, llm.output_messages.* |
LLM messages |
input.value, output.value |
Span input / output |
session.id, user.id |
Thread and user |
metadata |
Span metadata |
confident-trace를 exporter로 쓰는 설정은 OpenInference 통합 페이지에 있어요.
OpenLLMetry
| OpenLLMetry | Confident AI |
|---|---|
traceloop.span.kind = workflow |
Root agent span; traceloop.workflow.name → trace name |
traceloop.span.kind = agent |
agent span |
traceloop.span.kind = task |
custom span |
traceloop.span.kind = tool |
tool span |
llm.request.type, gen_ai.system + gen_ai.request.model |
llm span, model, and provider |
gen_ai.prompt.{n}.*, gen_ai.completion.{n}.* |
LLM messages |
gen_ai.usage.prompt_tokens, gen_ai.usage.completion_tokens |
Input / output tokens |
traceloop.entity.input, traceloop.entity.output |
Span input / output |
traceloop.association.properties.* |
Span metadata; session_id / user_id → thread and user |
Traceloop SDK를 표준 exporter 설정으로 Confident AI에 지정해요:
export TRACELOOP_BASE_URL="https://otel.confident-ai.com"
export TRACELOOP_HEADERS="x-confident-api-key=confident_us..."
속성 우선순위
스팬이 같은 개념을 여러 네임스페이스에 담으면 Confident AI는 이 순서로 해결해요:
confident.*— 항상 이기므로, 인스트루먼터가 설정한 무엇이든 덮어쓸 수 있어요gen_ai.*— 현재 이름, 그다음 폐기된 별칭- OpenInference (
openinference.*,llm.*) - OpenLLMetry (
traceloop.*,llm.*) - 프레임워크별 네임스페이스 (
ai.*,mastra.*, …) - 스팬 이름과 구조에서 추론
소비되지 않은 속성은 스팬 메타데이터로 그대로 보존돼요.
트레이스 수준 필드 — 이름, 태그, 스레드, user, customer, 환경, 테스트 케이스 필드 — 에는 상당하는
gen_ai.*가 없어요.confident-trace의update_trace()/trace_context()로, 또는 원시 SDK의confident.trace.*속성으로 설정하세요. 속성 레퍼런스를 보세요.
접근 방식 고르기
| If you... | Use |
|---|---|
| Write Python or TypeScript | confident-trace with automatic integrations |
| Use a framework with an OpenInference instrumentor | OpenInference + confident-trace as exporter |
| Already run OpenLLMetry / Traceloop | Point TRACELOOP_BASE_URL at the OTEL server |
| Run agents on AWS, Azure, or Google Cloud managed runtimes | Cloud runtime guides |
| Already have an OpenTelemetry Collector | Trace broadcasting |
| Write Go, Ruby, C#, Java, Rust, or anything else | Manual instrumentation with the OpenTelemetry SDK |
분산 트레이싱
서비스 간에 W3C 트레이스 컨텍스트를 전파해서 한 요청이 한 트레이스가 되게 해요.
Trace Broadcasting
같은 스팬을 Confident AI와 기존 관측성 백엔드에 보내요.
Trace Forwarding
Confident AI가 평가되고 비용이 붙은 트레이스를 OTLP collector로 밀어내게 해요.
수동 인스트루먼테이션
다섯 개 언어의 원시 OpenTelemetry SDK용 퀵스타트와, 전체 confident.* 속성
레퍼런스.