GN⁺: OpenTelemetry 작동에 성공했는데, 왜 이렇게 복잡할까?
(iconsolutions.com)- OpenTelemetry (OTel) 은 관측 가능성 프레임워크 및 도구 모음
- 기존 도구로는 Prometheus(메트릭), Logstash(로그), OpenTracing(분산 추적)이 있음
- OTel은 메트릭, 로그, 추적이라는 세 가지 신호를 표준화하고, OpenTelemetry Protocol (OTLP), OpenTelemetry Collector, 다양한 언어 SDK를 제공함
- 오픈 소스, 벤더 독립, 언어 독립, 분산, 제로 코드 등 모든 유행어를 충족함
OTel의 문제점
- 로그와 메트릭스는 기존 도구와 유사해 손쉽게 통합 가능. 설정 추가만으로도 OTel로 전환 가능
- 추적 구현의 어려움
-
Context Propagation: 분산 시스템 간 요청 정보를 전달하기 위해 필요
- 요청 단위를 Trace와 Span으로 나눔
- 예: "구매하기" 버튼 클릭 → Frontend → Backend → Payment/Shipping 서비스 간의 관계를 Span으로 표현
- OTel의 지원 방식:
- 다양한 Context Propagation 표준 제공 (예: b3, W3C Trace Context)
- OTel은 여러 표준을 지원해야 함
- 기존 OpenTracing에서 OTel로 전환 시 예상치 못한 충돌 발생
- Lightbend Telemetry는 OpenTelemetry 로그와 메트릭을 지원하지만, 추적은 지원하지 않음.
-
Context Propagation: 분산 시스템 간 요청 정보를 전달하기 위해 필요
API 간 충돌 문제
Spring과 Akka의 통합 문제
- Spring: 애플리케이션 부트스트래핑 및 구성 관리
- Akka: 이벤트 소싱, 스케줄링, 클러스터링 등에 사용
- 문제:
- OTel 사용 시, Spring과 Akka의 추적 API가 상호작용하지 않음
- 동일한 Trace ID를 공유하지 못함 → 잘못된 추적 결과
해결책: OpenTracing Shim
- OTel Tracer를 OpenTracing Tracer로 변환하는 도구
- 문제:
- Akka의 Lightbend Telemetry가 OpenTracing 구현을 맞추지 못함
- Jaeger와 OTel이 서로 다른 SpanContext를 요구하여 충돌 발생
해결 과정
OTel과 OpenTracing의 수동 통합
- OTel Context를 수동으로 Jaeger SpanContext로 변환:
- OTel 컨텍스트를 Java Map에 삽입
- Jaeger SpanContext에 해당 맵을 추출하여 수동으로 설정
- 코드 예:
var otelContext = new HashMap<>(); GlobalOpenTelemetry.get().getPropagators().getTextMapPropagator() .inject(Context.current(), otelContext, (carrier, key, value) -> carrier.put(key, value)); var openTracingContext = new TextMapCodec(false).extract(new TextMapAdapter(otelContext)); GlobalExtendedTracer.get().local().activateContext(openTracingContext);
- 결과:
- Spring과 Akka 간의 추적 데이터 통합 성공
- HTTP 경계 간 Trace가 제대로 연결됨
결론
복잡함의 원인
- 두 가지 다른 추적 라이브러리의 통합 시도
- OpenTelemetry가 제공하는 표준은 유용하나, 기존 도구와의 충돌 가능성 존재
OpenTelemetry의 가치
- OpenTelemetry는 관찰 가능성의 표준화를 위해 중요한 역할을 수행
- 복잡하지만 강력한 오픈 소스 프로젝트
향후 과제
- Akka의 Trace Context가 스레드 간 올바르게 전달되는지 확인 필요
- 프로젝트 개선을 위해 추가적인 테스트 및 피드백 필수
Hacker News 의견
-
Otel을 배우고 포팅하는 동안 Java 세계로 돌아간 느낌이었음. 코드 탐색 시 EnterpriseFizzBuzz 같은 느낌이었고, 발견 가능성이 전혀 없었음. NodeJS에서는 StatsD보다 약 4배의 CPU 사용량이 있었고, 자체 집계를 통해 이를 줄였음. OTEL은 코어당 하나의 프로세스를 사용하는 언어에 적대적임. Prometheus를 사용하는 것이 좋음.
-
Otel은 다양한 관측 가능성 공급업체가 제공하는 SDK, 에이전트, API로 인해 복잡하게 느껴질 수 있음. OpenTelemetry를 표준으로 사용하게 되었고, Grafana가 OpenTelemetry를 채택한 것에 찬사를 보냄. Datadog의 가격이 중간 규모 회사와 대기업 사이에서 통제 불가능해졌음. 문서화가 더 나아질 수 있으며, 프로그래밍 언어별로 온보딩 문서가 다름. NodeJS/Typescript 스택에서 OpenTelemetry를 빠르게 시작할 수 있는 패키지와 예제 Grafana 스택을 만들었음.
-
로컬 개발에서 로그, 추적, 메트릭 지원을 원했지만 여러 Docker 이미지를 실행하고 싶지 않았음. .NET 팀이 .NET Aspire를 출시했으며, 로컬 개발 스택에서 모든 것을 쉽게 시각화할 수 있음. k8s에 배포할 때 OTEL 엔드포인트를 DataDog 에이전트에 연결하면 모든 것이 작동함. DataDog의 맞춤형 추적 라이브러리와 SDK를 피하고 OTEL을 사용함.
-
OpenTelemetry는 필요에 따라 복잡할 수 있음. 우리 팀은 간단하게 사용하며, 수동 계측을 사용하여 관찰할 대상을 신중하게 선택함. 두 가지 백엔드를 사용하며, 하나는 저렴한 서드파티 서비스, 다른 하나는 Jaeger 설치로 로컬 개발을 위한 것임.
-
Python에서 Otel을 사용할 때 Logfire의 클라이언트를 사용하는 것이 좋음. Pydantic 팀이 만든 클라이언트가 공식 Otel 라이브러리보다 훨씬 좋고 간단함.
-
많은 웹 프레임워크가 대부분의 계측을 자동으로 처리함. opentelemetry-js를 사용하고 Signoz 같은 것을 자체 호스팅하면 한 시간 이내에 많은 데이터를 얻을 수 있음.
-
OpenTelemetry 채택을 쉽게 하기 위해 단일 명령어로 실행할 수 있는 오픈 소스 프로젝트를 시작했음.
-
Python에서 표준 스택을 사용하면 몇 가지 임포트만으로 모든 것을 자동으로 추적할 수 있음. Otel은 Otel 호환 소프트웨어를 판매하는 회사들을 위해 설계되었기 때문에 복잡함.
-
OpenTelemetry는 추적에서 시작되었지만, 메트릭과 로그는 전문 솔루션에 맡기는 것이 더 나음. 모든 것을 하나의 우산 아래에 두려는 시도는 "누수 추상화" 문제처럼 느껴짐. SQL 데이터베이스도 모든 것을 동시에 할 수 있지만, 그렇다고 해서 그래야 하는 것은 아님.