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
+46
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
# Capture a REAL node_exporter exposition from each monitored host into tests/fixtures/.
|
||||
#
|
||||
# Runs node_exporter in the foreground on the remote host for a few seconds, scrapes it
|
||||
# over loopback there, and saves the text. Nothing is installed as a service and no port
|
||||
# is opened: the only network hop is ssh.
|
||||
#
|
||||
# ./scripts/capture-node-exporter.sh # all hosts
|
||||
# ./scripts/capture-node-exporter.sh driveripper-ops # one host
|
||||
#
|
||||
# Why: metric names must be verified against the deployed exporter (see AGENTS.md), never
|
||||
# guessed from the upstream README.
|
||||
set -uo pipefail
|
||||
|
||||
VERSION="${NODE_EXPORTER_VERSION:-1.12.1}"
|
||||
OUT="$(cd "$(dirname "$0")/.." && pwd)/tests/fixtures"
|
||||
HOSTS=("${@:-driveripper-ops deskwork-ops gateway-ops}")
|
||||
PORT=9199
|
||||
ARGS="--collector.drm --collector.thermal_zone --collector.cpufreq --collector.hwmon --web.listen-address=127.0.0.1:${PORT}"
|
||||
|
||||
mkdir -p "$OUT"
|
||||
command -v ssh >/dev/null || { echo "ssh not found"; exit 1; }
|
||||
|
||||
for host in $HOSTS; do
|
||||
echo "=== $host"
|
||||
ssh -n -o ConnectTimeout=10 "$host" "set -e
|
||||
mkdir -p \$HOME/exporters && cd \$HOME/exporters
|
||||
if [ ! -x node_exporter ]; then
|
||||
curl -sSL -o ne.tgz https://github.com/prometheus/node_exporter/releases/download/v${VERSION}/node_exporter-${VERSION}.linux-amd64.tar.gz
|
||||
tar xzf ne.tgz && mv node_exporter-${VERSION}.linux-amd64/node_exporter .
|
||||
rm -rf ne.tgz node_exporter-${VERSION}.linux-amd64
|
||||
fi
|
||||
timeout 8 ./node_exporter ${ARGS} >/dev/null 2>&1 &
|
||||
sleep 3
|
||||
curl -s --max-time 5 127.0.0.1:${PORT}/metrics
|
||||
" > "$OUT/node_exporter_${host}.txt" 2>/dev/null
|
||||
lines=$(wc -l < "$OUT/node_exporter_${host}.txt")
|
||||
if [ "$lines" -lt 20 ]; then
|
||||
echo " FAILED (only $lines lines) — check ssh access to $host"
|
||||
rm -f "$OUT/node_exporter_${host}.txt"
|
||||
continue
|
||||
fi
|
||||
echo " saved $lines lines -> tests/fixtures/node_exporter_${host}.txt"
|
||||
echo " gpu: $(grep -cE '^node_gpu' "$OUT/node_exporter_${host}.txt") node_gpu series"
|
||||
grep -oE '^node_gpu[a-z_]*' "$OUT/node_exporter_${host}.txt" | sort -u | sed 's/^/ /' | head -20
|
||||
done
|
||||
Reference in New Issue
Block a user