OpenTelemetry GenAI — 도구 호출을 End-to-End로 추적하기

하나의 에이전트(agent)가 도구(tool) 다섯 개, MCP 서버(MCP server) 세 개, 하위 에이전트(sub-agent) 두 개를 호출한다고 가정해 봅니다. 이 모든 흐름을 가로지르는 하나의 트레이스(trace)가 필요합니다. OpenTelemetry GenAI 시맨틱 컨벤션(semantic conventions; v1.37 이상에서 안정화된 속성 집합)은 2026년 표준이며, Datadog, Langfuse, Arize Phoenix, OpenLLMetry, AgentOps가 모두 기본으로 지원합니다. 이 lesson은 필수 속성의 이름을 정리하고, 스팬(span) 계층(agent → LLM → tool)을 살펴보며, 어떤 OTel exporter에도 꽂아 쓸 수 있는 표준 라이브러리 기반 스팬 emitter를 함께 제공합니다.

유형: Build
언어: Python (표준 라이브러리, OTel span emitter)
선수 학습: Phase 13 · 07 (MCP 서버), Phase 13 · 08 (MCP 클라이언트)
소요 시간: 약 75분

학습 목표

  • LLM 스팬과 도구 실행(tool-execution) 스팬에 필요한 OTel GenAI 속성을 이름으로 말할 수 있습니다.
  • 에이전트 루프(agent loop), LLM 호출(LLM call), 도구 호출(tool call), MCP 클라이언트 디스패치(MCP client dispatch)를 모두 포괄하는 트레이스 계층을 직접 만들 수 있습니다.
  • 어떤 내용(content)을 캡처할지(opt-in)와 어떤 내용을 마스킹(redact)할지(기본값)를 판단할 수 있습니다.
  • 도구 코드를 다시 쓰지 않고도 로컬 컬렉터(local collector; Jaeger, Langfuse)에 스팬을 내보낼 수 있습니다.

문제

2026년 2월의 어느 디버깅 상황입니다. 사용자가 "내 에이전트가 어떤 때는 응답에 30초가 걸리고, 어떤 때는 3초가 걸린다"고 보고합니다. 트레이스가 없습니다. 로그에는 LLM 호출만 남아 있고, 도구 디스패치(tool dispatch)도, MCP 서버 왕복(round-trip)도, 하위 에이전트도 보이지 않습니다. 추측에 의존할 수밖에 없습니다. 결국 어떤 MCP 서버 하나가 가끔 콜드 스타트(cold-start)에서 멈춘다는 사실을 발견하게 됩니다.

엔드 투 엔드 추적(end-to-end tracing)이 없으면 이런 문제는 찾아낼 수 없습니다. OTel GenAI가 바로 이 문제를 해결합니다.

이 컨벤션은 2025-2026년에 걸쳐 OpenTelemetry 시맨틱 컨벤션 그룹(semantic-conventions group) 아래에서 안정화되었습니다. Datadog, Langfuse, Phoenix, OpenLLMetry, AgentOps가 모두 같은 스팬을 동일한 의미로 파싱할 수 있도록 안정적인 속성 이름(attribute name)을 정의합니다. 즉, 한 번만 계측(instrumentation)하면 어떤 백엔드(backend)로도 보낼 수 있습니다.

사전 테스트

2문제 · 이 강의를 시작하기 전에 얼마나 알고 있는지 확인해보세요

1.GenAI OpenTelemetry가 해결하는 핵심 과제는?

2.GenAI OpenTelemetry 이전의 주요 한계는?

0/2 답변 완료

개념

스팬 계층

agent.invoke_agent  (top, INTERNAL span)
 ├── llm.chat       (CLIENT span)
 ├── tool.execute   (INTERNAL)
 │    └── mcp.call  (CLIENT span)
 ├── llm.chat       (CLIENT span)
 └── subagent.invoke (INTERNAL)

전체 스팬은 하나의 트레이스 ID 아래에 중첩됩니다. 스팬 ID(span id)는 부모-자식(parent-child) 관계를 이어 줍니다.

필수 속성

2025-2026년 시맨틱 컨벤션 기준입니다.

  • gen_ai.operation.name"chat", "text_completion", "embeddings", "execute_tool", "invoke_agent".
  • gen_ai.provider.name"openai", "anthropic", "google", "azure_openai".
  • gen_ai.request.model — 요청한 모델 문자열입니다. 예: "gpt-4o-2024-08-06".
  • gen_ai.response.model — 실제 응답을 제공한 모델입니다.
  • gen_ai.usage.input_tokens / gen_ai.usage.output_tokens.
  • gen_ai.response.id — 상관관계(correlation) 추적용 제공자(provider) 응답 ID입니다.

도구 스팬의 경우:

  • gen_ai.tool.name — 도구 식별자(tool identifier)입니다.
  • gen_ai.tool.call.id — 특정 호출 ID입니다.
  • gen_ai.tool.description — 도구 설명입니다(선택 항목).

에이전트 스팬의 경우:

  • gen_ai.agent.name / gen_ai.agent.id / gen_ai.agent.description.

스팬 종류(SpanKind)

  • 프로세스 경계를 넘는 호출(LLM 제공자, MCP 서버 등)에는 SpanKind.CLIENT를 사용합니다.
  • 에이전트 자신의 루프 단계와 도구 실행에는 SpanKind.INTERNAL을 사용합니다.

옵트인(opt-in) 방식의 내용 캡처

기본 설정에서 스팬은 측정값(metric)과 시간(timing) 정보만 담고, 프롬프트(prompt)나 응답 완성문(completion)은 담지 않습니다. 큰 페이로드(payload)나 개인정보(PII)는 기본적으로 꺼져 있습니다. 내용을 함께 담고 싶다면 OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental과 내용 캡처(content-capture)용 환경 변수를 함께 설정해야 합니다. 운영(prod) 환경에서 켜기 전에 반드시 신중하게 검토해야 합니다.

스팬 이벤트(Events on spans)

토큰 수준의 이벤트는 스팬 이벤트(span event)로 기록할 수 있습니다.

  • gen_ai.content.prompt — 입력 메시지입니다.
  • gen_ai.content.completion — 출력 메시지입니다.
  • gen_ai.content.tool_call — 기록된 도구 호출입니다.

이벤트는 스팬 안에서 시간 순서로 정렬되어, 호출 흐름을 상세히 다시 재생(replay)할 때 유용합니다.

익스포터(Exporters)

OTel 스팬은 다음과 같은 백엔드로 내보낼(export) 수 있습니다.

  • Jaeger / Tempo. 오픈소스, 온프레미스(on-prem) 환경에 적합합니다.
  • Langfuse. LLM 관측(observability) 전용이며 토큰 사용량(token usage)을 시각화해 줍니다.
  • Arize Phoenix. 평가(eval)와 트레이싱(tracing)이 결합되어 있습니다.
  • Datadog. 상용 제품이며 gen_ai.* 속성을 기본으로 파싱합니다.
  • Honeycomb. 컬럼 지향(column-oriented) 저장 구조라 질의(query)가 편리합니다.

모두 와이어 포맷(wire format)으로 OTLP를 사용합니다. 즉, 애플리케이션 코드는 어떤 백엔드인지 신경 쓸 필요가 없습니다.

MCP를 가로지르는 컨텍스트 전파

MCP 클라이언트가 서버를 호출할 때는 요청에 W3C traceparent 헤더를 주입합니다. Streamable HTTP는 표준 헤더를 그대로 지원합니다. 반면 stdio 방식은 HTTP 헤더를 기본으로 전달하지 않습니다. 2026 스펙 로드맵(roadmap)에서는 JSON-RPC 호출에 _meta.traceparent 필드를 추가하는 방안이 논의되고 있습니다.

이 변경이 적용되기 전까지는 모든 요청의 _metatraceparent를 직접 넣어 줍니다. 서버는 이 트레이스 ID를 로그에 함께 남깁니다.

메트릭(Metrics)

스팬과 함께 GenAI 시맨틱 컨벤션은 메트릭도 정의합니다.

  • gen_ai.client.token.usage — 히스토그램(histogram)입니다.
  • gen_ai.client.operation.duration — 히스토그램입니다.
  • gen_ai.tool.execution.duration — 히스토그램입니다.

호출별 상세 데이터까지는 필요 없는 대시보드(dashboard)를 만들 때 이 메트릭을 사용합니다.

AgentOps 계층

AgentOps(2024년 설립)는 GenAI 관측 분야에 특화된 도구입니다. LangGraph, Pydantic AI, CrewAI 같은 인기 프레임워크를 감싸 OTel 스팬을 자동으로 내보내 줍니다. 사용 중인 스택이 지원 프레임워크라면 유용하지만, 그렇지 않다면 수동 계측을 직접 작성해야 합니다.

사용해 보기

code/main.py는 하나의 LLM을 호출하고, 도구 두 개를 디스패치하며, MCP 한 번의 왕복을 수행하는 에이전트에 대해 OTel 모양의 스팬을 stdout으로 내보냅니다. 형식은 OTLP-JSON과 비슷한 모양입니다. 실제 익스포터는 붙이지 않습니다. 이 lesson은 스팬의 모양과 속성 집합(attribute set)에 집중하기 위함입니다. 출력 결과를 OTLP 호환 뷰어(viewer)에 붙여 넣거나 그대로 읽어 봅니다.

살펴볼 지점은 다음과 같습니다.

  • 모든 스팬이 같은 트레이스 ID를 공유합니다.
  • 부모-자식 연결이 parentSpanId로 인코딩되어 있습니다.
  • 필수 gen_ai.* 속성이 모두 채워져 있습니다.
  • 내용 캡처는 기본으로 꺼져 있으며, 한 시나리오에서 환경 변수로 이를 켜 봅니다.

산출물 만들기

이 lesson은 outputs/skill-otel-genai-instrumentation.md를 만듭니다. 에이전트 코드베이스가 주어졌을 때, 이 스킬(skill)은 어디에 스팬을 추가할지, 어떤 속성을 채울지, 어떤 익스포터를 대상으로 할지에 대한 계측 계획(instrumentation plan)을 만들어 줍니다.

연습문제

  1. (쉬움) code/main.py를 실행합니다. 스팬 개수를 세고, 각각이 CLIENT인지 INTERNAL인지 구분해 봅니다.

  2. (중간) 내용 캡처를 환경 변수로 켜고, gen_ai.content.promptgen_ai.content.completion 이벤트가 실제로 나타나는지 확인합니다. 개인정보(PII) 측면에서 어떤 함의가 있는지 메모로 남깁니다.

  3. (중간) 도구 실행 메트릭 gen_ai.tool.execution.duration을 추가하고, 호출마다 히스토그램 샘플(histogram sample)을 내보냅니다.

  4. (어려움) 부모 에이전트 스팬에서 MCP 요청의 _meta.traceparent 필드로 traceparent를 전파합니다. MCP 서버가 같은 트레이스 ID를 볼 수 있는지 확인합니다.

  5. (어려움) OTel GenAI 시맨틱 컨벤션 스펙을 직접 읽어 봅니다. 이 lesson 코드가 내보내지 않는 시맨틱 컨벤션 속성을 하나 찾아 추가합니다.

핵심 용어

용어흔한 설명실제 의미
OTel"OpenTelemetry"트레이스, 메트릭, 로그를 위한 개방형 표준
GenAI semconv"GenAI 시맨틱 컨벤션"LLM / 도구 / 에이전트 스팬을 위한 안정적인 속성 이름
gen_ai.*"그 속성 네임스페이스"모든 GenAI 속성이 공유하는 접두사(prefix)
스팬(Span)"시간이 측정되는 작업"시작, 끝, 속성을 가진 하나의 작업 단위
트레이스(Trace)"스팬 사이의 계보"같은 트레이스 ID를 공유하는 스팬들의 트리
SpanKind"CLIENT / SERVER / INTERNAL"스팬이 어느 방향인지에 대한 힌트
OTLP"OpenTelemetry Line Protocol"익스포터가 사용하는 와이어 포맷
옵트인 내용 캡처(Opt-in content)"프롬프트 / 컴플리션 캡처"기본은 꺼져 있고, 환경 변수로만 켤 수 있음
traceparent"W3C 헤더"서비스 사이로 트레이스 컨텍스트를 전파함
익스포터(Exporter)"백엔드 전용 송신기"스팬을 Jaeger / Datadog 등으로 보내는 구성 요소

더 읽을거리

실습 코드

이 강의의 실습 코드 1개

main
Code

산출물

이 강의에서 생성된 프롬프트, 스킬, 코드 산출물 1개

otel-genai-instrumentation

Produce an instrumentation plan for an agent codebase to emit OTel GenAI spans end-to-end.

Skill

확인 문제

3문제 · 모두 맞추면 완료 표시가 가능합니다

1.프로덕션에서 GenAI OpenTelemetry의 가장 중요한 설계 원칙은?

2.GenAI OpenTelemetry가 올바른 선택이 아닌 경우는?

3.GenAI OpenTelemetry는 AI 생태계에 어떻게 들어맞나요?

0/3 답변 완료

추가 문제 풀기

AI가 강의 내용을 바탕으로 새로운 문제를 생성합니다