Bongbetic
crafted with stubborn curiosity by Bongbetic

Fenris glyph

Fenris ๐Ÿบ โ€” Your SSD's Tell-All Diary

Your NVMe drive has been keeping secrets. Fenris makes it confess โ€” in real time.
How much did you write today? How long until it taps out? No fairy dust โ€” just your actual bytes.

--- Fenris is a tiny, stubborn daemon that eavesdrops on your NVMe drive's SMART gossip, writes it down every few minutes, and serves you a live dashboard that actually means something. Not "vibes" โ€” **real GB written in the last 24 hours, real GB/hour, and a real countdown in hours, days, and years until your drive's endurance runs out**. > Think of it as a Fitbit for your SSD. Except it doesn't nag you to drink water. ## What it actually does (no hand-waving) - **Listens** โ€” polls `smartctl -j` on your NVMe device (default every 5 minutes, you pick). - **Remembers** โ€” appends every sample to `data/history.jsonl` and rolls up per-hour totals into `data/hourly.jsonl` (survives restarts, rebuilds itself if you yank the power). - **Calculates** โ€” rolling 24-hour window: *exact* bytes written in the last 24h, GB/h, GB/day, implied total TBW from `percentage_used`, remaining TB, and a projected life-remaining breakdown. Warming-up badge until it has 24h of coverage โ€” no fake confidence. - **Shows off** โ€” dense, live dashboard with wear-over-time + trailing-24h per-hour bars, sticky header, live countdown, and stale warnings if the daemon dozes off. ## You need - **Python 3.7+** - **smartmontools** (`smartctl`) - Root-ish access to read NVMe SMART (passwordless `smartctl` or just run with `sudo` โ€” your call) ### The sudo dance (one time) Fenris runs `sudo -n smartctl ...` so it doesn't get stuck asking for a password mid-nap: ```bash sudo visudo # add this line (swap in your username): youruser ALL=(root) NOPASSWD: /usr/sbin/smartctl ``` No sudo? Run the whole thing with `sudo` and it'll still behave. ## Get it running โ€” 30 seconds ### The cozy way ```bash ./fenris.sh # pick 1) Start monitoring โ†’ choose device / interval / port โ†’ done ``` ### The no-nonsense way ```bash python3 fenris.py start # defaults: /dev/nvme0, every 300s, port 8420 python3 fenris.py start --interval 60 --port 9000 # if you're impatient python3 fenris.py status # "are we live? how's the drive?" python3 fenris.py sample # one sneaky sample right now python3 fenris.py stop # tuck it back in ``` Dashboard lives at **http://localhost:8420** (or whatever port you chose). ## The menu, demystified Run `./fenris.sh` and you'll get: ``` 1) Start monitoring (background daemon + dashboard) 2) Stop monitoring 3) Status / current wear stats 4) Take one sample right now 5) Open dashboard URL --- h) Help / how this works q) Exit (go touch grass) ``` ## What Fenris jots down | Field | What's the gossip? | |-------|---------------------| | `percentage_used` | The drive's own wear-o-meter (0โ€“100%) | | `bytes_written` / `bytes_read` | Lifetime totals โ€” the receipts | | `available_spare` | Spare blocks left (%) | | `media_errors` | Uncorrectable boo-boos | | `power_on_hours` | How long it's been awake | | `temperature_c` | Is it sweating? | | `critical_warning` | NVMe's panic flags | Hourly rollups also stash `bytes_written` per hour, `pct_start`/`pct_end`, and temp peaks โ€” so the 24h math stays honest. ## The dashboard โ€” what's on screen - **Hero card: Projected life remaining** โ€” big, friendly `361 d 2 h` (plus `โ‰ˆ 361 days ยท โ‰ˆ 8666 hours ยท โ‰ˆ 0.99 years`), backed by `~280 GB/day` and `~101 TB left of ~202 TB total` on the test box. - **Data written (24h)** โ€” exact GB in the rolling window + coverage (`10.4h of 24h` until warmed up). - **Write rate** โ€” GB/h and GB/day, live. - **Wear, spare, temp, errors, power-on** โ€” the usual suspects, with progress bars and polite color-coding. - **Two charts, side by side:** wear over time + trailing-24h hourly write bars (with a cheeky "now" bar for the current partial hour). - **Live plumbing:** polling synced to your interval, ETag-cached, countdown to next sample, warming-up + stale banners, pauses when you hide the tab (saves your battery, you're welcome). **API for the tinkerers:** `GET /api/data` ยท `/api/hourly` ยท `/api/summary` ยท `/api/config` ยท `/api/status` โ€” all JSON, all friendly. ## Where's my stuff? ``` fenris/ โ”œโ”€โ”€ fenris.py # the whole show โ€” daemon + server + math โ”œโ”€โ”€ fenris.sh # the cozy menu โ”œโ”€โ”€ README.md # hi โ€” you're here โ”œโ”€โ”€ assets/bongbetic-brand/ # Bongbetic wordmarks & glyphs (for Gitea + dashboard) โ””โ”€โ”€ data/ โ”œโ”€โ”€ history.jsonl # raw samples (JSONL, append-only) โ”œโ”€โ”€ hourly.jsonl # per-hour rollups (auto-rebuilt on restart) โ”œโ”€โ”€ fenris.pid # daemon PID โ””โ”€โ”€ fenris.log # daemon chatter ``` ## CLI cheat sheet ```bash python3 fenris.py start [--device /dev/nvme0] [--interval 300] [--port 8420] python3 fenris.py stop python3 fenris.py status python3 fenris.py sample [--device /dev/nvme0] python3 fenris.py run # foreground mode โ€” what `start` spawns internally ``` ## Oops โ€” troubleshooting without the tears **"smartctl not found"** ```bash sudo apt install smartmontools # Debian/Ubuntu sudo pacman -S smartmontools # Arch โ€” you already knew ``` **"needs root" / permission denied** Set up the passwordless line above, or just `sudo ./fenris.sh`. **Dashboard says "stale"** Daemon napped or crashed. `python3 fenris.py status` will tell you. Kick it again with `start`. **Only 10 hours of data and it says "preliminary"?** That's honesty, not a bug. It needs 24h of real writes to give a tight estimate. Let it simmer โ€” the number gets sharper every hour. ---

Fenris ๐Ÿบ โ€” by Bongbetic ยท Be kind to your SSD and it'll be kind to you.
Bongbetic icon