Grafana 입문 4편 — Tempo + TraceQL · 분산 Trace 깊이

2026-05-18Grafana 입문에서 운영까지

Grafana 입문 4편. Tempo + TraceQL 깊이 — Trace · Span · Service · Operation 의 4 단어, OpenTelemetry (OTel) · Jaeger · Zipkin 의 프로토콜 호환, Tempo 의 object storage 비용 효율, TraceQL 의 syntax (span filter · structural relationship · aggregate), Service Graph 자동 생성, Tail-based sampling (모든 trace 저장 X), Metric Generator (trace → RED metric), Exemplar 의 metric→trace 연결. 분산 시스템 디버그 의 핵심.

📚 Grafana 입문에서 운영까지 · 4편 — Tempo + TraceQL · 분산 Trace 깊이

이 글은 Grafana 입문에서 운영까지 시리즈 4편이에요. 3편 Lokilogs 였다면, 이번 글 = 3 pillar 의 마지막 = traces.

이번 글의 범위

마이크로서비스 환경 에서 한 요청 의 전체 여정 = trace. 이 trace 를 수집 · 저장 · query 하는 도구 = Tempo (Grafana Labs 의 trace backend). Loki 가 logs 의 Prometheus 였다면, Tempo = traces 의 Loki.

자리 자산
개념 Trace · Span · Service · Operation
수집 OpenTelemetry · Jaeger · Zipkin
저장 Object Storage 의 비용 효율
Query TraceQL (PromQL · LogQL 영감)
부가 Service Graph · Metric Generator

Trace · Span 의 의미

분산 시스템 의 함정

Monolith 시절:
  요청 → DB → 응답
  한 process → 한 stack trace → 디버그 간단

마이크로서비스 시절:
  요청 → API Gateway → Auth Service → User Service → DB
                                   ↘ Cache Service
                                   ↘ Notification → Email Service
                                                  → SMS Service

→ 어디서 느림? · 어디서 에러? · 의존성 그림은?

Trace 의 정의

Trace = 한 요청 의 전체 여정 (모든 service 통과)
  ↓
Span = trace 의 한 service 의 작업 단위

예 — 한 trace:
  [Frontend] ─→ [API Gateway] ─→ [Auth] ─→ [User Service] ─→ [DB]
   trace_id = "abc123"
   span 1: Frontend         (span_id=001, parent=null)
   span 2: API Gateway      (span_id=002, parent=001)
   span 3: Auth             (span_id=003, parent=002)
   span 4: User Service     (span_id=004, parent=003)
   span 5: DB query         (span_id=005, parent=004)

Span 의 구조

Span:
  - trace_id        같은 trace 의 모든 span 동일
  - span_id         이 span 의 고유 ID
  - parent_span_id  부모 span (root 는 null)
  - service.name    어느 service
  - operation.name  어떤 작업 (HTTP method · DB query 등)
  - start_time      시작
  - duration        소요 시간
  - attributes      메타데이터 (http.status_code · http.method · ...)
  - events          중간 event 들
  - status          ok · error

Trace 의 시각화

Trace timeline:
  ├─ Frontend                 [████████████████ 1.2s]
  │   └─ API Gateway          [██████████ 850ms]
  │       └─ Auth             [██ 50ms]
  │       └─ User Service     [████████ 700ms]
  │           └─ DB Query     [████████ 680ms]  ← 가장 느림!

한 view = 어느 service 가 bottleneck 즉시 발견.

OpenTelemetry · Jaeger · Zipkin

OpenTelemetry (OTel) — 표준

OpenTelemetry (OTel, 관측성 표준 SDK) 는 Trace · Metric · Log 셋을 한 API 로 묶어요.

OpenTelemetry:
  - CNCF (Cloud Native Computing Foundation) 의 표준
  - Trace · Metric · Log 모두 한 API
  - 모든 vendor 호환 (Grafana · Datadog · New Relic · ...)
  - 2019 부터 합쳐진 표준 (OpenTracing + OpenCensus)

3 프로토콜 호환

Tempo 가 받는 trace format:
  - OpenTelemetry (OTLP — OpenTelemetry Protocol)
  - Jaeger (legacy)
  - Zipkin (legacy)

→ 어느 프로토콜 의 trace 도 Tempo 가 수신

Jaeger 와 Zipkin 의 자리

Jaeger:
  - Uber 출신 (오픈소스 후)
  - 자체 UI 보유 (Tempo 는 Grafana UI 사용)
  - 여전히 인기

Zipkin:
  - Twitter 출신
  - 가장 오래 된 표준
  - 단순 한 deployment

OpenTelemetry:
  - 둘 다 통합 한 표준
  - 새 프로젝트 = OTel 권장

OpenTelemetry Instrumentation

# Python 예
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.resources import Resource

# Setup
resource = Resource.create({"service.name": "user-api"})
trace.set_tracer_provider(TracerProvider(resource=resource))
trace.get_tracer_provider().add_span_processor(
    BatchSpanProcessor(
        OTLPSpanExporter(endpoint="http://tempo:4317")
    )
)

tracer = trace.get_tracer(__name__)

# Usage
@app.get("/users/{user_id}")
async def get_user(user_id: int):
    with tracer.start_as_current_span("get_user") as span:
        span.set_attribute("user.id", user_id)

        with tracer.start_as_current_span("db_query"):
            user = await db.get_user(user_id)
            span.set_attribute("db.rows", 1)

        return user

Auto-instrumentation

# Python — code 수정 없이 자동 instrumentation
pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install
opentelemetry-instrument \
  --traces_exporter otlp \
  --service_name my-api \
  python app.py

여기서 시험 함정 — Auto-instrumentation 이 manual 보다 멋져 보여도 모든 framework 가 자동 지원 X. 비표준 framework = manual instrumentation 필요.

eBPF Auto-instrumentation (Beyla)

eBPF (커널에서 안전하게 도는 hook) 기반의 Beyla 는 코드 한 줄도 안 건드려요.

Beyla (Grafana Labs):
  - eBPF 기반
  - 코드 수정 0 (zero code change)
  - HTTP · gRPC · DB call 자동 trace
  - 모든 언어 지원 (Go · Python · Java · Node · Ruby · Rust · ...)

장점:
  - legacy app 의 instrumentation 자동
  - language 무관

단점:
  - kernel 의식 (eBPF)
  - 일부 framework 한계

Tempo 의 저장 구조

Object Storage 의 비용 효율

Jaeger 의 전통적 backend:
  - Cassandra (또는 Elasticsearch)
  - 운영 부담 큼
  - 비용 높음

Tempo 의 backend:
  - S3 · GCS · Azure Blob · 로컬
  - 운영 단순
  - 비용 1/10

Block 의 구조

Bloom filter (있을 가능성만 빠르게 판별하는 자료구조) 가 block scan 의 부담을 잘라 줘요.

Tempo Block:
  - 한 시간 의 trace 들의 묶음
  - flat file (압축됨)
  - object storage 에 저장
  - 검색 = bloom filter + 의도된 block scan

TraceID Lookup vs Search

1. TraceID Lookup (O(1))
   - trace_id 알면 바로 검색
   - 가장 빠름

2. Search (TraceQL)
   - service · operation · duration 같은 조건
   - block scan 필요 (조금 느림)
   - bloom filter 의 최적화

TraceQL — Query Language

TraceQL (Tempo 의 trace 전용 query 언어) 은 PromQL · LogQL 의 발상을 가져왔어요.

4 종 Query

1. Span Filter
   { resource.service.name = "api" }

2. Span Field Comparison
   { duration > 1s }

3. Structural Relationship
   { resource.service.name = "api" } >> { name = "db_query" }

4. Aggregate
   { duration > 1s } | count() > 0

Span Filter

# service 별
{ resource.service.name = "user-api" }

# HTTP 의 status code
{ span.http.status_code = 500 }

# duration
{ duration > 1s }

# operation 이름
{ name =~ ".*db.*" }

# attribute
{ span.user.id = "12345" }

# 조합 (AND)
{ resource.service.name = "user-api" && span.http.status_code = 500 }

# 조합 (OR)
{ duration > 5s || span.http.status_code = 500 }

Structural Relationship

# A 의 child 가 B
{ resource.service.name = "frontend" } > { resource.service.name = "backend" }

# A 의 descendant 가 B (간접 child 포함)
{ resource.service.name = "frontend" } >> { resource.service.name = "db" }

# A 가 child of B
{ resource.service.name = "db" } < { resource.service.name = "backend" }

# A 의 sibling 이 B
{ resource.service.name = "auth" } ~ { resource.service.name = "cache" }

여기서 정말 중요한 시험 함정 — Structural Relationship = TraceQL 의 핵심 차별성. 단순 filter 가 아닌 trace 안 의 흐름 으로 query. "이 service 가 다음 service 호출 시 에러" 같은 패턴 자동 발견.

Aggregate

# 한 trace 에 span > 100 개
{ } | count() > 100

# 한 service 의 평균 duration
{ resource.service.name = "api" } | avg(duration) > 500ms

# Service 의 span 분포
{ resource.service.name = "api" } | quantile_over_time(duration, 0.99) > 1s

TraceQL Metric (Tempo의 새 기능)

# trace 의 metric 생성
{ resource.service.name = "api" } | rate() by (resource.service.name)

# 동일 의미: 서비스 별 trace 의 초당 발생

LogQL 의 metric query 와 같은 발상. Trace → metric 시계열.

Service Graph — 자동 dependency

Service Graph 의 자리

Trace 를 분석:
  - "frontend 가 backend 호출" (span 의 parent-child)
  - "backend 가 db 호출"
  - "backend 가 cache 호출"

→ Service Dependency Graph 자동 생성
   [frontend] → [backend] → [db]
                          → [cache]

데이터

Service Graph 의 metric:
  - traces_service_graph_request_total  (요청 수)
  - traces_service_graph_request_failed_total  (실패)
  - traces_service_graph_request_server_seconds  (server 시간)
  - traces_service_graph_request_client_seconds  (client 시간)

Tempo 의 Metric Generatortrace 보면서 자동 생성. Prometheus 로 export.

Grafana 의 Visualization

Grafana Tempo datasource > Service Graph:
  - 자동 노드 + 엣지 그림
  - 각 service 의 RPS (초당 요청 수) · 에러율 표시
  - 엣지 두께 = 호출 빈도
  - 색 = 에러율

마이크로서비스 환경 의 지도 자동.

Metric Generator — Trace → Metric

동기

Trace 의 한계:
  - 양 매우 큼 (모든 요청 의 모든 span)
  - sampling 필요 (모든 trace 저장 X)
  - 빠른 query 어려움

해결 — Metric Generator:
  - Tempo 가 trace 받으면 자동 RED metric 생성
  - Rate · Error · Duration metric
  - Prometheus 로 export
  - dashboard query 매우 빠름 (Prometheus 직접)

RED metric (Rate · Error · Duration 3종) 은 서비스 건강을 한눈에 보는 표준 셋이에요.

생성 metric

traces_spanmetrics_calls_total                  요청 수
traces_spanmetrics_latency_bucket               latency histogram
traces_spanmetrics_calls_total{status_code="..."}  status 별

각 service · operation · status 별 자동.

활용

# RED metric (trace 에서 자동 추출)
# Rate
sum(rate(traces_spanmetrics_calls_total[5m])) by (service)

# Errors
sum(rate(traces_spanmetrics_calls_total{status_code="STATUS_CODE_ERROR"}[5m])) by (service)

# Duration
histogram_quantile(0.99,
  sum(rate(traces_spanmetrics_latency_bucket[5m])) by (le, service)
)

→ application 의 code 수정 없이 RED metric 자동. Auto-instrumentation 의 강점.

Tail-based Sampling

Sampling 의 의미

모든 trace 저장 = 매우 비싸:
  - 1000 RPS × 10 span/trace × 24h = 약 8억 span/일
  - 저장소 비용 폭증

해결 — Sampling:
  - Head sampling: trace 시작 시 결정 (1% · 10% 등 무작위)
  - Tail sampling: trace 끝나면 결정 (에러 · 느린 trace 위주)

Head Sampling 의 한계

Head Sampling:
  - "1% sample" → 100 trace 중 99 drop
  - 에러 trace 도 99% drop
  - 디버그 자료 부족

Tail Sampling 의 가치

Tail Sampling (Tempo · OTel Collector 의 기능):
  - 모든 trace 받음 → 분석
  - 의미 있는 trace 만 저장:
    * 모든 에러 trace (100%)
    * 느린 trace (p99 이상)
    * sampling rate (5% 의 정상 trace)
  - 의미 없는 trace drop

→ 비용 1/10 + 디버그 자료 100% 유지

Tail Sampling Config (OTel Collector)

processors:
  tail_sampling:
    decision_wait: 10s
    num_traces: 100000
    policies:
      # 1. 모든 에러
      - name: errors
        type: status_code
        status_code:
          status_codes: [ERROR]

      # 2. 느린 trace
      - name: slow
        type: latency
        latency:
          threshold_ms: 1000

      # 3. 5% 의 정상 trace
      - name: probabilistic
        type: probabilistic
        probabilistic:
          sampling_percentage: 5

Exemplar — Metric ↔ Trace 연결

Exemplar (metric sample 에 붙는 대표 trace 포인터) 가 metric 과 trace 를 한 클릭으로 이어 줘요.

동기

Dashboard 의 metric 보고 있음:
  "p99 latency 가 5s 폭증!"

질문: "어느 특정 trace 가 그 5s 야?"

답: Exemplar

Exemplar 의 의미

Histogram metric 의 sample 마다:
  - 평소: count · sum 만
  - Exemplar 있으면: 그 sample 의 *실제 trace_id* 도 저장

Grafana 의 visualization:
  - histogram chart 의 점 들 (exemplar)
  - 점 클릭 → 자동으로 Tempo 의 trace view

Setup

# Python 의 prometheus_client
from prometheus_client import Histogram

LATENCY = Histogram(
    'http_request_duration_seconds',
    'HTTP latency',
    ['endpoint']
)

# Trace context 와 함께 observe
from opentelemetry.trace import get_current_span

current_span = get_current_span()
trace_id = format(current_span.get_span_context().trace_id, '032x')

LATENCY.labels(endpoint='/api/users').observe(
    elapsed,
    exemplar={'trace_id': trace_id}
)

→ Prometheus 의 모든 sample 이 trace_id 와 결합 → Grafana 에서 클릭 한 번에 trace.

함정 정리

사고 1: 모든 trace 저장 → 비용 폭증

원인 — Sampling 없이 100% 저장 → 저장소 · network 비용 폭발.

해결Tail-based sampling. 에러 · 느린 trace 만 저장 + 정상 일부.

사고 2: Service name 일관성 X

원인 — 한 service 가 어떤 곳에선 "api" · 다른 곳에선 "user-api" · 또 다른 곳에선 "User API".

해결resource.service.name 의 표준화. environment variable 또는 config 일원화.

사고 3: Span 의 너무 깊은 nesting

원인 — 단순 query 가 수백 span 의 깊은 tree → trace view 의 가독성 0.

해결의미 있는 span 만. function call 마다 span X. 서비스 boundary · 외부 호출 · 의도된 단계.

사고 4: Trace ID 의 log 안 박힘

원인 — application log 안에 trace_id 없음 → log 와 trace 연결 X.

해결모든 log 에 trace_id 박기. OpenTelemetry 의 logging instrumentation 활용.

사고 5: OTel Collector 의 부담

원인 — 모든 service → OTel Collector 한 인스턴스 → Collector 의 CPU/메모리 폭발.

해결Collector 의 horizontal scaling + tail sampling 의 분산 + agent + gateway 의 2단계.

사고 6: Auto-instrumentation 의 누락

원인 — Auto-instrumentation 활성화 → 일부 framework 자동 X → 누락된 service 의 trace.

해결지원 framework 확인 + manual instrumentation 보강.

사고 7: Tempo 의 metric generator 의 cardinality

원인 — Metric Generator 가 모든 service × operation × status metric → cardinality 폭발.

해결generator 의 label 제한 + dimensions 의 의식.

사고 8: Block compaction 의 잘못

원인 — Tempo 의 compactor 안 동작 → block 수 폭증 → query 느림.

해결 — Compactor pod 의 resource 충분 + config 의 retention 명시.

사고 9: Trace 의 PII 누출

PII (개인식별정보 — 이메일·신용카드 등) 가 span 에 박히면 그대로 저장소까지 흘러가요.

원인 — span attribute 에 user email · password · 신용카드 박힘.

해결 — OTel Collector 의 attribute processor 로 redaction + application 의 의식.

사고 10: Trace + Log + Metric 의 timestamp 불일치

원인 — UTC vs Local · clock skew → correlation 시 시각 안 맞음.

해결모든 service 의 NTP (시각 동기화 프로토콜) 동기화 + UTC 표준 + clock skew 의식 (보통 < 1s).

운영 권장 패턴

Pattern 1: 표준 stack 의 OTel Collector

# otel-collector-config.yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:
    timeout: 10s
    send_batch_size: 1024

  tail_sampling:
    decision_wait: 10s
    policies:
      - name: errors
        type: status_code
        status_code:
          status_codes: [ERROR]
      - name: slow
        type: latency
        latency:
          threshold_ms: 1000
      - name: probabilistic
        type: probabilistic
        probabilistic:
          sampling_percentage: 5

  attributes/redact:
    actions:
      - key: user.email
        action: delete
      - key: http.request.body
        action: delete

exporters:
  otlp/tempo:
    endpoint: tempo:4317
    tls:
      insecure: true

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch, tail_sampling, attributes/redact]
      exporters: [otlp/tempo]

Pattern 2: Application 의 instrumentation 표준

# 모든 service 의 표준 setup (Python)

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.resources import Resource
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor

def setup_tracing(service_name: str, environment: str):
    resource = Resource.create({
        "service.name": service_name,
        "service.namespace": "company",
        "deployment.environment": environment,
        "service.version": os.getenv("APP_VERSION", "unknown"),
    })

    provider = TracerProvider(resource=resource)
    provider.add_span_processor(
        BatchSpanProcessor(
            OTLPSpanExporter(endpoint=os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT"))
        )
    )
    trace.set_tracer_provider(provider)

    # Auto-instrumentation
    FastAPIInstrumentor.instrument_app(app)
    SQLAlchemyInstrumentor().instrument(engine=db_engine)
    HTTPXClientInstrumentor().instrument()

# Application 시작 시
setup_tracing("user-api", "production")

Pattern 3: Service Graph + Alerts

# Tempo metric_generator config
metric_generator:
  registry:
    external_labels:
      cluster: prod

  storage:
    path: /var/tempo/generator/wal
    remote_write:
      - url: http://prometheus:9090/api/v1/write

  processor:
    service_graphs:
      enable_messaging_system_latency_histogram: true
      dimensions:
        - environment
    span_metrics:
      dimensions:
        - http.method
        - http.status_code

→ Prometheus 에 Service Graph metric + Span metric 자동 push.

# Service Graph 기반 alert
- alert: ServiceDependencyErrorRate
  expr: |
    sum(rate(traces_service_graph_request_failed_total[5m])) by (client, server) /
    sum(rate(traces_service_graph_request_total[5m])) by (client, server) > 0.05
  for: 5m
  labels:
    severity: critical
  annotations:
    summary: "{{ $labels.client }} → {{ $labels.server }} error rate > 5%"

Pattern 4: Trace + Log 의 link

Loki datasource 의 설정 (3편 의 Derived Field):

Field name: TraceID
Regex: trace_id=(\w+)
URL: ${__value.raw}
Internal link: Tempo datasource

→ Loki 의 log 에 trace_id=xxx 보이면 자동 클릭 가능
→ 클릭 = Tempo 의 trace view

반대로:

Tempo datasource 의 설정 — Trace to logs:

Datasource: Loki
Tags: ['service.name']
Query: {service="${__tags.service.name}"} |= "${__span.traceID}"

→ Tempo 의 span 에서 "View logs" 클릭
→ Loki 의 해당 service 의 같은 trace 의 log

3 pillar 의 완전한 correlation.

Pattern 5: 비즈니스 의식 의 span

# 단순 function span X
# 의미 있는 boundary 만

@app.post("/orders")
async def create_order(order_data: OrderCreate):
    with tracer.start_as_current_span("create_order") as span:
        # 비즈니스 attribute
        span.set_attribute("order.amount", order_data.amount)
        span.set_attribute("order.currency", order_data.currency)
        span.set_attribute("user.tier", user.tier)

        # 외부 service 호출 = span
        with tracer.start_as_current_span("validate_inventory"):
            await inventory_service.check(order_data.items)

        with tracer.start_as_current_span("process_payment"):
            result = await payment_service.charge(
                user.id, order_data.amount
            )
            span.set_attribute("payment.transaction_id", result.id)

        with tracer.start_as_current_span("save_order"):
            order = await db.save_order(order_data)
            span.set_attribute("order.id", order.id)

        # 비동기 작업도 trace
        with tracer.start_as_current_span("send_confirmation"):
            await notification_service.send(user.email, order)

        return order

Pattern 6: Exemplar 의 활용

# Grafana panel 의 query
histogram_quantile(0.99,
  sum(rate(http_request_duration_seconds_bucket[5m])) by (le)
)

# Panel 의 옵션:
#   Exemplars: ON
#   Datasource link: Tempo

→ 그래프 의 점 클릭 = trace view 즉시

p99 latency 차트 의 모든 spike = 클릭 한 번에 정확한 trace. 디버그 속도 폭증.

시험 직전 한 번 더 — Tempo + TraceQL 압축 노트

Trace · Span

  • Trace = 한 요청 의 전체 여정 (trace_id 동일)
  • Span = trace 의 한 service 의 작업 단위 (span_id · parent_span_id)
  • Span = service · operation · duration · attributes · events · status

프로토콜

  • OpenTelemetry (OTLP) — CNCF 표준, 권장
  • Jaeger — Uber, 자체 UI 보유
  • Zipkin — Twitter, 가장 오래
  • Tempo = 3 프로토콜 모두 호환

Instrumentation

  • Manual — 코드 안의 tracer.start_as_current_span
  • Auto-instrumentation — opentelemetry-instrument
  • eBPF (Beyla) — 코드 수정 0, 모든 언어

Tempo Storage

  • Object Storage (S3 · GCS · Azure)
  • Block (압축 flat file)
  • TraceID Lookup (O(1)) vs Search (block scan)
  • Bloom filter 의 최적화

TraceQL 4 type

  1. Span Filter — { resource.service.name = "api" }
  2. Field Comparison — { duration > 1s }
  3. Structural Relationship — >> > < ~
  4. Aggregate — | count() · | avg(duration)

Service Graph

  • trace 자동 분석 → dependency graph
  • traces_service_graph_request_total 같은 metric 생성
  • Prometheus 로 export → Grafana visualization

Metric Generator

  • trace → RED metric 자동
  • traces_spanmetrics_calls_total · _latency_bucket
  • Auto-instrumentation 의 강점 (코드 수정 0)

Tail Sampling

  • Head sampling = trace 시작 시 결정 (한계: 에러도 99% drop)
  • Tail sampling = trace 끝나면 결정 (에러 · 느린 trace · 일부 정상)
  • OTel Collector 의 tail_sampling processor

Exemplar

  • Histogram sample 에 trace_id 결합
  • Grafana 차트 의 점 클릭 → trace view
  • Prometheus client 의 exemplar 인자

사고

  • 모든 trace 저장 (비용 폭증)
  • service.name 일관성 X
  • 너무 깊은 span nesting (가독성 0)
  • log 에 trace_id 안 박힘 (correlation X)
  • OTel Collector 의 부담 (scaling 필요)
  • Auto-instrumentation 누락 framework
  • Metric Generator cardinality 폭발
  • Block compaction 잘못
  • Trace 의 PII 누출
  • Timestamp 불일치 (NTP)

패턴

  • 표준 OTel Collector (batch + tail_sampling + attribute redact)
  • Application instrumentation 표준 (FastAPI · SQLAlchemy · HTTPX 자동)
  • Service Graph + dependency alert
  • Trace ↔ Log link (Derived Field · Trace to logs)
  • 비즈니스 attribute (order.amount · user.tier)
  • Exemplar 의 활용 (p99 spike → 정확한 trace)

공식 문서: Grafana Tempo · OpenTelemetry 에서 더 깊은 spec 을 확인할 수 있어요.

시리즈 다른 편 (앞뒤 글 모음)

이전 글:

다음 글:

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!