Where Distributed Tracing Breaks
Reconnect a Broken Trace
한국어 원문으로 표시합니다.
목표
트레이스는 한 군데만 안 이어져도 통째로 쓸모없어집니다. 그런데 끊겨도 오류가 안 나기 때문에, 대시보드를 열어 보기 전까지는 아무도 모릅니다.
이 실습은 이미 끊겨 있는 서비스 셋을 주고 잇게 합니다.
시작
cp /opt/lab/trace/* . && chmod +x run.sh
./run.sh # a → b → c 로 요청 하나를 흘린다
python3 tree.py # 이어졌는지 본다
파일
| 파일 | 하는 일 |
|---|---|
svc.py |
서비스 하나. 버그가 하나 있다 |
run.sh |
셋을 띄우고 요청 하나를 흘린다 |
tree.py |
로그를 읽어 이어졌는지 판정한다 |
알아 둘 것
run.sh 는 서비스를 죽일 때 pkill -f svc.py 를 쓰지 않습니다. 그 패턴은
스크립트를 실행한 셸의 명령줄에도 걸려서 자기 자신을 죽입니다. PID 를
적어 두고 그것만 죽입니다.
traceparent
00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
│ │ │ │
│ trace id (16바이트) 부모 span 플래그
버전
단계
- 끊긴 것 확인 →
01-broken.txt - 어디서 왜 →
02-where.md - 잇기 → 채점기가 직접 돌려 확인
- 형식 읽기 →
04-format.md - 샘플링 일관성 →
05-sampling.txt - 동시 요청 →
06-concurrent.txt - 정리 →
07-notes.md
끊긴 것을 눈으로 본다
/opt/lab/trace/ 를 작업 디렉터리로 복사해 ./run.sh 를 돌리고 python3 tree.py 결과를 01-broken.txt 에 남기세요.
cp /opt/lab/trace/* . && chmod +x run.sh 로 시작합니다. 서비스 셋(a→b→c)에 요청 하나가 흐릅니다.
증상이 실제 현장과 같습니다 — 각 서비스는 트레이스를 잘 보내는데 이어지지 않습니다. 대시보드에는 스팬 하나짜리 트레이스가 잔뜩 쌓입니다.
어디서 왜 끊기는지 짚는다
svc.py 를 읽고 어느 줄이 문제인지 02-where.md 에 적으세요. 왜 그 한 줄이 트레이스를 끊는지도 함께.
다음 서비스로 요청을 보내는 자리를 보세요. 받은 쪽은 헤더가 없으면 새 trace id 를 만듭니다 — 그게 맞는 동작입니다. 문제는 보내는 쪽입니다.
트레이스가 끊기는 자리는 거의 항상 호출하는 쪽입니다. 받는 쪽 코드를 아무리 봐도 안 나옵니다.
하나로 잇는다
svc.py 를 고쳐 세 서비스가 하나의 trace id 를 공유하고 부모–자식이 이어지게 하세요.
보내는 요청에 traceparent 헤더를 붙입니다. 형식은 버전-trace-내span-플래그 입니다. 부모 자리에 넣는 것은 받은 부모가 아니라 지금 내 span 입니다 — 여기서 자주 틀립니다.
채점기는 직접 돌려서 trace id 종류 1개, 루트 1개, 부모를 못 찾는 스팬 0개를 확인합니다.
traceparent 를 조각내 읽는다
04-format.md 에 traceparent 의 네 조각이 각각 무엇인지 적고, 3단계 로그에서 실제 값 하나를 예로 드세요.
00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01. 앞에서부터 버전, trace id(16바이트), 부모 span(8바이트), 플래그입니다.
길이가 정해져 있어서 눈으로도 검증할 수 있습니다 — trace id 가 32자가 아니면 그 자리에서 틀린 것입니다.
샘플링은 한 번만 정한다
루트 서비스가 플래그를 00(수집 안 함)으로 시작해도 세 서비스가 모두 같은 플래그를 남기는지 확인해 05-sampling.txt 에 남기세요.
결정은 루트에서 한 번 하고 그대로 실어 나릅니다. 중간에서 다시 정하면 트레이스가 반쪽이 됩니다 — 앞 절반은 수집되고 뒤 절반은 없는 트레이스만큼 디버깅에 방해되는 것도 없습니다.
루트에서 시작 플래그를 바꿔 돌린 뒤 tree.py 의 플래그 줄을 남기세요.
동시에 여러 개를 흘려도 안 섞이는가
요청 세 개를 동시에 흘려 각각이 따로따로 온전한 트레이스를 이루는지 확인하고 06-concurrent.txt 에 남기세요.
run.sh 를 참고해 서비스를 띄운 뒤 curl 셋을 & 로 동시에 보내세요. 제대로면 trace id 3종, 각 trace 마다 스팬 3개, 루트 3개, 고아 0개입니다.
여기서 깨지는 전형적인 원인은 컨텍스트를 전역 변수에 담는 것입니다. 요청 하나로 테스트하면 멀쩡하고, 트래픽이 붙는 순간 트레이스가 서로 섞입니다. 언어마다 요청별 저장소가 따로 있는 이유입니다.
세 가지를 정리한다
07-notes.md 에 세 줄 이상. 트레이스가 끊기는 자리, 부모 자리에 무엇을 넣는지, 샘플링 결정을 어디서 하는지.
본문에 호출, 부모, 샘플링 이 들어가야 합니다.