전체 그래프
OpenTelemetry

OTel Signals

data-engineeringobservabilityopentelemetry

상위: OpenTelemetry

요약

OpenTelemetry는 Traces, Metrics, Logs 세 가지 텔레메트리 신호(Signal)를 정의한다. 각 신호는 시스템의 다른 측면을 관찰하며, Context Propagation을 통해 서로 상관관계를 맺는다.

Traces (분산 추적)

요청이 분산 시스템을 통과하는 전체 경로를 추적한다.

구성 요소

  • Trace: 하나의 요청에 대한 전체 경로. 여러 Span의 집합
  • Span: 하나의 작업 단위. 이름, 시작/종료 시간, 속성(Attributes), 이벤트(Events), 상태(Status)를 가짐
  • SpanContext: Trace ID + Span ID + Trace Flags. 서비스 간 전파되는 핵심 정보

Span 계층 구조

Trace (trace_id: abc123)
├── Span A: "HTTP GET /api/orders"     (Root Span)
   ├── Span B: "DB Query: SELECT..."  (Child Span)
   └── Span C: "HTTP POST /payment"   (Child Span)
       └── Span D: "Process Payment"  (Grandchild Span)

예시 (Python)

from opentelemetry import trace

tracer = trace.get_tracer("order-service")

with tracer.start_as_current_span("process_order") as span:
    span.set_attribute("order.id", "12345")
    span.set_attribute("order.amount", 99.99)

    with tracer.start_as_current_span("validate_payment"):
        # 결제 검증 로직
        pass

    with tracer.start_as_current_span("save_to_db"):
        # DB 저장 로직
        span.add_event("order_saved", {"db.table": "orders"})

Span 종류 (SpanKind)

Kind설명예시
SERVER서버가 수신한 요청HTTP 핸들러
CLIENT외부 서비스 호출HTTP/gRPC 클라이언트
PRODUCER메시지 생산Kafka Producer
CONSUMER메시지 소비Kafka Consumer
INTERNAL내부 작업비즈니스 로직

Metrics (지표)

시간에 따른 수치 측정값을 기록한다. 시스템 상태를 집계된 형태로 파악할 때 사용한다.

Instrument 종류

Instrument설명예시
Counter단조 증가 값총 요청 수, 에러 수
UpDownCounter증감 가능 값활성 연결 수
Histogram분포 측정응답 시간, 요청 크기
Gauge특정 시점 값CPU 사용률, 메모리

예시 (Python)

from opentelemetry import metrics

meter = metrics.get_meter("order-service")

# Counter: 주문 
order_counter = meter.create_counter(
    name="orders.total",
    description="Total number of orders",
    unit="1"
)

# Histogram: 처리 시간
latency_histogram = meter.create_histogram(
    name="orders.duration",
    description="Order processing duration",
    unit="ms"
)

def process_order(order):
    order_counter.add(1, {"status": "processing"})
    start = time.time()
    # ... 처리 로직
    duration = (time.time() - start) * 1000
    latency_histogram.record(duration, {"endpoint": "/orders"})

Logs (로그)

타임스탬프가 찍힌 텍스트 기록. OTel은 기존 로깅 라이브러리(Python logging, Log4j 등)와 통합하여, 로그에 Trace ID/Span ID를 자동으로 주입한다.

핵심 포인트

  • OTel은 새로운 로깅 API를 강제하지 않는다. 기존 로거를 그대로 사용하면서 트레이스와 상관관계만 추가한다
  • 자동 계측(auto-instrumentation) 활성화 시, 로그에 trace_idspan_id가 자동 삽입된다
  • 이를 통해 "이 에러 로그가 어떤 요청에서 발생했는지" 바로 추적 가능

예시

import logging
# OTel 자동 계측이 활성화되면, 기존 로그에 trace context가 자동 주입
logger = logging.getLogger(__name__)

def process_order(order_id):
    logger.info(f"Processing order {order_id}")
    # 출력: Processing order 12345 [trace_id=abc123 span_id=def456]

세 신호의 관계

Traces ←→ Logs     : Trace ID로 연결 ( 로그가 어떤 요청?)
Traces ←→ Metrics  : Exemplar로 연결 ( 지연 급등이 어떤 트레이스?)
Logs   ←→ Metrics  : 시간대로 상관관계 (에러 로그 급증 = 에러율 지표 상승)

Exemplar: Metric 데이터 포인트에 Trace ID를 첨부하는 기능. "이 p99 레이턴시 급등의 원인이 된 구체적인 트레이스"를 바로 찾을 수 있다.

관련 개념