TT Lab
블로그 시작하기
배우기 러닝패스 코스

프로파일링: 느린 요청 하나를 함수까지

스팬에서 프로파일로: 레이블과 OpenTelemetry profiles

TT Lab 에서 이어서 보기

한 줄 요약

프로파일 표본에 trace_id·span_id 같은 레이블을 붙이면 트레이스의 스팬 하나에서 그 시간의 프로파일로 건너갈 수 있습니다. Go 는 pprof.Do 로, Pyroscope 는 span profiles 로, OpenTelemetry 는 profiles 신호의 Link 로 같은 일을 합니다.

왜 이게 필요했나

앞의 모듈들에서 트레이스와 프로파일은 따로 놀았습니다. 트레이스는 「이 요청의 pricing.quote 가 36ms」, 프로파일은 「서비스 전체의 80% 가 couponPattern」을 말했습니다. 둘이 같은 원인을 가리킨다고 짐작할 수는 있지만 증명은 아닙니다. 서비스 전체가 쓰는 CPU 와 그 느린 요청 하나가 쓴 CPU 는 다를 수 있기 때문입니다. 한 고객사만 느리다거나, 특정 기능 플래그가 켜진 요청만 느린 경우가 그렇습니다.

어떻게 동작하나

Go 런타임은 고루틴마다 레이블 묶음을 들고 다니고, CPU 표본을 찍을 때 그 레이블을 표본에 붙입니다. pricing 은 요청을 처리하는 동안 이렇게 감쌉니다.

labels := pprof.Labels("trace_id", traceID, "span_id", spanID, "coupon", hasCoupon)
pprof.Do(r.Context(), labels, func(_ context.Context) { /* 요청의 일 */ })

그러면 프로파일을 받은 뒤 go tool pprof -tags 로 레이블별 비중을 보고, -tagfocus=span_id=<id> 로 그 스팬의 표본만 남길 수 있습니다. Pyroscope 의 Go·Java 연동은 같은 방식으로 루트 스팬의 span_id 를 레이블로 붙이고, Grafana 의 트레이스 화면에서 스팬을 누르면 그 표본만 모은 플레임 그래프를 엽니다.

OpenTelemetry 는 이것을 신호 수준에서 표준으로 만들고 있습니다. profiles 신호의 사양은 표본이 trace ID 와 span ID 를 담은 Link 를 가질 수 있다고 적고, 프로파일이 같은 resource 문맥으로 로그·메트릭·트레이스와 이어져야 한다고 요구합니다. 사양의 상태는 2026년 10월 현재 Alpha 입니다.

두 가지 한계를 숫자로 기억해 둡니다.

현장에서 만나는 모습

「어느 고객사만 느리다」는 문의가 오면 tenant 레이블로 나눈 프로파일 두 장을 견주는 것이 가장 빠릅니다. 같은 서비스, 같은 시간인데 tenant=A 의 표본만 특정 함수에 몰려 있으면 그 고객사의 데이터 모양이 원인입니다. 레이블 하나가 「전체 평균」에 묻힌 차이를 꺼내 줍니다.

이 실습의 pricing 에서는 쿠폰 요청이 요청 수로는 다섯에 하나인데 CPU 의 대부분을 씁니다. coupon 레이블 하나로 그 차이가 숫자로 드러나고, 그 안의 느린 스팬 하나를 열면 같은 함수가 다시 보입니다. 묶음과 하나가 같은 결론을 가리킬 때 그 결론은 단단해집니다.

레이블은 CPU 프로파일 말고도 쓸모가 있습니다. Go 런타임은 goroutine 프로파일에도 레이블을 싣기 때문에, 멈춘 고루틴이 어느 요청의 일이었는지도 같은 방식으로 찾을 수 있습니다.

흔히 틀리는 읽기

trace_id 와 span_id 를 헷갈리는 일이 가장 흔합니다. trace_id 는 서비스 경계를 넘어도 같지만, span_id 는 서비스마다, 구간마다 다릅니다. 프로파일의 레이블은 그 프로세스가 만든 span_id 이므로, 파이썬 쪽 스팬의 ID 로 Go 프로파일을 거르면 아무것도 나오지 않습니다. 이 실습에서 Go 쪽 기록을 따로 여는 이유입니다.

표본이 하나도 없는 스팬을 「CPU 를 안 썼다」로 읽는 것도 틀립니다. 짧아서 표본 간격 사이에 끝났을 수도 있고, CPU 가 아니라 기다리는 데 시간을 썼을 수도 있습니다. 두 경우를 가르려면 스팬 길이와 그 스팬의 표본 수(곱하기 10ms)를 견줍니다. 길이는 긴데 표본이 적으면 기다린 것입니다.

다음 실습에서 할 것

api 에 부하를 주는 동안 pricing 의 CPU 프로파일을 받고, 레이블 키와 쿠폰 요청의 CPU 몫을 봅니다. 느린 쿠폰 스팬 하나를 골라 그 표본만 남긴 프로파일을 만들고, 스팬 하나와 묶음이 각각 무엇을 말하는지 견준 뒤 증거를 한 문서로 정리합니다.

English corner