예전에 Jaeger로 분산 추적을 띄워보는 글을 쓴 적이 있다. OpenTelemetry 계측을 붙인 서비스를 운영하다 보면 백엔드보다 계측 쪽에서 신경 쓸 일이 더 많다. 마침 OpenTelemetry 공식 블로그에 이 문제를 정면으로 다룬 글이 올라와서, 운영자 입장에서 읽고 정리해 둔다.
요약하면, 시맨틱 컨벤션이 stable이 됐다고 해서 계측 라이브러리가 바로 그 모양으로 텔레메트리를 내보내지는 않는다. 이 격차를 눈에 보이게 하려고 OpenTelemetry 프로젝트는 두 가지를 만들고 있다. 버전별로 "무엇을 방출한다고 기술돼 있나"를 보여주는 Ecosystem Explorer와, "실제로 무엇이 방출되나"를 측정하는 semantic-conventions-conformance 프로젝트다. 업그레이드 전에 텔레메트리 변화를 알고 싶다면 지금은 Explorer의 버전 비교와 Weaver live-check를 함께 쓰는 방법이 현실적이다.
1. 개요
원문은 2026-09-25 OpenTelemetry 블로그에 올라온 Jay DeLuca(Grafana Labs)의 "Exploring the OpenTelemetry Instrumentation Ecosystem"이다. 새 기능 발표라기보다, 계측 생태계의 구조적인 문제와 이를 풀려는 프로젝트들의 현재 상태를 설명하는 글이다.
용어부터 정리하자. OpenTelemetry는 API, SDK, 프로토콜, 시맨틱 컨벤션, 계측, 그리고 Collector 같은 도구로 이뤄진다. API와 프로토콜은 텔레메트리를 어떻게 만들고 주고받는지를 정한다.
계측(instrumentation)은 애플리케이션 안에서 일어나는 일을 관찰해 스팬, 메트릭, 로그 같은 텔레메트리로 바꾸는 실제 코드다. Java agent가 HTTP 클라이언트 호출을 가로채 스팬을 만드는 부분이 여기에 해당한다.
시맨틱 컨벤션(semantic conventions)은 계측 작성자들이 관찰 대상을 기술할 때 쓰는 공통 어휘이자 약속이다. 이게 있어야 Go 서비스의 HTTP 요청과 Python 서비스의 HTTP 요청이 백엔드에서 같은 모양으로 보인다.
대시보드나 알람 쿼리는 속성 이름에 기대고 있다. 그래서 운영자에게 시맨틱 컨벤션은 사실상 API 계약과 같다.
2. 컨벤션이 stable이어도 구현이 늦는 이유
컨벤션이 stable로 올라가는 순간은 끝이 아니라 출발점이다. 컨벤션 문서가 발표된다고 각 언어의 계측 코드가 자동으로 바뀌지는 않는다. 어떤 라이브러리가 새 컨벤션을 이미 반영했는지도 컨벤션 문서만 봐서는 알 수 없다.
원문의 타임라인을 보면 시간 규모가 감이 온다. HTTP 시맨틱 컨벤션은 2019년 6월에 스펙에 들어갔고, 핵심 컨벤션이 stable이 된 건 2023년 11월이다. Database 컨벤션은 비슷한 시기에 시작했지만 stable 도달은 2025년 5월이다. 컨벤션을 확정하는 데만 몇 년이 걸리고, 계측 구현은 그 뒤에 따라간다.
그럼 계측 소스를 직접 열어보면 되지 않나 싶지만, 막상 해보면 여기서 막힌다. 실제로 어떤 속성이 붙는지는 설정 옵션과 애플리케이션 동작에 따라 달라질 수 있다. 코드 한 파일만 봐서는 "우리 서비스에서 이 스팬에 무엇이 찍힐지"를 확정하기 어렵다.
현장에서는 릴리스 노트와 이슈 트래커, 문서를 번갈아 뒤지다가 결국 스테이징에 올려 직접 확인하는 방법으로 푼다. 원문에 인용된 Karimot Isiaka의 사용자 리서치도 같은 모습을 보여준다. 사람들이 계측 관련 답을 얻으려고 문서, 저장소, 릴리스 노트를 일일이 뒤져 짜맞춘다는 것이다.
3. Ecosystem Explorer가 보여주는 것
OpenTelemetry Ecosystem Explorer(https://explorer.opentelemetry.io/)는 OTel 생태계 구성요소를 카탈로그로 만들고, 각 구성요소가 무엇을 하는지 설명하는 웹사이트다. 현재 조회할 수 있는 대상은 Java agent와 Collector다.
업그레이드를 앞둔 운영자에게 쓸모 있는 건 Java 계측의 버전 선택 기능이다. 버전을 고르면 그 버전이 방출한다고 기술된 텔레메트리와 설정 옵션을 볼 수 있고, 두 릴리스를 나란히 비교할 수도 있다. 흩어진 릴리스 노트를 짜맞추던 작업을 버전별 뷰 하나로 대신하려는 게 Explorer의 목적이다.
다만 지금 Explorer가 보여주는 건 "이 컴포넌트가 무엇을 방출한다고 기술돼 있나"다. 실측이 아니라 선언이다.
앞으로는 아래에서 설명할 conformance 프로젝트의 실측 결과를 이 카탈로그에 결합하려 한다. 그러면 "구현이 실제로 어디까지 왔는지"와 "메인테이너와 기여자가 어디에 집중해야 하는지"까지 보여줄 수 있다. 이 부분은 아직 완성되지 않았다.
원문은 카탈로그 데이터를 모으는 것 자체가 일의 대부분이라고 강조한다. Java에서 기초 메타데이터 지원부터 내용이 채워진 instrumentation catalog까지 가는 데 1년 넘게 걸렸다. 정보 중 일부는 코드에서 자동 생성할 수 있지만, 일부는 메인테이너가 의도와 설정을 직접 기술해야 하고, 일부는 런타임에 돌려봐야만 알 수 있다.
4. semantic-conventions-conformance와 Weaver live-check
4-1. 프로젝트가 하는 일
semantic-conventions-conformance 프로젝트는 작은 테스트 시나리오를 실행해 텔레메트리를 모은다. 그리고 그걸 시맨틱 컨벤션과 시나리오에 선언한 기대값에 대조한다. 대조에는 Weaver의 live-check 기능을 쓴다.
저장소에는 HTTP, database, gen-ai 같은 도메인별 시나리오와 Python, Java, JavaScript, Ruby, .NET, PHP, Go용 실행기가 들어 있다.
결과는 JSON으로 공개된다. 여러 시나리오 결과를 집계해 어떤 구현체가 어떤 속성, 메트릭, 신호를 놓쳤는지 분석할 수 있다. 결과 사이트는 https://open-telemetry.github.io/semantic-conventions-conformance에 있다.
4-2. Weaver는 무엇인가
OpenTelemetry Weaver는 프로젝트의 텔레메트리 스키마를 시맨틱 컨벤션 레지스트리 형식으로 정의하는 도구다. 정의해 둔 스키마로 문서나 코드를 생성할 수 있고, 실제로 방출된 텔레메트리를 스키마에 대조해 검사할 수도 있다. 후자가 live-check다.
live-check는 OTLP 수신기로 텔레메트리를 받아 레지스트리와 비교한다. 발견 사항은 violation, improvement, information 세 단계로 분류하고, 이 중 violation이 가장 심각한 단계다.
4-3. HTTP 클라이언트 비교에서 드러난 것
원문에는 7개 언어의 HTTP 클라이언트 conformance 실행을 비교한 스냅샷이 실려 있다. 필수(required) 속성 4개는 테스트된 계측 거의 전부에서 관찰됐다. 반면 권장(recommended) 속성 2개는 상대적으로 덜 일관되게 관찰됐다.
운영 관점에서 이 차이는 의미가 있다. 필수 속성만으로 짠 대시보드는 언어가 섞여도 잘 버틸 가능성이 크다. 반면 권장 속성에 기댄 쿼리는 서비스 언어에 따라 빈 값이 나올 수 있다. 다언어 MSA에서 공통 대시보드를 만든다면 권장 속성에 걸린 패널부터 의심해 보자.
4-4. 결과를 읽을 때 주의할 점
표의 빈 셀은 "이번 실행에서 관찰되지 않았다"는 뜻이다. "그 계측이 절대 그 속성을 방출하지 않는다"는 뜻이 아니다. 선택적 속성은 상황에 따라 안 붙을 수 있고, 시나리오가 그 상황을 만들지 않았을 수도 있다. 실험적 텔레메트리나 커스텀 텔레메트리도 결과에 표시돼야 한다는 게 원문의 입장이다.
그러니 conformance 결과를 "이 언어는 불량"이라는 판정표로 쓰면 안 된다. 우리 서비스가 쓰는 속성이 비어 있다면, 직접 재현해볼 단서로 쓰는 게 올바른 사용법이다.
4-5. 실제로 쓰이고 있는 곳
Java SIG는 이미 이 conformance 데이터로 Java agent 3.0 릴리스 진행 상황을 추적하고 있다. Database 컨벤션은 이미 stable이고, RPC와 messaging 쪽도 진전이 있었다.
Java agent는 2.0에서 stable HTTP 컨벤션을 채택했는데, 감사 과정에서 격차가 드러나 그때 고쳐졌다. stable을 채택했다고 선언한 뒤에도 실측해 보면 빠진 부분이 나올 수 있다는 예다.
5. 지금 당장 확인해볼 수 있는 것
Explorer와 conformance가 완성되기를 기다릴 필요는 없다. 업그레이드 전에 해볼 수 있는 확인 순서를 정리한다.
5-1. Explorer에서 버전 비교
Java agent를 쓰고 있다면 Explorer에서 현재 버전과 올릴 버전을 골라 비교한다. 우리가 켜 둔 계측 모듈에서 기술된 텔레메트리와 설정 옵션이 어떻게 달라지는지 먼저 본다. Collector 컴포넌트도 같은 사이트에서 조회된다.
5-2. conformance 결과 페이지 확인
Java 외 언어라면 conformance 결과 사이트에서 우리 언어의 HTTP 또는 database 시나리오 결과를 확인한다. 대시보드가 기대는 속성이 관찰되지 않았다면 그 속성을 로컬 검증 대상으로 적어 둔다.
5-3. 로컬에서 Weaver live-check 돌려보기
가장 확실한 방법은 업그레이드할 버전을 붙인 애플리케이션을 live-check에 직접 물려보는 것이다. live-check는 기본으로 127.0.0.1:4317에서 OTLP gRPC를 받는다. 기본 레지스트리는 upstream 시맨틱 컨벤션 저장소(https://github.com/open-telemetry/semantic-conventions.git[model])다.
먼저 짚고 갈 옵션이 있다. live-check는 OTLP 수신이 없으면 기본 10초 뒤에 리스너를 스스로 멈춘다. 이 시간은 --inactivity-timeout(리스너를 멈추기 전 최대 무활동 시간, 초 단위)으로 정한다. JVM과 애플리케이션이 뜨는 데 10초 넘게 걸리면 트래픽이 들어오기도 전에 live-check가 끝나고, 리포트가 비거나 일부만 담길 수 있다. 그래서 아래 예시에서는 --inactivity-timeout 0으로 무제한을 주고, 끝낼 때 직접 멈춘다. 무제한이 부담스러우면 기동 시간보다 넉넉한 값(예: 300)을 준다.
터미널은 두 개를 쓴다. 터미널 1에서 live-check를 포그라운드로 띄운다.
# 터미널 1: live-check (OTLP gRPC 4317, admin 포트 기본 4320) $ weaver registry live-check --inactivity-timeout 0 --format json --output ./lc-out
터미널 2에서는 애플리케이션을 백그라운드로 띄우고 요청을 보낸 뒤, 같은 터미널에서 live-check를 멈춘다.
# 터미널 2: 애플리케이션과 트래픽 $ export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 $ export OTEL_EXPORTER_OTLP_PROTOCOL=grpc $ java -javaagent:./opentelemetry-javaagent.jar -jar app.jar > app.log 2>&1 & $ APP_PID=$! # app.log에서 기동 완료를 확인한 뒤 평소 트래픽과 비슷한 요청을 몇 번 보낸다 $ curl -s http://localhost:8080/api/orders/1 > /dev/null # 스팬이 내보내질 때까지 몇 초 기다린 뒤 live-check를 멈춘다 (둘 중 하나) $ curl -s -X POST http://localhost:4320/stop $ kill -HUP $(pgrep -f "weaver registry live-check") $ kill $APP_PID $ ls ./lc-out
live-check는 SIGHUP을 받거나 admin 포트(기본 4320)의 /stop으로 요청을 받으면 수집을 끝내고 리포트를 쓴다. kill -HUP은 live-check 프로세스에 보내야 하는데, 터미널 2에서는 $!로 PID를 알 수 없어서 pgrep으로 찾았다. 터미널을 오가기 번거로우면 /stop 엔드포인트 쪽이 편하다. 마지막 요청 뒤에 잠깐 기다리는 이유는, Java agent가 스팬을 배치로 모아 몇 초 간격으로 내보내기 때문이다.
업그레이드 전 버전과 후 버전으로 두 번 돌려 ./lc-out의 JSON을 비교하면, 우리 서비스 트래픽 기준으로 어떤 속성이 새로 생기고 빠지는지 볼 수 있다. 결과 내용은 애플리케이션과 요청 패턴에 따라 달라지므로 여기에 예시 값은 적지 않는다.
막상 돌려보면 아래 세 군데에서 자주 걸린다.
- 무활동 타임아웃:
--inactivity-timeout을 주지 않으면 기본 10초 동안 수신이 없을 때 live-check가 먼저 끝나 버린다. JVM 기동이 느린 애플리케이션이라면 이 설정이 짧아서 리포트가 비어 있을 수 있다. 0(무제한)이나 충분히 큰 값을 준다. - 포트 충돌: 로컬 Collector가 4317을 이미 잡고 있으면 live-check가 뜨지 않는다. Collector를 내리거나
--otlp-grpc-port로 다른 포트를 지정하고, 애플리케이션의OTEL_EXPORTER_OTLP_ENDPOINT도 같이 바꿔준다. - 프로토콜 불일치: Java agent 2.x의 기본 OTLP 프로토콜은
http/protobuf다. live-check는 gRPC를 받으므로OTEL_EXPORTER_OTLP_PROTOCOL=grpc를 빼먹으면 아무것도 수집되지 않는다. 리포트가 비어 있다면 이 설정부터 확인해보자.
하나 더, 기본 레지스트리는 upstream 최신 모델이다. 특정 컨벤션 버전에 대조하고 싶으면 -r 옵션으로 레지스트리 위치를 명시한다. 결과를 나중에 재현하려면 어떤 컨벤션 버전과 대조했는지 같이 기록해 두자. 이건 6장에서 원문이 말하는 재현 가능한 리포트의 조건이기도 하다.
6. 메인테이너와 호환 프로젝트 쪽에서 보는 과제
6-1. 레지스트리 등록 동결이 드러낸 문제
최근 OpenTelemetry 생태계 레지스트리의 신규 등록 동결(registry freeze)이 이 문제를 부각시켰다. 메인테이너가 검증할 시간과 도구보다 제출이 더 많았다. 게다가 목록에 프로젝트를 올리는 것만으로는 그 통합이 실제로 무엇을 하는지 사용자에게 알려주지 못했다.
OTel 조직 바깥에서 "OpenTelemetry 호환" 또는 "네이티브"를 내세우는 프로젝트에도 같은 질문이 걸린다. 사용자가 무엇을 기대할 수 있는지, 메인테이너가 그걸 어떻게 입증하고 최신으로 유지하는지다. 레지스트리 논의에서 Explorer가 그 후계자로 거론됐지만, 원문은 아직 그 역할을 맡을 준비가 안 됐다고 분명히 적었다.
6-2. 재현 가능한 리포트에 필요한 네 가지
장기 목표는 프로젝트가 어떤 신호를 방출하는지, 어떤 컨벤션을 따르는지, 테스트 시나리오의 텔레메트리가 요건을 만족하는지를 반복 가능한 점검으로 입증하게 하는 것이다. 원문은 그 리포트에 다음 네 가지가 있어야 한다고 적는다.
- 테스트 대상 릴리스
- 적용 중인 설정 옵션과 그 동작
- 실행한 테스트 시나리오
- 대조한 시맨틱 컨벤션 버전
사내에서 계측 검증을 CI에 넣을 때도 이 네 항목을 그대로 리포트 머리말로 쓰자. 하나라도 빠지면 다음 업그레이드 때 결과를 비교할 기준이 사라진다.
6-3. Weaver 채택과 자가 점검 제안
원문은 Weaver 채택을 권장하지만 Explorer 참여의 필수 조건은 아니라고 명시한다. 문서만으로 시작해도 텔레메트리 정의가 구조화되고 재사용 가능해진다. 코드 생성은 필요할 때 그 위에 얹으면 된다.
관련해서 "OpenTelemetry Support Self-Assessment and Maintainer Guidance"라는 제안 프로젝트도 있다. 메인테이너가 직접 돌려볼 수 있는 도구와 프로젝트 유형별 가이드를 제공하자는 내용이다. 결과 공유는 메인테이너 재량이고, 공유된다면 Explorer가 그 근거를 옆에 노출하는 방안도 검토할 수 있다고 한다.
이 방향은 OTel 프로젝트가 그래주에이션 이후를 위해 제안한 로드맵과 맞닿아 있다. 그 로드맵은 계측 도구 개선, 유지보수 비용 절감, 언어 전반의 시맨틱 컨벤션 도구 확대를 요구한다. 원문은 Explorer가 격차를 눈에 보이게 만들어 이 목표에 기여한다고 설명한다.
6-4. 메인테이너에게 원문이 권하는 첫 단계
원문의 권고는 컴포넌트 하나부터 시작하라는 것이다. 그 컴포넌트의 소스, 설정, 문서, 테스트가 이미 무엇을 말해주는지 확인한다. 그다음 자동 생성할 수 있는 부분과 런타임 점검이 필요한 부분을 나누고, Explorer 저장소에 이슈로 예시를 가져온다. 이미 Weaver로 텔레메트리를 정의하고 있다면 레지스트리와 예시 컴포넌트를 이슈로 공유해 달라는 요청도 있다.
Explorer 편입을 준비하는 프로젝트에는 방출할 텔레메트리를 정의하고, 그걸 만드는 구성요소와 설정을 설명하고, 이 설명을 릴리스와 함께 공개하라고 권한다.
7. 정리
2026-09-25 기준으로 Java agent instrumentation catalog는 공개돼 있고, 다른 언어와 구성요소는 작업이 진행 중이다. OTel 팀은 각 SIG 사용자에게 어떤 근거가 실제로 유용한지 다른 SIG들과 논의하려 한다. 앞으로는 릴리스마다 반복 측정해서 어떤 SIG가 어떤 격차를 닫았는지, 여러 SIG가 공통으로 겪는 문제가 무엇인지까지 보여주는 걸 목표로 한다.
운영자로서 권장은 이렇다. Java agent라면 업그레이드 전에 Explorer 버전 비교를 먼저 본다. 그 밖의 언어라면 conformance 결과를 참고하되, 최종 판단은 우리 트래픽으로 돌린 Weaver live-check 결과로 한다. 대시보드와 알람이 기대는 속성 목록을 미리 뽑아 두면 이 비교가 훨씬 빨라진다. 컨벤션이 stable이라는 사실만 믿고 계측 라이브러리를 올리지는 말자.