"""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_map() -> dict[str, dict]: """Return Prometheus-backed NF status keyed by display name.""" try: results = await query("up") except Exception: return {n: {"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 seen async def get_nf_status() -> list: """Return a list of {name, state, instance} for every known NF.""" return list((await get_nf_status_map()).values())