Add homelab dashboards: system, LLM, and UPS on one domain
Three dashboards served by one FastAPI app with a SQLite history store
(raw / 1m / 1h) and hand-written SVG charts: no Prometheus, no Grafana,
no CDN, no build step. Nothing is fetched from the internet at runtime.
* system: a stdlib-only agent (agent/host_agent.py) reports /proc and
/sys counters; the dashboard turns them into rates over a labelled
window, so every number says how it was measured.
* llm: gufo/llama.cpp and vLLM /metrics are parsed by an in-house
exposition parser. Measured delta/elapsed throughput beats a native
per-request gauge, and each value carries its provenance.
* ups: a NUT wire-protocol client plus health checks that name what
they looked at. Commands are gated by NUT_ALLOW_ACTIONS,
DASH_READ_ONLY and a DANGER confirmation, re-checked server-side.
Missing values render as n/a rather than 0, and an unconfigured source
answers 404 {"configured": false} without dialling anything, so "not
deployed here" never looks like an outage.
253 tests at 94% coverage against captured real fixtures; ruff and
pyright clean.
LLM-Generated: true
This commit is contained in:
Executable
+65
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env bash
|
||||
# Local development server: start|stop|status|restart|logs|tunnel-check
|
||||
#
|
||||
# ./scripts/dev-server.sh restart # reads .env.dev if present, runs on DASH_PORT
|
||||
#
|
||||
# The server keeps running after this shell exits (nohup + pidfile) so you can browse it
|
||||
# while an agent works. Logs: data/logs/dev.log
|
||||
set -uo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$ROOT"
|
||||
PIDFILE="$ROOT/data/dev-server.pid"
|
||||
LOG="$ROOT/data/logs/dev.log"
|
||||
mkdir -p "$ROOT/data/logs"
|
||||
|
||||
running() { [ -f "$PIDFILE" ] && kill -0 "$(cat "$PIDFILE")" 2>/dev/null; }
|
||||
|
||||
start() {
|
||||
if running; then
|
||||
echo "already running (pid $(cat "$PIDFILE")) — http://127.0.0.1:${DASH_PORT:-8090}"
|
||||
return 0
|
||||
fi
|
||||
if [ -f "$ROOT/.env.dev" ]; then
|
||||
set -a; . "$ROOT/.env.dev"; set +a
|
||||
echo "loaded .env.dev"
|
||||
fi
|
||||
PORT="${DASH_PORT:-8090}"
|
||||
nohup .venv/bin/dashboards >"$LOG" 2>&1 &
|
||||
echo $! >"$PIDFILE"
|
||||
sleep 3
|
||||
if running && curl -sf -o /dev/null "http://127.0.0.1:${PORT}/api/health"; then
|
||||
echo "started pid $(cat "$PIDFILE") — http://127.0.0.1:${PORT}"
|
||||
else
|
||||
echo "FAILED to start; last lines of $LOG:"
|
||||
tail -20 "$LOG"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
stop() {
|
||||
if running; then
|
||||
kill "$(cat "$PIDFILE")" 2>/dev/null
|
||||
sleep 1
|
||||
echo "stopped"
|
||||
else
|
||||
echo "not running"
|
||||
fi
|
||||
rm -f "$PIDFILE"
|
||||
}
|
||||
|
||||
case "${1:-start}" in
|
||||
start) start ;;
|
||||
stop) stop ;;
|
||||
restart) stop; start ;;
|
||||
status)
|
||||
if running; then
|
||||
echo "running pid $(cat "$PIDFILE")"
|
||||
curl -s "http://127.0.0.1:${DASH_PORT:-8090}/api/health" \
|
||||
| .venv/bin/python -c "import json,sys; d=json.load(sys.stdin); print('status:', d['status']); [print(' ', s['key'], 'ok' if s['ok'] else 'DOWN', (s['error'] or '')[:90]) for s in d['sources']]"
|
||||
else
|
||||
echo "not running"
|
||||
fi ;;
|
||||
logs) tail -n 40 "$LOG" ;;
|
||||
*) echo "usage: $0 start|stop|restart|status|logs"; exit 2 ;;
|
||||
esac
|
||||
Reference in New Issue
Block a user