샘플링
트레이스의 일부만 남기되, 트레이스 하나하나를 일부만 남기지는 않기.
결정은 루트에서 한 번만 내립니다
트레이스는 통째로 남거나 통째로 버려집니다. 결정은 루트 스팬이 시작할 때 내려지고 모든 자식이 그것을 물려받으므로, 하나의 실행이 절반만 기록되는 일은 없습니다.
나머지 모든 것이 이 규칙에서 따라 나옵니다. 스팬의 30%가 무작위로 빠진 트레이스는 샘플링된 트레이스로 읽히지 않습니다. 관측 대상 시스템의 버그로 읽힙니다. 일어나지 않은 것처럼 보이는 도구 호출, 부모가 없는 모델 호출, 검색이 있어야 할 자리의 빈틈으로 말입니다. 그 빈틈이 에이전트가 아니라 관측 도구 때문이라는 것을 알아내기까지 오후 한나절을 씁니다.
기본값은 전부 남깁니다
샘플링을 설정하지 않으면 정책은 always이고, 물량이 달리 말하기
전까지는 그것이 옳은 기본값입니다. 샘플링은 정작 읽고 싶어질 바로 그 실행을
내주는 거래입니다. 저장 공간이나 대역폭이 어쩔 수 없게 만들 때에만
치르십시오.
다섯 가지 전략
| 전략 | 동작 |
|---|---|
always | 전부 남깁니다. 기본값입니다. |
never | 아무것도 남기지 않습니다. |
ratio | 정해진 비율만 남깁니다. 트레이스마다 루트에서 한 번 무작위로 뽑습니다. |
deterministic | 정해진 비율만 남기되, 트레이스 id를 해시해서 정합니다. 모든 컬렉터가 서로 대화하지 않고도 같은 답에 이릅니다. |
tail | 트레이스가 끝날 때까지 결정을 미룬 다음, 비율이 무엇이라고 하든 모든 오류와 모든 느린 실행을 남깁니다. |
비율 정하기
--sample, 또는 MCPD_SAMPLE은 0.0에서 1.0 사이의
비율을 받아 결정론적 전략을 설정합니다. 그 범위를 벗어난 값은 무엇을
넘겼는지 이름을 대는 메시지와 함께 데몬을 시작 단계에서 멈춰 세웁니다. 범위
안으로 깎지 않습니다. 잘못 입력한 비율이 조용히 1.0이 되면 한 달 뒤 저장
요금서로 발견되기 때문입니다.
열 개 중 하나만 남기기
mcpd --sample 0.1
모든 SDK가 같은 비율을 읽습니다. 클라이언트 설정의 sample이거나
환경의 MCPD_SAMPLE입니다. 클라이언트에서 샘플링하는 쪽이 더
쌉니다. 샘플링되지 않은 스팬은 큐에 들어가지도 내보내지지도 않으므로 대역폭이
전혀 들지 않습니다. 데몬에서 샘플링하면 왕복 비용은 들지만 비율이 한곳에
모이며, 열두 개 서비스가 하나의 인스턴스로 보고할 때 원하는 것이 바로
그것입니다.
다섯 전략 중 데몬이 닿을 수 있는 것은 always와
deterministic입니다. --sample과 설정 파일의
프로젝트별 sample은 둘 다 deterministic 전략을 설정합니다.
never, ratio, tail은 정책 타입에
구현되어 있지만, 이 빌드에서는 플래그로도 설정 파일로도 닿을 수 없습니다.
해시가 무리 전체의 판단을 일치시키는 이유
로드 밸런서 뒤에 mcpd 인스턴스를 여러 개 두면 한 트레이스의 스팬이 전부 같은 인스턴스로 도착하지는 않습니다. 인스턴스마다, 또는 스팬마다 동전을 던지는 샘플러는 트레이스의 일부만 남기고 나머지를 버릴 것이고, 그것이 첫 번째 규칙이 막으려는 실패입니다.
결정론적 전략은 트레이스 id를 64비트 전체 범위에 대응시키고, 그 값이 비율이 뜻하는 문턱값보다 아래일 때 트레이스를 남깁니다. 모든 인스턴스가 같은 id에서 같은 수를 계산하므로, 공유 상태도 조율 프로토콜도 없이, 어긋날 것도 없이 모두 같은 결론에 이릅니다. 같은 id는 재시도에서도 같은 답을 주므로, 다시 보낸 배치가 절반만 도착하는 일도 없습니다.
이 대응을 정직하게 만드는 두 가지 세부 사항이 있습니다. 첫째, id의 뒤쪽 16개 16진수 문자를 읽습니다. OpenTelemetry는 트레이스 id가 무작위이기를 요구하지만 앞쪽 바이트를 타임스탬프에서 만들어 내는 생산자도 있고, 그쪽을 읽는 샘플러는 표본을 뽑는 것이 아니라 하루 중 시각과 상관관계를 갖게 됩니다. 둘째, id가 16진수가 아예 아닐 때는 전부 남기는 쪽으로 무너지는 대신 마무리 혼합이 붙은 진짜 해시로 되돌아가므로, 실제로 실현되는 비율이 요청한 비율에 가깝게 유지됩니다.
SDK에서는 상류의 결정이 이깁니다
SDK가 들어온 W3C traceparent로 트레이스를 이어 가면, ID와 함께
sampled 플래그를 물려받고 자기 비율은 적용하지 않습니다. 이는 양쪽 모두에
적용됩니다. 플래그가 켜져 있으면 로컬 비율과 상관없이 트레이스를 남기고,
꺼져 있으면 로컬 비율과 상관없이 버립니다.
이 빌드의 데몬은 이렇게 하지 않습니다. OTLP로 들어온 스팬에 대해 데몬은 그
trace-flags 바이트를 속성 mcpd.otlp.flags에 남기지만, 데몬의
샘플러는 그것을 읽지 않습니다. 비율이 설정된 데몬은 플래그가 무엇이든 모든
트레이스에 그 비율을 적용합니다.
다른 방식은 들리는 것보다 나쁩니다. 서비스마다 자기 비율을 적용한다면, 네 서비스를 지나는 트레이스는 둘에서 남고 둘에서 버려질 것이고, 마지막에 손에 남는 것은 분산 트레이스가 아닙니다. 트레이스 모양을 한 구멍들입니다.
테일 샘플링은 읽을 만한 실행을 남깁니다
헤드 샘플러는 아무것도 알기 전에 결정합니다. 싸지만 눈이 멀어 있습니다. 10분의 1로 두면 실패도 10분의 1만 남깁니다. 실제로 열어 보게 되는 트레이스는 드문 쪽이고, 드물다는 것이야말로 비율 샘플러가 가장 못하는 일입니다.
지연 시간 기록은 저렇게 생겼습니다. 평평한 기준선과 몇 번의 이탈입니다. 물량은 기준선에 있고 답은 이탈에 있습니다. 테일 샘플링은 트레이스가 끝날 때까지 붙들고 있다가, 그 안에서 무언가 오류를 냈으면 남기고, 정한 문턱값보다 오래 걸렸으면 남기고, 그 밖에는 앞과 같은 결정론적 해시를 적용합니다. 오류를 남기는 것은 기본으로 켜져 있습니다. 가장 필요한 트레이스가 드문 쪽이고, 비율 샘플러가 가장 버리기 쉬운 것도 그쪽이기 때문입니다.
대가는 버퍼링입니다. 테일 샘플러는 결정할 수 있을 때까지 끝나지 않은 모든 트레이스를 메모리에 붙들고 있어야 하고, 그래서 이것은 기본값이 아니라 의도적인 선택입니다. 위에서 말했듯 테일 전략은 정책 타입에 구현되어 있고 이 빌드에서는 플래그로도 설정 파일로도 닿을 수 없습니다. 데몬의 수집 경로는 헤드 결정을 적용합니다.
무엇이 버려졌는지 알기
샘플러가 버리는 스팬은 하나하나
mcpd_traces_sampled_out_total을 올리고, 이 값은
/metrics에서 Prometheus 텍스트 형식으로 나갑니다. 비율은 팀이
읽는 곳에 적어 두십시오. 문서에 적힌 샘플링 비율이 있는 상태에서 트레이스가
없으면 그것은 설명이 되지만, 설명 없이 트레이스가 없으면 지원 요청이 되고, 그
요청을 넣는 사람은 대개 비율을 정한 쪽입니다.
다음
- 덜 저장하는 또 다른 방법: 마스킹과 보존 기간.
- 모든 플래그와 환경 변수: 설정.
-
/metrics와 데몬 자신의 나머지 시그널 읽기: 운영하기.