feat: add analytics dashboard with traffic monitoring

- Parse Caddy access logs every 30s into traffic_events SQLite table
- GeoIP country lookup via maxmind (GeoLite2-Country.mmdb)
- 90-day retention with automatic purge
- Analytics page with interval (24h/7d/30d) and per-host filtering:
  - Stats cards: total requests, unique IPs, blocked count, block rate
  - Requests-over-time area chart (ApexCharts)
  - SVG world choropleth map (d3-geo + topojson-client, React 19 compatible)
  - Top countries table with flag emojis
  - HTTP protocol donut chart
  - Top user agents horizontal bar chart
  - Recent blocked requests table with pagination
- Traffic (24h) summary card on Overview page linking to analytics
- 7 authenticated API routes under /api/analytics/
- Share caddy-logs volume with web container (read-only)
- group_add caddy GID to web container for log file read access

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
fuomag9
2026-02-26 20:43:23 +01:00
parent 674e06e3c9
commit 8be69d2774
23 changed files with 2584 additions and 16 deletions
+9 -2
View File
@@ -18,19 +18,26 @@
"@mui/icons-material": "^7.3.8",
"@mui/material": "^7.3.6",
"@types/better-sqlite3": "^7.6.13",
"apexcharts": "^5.6.0",
"bcryptjs": "^3.0.3",
"better-sqlite3": "^12.6.2",
"d3-geo": "^3.1.1",
"drizzle-orm": "^0.45.1",
"maxmind": "^5.0.5",
"next": "^16.1.3",
"next-auth": "^5.0.0-beta.30",
"react": "^19.2.3",
"react-dom": "^19.2.3"
"react-apexcharts": "^2.0.1",
"react-dom": "^19.2.3",
"topojson-client": "^3.1.0"
},
"devDependencies": {
"drizzle-kit": "^0.31.9",
"@types/d3-geo": "^3.1.0",
"@types/node": "^25.2.3",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@types/topojson-client": "^3.1.5",
"drizzle-kit": "^0.31.9",
"eslint": "^9.39.2",
"eslint-config-next": "^16.1.3",
"typescript": "^5.9.3"