fix: probe Prometheus /metrics at server root, not under /v1 (v2.03.10)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c3cf123afe
commit
c292ff2242
@ -9,6 +9,13 @@ The version is defined in [`blitztext/__init__.py`](blitztext/__init__.py).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2.03.10] - 2026-06-09
|
||||
|
||||
### Fixed
|
||||
- **Server RAM probe.** Prometheus `/metrics` is almost always at the server
|
||||
root (`http://host:port/metrics`), not under `/v1`. Now tries the root URL
|
||||
first before falling back to the API base path.
|
||||
|
||||
## [2.03.09] - 2026-06-09
|
||||
|
||||
### Added
|
||||
|
||||
@ -6,4 +6,4 @@ counterpart to the macOS Blitztext menu bar app: it runs natively on the host
|
||||
(not in a container) so it can type into any application via xdotool.
|
||||
"""
|
||||
|
||||
__version__ = "2.03.09"
|
||||
__version__ = "2.03.10"
|
||||
|
||||
@ -154,34 +154,45 @@ def probe_server_ram_mb(base_url: str, timeout: float = 3.0) -> float | None:
|
||||
Returns RSS in MB if the server exposes Prometheus metrics with either
|
||||
``process_resident_memory_bytes`` (standard Python/Go exporter) or
|
||||
``container_memory_rss`` (cAdvisor). Returns None if not available.
|
||||
|
||||
Tries the server root first (http://host:port/metrics) then the api base
|
||||
path (http://host:port/v1/metrics), because Prometheus endpoints are almost
|
||||
always mounted at root even when the API lives under /v1.
|
||||
"""
|
||||
if not base_url:
|
||||
return None
|
||||
base = _api_base(base_url)
|
||||
try:
|
||||
req = urllib.request.Request(base + "/metrics")
|
||||
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
||||
text = resp.read().decode("utf-8", "replace")
|
||||
except Exception:
|
||||
p = urlparse(base_url.rstrip("/"))
|
||||
root = f"{p.scheme}://{p.netloc}"
|
||||
candidates = [root + "/metrics"]
|
||||
api_base_metrics = _api_base(base_url) + "/metrics"
|
||||
if api_base_metrics != candidates[0]:
|
||||
candidates.append(api_base_metrics)
|
||||
|
||||
def _parse(text: str) -> float | None:
|
||||
for line in text.splitlines():
|
||||
line = line.strip()
|
||||
if line.startswith("#"):
|
||||
continue
|
||||
for metric in ("process_resident_memory_bytes", "container_memory_rss"):
|
||||
if line.startswith(metric):
|
||||
parts = line.split()
|
||||
if len(parts) >= 2:
|
||||
try:
|
||||
return float(parts[-1]) / (1024 * 1024) # bytes → MB
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
# Parse Prometheus text format — we only need two specific metric names.
|
||||
# Lines look like: process_resident_memory_bytes 1.23456e+08
|
||||
best: float | None = None
|
||||
for line in text.splitlines():
|
||||
line = line.strip()
|
||||
if line.startswith("#"):
|
||||
for url in candidates:
|
||||
try:
|
||||
req = urllib.request.Request(url)
|
||||
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
||||
result = _parse(resp.read().decode("utf-8", "replace"))
|
||||
if result is not None:
|
||||
return result
|
||||
except Exception:
|
||||
continue
|
||||
for metric in ("process_resident_memory_bytes", "container_memory_rss"):
|
||||
if line.startswith(metric):
|
||||
parts = line.split()
|
||||
if len(parts) >= 2:
|
||||
try:
|
||||
best = float(parts[-1]) / (1024 * 1024) # bytes → MB
|
||||
return best
|
||||
except ValueError:
|
||||
pass
|
||||
return best
|
||||
return None
|
||||
|
||||
|
||||
def detect_remote_device(base_url: str, timeout: float = 3.0) -> str:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user