상위: OpenTelemetry
요약
Context Propagation은 분산 시스템에서 서비스 간 트레이스 컨텍스트를 전달하는 메커니즘이다. Service A가 Service B를 호출할 때, Trace ID와 Span ID를 HTTP 헤더 등에 실어 보내 하나의 Trace로 연결한다. W3C Trace Context가 기본 표준이다.
왜 필요한가?
분산 시스템에서 하나의 요청은 여러 서비스를 거친다.
User → API Gateway → Order Service → Payment Service → DB
각 서비스가 독립적으로 Span을 생성하면 서로 연결할 수 없다. Context Propagation이 "이 Span들은 모두 같은 요청의 일부"라는 정보를 전파한다.
W3C Trace Context
OTel의 기본 전파 표준. 두 개의 HTTP 헤더를 사용한다.
traceparent
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
│ │ │ │
│ │ │ └─ Trace Flags (01 = sampled)
│ │ └─ Parent Span ID (8 bytes)
│ └─ Trace ID (16 bytes)
└─ Version (00)
- Trace ID: 전체 요청을 식별하는 고유 ID. 모든 서비스에서 동일
- Parent Span ID: 호출한 쪽의 Span ID. 부모-자식 관계 형성
- Trace Flags: 샘플링 여부.
01이면 샘플링됨
tracestate (선택)
벤더별 추가 정보를 전달한다.
tracestate: congo=t61rcWkgMzE,rojo=00f067aa0ba902b7
전파 흐름
┌──────────────┐ traceparent 헤더 ┌──────────────┐
│ Order Service │ ────────────────→ │Payment Service│
│ │ │ │
│ Span A │ │ Span B │
│ trace: abc │ │ trace: abc │
│ span: 111 │ │ parent: 111 │
└──────────────┘ └──────────────┘
- Order Service가 Span A를 생성 (trace_id=abc, span_id=111)
- Payment Service 호출 시
traceparent헤더에 abc/111 삽입 - Payment Service가 헤더를 파싱하여 Span B 생성 (trace_id=abc, parent=111)
- 두 Span이 같은 Trace에 속하게 됨
Propagator 종류
| Propagator | 헤더 | 설명 |
|---|---|---|
| W3C TraceContext | traceparent, tracestate | OTel 기본. 업계 표준 |
| B3 | X-B3-TraceId 등 | Zipkin 호환. 레거시 시스템 |
| Jaeger | uber-trace-id | Jaeger 네이티브 |
| AWS X-Ray | X-Amzn-Trace-Id | AWS 서비스 연동 |
복합 Propagator
여러 형식을 동시에 지원할 수 있다. 레거시 시스템과 신규 시스템이 혼재할 때 유용.
from opentelemetry.propagators.composite import CompositePropagator
from opentelemetry.propagators.b3 import B3MultiFormat
from opentelemetry.propagate import set_global_textmap
# W3C + B3 모두 지원
set_global_textmap(CompositePropagator([
TraceContextTextMapPropagator(),
B3MultiFormat(),
]))
Baggage
Trace Context 외에 사용자 정의 키-값 쌍을 서비스 간 전파하는 메커니즘. 예를 들어 user.id나 tenant.id를 한 번 설정하면 이후 모든 서비스에서 사용 가능.
from opentelemetry import baggage, context
# 설정
ctx = baggage.set_baggage("user.id", "user-123")
context.attach(ctx)
# 다른 서비스에서 읽기
user_id = baggage.get_baggage("user.id") # "user-123"
주의: Baggage는 모든 하위 서비스로 전파되므로, 민감한 정보(토큰, 비밀번호)를 넣으면 안 된다.
관련 개념
- OTel Signals: Context Propagation으로 연결되는 텔레메트리 신호
- OTel Instrumentation: 자동 계측이 Propagation을 자동 처리