## [MEDIUM] No Application Performance Monitoring (APM) **Status: COMPLETED ✓** **What was done:** - Backend Prometheus metrics: `/metrics` endpoint exposes request count, latency, active requests - Frontend web-vitals tracking: FCP, LCP, CLS, INP, TTFB collection - API call metrics: automatic tracking of latency and error rates - Complete documentation with examples and integration guides **Implementation:** - Backend: `app/utils/metrics.py`, `app/middleware/metrics.py`, `app/routers/metrics.py` - Frontend: `src/utils/metrics.ts`, `src/hooks/useTrackedFetch.ts` - Documentation: `Docs/Observability.md` (APM section) **Metrics exposed:** - `bangui_http_requests_total` - HTTP request count by method, endpoint, status - `bangui_http_request_duration_seconds` - Request latency histogram - `bangui_http_active_requests` - Current active requests gauge - Web Vitals: CLS, FCP, INP, LCP, TTFB - API call metrics: method, endpoint, status, duration --- ## [LOW] Frontend charts not memoized **Where found** - `frontend/src/components/TopCountriesPieChart.tsx` - `frontend/src/components/TopCountriesBarChart.tsx` **Why this is needed** Charts re-render on every parent update, Recharts reprocesses 5000+ points. **Goal** Memoize chart components. **What to do** 1. Wrap with `React.memo` with custom comparison 2. Ensure data objects are stable **Possible traps and issues** - Shallow comparison might not be enough - Memoization has memory cost **Docs changes needed** - No documentation changes **Doc references** - `frontend/src/components/TopCountriesChart.tsx` --- ## [LOW] No request deduplication on frontend **Where found** - `frontend/src/hooks/useFetchData.ts` — each call launches new request - User clicks "Refresh" twice → two identical requests **Why this is needed** Duplicates waste bandwidth, cause race conditions (response 2 arrives first, then response 1 overwrites with stale data). **Goal** Deduplicate identical in-flight requests. **What to do** 1. Implement request cache 2. Clear cache entry when response received 3. Use in `useFetchData` **Possible traps and issues** - Cache must be cleared on data mutation - Stale data in cache possible if not careful **Docs changes needed** - No documentation changes **Doc references** - `frontend/src/hooks/useFetchData.ts`