The attempts log is your post-incident reading material and your weekly health check. The goal isn't to read every row — it's to make patterns visible at a glance.
The display
Last 100 rows, newest first, color-coded by success/failure. That's it.
Patterns to watch for
- Bursts from one IP, then silence — hit your retry limit, got blacklisted. Working as intended.
- Steady drip from many IPs — distributed scanner. Investigate WAF / fail2ban / change-port.
- curl / python-requests / wget UAs — 100% bots. Your real traffic is browsers.
- Successful login from an IP you don't recognize — STOP READING THIS DASHBOARD AND GO TO TRACK 7.
Retention
SQLite handles millions of rows without complaint, but UI gets useless past 100 visible. Keep all rows in DB (cheap forensics), display the last 100 by default, with a "load 500 more" button if you ever need to dig.