feat: add quantiles() method to LatencyTracker for OpenMetrics
All checks were successful
ci / secrets (push) Successful in 10s
ci / test (push) Successful in 20s
ci / build (push) Successful in 15s

Returns {count, sum, 0.5, 0.95, 0.99} in seconds for Prometheus
summary exposition. Companion to the existing stats() (milliseconds).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
user
2026-02-21 20:42:15 +01:00
parent 3593481b30
commit 9a56dc778e
2 changed files with 34 additions and 0 deletions

View File

@@ -67,6 +67,23 @@ class LatencyTracker:
"p99": round(ms[min(int(n * 0.99), n - 1)], 1),
}
def quantiles(self) -> dict | None:
"""Return ``{count, sum, 0.5, 0.95, 0.99}`` in seconds, or None.
Designed for Prometheus/OpenMetrics summary exposition.
"""
n = len(self._samples)
if n == 0:
return None
s = sorted(self._samples)
return {
"count": n,
"sum": sum(s),
"0.5": s[int(n * 0.50)],
"0.95": s[min(int(n * 0.95), n - 1)],
"0.99": s[min(int(n * 0.99), n - 1)],
}
class Metrics:
"""Connection metrics.

View File

@@ -52,6 +52,23 @@ class TestLatencyTracker:
assert s["min"] == 500.0
assert s["max"] == 500.0
def test_quantiles_empty(self):
lt = LatencyTracker()
assert lt.quantiles() is None
def test_quantiles_seconds(self):
lt = LatencyTracker()
for i in range(1, 101):
lt.record(i / 1000)
q = lt.quantiles()
assert q is not None
assert q["count"] == 100
assert 0.050 <= q["0.5"] <= 0.052
assert 0.095 <= q["0.95"] <= 0.097
assert 0.099 <= q["0.99"] <= 0.101
assert "sum" in q
assert q["sum"] > 0
# -- RateTracker -------------------------------------------------------------