LabHub
배우기 러닝패스 코스

분산 트레이싱이 끊기는 자리 · 지표와 추적이 같은 질문에 답하게 · 이론

대시보드에서 본 것을 추적에서 다시 찾으려면

LabHub 에서 이어서 보기

한 줄 요약

지표와 추적이 같은 이름·같은 값의 속성을 갖고 있고 표본 비율이 스팬에 적혀 있어야, 대시보드에서 본 봉우리를 트레이스에서 다시 찾을 수 있다.

왜 이게 필요했나

장애 회고에서 나온 요청은 간단했다. "오류율 패널이 09시 40분에 튀는데, 그때의 실패한 요청 하나만 열어 보자." 그런데 열 수가 없었다. 지표에는 handler="/order/:id" 라는 라벨이 붙어 있었고, 스팬에는 http.target="/order/8821" 이 붙어 있었다. 이름도 다르고 값도 달랐다. 둘을 이어 주는 것이 사람의 머릿속밖에 없어서, 봉우리에서 트레이스로 가는 길이 없었다.

더 나쁜 일이 그다음에 있었다. 누군가 "스팬으로 세면 되지 않느냐" 며 덤프에서 오류율을 계산했고 29% 라는 숫자를 가져왔다. 지표는 같은 구간에 7.5% 를 가리키고 있었다. 한참 뒤에야 원인을 알았다 — 그 서비스는 오류가 난 요청은 전부 남기고 성공한 요청은 다섯 건에 하나만 남기고 있었다. 표본이 오류 쪽으로 기울어 있으니 그 표본에서 센 비율이 맞을 리가 없었다.

어떻게 동작하나

두 신호를 짝지으려면 세 가지가 필요하다.

첫째, 공통 속성이 같은 이름과 같은 값으로 양쪽에 있어야 한다. 지표는 카디널리티 때문에 주소를 그대로 쓸 수 없어서 등록된 경로 틀을 쓴다. 추적은 원래 주소를 그대로 담아도 되지만, 짝짓기용 속성만은 지표와 같은 값이어야 한다. 그래서 스팬에는 두 가지를 함께 둔다 — 짝짓기용 http.route 와 조사용 원래 주소. 이름은 [HTTP 스팬 시맨틱 컨벤션](https://opentelemetry.io/docs/specs/semconv/http/http-spans/) 과 [HTTP 지표 시맨틱 컨벤션](https://opentelemetry.io/docs/specs/semconv/http/http-metrics/) 이 같은 http.route 로 맞춰 두었으니 직접 짓지 말고 그대로 쓰는 편이 낫다.

둘째, 비율은 스팬으로 세면 안 된다. 지표는 모든 요청을 세지만 추적은 표본만 남긴다. 표본이 고르게 뽑혔더라도 스팬으로 센 개수는 몇 분의 일이고, 표본이 오류 쪽으로 기울어 있으면 비율 자체가 통째로 틀린다. 실습에서 같은 자료로 7.5% 와 29.0% 를 직접 만들어 본다.

셋째, 표본 확률을 스팬에 적어 두어야 되돌릴 수 있다. 스팬 하나가 몇 건을 대표하는지는 그 스팬이 남을 확률의 역수다. 확률 1/5 로 남은 스팬은 다섯 건을, 확률 1 로 남은 스팬은 한 건을 대표한다. 그 가중치를 더하면 개수와 비율이 대체로 되돌아온다 — 이 셈을 표준에서는 adjusted count 라고 부르고, [확률 표본 추출 명세](https://opentelemetry.io/docs/specs/otel/trace/tracestate-probability-sampling/) 에 정의가 있다.

되돌릴 수 없는 것도 분명히 알아야 한다. 표본에 한 건도 들어오지 않은 조합은 0 으로 남는다 — 드물게 나는 오류가 대시보드에서 통째로 사라지는 일이 여기서 생긴다. 분위수도 되돌아오지 않는다. 가중치는 개수를 고치지 분포의 모양을 고치지 못하고, 특히 꼬리는 표본이 적을수록 심하게 흔들린다. 그래서 개수와 비율은 지표에서 읽고, 추적은 하나의 예를 찾는 데 쓰는 것이 옳다.

지표에서 추적으로 건너가는 다리는 그 예를 미리 골라 두는 일이다. 구간마다 대표 한 건의 trace_id 를 남겨 두면 패널에서 그 트레이스로 바로 갈 수 있다. 이 방식의 표준 이름이 exemplar 이고 노출 형식의 규격은 [Prometheus 노출 형식 문서](https://prometheus.io/docs/instrumenting/exposition_formats/) 와 [OpenTelemetry 지표 데이터 모델](https://opentelemetry.io/docs/specs/otel/metrics/data-model/) 에 있다. 다만 이 실습 환경에서는 exemplar 를 실제로 저장하거나 조회할 수 없다. 이 이미지에는 Prometheus 가 아예 없고, 관측 실습 파드의 Prometheus 도 exemplar 저장 기능을 끄고 떠 있다. 그래서 여기서는 대표를 고르는 일과 그 표를 만드는 일까지만 하고, 지표는 노출 형식 텍스트 파일로 다룬다.

한계도 그대로 적어 둔다. 대표는 구간마다 한 건뿐이라 보통의 요청으로 건너갈 수는 없고, 표본에서 빠진 요청은 아무리 느렸어도 대표가 될 수 없다.

여기서 다루지 않는 것도 분명히 해 둔다. 지표 SDK 의 누적과 델타를 고르고 뷰를 설정하는 일은 지표 시간성 모듈의 몫이고 어떤 사건을 SLI 로 삼을지 정하는 일은 SLI 모듈의 몫이다. 이 모듈이 하는 것은 그 둘 사이다 — 두 신호를 짝지을 수 있게 계측하는 일이고, 산출물은 지표 설정도 SLI 정의도 아닌 속성 규칙 파일과 두 신호를 대조하는 검사기다.

현장에서 만나는 모습

가장 흔한 사고는 경로 값이 어긋나는 것이다. 지표 쪽은 프레임워크가 자동으로 경로 틀을 넣어 주는데 추적 쪽은 손으로 계측하면서 주소를 그대로 넣는 경우가 많다. 그러면 계열 아홉 개짜리 지표와 서른 개 넘는 스팬 묶음이 마주 보게 되고, 짝지을 방법이 없다. 이 어긋남은 대시보드가 멀쩡해 보여서 장애가 나기 전까지 아무도 모른다.

두 번째는 오류를 전부 남기는 표본 정책이다. 좋은 뜻으로 넣는데, 그 표본으로 비율을 세는 사람이 반드시 나타난다. 표본 확률을 스팬에 적어 두면 적어도 되돌릴 길이 생기고, 적어 두지 않으면 그 자료는 비율 계산에 영원히 쓸 수 없다.

다음 실습에서 할 것

먼저 스팬 덤프만으로 요청 수·오류 수·지연 분포를 세어 본다. 그다음 지표 쪽이 내놓은 노출 형식 파일과 견주어 이름과 값이 어떻게 어긋나 있는지 표로 만들고, 계측을 고쳐 두 신호가 같은 열쇠로 붙게 한다. 이어서 표본 추출기를 바꿔 가며 같은 자료에서 서로 다른 오류율이 나오는 것을 직접 만들고, 표본 확률의 역수로 보정해 되돌린 뒤 보정으로도 못 고치는 것을 적는다. 마지막으로 구간마다 대표 트레이스를 뽑는 다리를 만들고, 규칙을 파일로 굳혀 두 번째 서비스에 적용해 두 신호가 맞는지 검사기로 확인한다.