所有 Span 都以 unknown_service 的名义进来了
한국어 원문으로 표시합니다.
목표
리소스가 기본값·환경변수·코드에서 어떤 우선순위로 정해지는지 실제 SDK 로 확인하고, OTLP 에서 리소스가 묶이는 구조와 안정 HTTP 시맨틱 컨벤션을 코드로 지킨 뒤 스키마가 다른 리소스를 안전하게 병합합니다.
왜 중요한가
텔레메트리는 '어디서 왔는가' 를 리소스로 말합니다. service.name 이 unknown_service 로 들어오면 대시보드의 서비스 목록이 한 칸으로 뭉치고, 환경변수와 코드가 서로 다른 값을 주면 누가 이겼는지 알기 전에는 원인을 찾을 수 없습니다. 시맨틱 컨벤션은 백엔드와 대시보드가 속성 이름과 상태의 뜻을 약속한 것이라, 404 를 오류로 표시하거나 경로 원문을 스팬 이름에 넣으면 오류율과 카디널리티가 함께 틀어집니다.
준비된 환경
/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py init 이 /root/otca-resource/ 에 resource.py·grouping.py·server.py·merge.py 시작 파일을 둡니다. /opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py probe [env파일] 은 OTEL_ 환경변수를 모두 지운 새 프로세스에 env 파일의 값만 넣고 Resource.create({}) 를 부릅니다. /opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show N 은 N단계 실험 결과를 보여 줍니다. lab-dev 이미지의 OpenTelemetry Python SDK 1.44.0(/opt/otel-lab)을 쓰고 네트워크는 쓰지 않습니다. 채점기는 같은 SDK 로 여러분의 파일을 다시 실행해 동작과 적은 값을 대조합니다.
단계
/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py init으로 재료를 만든 뒤/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py probe를 실행합니다. OTEL_ 환경변수를 모두 지운 새 프로세스에서Resource.create({})결과를 보여 줍니다./root/otca-resource/01-default.txt에service_name=,sdk_language=(telemetry.sdk.language),has_instance_id=(service.instance.id 가 있는지 true/false)를 적으세요./root/otca-resource/02-otel.env에OTEL_RESOURCE_ATTRIBUTES=service.name=cart,deployment.environment.name=staging과OTEL_SERVICE_NAME=checkout두 줄을 씁니다./opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py probe /root/otca-resource/02-otel.env결과를 보고/root/otca-resource/02-env.txt에service_name=,environment=,winner=(service.name 을 정한 환경변수 이름)를 적으세요./root/otca-resource/resource.py의make_resource()가Resource.create로 service.namecheckout-api, service.version2.4.1을 정해 돌려주게 고칩니다. 채점기는OTEL_SERVICE_NAME=checkout,OTEL_RESOURCE_ATTRIBUTES=service.version=0.0.1,deployment.environment.name=prod를 준 프로세스에서 이 함수를 부릅니다./opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 3결과를/root/otca-resource/03-code.txt에service_name=,service_version=,environment=로 적으세요./root/otca-resource/04-otel.env에OTEL_RESOURCE_ATTRIBUTES한 줄을 씁니다.team.owner의 값은payments,risk이고cloud.region=ap-northeast-2도 함께 넣습니다. 쉼표는 퍼센트 인코딩(%2C)합니다./opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 4는 인코딩한 값과, 같은 값을 인코딩하지 않았을 때를 함께 보여 줍니다./root/otca-resource/04-encoding.txt에team_owner=와unencoded_team_owner=를 적으세요./root/otca-resource/grouping.py의emit(provider_a, provider_b)가 provider_a 의 트레이서로 스팬 2개, provider_b 로 스팬 1개를 만들고 끝내게 고칩니다./opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 5는 두 프로바이더(service.name frontend, orders-db)의 스팬을 OTLP 로 인코딩한 결과를 보여 줍니다./root/otca-resource/05-grouping.txt에resource_spans=,spans=,service_name_on_spans=(스팬 속성에 service.name 이 있는지 true/false)를 적으세요./root/otca-resource/server.py의handle(tracer, request)가 요청 하나의 서버 스팬을 안정(stable) HTTP 시맨틱 컨벤션대로 만들게 고칩니다. 채점기는 201·404·503 요청 세 개로 확인합니다 — 종류 SERVER, 이름{메서드} {경로 템플릿}, 속성http.request.method·url.path·http.route·http.response.status_code(정수), 옛 이름(http.method·http.target·http.status_code) 없음, 5xx 이면 상태 ERROR 와error.type(상태 코드 문자열), 그 밖에는 상태를 비워 둠.{RS} show 6으로 만든 스팬을 볼 수 있습니다./opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 7은 탐지된 리소스(schema 1.21.0, service.name unknown_service)에 설정한 리소스(schema 1.26.0, service.name checkout)를merge한 결과를 보여 줍니다./root/otca-resource/07-merge.txt에naive_service_name=을 적고,/root/otca-resource/merge.py의combine(detected, configured)가 설정한 값이 이기고 탐지된 host.name 은 남으며 schema_url 은 설정한 리소스를 따르는 새 리소스를 돌려주게 고치세요. 입력 리소스는 바꾸지 않습니다.
참고
- 명세는 OTEL_RESOURCE_ATTRIBUTES 의 값에서 쉼표와 등호를 퍼센트 인코딩하라고 하고, 오류가 있으면 값 전체를 버리라고 권합니다(SHOULD). 4단계에서 보는 부분 적용은 이 SDK 버전의 실제 동작이며 다른 언어 SDK 와 다를 수 있습니다.
- 흔한 실수:
Resource(...)생성자로 만들어 환경변수가 무시되는 것, 서버 스팬에서 4xx 를 ERROR 로 표시하는 것, merge 가 조용히 실패한 결과를 그대로 쓰는 것. - Resource SDK · HTTP spans · SDK configuration
아무것도 설정하지 않은 서비스의 이름
/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py init 으로 재료를 만든 뒤 /opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py probe 를 실행합니다. OTEL_ 환경변수를 모두 지운 새 프로세스에서 Resource.create({}) 결과를 보여 줍니다. /root/otca-resource/01-default.txt 에 service_name=, sdk_language=(telemetry.sdk.language), has_instance_id=(service.instance.id 가 있는지 true/false)를 적으세요.
service.name 은 필수 속성이라 비어 있으면 SDK 가 기본값을 채웁니다. 어떤 속성은 설정하지 않아도 SDK 가 스스로 만듭니다.
환경변수 두 개가 같은 이름을 말할 때
/root/otca-resource/02-otel.env 에 OTEL_RESOURCE_ATTRIBUTES=service.name=cart,deployment.environment.name=staging 과 OTEL_SERVICE_NAME=checkout 두 줄을 씁니다. /opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py probe /root/otca-resource/02-otel.env 결과를 보고 /root/otca-resource/02-env.txt 에 service_name=, environment=, winner=(service.name 을 정한 환경변수 이름)를 적으세요.
두 변수 모두 리소스를 만들지만 우선순위가 정해져 있습니다. 결과에 남은 service.name 을 보고 판단하세요.
코드에서 정한 값과 환경변수
/root/otca-resource/resource.py 의 make_resource() 가 Resource.create 로 service.name checkout-api, service.version 2.4.1 을 정해 돌려주게 고칩니다. 채점기는 OTEL_SERVICE_NAME=checkout, OTEL_RESOURCE_ATTRIBUTES=service.version=0.0.1,deployment.environment.name=prod 를 준 프로세스에서 이 함수를 부릅니다. /opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 3 결과를 /root/otca-resource/03-code.txt 에 service_name=, service_version=, environment= 로 적으세요.
Resource.create 는 탐지기와 환경변수로 만든 리소스 위에 인자로 받은 속성을 덮어씁니다. 인자에 없는 키는 환경변수 값이 남습니다. Resource(...) 생성자는 환경변수를 읽지 않습니다.
쉼표가 든 값
/root/otca-resource/04-otel.env 에 OTEL_RESOURCE_ATTRIBUTES 한 줄을 씁니다. team.owner 의 값은 payments,risk 이고 cloud.region=ap-northeast-2 도 함께 넣습니다. 쉼표는 퍼센트 인코딩(%2C)합니다. /opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 4 는 인코딩한 값과, 같은 값을 인코딩하지 않았을 때를 함께 보여 줍니다. /root/otca-resource/04-encoding.txt 에 team_owner= 와 unencoded_team_owner= 를 적으세요.
이 변수에서 쉼표는 속성 구분자입니다. 값 안의 쉼표와 등호는 인코딩해야 합니다. 인코딩하지 않은 쪽의 SDK 경고도 읽어 보세요.
OTLP 에서 리소스는 어디에 붙나
/root/otca-resource/grouping.py 의 emit(provider_a, provider_b) 가 provider_a 의 트레이서로 스팬 2개, provider_b 로 스팬 1개를 만들고 끝내게 고칩니다. /opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 5 는 두 프로바이더(service.name frontend, orders-db)의 스팬을 OTLP 로 인코딩한 결과를 보여 줍니다. /root/otca-resource/05-grouping.txt 에 resource_spans=, spans=, service_name_on_spans=(스팬 속성에 service.name 이 있는지 true/false)를 적으세요.
OTLP 는 같은 리소스를 가진 스팬을 묶어 리소스를 한 번만 적습니다. 스팬 하나하나에는 리소스가 없습니다.
404 는 서버의 오류가 아니다
/root/otca-resource/server.py 의 handle(tracer, request) 가 요청 하나의 서버 스팬을 안정(stable) HTTP 시맨틱 컨벤션대로 만들게 고칩니다. 채점기는 201·404·503 요청 세 개로 확인합니다 — 종류 SERVER, 이름 {메서드} {경로 템플릿}, 속성 http.request.method·url.path·http.route·http.response.status_code(정수), 옛 이름(http.method·http.target·http.status_code) 없음, 5xx 이면 상태 ERROR 와 error.type(상태 코드 문자열), 그 밖에는 상태를 비워 둠. {RS} show 6 으로 만든 스팬을 볼 수 있습니다.
서버 입장에서 4xx 는 요청 쪽 문제라 오류 상태로 표시하지 않습니다. 스팬 이름에 경로 원문을 쓰면 요청마다 이름이 달라집니다.
스키마 URL 이 달라 병합이 조용히 실패했다
/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 7 은 탐지된 리소스(schema 1.21.0, service.name unknown_service)에 설정한 리소스(schema 1.26.0, service.name checkout)를 merge 한 결과를 보여 줍니다. /root/otca-resource/07-merge.txt 에 naive_service_name= 을 적고, /root/otca-resource/merge.py 의 combine(detected, configured) 가 설정한 값이 이기고 탐지된 host.name 은 남으며 schema_url 은 설정한 리소스를 따르는 새 리소스를 돌려주게 고치세요. 입력 리소스는 바꾸지 않습니다.
스키마 URL 이 서로 다른 두 리소스의 병합은 명세상 오류이고, 이 SDK 는 오류를 기록한 뒤 원래 리소스를 그대로 돌려줍니다. 리소스는 불변이므로 새 리소스를 만들어 병합하세요.