Загружаем каталог…
Загружаем каталог…
1. 정수 카운터에서 왜 소수가 나오나 increase(http_requests_total[1m]) 가 정수 카운터인데도 5.33 을 돌려줬다. 처음엔 부동소수 오차나 버그를 의심했는데, Prometheus 소스 promql/functions.go 의 extrapolatedRate 를 따라가 보니 의도된 동작이었다. 윈도우 안 샘플이 덮지 못한 경계까지의 빈틈을 선형으로 외삽 하기 때문이다. rate() 와 increase() 는 둘 다 이 함수 하나를 부른다. 차이는 마지막에 윈도우 길이(초)로 나누느냐뿐이라, 공식 문서도 increase 를 rate 에 윈도우 초를 곱한 syntactic sugar라고 설명한다. 2. "마지막 − 처음"이라는 오해 흔한 이해는 increase = 마지막 값 − 첫 값 이다. 실제 계산은 그 값(raw)에 배율을 곱한다. factor = (covered + left + right) / covered covered 는 첫 샘플부터 마지막 샘플까지의 시간, left · right 는 윈도우 경계까지 남은 빈틈이다. range selector는 (start, end] 구간이라 왼쪽 경계와 같은 타임스탬프의 샘플은 빠진다는 점도 함께 기억해 둘 만하다. scrape 15초, [1m] 윈도우에서 샘플이 t=5, 20, 35, 50초에 값 100, 101, 103, 104로 찍혔다고 하자. raw는 4, covered는 45초, 빈틈은 왼쪽 5초·오른쪽 10초다. 배율 60/45가 곱해져 결과는 4 × 4/3 ≈ 5.33 이 된다. 윈도우 60초 전체에서 같은 기울기로 늘었으리라 추정한 값이다. increase()는 "관측된 증가량"이 아니라 "윈도우 전체에 대한 추정 증가량"이다. 3. 외삽을 언제 멈추나 무조건 경계까지 늘리면 윈도우 중간에 새로 뜬 파드의 카운터가 크게 부풀려진다. 그래서 두 가지 브레이크가 있다. 첫째, 1.1배 임계 . 평균 샘플 간격 avg = covered / (샘플수 − 1) 을 구하고, 빈틈이 avg × 1.1 이상이면 "있어야 할 자리에 샘플이 없다", 즉 시리즈가 윈도우 안에서 시작하거나 끝났다고 본다. 이때는 경계까지가 아니라 avg / 2 만 외삽한다. 둘째, 카운터의 0점 클램프 (왼쪽만). 카운터는 음수가 될 수 없으므로 기울기로 0이 되는 지점 covered × (첫 값 / raw) 을 역산해, 왼쪽 외삽이 그보다 길어지지 않게 자른다. 빈틈 외삽 거리 < 1.1 × avg 경계까지 전부 ≥ 1.1 × avg avg / 2 카운터의 왼쪽 위 값과 0점까지 거리 중 작은 쪽 중간에 값이 줄면 카운터 리셋으로 보고 직전 값을 raw에 더해 준다. 100 → 110 → 5 → 15라면 raw는 −85 + 110 = 25다. 4. 직접 돌려보기 알고리즘을 Python으로 옮겨 숫자를 확인했다. 소스의 기본 경로(수정자 없는 range selector)만 단순화한 것이다. def extrapolated_increase(samples, range_start, range_end, is_counter=True): """samples: [(t초, 값)] — 이미 (range_start, range_end] 안에 든 것만""" if len(samples) < 2: return None # 간격을 추정할 수 없음 (t0, v0), (tn, vn) = samples[0], samples[-1] raw = vn - v0 for (_, prev), (_, curr) in zip(samples, samples[1:]): if curr < prev: # 카운터 리셋 raw += prev covered = tn - t0 avg = covered / (len(samples) - 1) to_start, to_end = t0 - range_start, range_end - tn if to_start >= avg * 1.1: # 시리즈가 윈도우 안에서 시작 to_start = avg / 2 if is_counter and raw > 0 and v0 >= 0: to_start = min(to_start, covered * (v0 / raw)) # 0 아래로 외삽 금지 if to_end >= avg * 1.1: # 시리즈가 윈도우 안에서 끝남 to_end = avg / 2 return raw * (covered + to_start + to_end) / covered print(extrapolated_increase([(5, 100), (20, 101), (35, 103), (50, 104)], 0, 60)) # 5.33 print(extrapolated_increase([(35, 1), (50, 5)], 0, 60)) # 7.67 print(extrapolated_increase([(30, 100), (60, 103)], 0, 60)) # 6.0 두 번째는 t=35에 태어난 시리즈다. 왼쪽 빈틈 35초는 임계 16.5초를 넘어 7.5초로 줄고, 0점까지 거리 3.75초로 다시 잘린다. 결과 7.67은 t=31.25에 0에서 출발해 t=60까지 기울기 4/15로 늘렸을 때의 값과 같다. 세 번째가 노트에 없던 실패 케이스 다. scrape 30초에 [1m] 윈도우를 쓰면 t=0 샘플이 left-open 경계에 걸려 빠지고 두 개만 남는다. 실제 증가량은 3인데 배율 2가 곱해져 6이 나온다. 샘플이 적을수록 배율과 오차가 같이 커지기 때문에, 윈도우를 scrape 간격의 최소 4배로 잡으라는 권장이 흔히 인용된다. 같은 이유로 [15s] 처럼 샘플이 하나뿐인 윈도우는 결과가 아예 비어 버린다. 5. 정리 rate / increase 는 샘플 사이 증가량(리셋 보정 포함)을 구한 뒤, 경계 빈틈이 평균 간격의 1.1배 미만이면 경계까지, 이상이면 반 간격만 외삽하고, 카운터는 0 아래로 내려가지 않게 자른다. 그래서 소수 결과는 버그가 아니며, 짧은 윈도우에서 오차가 커진다. 히스토그램 버킷에도 같은 rate 가 먼저 적용되므로, histogram_quantile 글 의 결과에도 이 외삽이 그대로 섞인다. 다음에는 최신 main에 들어온 anchored / smoothed 수정자, 즉 외삽 대신 경계 보간을 쓰는 extendedRate 가 이 오차를 어떻게 줄이는지 볼 생각이다. 참고 자료 Prometheus 소스 promql/functions.go — extrapolatedRate , funcRate , funcIncrease (commit e71425d) Prometheus Docs querying/functions.md — rate() , increase() Prometheus Docs querying/basics.md — range vector selector의 구간 정의
То, что RADAR обнаружил и классифицировал для этой возможности. Это опубликованный источником текст, а не подтверждение, что предложение ещё действует.
카운터가 4 늘었는데 increase()는 왜 5.33일까 — Prometheus rate의 경계 외삽. 1. 정수 카운터에서 왜 소수가 나오나 increase(http_requests_total[1m]) 가 정수 카운터인데도 5.33 을 돌려줬다. 처음엔 부동소수 오차나 버그를 의심했는데, Prometheus 소스 promql/functions.go 의 extrapolatedRate 를 따라가 보니 의도된 동작이었다. 윈도우 안 샘플이 덮지 못한 경계까지의 빈틈을 선형으로 외삽 하기 때문이다. rate() 와 increase() 는 둘 다 이 함수 하나를 부른다. 차이는 마지막에 윈도우 길이(초)로 나누느냐뿐이라, 공식 문서도 increase 를 rate 에 윈도우 초를 곱한 syntactic…
Открыть источник