# Analítica de uso del API — panel "API · Uso"

**Fecha:** 2026-07-06

Registro por petición del API (`api.fermenty.*`) y panel admin con volumen,
usuarios conectados, latencia y errores. Pensado para seguir la adopción de la
app (simulador hoy, Flutter mañana) sin herramientas externas.

## Cómo funciona

```
petición API → grupo middleware `api` (bootstrap/app.php)
             → LogApiRequest::terminate()          ← tras enviar la respuesta
             → INSERT en api_request_logs
             → /acp/api agrega y pinta
```

### Piezas

| Pieza | Ruta |
|---|---|
| Middleware | `app/Http/Middleware/LogApiRequest.php` |
| Modelo | `app/Models/ApiRequestLog.php` (MassPrunable, `RETENTION_DAYS = 90`) |
| Migración | `database/migrations/2026_07_06_000001_create_api_request_logs_table.php` |
| Controlador admin | `app/Http/Controllers/Admin/ApiStatsAdminController.php` |
| Vista | `resources/views/admin/api_stats/index.blade.php` + `_columns.blade.php` |
| Ruta | `GET /acp/api` → `admin.api.index` (sidebar "API · Uso") |
| Poda | `routes/console.php` → `model:prune` diario a las 04:00 |
| Tests | `tests/Feature/ApiRequestLogTest.php` (6 tests) |

### Qué se guarda por petición

`user_id` (null si pública), `method`, `route` (nombre, p.ej. `api.v1.batches.index`),
`path` (URI real), `status`, `duration_ms` (desde `LARAVEL_START`), `ip`, `created_at`.
No se guarda user-agent ni payload — es analítica de volumen, no auditoría.

### Decisiones de diseño

- **`terminate()`, no `handle()`**: el insert ocurre después de responder; no
  añade latencia. Envuelto en try/catch — el log jamás tumba una respuesta.
- **Registrado en el grupo `api`** (`$middleware->api(append:)`), no en la lista
  del host: así los tests que registran `Route::middleware('api')` también lo
  ejercitan, y cualquier futura superficie que use el grupo queda cubierta.
- **Los OPTIONS (preflight CORS) no se registran.**
- **Retención 90 días** vía `MassPrunable` (delete en una sola query).
- **Charts SVG server-rendered** en el Blade (sin librerías JS — el build de
  assets sigue con el workaround de node-sass). Una serie por chart, tooltip
  JS compartido y vista tabla accesible (`<details>`).

## El panel /acp/api

- **Rango**: 7 / 14 / 30 / 90 días (`?days=`), escopa toda la página.
- **KPIs**: peticiones (total + hoy), usuarios API únicos (total + hoy),
  latencia media, errores ≥ 400 (+ % del total).
- **Charts**: peticiones/día y usuarios únicos/día (huecos rellenados a 0).
- **Tablas**: endpoints más usados (peticiones, usuarios, media ms, errores),
  usuarios más activos (enlazan a su ficha admin), errores recientes.

## Notas operativas

- En producción no hay que hacer nada: la migración en `deploy.sh` + el cron de
  `schedule:run` ya cubren tabla y poda.
- "Usuarios conectados" = usuarios únicos autenticados que hicieron ≥ 1 petición
  en el periodo (no hay sesiones persistentes en un API stateless).
- Si el volumen crece mucho (>> 100k filas/día), plantear agregación horaria en
  tabla aparte antes que tocar la retención.
