42 lines
1.5 KiB
Python
42 lines
1.5 KiB
Python
"""Prometheus client — queries the HPE P5G Prometheus instance."""
|
|
|
|
import httpx
|
|
from app.config import PROMETHEUS_URL, PROMETHEUS_PREFIX, TARGET_TYPE_MAP, ALL_NFS
|
|
|
|
_BASE = PROMETHEUS_URL.rstrip("/") + PROMETHEUS_PREFIX
|
|
|
|
|
|
async def query(promql: str) -> list:
|
|
"""Run an instant PromQL query, return the result list."""
|
|
async with httpx.AsyncClient(timeout=5) as client:
|
|
r = await client.get(f"{_BASE}/api/v1/query", params={"query": promql})
|
|
r.raise_for_status()
|
|
return r.json()["data"]["result"]
|
|
|
|
|
|
async def get_nf_status() -> list:
|
|
"""Return a list of {name, state, instance} for every known NF."""
|
|
try:
|
|
results = await query("up")
|
|
except Exception:
|
|
return [{"name": n, "state": "unknown", "instance": ""} for n in ALL_NFS]
|
|
|
|
seen: dict[str, dict] = {}
|
|
for r in results:
|
|
metric = r["metric"]
|
|
target = metric.get("target_type", metric.get("job", "")).lower()
|
|
name = TARGET_TYPE_MAP.get(target)
|
|
if not name:
|
|
continue
|
|
state = "up" if r["value"][1] == "1" else "down"
|
|
# Keep worst state if multiple instances
|
|
if name not in seen or seen[name]["state"] != "down":
|
|
seen[name] = {"name": name, "state": state, "instance": metric.get("instance", "")}
|
|
|
|
# Fill in NFs with no Prometheus data
|
|
for n in ALL_NFS:
|
|
if n not in seen:
|
|
seen[n] = {"name": n, "state": "unknown", "instance": ""}
|
|
|
|
return list(seen.values())
|