OpenTelemetry
오픈텔레메트리
관측 가능성 표준 프레임워크. 트레이스, 메트릭, 로그 통합.
오픈텔레메트리
관측 가능성 표준 프레임워크. 트레이스, 메트릭, 로그 통합.
OpenTelemetry(OTel)는 분산 시스템의 관측 데이터(트레이스, 메트릭, 로그)를 수집, 처리, 내보내기 위한 오픈소스 표준 프레임워크입니다. CNCF(Cloud Native Computing Foundation)의 프로젝트로, Kubernetes 다음으로 활발한 프로젝트입니다. 벤더 중립적이어서 특정 관측 도구에 종속되지 않습니다.
OpenTelemetry는 OpenTracing과 OpenCensus가 합쳐져 탄생했습니다. 두 프로젝트의 장점을 결합하여 단일 표준을 제공합니다. API(인터페이스 정의), SDK(구현체), Collector(데이터 수집/처리/내보내기), OTLP(OpenTelemetry Protocol)로 구성됩니다.
애플리케이션에 OpenTelemetry SDK를 통합하면 트레이스, 메트릭, 로그를 생성합니다. 자동 계측(auto-instrumentation)으로 HTTP 요청, 데이터베이스 쿼리 같은 공통 작업을 코드 수정 없이 추적할 수 있습니다. 수동 계측으로 비즈니스 로직에 맞는 커스텀 span과 메트릭을 추가합니다.
OpenTelemetry Collector는 에이전트나 게이트웨이로 배포되어 데이터를 수신, 처리(필터링, 변환, 샘플링), 내보냅니다. 하나의 Collector로 Jaeger, Prometheus, Datadog 등 여러 백엔드로 동시에 데이터를 보낼 수 있습니다. 애플리케이션 코드 변경 없이 백엔드를 교체할 수 있는 유연성을 제공합니다.
// tracing.js - Node.js OpenTelemetry SDK 설정
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');
const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-grpc');
const { PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
const sdk = new NodeSDK({
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'order-api',
[SemanticResourceAttributes.SERVICE_VERSION]: '2.1.0',
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: process.env.NODE_ENV
}),
// 트레이스 내보내기
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://otel-collector:4317'
}),
// 메트릭 내보내기
metricReader: new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter(),
exportIntervalMillis: 30000
}),
// 자동 계측 (Express, HTTP, DB 등)
instrumentations: [
getNodeAutoInstrumentations({
'@opentelemetry/instrumentation-fs': { enabled: false }, // 파일시스템 제외
'@opentelemetry/instrumentation-http': {
ignoreIncomingPaths: ['/health', '/metrics']
}
})
]
});
sdk.start();
process.on('SIGTERM', () => sdk.shutdown());
# otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 1s
send_batch_size: 1024
memory_limiter:
check_interval: 1s
limit_mib: 4000
spike_limit_mib: 500
# 샘플링 (10%만 수집)
probabilistic_sampler:
sampling_percentage: 10
# 민감 정보 제거
attributes:
actions:
- key: http.request.header.authorization
action: delete
exporters:
# 트레이스 -> Tempo
otlp/tempo:
endpoint: tempo:4317
tls:
insecure: true
# 메트릭 -> Prometheus
prometheus:
endpoint: 0.0.0.0:8889
# 로그 -> Loki
loki:
endpoint: http://loki:3100/loki/api/v1/push
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, batch, probabilistic_sampler]
exporters: [otlp/tempo]
metrics:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [prometheus]
logs:
receivers: [otlp]
processors: [memory_limiter, batch, attributes]
exporters: [loki]
SRE: "Datadog 비용이 너무 높아요. 자체 Observability 스택으로 전환하면 어떨까요?"
개발자: "그러면 코드를 전부 수정해야 하는 거 아닌가요?"
시니어: "OpenTelemetry를 쓰고 있으면 Collector 설정만 바꾸면 돼요. 코드는 그대로 두고 exporter만 Tempo, Prometheus, Loki로 바꾸면 됩니다. 벤더 종속이 없는 게 OTel의 장점이에요."
면접관: "OpenTelemetry 도입 경험이 있으신가요?"
지원자: "네, Python과 Node.js 서비스에 OTel SDK를 통합했습니다. 자동 계측으로 HTTP, PostgreSQL, Redis 호출을 코드 수정 없이 추적하고, 비즈니스 로직에는 수동으로 custom span을 추가했어요. Collector를 사이드카로 배포해서 샘플링과 데이터 정제를 담당하게 했습니다. 백엔드 변경이 있어도 코드는 건드리지 않아서 유지보수가 쉬웠어요."
리뷰어: "이 비동기 작업에도 span을 전파해야 해요. context.with(span.context())로 감싸주세요, 안 그러면 트레이스가 끊겨요."
작성자: "아, Promise.all 안의 작업들이 별개 트레이스로 보이는 게 이거 때문이었군요. context 전파 추가하겠습니다."