dashboard/app/routers/processes.py

53 lines
1.6 KiB
Python

import asyncio
from fastapi import APIRouter
from fastapi.responses import HTMLResponse
from app.collect import procs as proc_col
from app.render import render
router = APIRouter(prefix="/api", tags=["processes"])
SORT_KEYS = ("pid", "name", "cpu", "rss", "mem_pct", "io_read", "io_write", "gpu")
@router.get("/processes")
async def processes(q: str = "", sort: str = "cpu", order: str = "desc"):
"""Render the Processes tab fragment: filterable, sortable process table.
The full sample is taken in a worker thread, then optionally filtered
by substring match on name or exact match on pid. Sorting is done with
None values last (the tuple key trick); at most 300 rows are rendered.
Invalid sort/order values fall back to cpu/desc.
Args:
q: search filter, empty for all.
sort: column to sort by, one of SORT_KEYS.
order: "asc" or "desc".
Returns:
The rendered processes.html as an HTMLResponse.
"""
if sort not in SORT_KEYS:
sort = "cpu"
if order not in ("asc", "desc"):
order = "desc"
procs = await asyncio.to_thread(proc_col.sample)
if q:
ql = q.lower()
procs = [p for p in procs if ql in p["name"].lower() or str(p["pid"]) == ql]
reverse = order == "desc"
try:
procs.sort(key=lambda p: (p[sort] is None, p[sort]), reverse=reverse)
except (KeyError, TypeError):
pass
return HTMLResponse(
render(
"processes.html",
procs=procs[:300],
total=len(procs),
q=q,
sort=sort,
order=order,
)
)