글 / 통합 검증

OpenTelemetry 요청 추적

요청마다 Trace ID 하나를 부여하여 traceparent 헤더로 전파하면 여러 서비스의 Span이 하나의 흐름으로 연결된다.

작성일 · 읽는 시간 2분 · OpenTelemetry Python 1.44 기준

문제 정의

요청 하나가 여러 서비스를 경유하면 로그도 서비스별로 분산된다. 어느 로그 줄이 같은 요청에서 생성되었는지 시각만으로는 대응시키기 어렵다.

Trace와 Span

  • span: 작업 하나를 나타내는 단위이다. 자신의 span id를 가지며, 최초의 span이 아니면 부모 span id도 가진다.
  • trace: trace id가 같은 span의 집합이다.

trace에 속한 span과 부모 span id로 이어지는 관계

서비스 간 전파

서비스 A가 B를 호출할 때 trace id와 자신의 span id를 traceparent 헤더에 포함하여 전송한다. B는 그 값으로, 같은 trace에 속하면서 A의 span을 부모로 하는 span을 생성한다. 헤더의 형식은 W3C Trace Context가 규정한다.

traceparent 헤더로 서비스 A의 span 정보가 B로 전파되는 구성

text
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
  • 00: 버전
  • 16진수 32자리: trace id
  • 16진수 16자리: 호출 측의 span id
  • 01: 플래그. 마지막 비트는 호출 측이 기록했을 수 있음을 나타내는 표시(sampled)이다.

traceparent 헤더 값의 버전·trace id·span id·플래그 배치

최소 예제

pythontrace_demo.py
from opentelemetry import trace
from opentelemetry.propagate import inject
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter

provider = TracerProvider()
# 끝난 span을 콘솔로 내보낸다
provider.add_span_processor(BatchSpanProcessor(ConsoleSpanExporter()))
trace.set_tracer_provider(provider)
tracer = trace.get_tracer("demo")

with tracer.start_as_current_span("order"):
    with tracer.start_as_current_span("stock"):
        headers = {}
        # 지금 span의 정보를 traceparent 헤더로 넣는다
        inject(headers)
        print(headers)

콘솔에 span 두 개가 JSON으로 출력된다. 두 span의 trace_id는 같고, stock의 parent_id는 order의 span_id이다.