# Plan de métricas del bot

Este documento recoge:

1. Inventario de las métricas **ya existentes** en el código.
2. Clasificación de cada métrica:
   - **core**: queremos cuidarla y mantenerla estable.
   - **nice-to-have**: útil, pero no crítica; se puede ajustar.
   - **debug**: orientada a depuración / exploración.
   - **dudosa**: probablemente haya que redefinirla o eliminarla.
3. Propuesta de **set “core v1”** (existentes + nuevas).
4. Notas sobre **persistencia** y derivación desde BD.
5. Próximos pasos para implementación.

---

## 1. Inventario actual de métricas

> Nota: solo se listan métricas usadas en código de producción (no tests ni docs).

### 1.1. HTTP / Webhook / Tráfico

| Métrica                                   | Tipo     | Ámbito            | Labels principales                         | Uso actual / intención                                        | Categoría |
|------------------------------------------|----------|-------------------|--------------------------------------------|----------------------------------------------------------------|-----------|
| `webhook_events_total_*`                 | counter  | Webhook           | `evtNorm` embebido en el nombre (`*_xxx`)  | Contar eventos de webhook por tipo (messages.upsert, etc.).    | core      |
| `webhook_errors_total`                   | counter  | Webhook           | –                                          | Errores procesando webhooks.                                  | core      |
| `unknown_groups_discovered_total`        | counter  | Webhook/grupos    | –                                          | Mensajes recibidos de grupos no conocidos en BD.              | nice-to-have |
| `messages_blocked_group_total`           | counter  | Webhook/grupos    | –                                          | Mensajes bloqueados por venir de grupos no permitidos.        | nice-to-have |

### 1.2. Onboarding (grupos, DMs, asignaciones)

| Métrica                                   | Tipo     | Ámbito              | Labels principales                                         | Uso actual / intención                                         | Categoría      |
|------------------------------------------|----------|---------------------|------------------------------------------------------------|-----------------------------------------------------------------|----------------|
| `onboarding_prompts_sent_total`          | counter  | Onboarding-grupos   | `group_id`, `source`, `reason`                            | Prompts de onboarding enviados al grupo.                       | core (producto)|
| `onboarding_prompts_skipped_total`       | counter  | Onboarding-grupos   | `group_id`, `source?`, `reason`                           | Casos donde se decide no enviar prompt al grupo.               | core (producto)|
| `onboarding_assign_failures_total`       | counter  | Onboarding-asignac. | `group_id`, `source`, `reason`                            | Fallos al autoasignar tarea en onboarding.                     | nice-to-have   |
| `onboarding_dm_skipped_total`            | counter  | Onboarding-DM       | `reason`, `group_id`                                      | Razones por las que NO se envía DM de onboarding.              | core (producto)|
| `onboarding_dm_sent_total`               | counter  | Onboarding-DM       | `variant`, `part`, `group_id`                             | DMs de onboarding efectivamente enviados.                      | core (producto)|
| `onboarding_recipients_capped_total`     | counter  | Onboarding-DM       | `group_id`                                                | Número de destinatarios que se quedaron fuera por cap.         | nice-to-have   |
| `onboarding_bundle_sent_total`           | counter  | Onboarding-DM       | `variant`, `group_id`                                     | “Bundles” de onboarding enviados.                              | nice-to-have   |
| `onboarding_dm_sent_abs`                 | gauge    | Onboarding-analytics| –                                                          | Valor absoluto de DMs enviados (derivado).                     | debug          |
| `onboarding_recipients_abs`              | gauge    | Onboarding-analytics| –                                                          | Destinatarios totales (derivado).                              | debug          |
| `onboarding_converted_users_abs`         | gauge    | Onboarding-analytics| –                                                          | Usuarios convertidos (derivado).                               | debug          |
| `onboarding_conversion_rate`             | gauge    | Onboarding-analytics| –                                                          | Ratio de conversión calculado.                                 | debug / dudosa |

### 1.3. Reacciones / Cola de respuestas

| Métrica                                           | Tipo     | Ámbito           | Labels principales      | Uso actual / intención                                | Categoría     |
|--------------------------------------------------|----------|------------------|-------------------------|--------------------------------------------------------|--------------|
| `reactions_enqueued_total`                       | counter  | Reacciones/cola  | `emoji`                 | Reacciones encoladas para enviar.                     | nice-to-have |
| `reactions_sent_total`                           | counter  | Reacciones/cola  | `emoji`                 | Reacciones enviadas con éxito.                        | nice-to-have |
| `reactions_failed_total`                         | counter  | Reacciones/cola  | `emoji`                 | Reacciones que fallaron al enviar.                    | nice-to-have |
| `responses_skipped_unresolvable_recipient_total` | counter  | Cola respuestas  | `reason` (`non_numeric`, `too_long`, `bad_domain`…) | Respuestas descartadas por no poder resolver el JID.  | debug (útil) |

### 1.4. Recordatorios

| Métrica                                | Tipo     | Ámbito       | Labels principales | Uso actual / intención                                  | Categoría     |
|----------------------------------------|----------|--------------|--------------------|----------------------------------------------------------|--------------|
| `reminders_skipped_outside_window_total` | counter | Recordatorios| –                  | Recordatorios omitidos por estar fuera de ventana horaria. | dudosa (parcial) |

### 1.5. Group sync / grupos / miembros

| Métrica                              | Tipo     | Ámbito        | Labels principales          | Uso actual / intención                                         | Categoría     |
|--------------------------------------|----------|---------------|-----------------------------|-----------------------------------------------------------------|--------------|
| `sync_runs_total`                    | counter  | Group sync    | –                           | Número de ejecuciones de sync.                                 | core (ops)   |
| `sync_errors_total`                  | counter  | Group sync    | –                           | Errores en ejecuciones de sync.                                | core (ops)   |
| `sync_skipped_group_total`          | counter  | Group sync    | –                           | Grupos ignorados en la reconciliación (varios motivos).        | nice-to-have |
| `allowed_groups_labels_filled_total` | counter  | Group sync    | –                           | Conteo de grupos donde se rellenaron labels de allowed_groups. | debug        |
| `active_groups`                      | gauge    | Group sync    | –                           | Número de grupos activos cacheados.                            | core         |
| `active_members`                     | gauge    | Group sync    | –                           | Conteo de miembros activos (BD).                               | core         |
| `last_sync_timestamp_seconds`        | gauge    | Group sync    | –                           | Marca de tiempo del último sync correcto.                      | core         |
| `last_sync_ok`                       | gauge    | Group sync    | –                           | 1 si último sync OK, 0 si falló.                               | core         |
| `last_sync_duration_ms`              | gauge    | Group sync    | –                           | Duración del último sync.                                      | core         |
| `alias_coverage_ratio`               | gauge    | Group sync    | `group_id`                  | Cobertura de alias de identidad en el grupo.                   | debug/nice   |
| `allowed_groups_total_pending`       | gauge    | Allowed groups| –                           | Grupos en estado `pending`.                                    | core         |
| `allowed_groups_total_allowed`       | gauge    | Allowed groups| –                           | Grupos en estado `allowed`.                                    | core         |
| `allowed_groups_total_blocked`       | gauge    | Allowed groups| –                           | Grupos en estado `blocked`.                                    | core         |
| `group_sync_seconds_until_next`      | gauge    | Group sync    | –                           | Segundos hasta el próximo sync, o -1 si inactivo.              | core         |

### 1.6. Identidad / alias

| Métrica                           | Tipo     | Ámbito    | Labels principales | Uso actual / intención                            | Categoría |
|-----------------------------------|----------|-----------|--------------------|----------------------------------------------------|----------|
| `identity_alias_upsert_errors_total` | counter| Identidad | –                  | Errores al hacer upsert de alias.                 | debug    |
| `identity_alias_upserts_total`      | counter| Identidad | –                  | Número de upserts de alias realizados.            | debug    |
| `identity_alias_resolved_total`     | counter| Identidad | –                  | Alias resueltos correctamente.                    | debug    |
| `identity_alias_unresolved_total`   | counter| Identidad | –                  | Casos en los que no se pudo resolver alias.       | debug    |

### 1.7. Administración (allow/block/list)

| Métrica                    | Tipo     | Ámbito      | Labels principales | Uso actual / intención                                | Categoría     |
|----------------------------|----------|-------------|--------------------|--------------------------------------------------------|--------------|
| `admin_actions_total_allow`| counter  | Admin       | –                  | Acciones de “allow” hechas por admins.                | nice-to-have |
| `admin_actions_total_block`| counter  | Admin       | –                  | Acciones de “block” hechas por admins.                | nice-to-have |
| `admin_actions_total_list` | counter  | Admin       | –                  | Invocaciones a listados de allowed_groups.            | nice-to-have |

### 1.8. Comandos

| Métrica                    | Tipo     | Ámbito     | Labels principales     | Uso actual / intención                                  | Categoría      |
|----------------------------|----------|------------|------------------------|----------------------------------------------------------|---------------|
| `commands_alias_used_total`| counter  | Comandos   | `action=info|mias|...` | Uso de alias de comandos.                               | nice-to-have  |
| `commands_unknown_total`   | counter  | Comandos   | –                      | Mensajes que no se mapean a ningún comando.             | core (debug/ux)|
| `commands_blocked_total`   | counter  | Comandos   | –                      | Comandos bloqueados (p.ej. grupo no permitido).         | core (producto/ops) |
| `ver_dm_transition_total`  | counter  | Comandos   | –                      | Veces que se hace transición a “ver por DM”.            | nice-to-have  |
| `web_tokens_issued_total`  | counter  | Web tokens | –                      | Número de tokens web emitidos.                          | nice-to-have  |

### 1.9. Mantenimiento / “evolution” (instancia WA)

| Métrica                                   | Tipo     | Ámbito       | Labels principales         | Uso actual / intención                                     | Categoría   |
|-------------------------------------------|----------|--------------|----------------------------|-------------------------------------------------------------|------------|
| `evolution_instance_state_changes_total`  | counter  | Evolution    | `instance`                 | Número de cambios de estado de la instancia.               | core (ops) |
| `evolution_health_check_errors_total`     | counter  | Evolution    | `instance`                 | Errores en health checks.                                  | core (ops) |
| `evolution_instance_restart_attempts_total`| counter | Evolution    | `instance`                 | Intentos de reinicio de la instancia.                      | core (ops) |
| `evolution_instance_restart_success_total`| counter  | Evolution    | `instance`                 | Reinicios exitosos de la instancia.                        | core (ops) |
| `evolution_instance_state`                | gauge    | Evolution    | `instance`, `state`        | Estados actuales de la instancia (por valor de `state`).   | core (ops) |
| `evolution_instance_last_state_change_ts` | gauge    | Evolution    | `instance`                 | Timestamp del último cambio de estado.                     | nice-to-have |
| `evolution_instance_state_age_seconds`    | gauge    | Evolution    | `instance`                 | Tiempo en segundos en el estado actual.                    | nice-to-have |

---

## 2. Propuesta de set “core v1” (existentes)

### 2.1. Operación / salud

**Mantener como core:**

- Webhook / HTTP:
  - `webhook_events_total_*`
  - `webhook_errors_total`
- Group sync:
  - `sync_runs_total`
  - `sync_errors_total`
  - `active_groups`
  - `active_members`
  - `last_sync_timestamp_seconds`
  - `last_sync_ok`
  - `last_sync_duration_ms`
  - `group_sync_seconds_until_next`
  - `allowed_groups_total_pending`
  - `allowed_groups_total_allowed`
  - `allowed_groups_total_blocked`
- Evolution / instancia WA:
  - `evolution_instance_state_changes_total`
  - `evolution_health_check_errors_total`
  - `evolution_instance_restart_attempts_total`
  - `evolution_instance_restart_success_total`
  - `evolution_instance_state`

### 2.2. Experiencia de usuario / producto

**Mantener como core:**

- Onboarding:
  - `onboarding_prompts_sent_total`
  - `onboarding_prompts_skipped_total`
  - `onboarding_dm_sent_total`
  - `onboarding_dm_skipped_total`
- Comandos:
  - `commands_unknown_total`
  - `commands_blocked_total`

---

## 3. Métricas existentes marcadas como “nice-to-have” o “debug”

### 3.1. Nice-to-have (mantener pero sin contrato fuerte)

- Webhook / grupos:
  - `unknown_groups_discovered_total`
  - `messages_blocked_group_total`
- Onboarding:
  - `onboarding_assign_failures_total`
  - `onboarding_recipients_capped_total`
  - `onboarding_bundle_sent_total`
- Reacciones:
  - `reactions_enqueued_total` / `reactions_sent_total` / `reactions_failed_total`
- Group sync:
  - `sync_skipped_group_total`
  - `alias_coverage_ratio` (si se usa en dashboards)
- Administración:
  - `admin_actions_total_allow`
  - `admin_actions_total_block`
  - `admin_actions_total_list`
- Comandos:
  - `commands_alias_used_total`
  - `ver_dm_transition_total`
  - `web_tokens_issued_total`
- Evolution:
  - `evolution_instance_last_state_change_ts`
  - `evolution_instance_state_age_seconds`

### 3.2. Debug / dudosas (candidatas a simplificar o eliminar)

- Onboarding analytics:
  - `onboarding_dm_sent_abs`
  - `onboarding_recipients_abs`
  - `onboarding_converted_users_abs`
  - `onboarding_conversion_rate`
- Identidad / alias:
  - `identity_alias_upsert_errors_total`
  - `identity_alias_upserts_total`
  - `identity_alias_resolved_total`
  - `identity_alias_unresolved_total`
- Cola de respuestas:
  - `responses_skipped_unresolvable_recipient_total` (debug útil → mantener como tal).
- Recordatorios:
  - `reminders_skipped_outside_window_total` (parcial: solo una razón de skip, sin contexto de enviados totales).

---

## 4. Métricas nuevas propuestas (faltantes importantes)

> Nota: nombres sujetos a ajuste, pero la idea es que sean lo más “Prometheus-friendly” posible.

### 4.1. Tareas

- **Counters (idealmente derivables de BD, o directamente desde DB en `/metrics`):**
  - `tasks_created_total`  
    - Definición: `COUNT(*) FROM tasks`.
  - `tasks_completed_total`  
    - Definición: `COUNT(*) FROM tasks WHERE completed = 1`.

- **Gauges (derivables de BD):**
  - `tasks_active`  
    - Definición: tareas no completadas (criterio exacto según modelo).
  - `tasks_overdue`  
    - Definición: tareas no completadas con `due_date < hoy`.
  - (Opcional) `tasks_active_by_group` con label `group_id` **solo si** el número de grupos es manejable y se considera útil.

### 4.2. Mensajes y cola de respuestas

- **Tráfico recibido (webhook):**
  - `bot_messages_received_total` (counter, en memoria)
    - Labels: `kind=text|reaction|system|other`.

- **Tráfico enviado por el bot (muy importante, idealmente persistente):**
  - `bot_messages_sent_total` (counter, **persistente** o derivado de BD si posible)
    - Labels: `kind=reply|reminder|onboarding|error|other`.

- **Cola de respuestas:**
  - Counters:
    - `response_queue_enqueued_total` (por tipo de mensaje/reacción).
    - `response_queue_sent_total`.
    - `response_queue_failed_total`.
    - `response_queue_retried_total`.
    - `response_queue_exhausted_total` (cuando se dan por fallidos tras reintentos).
  - Gauges (desde BD):
    - `response_queue_pending`  
      - `COUNT(*) FROM response_queue WHERE status='pending'`.
    - `response_queue_oldest_age_seconds`  
      - `now - MIN(created_at)` de los pendientes.

### 4.3. Recordatorios (visión completa)

- Counters:
  - `reminders_scheduled_total`  
    - Cuando se programa un recordatorio.
  - `reminders_sent_total`  
    - Recordatorios enviados efectivamente.
  - `reminders_failed_total`  
    - Intentos de envío de recordatorio fallidos.
  - `reminders_skipped_total`  
    - Con labels `reason=outside_window|user_opt_out|group_not_allowed|gating|invalid_time|other`.

- Opcionalmente ratios calculables en dashboards:
  - `reminders_skipped_total / (reminders_sent_total + reminders_skipped_total)`.

### 4.4. Uso de ICS / Web

- ICS:
  - `ics_requests_total` (counter)
    - Labels: `type=personal|group|aggregate`, `status_class=2xx|4xx|5xx`.

- HTTP genérico (si se desea):
  - `http_requests_total`
    - Labels: `handler=webhook|metrics|ics|web_ui|...`, `status_class=2xx|4xx|5xx`.

### 4.5. Otras métricas posibles (según prioridad)

- Usuarios / grupos (como gauges desde BD):
  - `groups_total`, `groups_active_total`.
  - `group_members_total` (activos).
  - `users_total`.
  - `users_active_30d` (si hay `last_seen_at`).

---

## 5. Persistencia vs. métricas derivadas

### 5.1. Derivadas desde BD (sin cambiar `Metrics`)

Buenas candidatas:

- `tasks_*` (`created`, `completed`, `active`, `overdue`).
- `groups_*` (`total`, `active`).
- `group_members_total`.
- `allowed_groups_total_*` (ya se hace).
- `response_queue_pending`, `response_queue_oldest_age_seconds`.

Ventaja: son **persistentes por diseño**, no dependen de reinicios del proceso.

### 5.2. Contadores en memoria (se reinician)

Buenas candidatas:

- Tráfico “reciente”:
  - `bot_messages_received_total`.
  - `http_requests_total`.
- Eventos de corto plazo:
  - `sync_runs_total`, `sync_errors_total`.
  - `evolution_*` (si además se pueden inferir de logs/BD, no es grave que se reinicien).

Estos están bien para **tendencias recientes**, SLIs y alertas basadas en tasas.

### 5.3. Contadores que probablemente queremos **persistir**

Lista corta para no complicar demasiado:

- `bot_messages_sent_total`
- `reminders_sent_total`
- (Opcional) `webhook_events_received_total` (si se agrega unificado, en lugar de solo por tipo).

Opciones:

1. Crear una tabla `persistent_metrics(name TEXT PRIMARY KEY, value INTEGER NOT NULL)`.
2. Implementar funciones de “incremento persistente” que actualicen BD y, opcionalmente, el estado de `Metrics`.
3. Al renderizar `/metrics`, leer estos valores persistentes y exponerlos.

---

## 6. Próximos pasos sugeridos

1. **Validar este set “core v1”**:  
   - Confirmar que las métricas “core existentes” listadas arriba son realmente las que quieres cuidar.
   - Elegir cuáles de las nuevas propuestas son **imprescindibles** en la primera iteración (p.ej. tareas + mensajes + cola + recordatorios).

2. **Definir contrato de nombres**:
   - Cerrar nombres finales de:
     - `tasks_*`
     - `bot_messages_*`
     - `response_queue_*`
     - `reminders_*`
     - `ics_requests_total` / `http_requests_total`.

3. **Implementar por fases**:
   - Fase 1: gauges derivadas de BD en `/metrics` (tareas, cola, grupos, etc.).
   - Fase 2: counters en memoria (mensajes recibidos/enviados, recordatorios, cola).
   - Fase 3: mecanismo de métricas persistentes y migrar los 2–3 contadores elegidos.

4. **Limpiar / reclasificar métricas “debug/dudosas”**:
   - Mantener `responses_skipped_unresolvable_recipient_total` como debug útil.
   - Simplificar o eliminar gauges de onboarding `*_abs` / `conversion_rate` si no se usan.
   - Revisar `reminders_skipped_outside_window_total` cuando exista el set completo de `reminders_*`.

Este documento sirve como referencia para saber qué métricas existen, cuáles son “de contrato” y cuáles se pueden tocar con menos miedo, además de qué huecos importantes hay que cubrir en próximas iteraciones.
