d360c9a5ba
- Systemauslastungs-Sektion wird immer gerendert (nicht nur bei Erfolg) - Fehlermeldung wenn /api/admin/system/stats nicht erreichbar ist - Feature-Status auf In Review gesetzt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
87 lines
3.9 KiB
Markdown
87 lines
3.9 KiB
Markdown
# PROJ-17: Admin Dashboard – Systemauslastung & Archiv-Übersicht
|
||
|
||
## Status: In Review
|
||
**Created:** 2026-03-14
|
||
**Last Updated:** 2026-03-14
|
||
|
||
## Dependencies
|
||
- Requires: PROJ-1 (Authentifizierung) – nur Admins sehen das Dashboard
|
||
- Requires: PROJ-5 (Speicherung) – erste/letzte Mail aus dem Archiv
|
||
|
||
## User Stories
|
||
- Als Admin möchte ich die aktuelle CPU-Auslastung sehen, damit ich Engpässe erkennen kann.
|
||
- Als Admin möchte ich die RAM-Auslastung (gesamt / verwendet / frei) sehen.
|
||
- Als Admin möchte ich alle eingebundenen Festplatten/Partitionen mit Füllstand sehen (Balken).
|
||
- Als Admin möchte ich die älteste und neueste archivierte Mail sehen (Datum, Von, Betreff), damit ich den Archivierungszeitraum auf einen Blick erkenne.
|
||
|
||
## Acceptance Criteria
|
||
- [x] CPU: Load Average (1min / 5min / 15min) aus `/proc/loadavg`
|
||
- [x] RAM: MemTotal, MemUsed, MemAvailable aus `/proc/meminfo`; Prozentbalken
|
||
- [x] Disk: alle physischen Partitionen (keine tmpfs/proc/sysfs/devtmpfs/overlay) via `syscall.Statfs`; je Partition: Mountpoint, Gesamt, Belegt, Frei, Prozent
|
||
- [x] Erste Mail im Archiv: Datum, Von, Betreff (älteste Datei im Store)
|
||
- [x] Letzte Mail im Archiv: Datum, Von, Betreff (neueste Datei im Store)
|
||
- [x] Endpoint: `GET /api/admin/system/stats` (Admin-only)
|
||
- [x] Storage-Erweiterung: `store.FirstAndLastMail()` liefert Metadaten der ältesten und neuesten Mail
|
||
|
||
## API Response Schema
|
||
|
||
```json
|
||
{
|
||
"cpu": {
|
||
"load1": 0.42,
|
||
"load5": 0.38,
|
||
"load15": 0.31,
|
||
"num_cpu": 4
|
||
},
|
||
"ram": {
|
||
"total_bytes": 8388608000,
|
||
"used_bytes": 3221225472,
|
||
"free_bytes": 5167382528,
|
||
"used_pct": 38.4
|
||
},
|
||
"disks": [
|
||
{
|
||
"mount": "/",
|
||
"total_bytes": 53687091200,
|
||
"used_bytes": 12884901888,
|
||
"free_bytes": 40802189312,
|
||
"used_pct": 24.0,
|
||
"fstype": "ext4"
|
||
}
|
||
],
|
||
"archive": {
|
||
"first_mail": { "id": "abc123", "date": "2024-01-15T08:00:00Z", "from": "...", "subject": "..." },
|
||
"last_mail": { "id": "def456", "date": "2026-03-14T10:08:00Z", "from": "...", "subject": "..." }
|
||
}
|
||
}
|
||
```
|
||
|
||
## Technical Design
|
||
|
||
### Backend (`internal/api/server.go`)
|
||
- Neuer Handler `handleSystemStats`
|
||
- CPU: `/proc/loadavg` parsen → load1, load5, load15 + `runtime.NumCPU()`
|
||
- RAM: `/proc/meminfo` parsen → MemTotal, MemFree, MemAvailable, Buffers, Cached
|
||
- `used = total - available`
|
||
- Disks: `/proc/mounts` lesen, für jeden Eintrag `syscall.Statfs()` aufrufen
|
||
- Ausschließen: fstype in {tmpfs, proc, sysfs, devtmpfs, cgroup, cgroup2, overlay, squashfs, debugfs, tracefs, securityfs, pstore, efivarfs, bpf, hugetlbfs, mqueue, ramfs}
|
||
- Erste/letzte Mail: `store.FirstAndLastMail()` → walk store dir, min/max ModTime
|
||
|
||
### Storage (`internal/storage/storage.go`)
|
||
- Neue Methode `FirstAndLastMail() (*MailRef, *MailRef, error)`
|
||
- `MailRef{ID, ModTime}` → ID wird an `handleSystemStats` übergeben, der dann via `mailparser.Parse()` From+Subject+Date extrahiert
|
||
|
||
### Frontend (`src/app/admin/page.tsx`)
|
||
- Neue Kacheln im Dashboard-Tab:
|
||
- **CPU-Auslastung**: Load Average mit `num_cpu` Kontext
|
||
- **Arbeitsspeicher**: Fortschrittsbalken (used/total), Zahlen darunter
|
||
- **Festplatten**: eine Karte pro Partition mit Balken + Zahlen
|
||
- **Archivzeitraum**: erste und letzte Mail als kompakte Zeilen (Datum · Von · Betreff)
|
||
|
||
## Implementation Notes
|
||
- **Backend:** `handleSystemStats` in `internal/api/server.go` — CPU via `/proc/loadavg`, RAM via `/proc/meminfo`, alle Disks via `/proc/mounts` + `syscall.Statfs`, Archiv-Zeitspanne via `store.FirstAndLastMail()`
|
||
- **Storage:** `FirstAndLastMail()` + `MailRef` in `internal/storage/storage.go` — walkt Store-Verzeichnis, liefert älteste/neueste Mail per ModTime
|
||
- **Route:** `GET /api/admin/system/stats` (Admin-only, Token-Auth)
|
||
- **Frontend:** Dashboard-Tab in `src/app/admin/page.tsx` mit CPU, RAM, Disk-Partitionen und Archivzeitraum; Auto-Refresh alle 30 Sekunden
|
||
- **Bereit für Test auf** `root@192.168.1.131`
|