# Monitoramento

Dashboard de monitoramento em tempo real, health checks, metricas Prometheus e conformidade ANS.

## Pre-requisitos

- Portal admin acessivel com WebSocket funcional
- Backend PIX operacional com todos os servicos (DICT, SPI, Settlement)
- Redis e NATS conectados (para health checks completos)
- Endpoint `/metrics` acessivel para scraping Prometheus (opcional)

## Arquitetura de Monitoramento

```mermaid
flowchart TB
    subgraph Backend["Backend PIX"]
        HC["HealthChecker<br/>(10s / 30s)"]
        QM["QueueMonitor<br/>(15s)"]
        BC["Broadcaster<br/>(PubSub)"]
        ME["/metrics<br/>(Prometheus)"]
        TE["Shared.Telemetry<br/>(metricas)"]
    end

    subgraph Servicos["Servicos Verificados"]
        DB["PostgreSQL"]
        RD["Redis"]
        NT["NATS"]
        DI["DICT Service :4001"]
        SP["SPI Service :4002"]
        BA["BACEN CPM/CSM"]
    end

    subgraph Frontend["Portal Admin"]
        WS["WebSocket Client<br/>(Phoenix Socket)"]
        DS["Dashboard<br/>(6 paineis)"]
    end

    subgraph Observ["Observabilidade"]
        PR["Prometheus"]
        GR["Grafana"]
        AL["Alertmanager"]
    end

    HC --> DB & RD & NT & DI & SP
    HC -->|30s| BA
    QM --> NT
    HC & QM --> BC
    BC -->|PubSub| WS
    WS --> DS
    TE --> ME
    ME --> PR
    PR --> GR
    PR --> AL
```

## WebSocket (Phoenix Channels)

O monitoramento em tempo real utiliza 6 canais WebSocket via Phoenix Channels:

### Canais

| Canal | Topico | Intervalo | Dados |
|-------|--------|-----------|-------|
| `transactions:live` | Transacoes | Tempo real | Novas transacoes, mudancas de status, TPS |
| `system:health` | Saude | 10s | Status de DB, Redis, NATS, servicos internos |
| `settlement:status` | Liquidacao | Tempo real | Ciclos, netting, reconciliacao |
| `dict:operations` | DICT | Tempo real | Criacao/exclusao de chaves, claims |
| `bacen:channels` | BACEN | 30s | Saude dos canais CPM e CSM |
| `queues:depth` | Filas | 15s | Consumer lag por worker NATS |

### Conexao WebSocket

```typescript
// frontend/admin/src/stores/monitoring.ts
import { Socket, Channel } from 'phoenix'

const socket = new Socket('/socket', {
  params: { token: authStore.token }
})
socket.connect()

// Conectar a todos os canais de monitoramento
const channels = [
  'transactions:live',
  'system:health',
  'settlement:status',
  'dict:operations',
  'bacen:channels',
  'queues:depth'
]

channels.forEach(topic => {
  const channel = socket.channel(topic, {})
  channel.join()
    .receive('ok', () => console.log(`Conectado: ${topic}`))
    .receive('error', (err) => console.error(`Erro: ${topic}`, err))

  channel.on('update', (payload) => {
    // Atualizar store Pinia com dados recebidos
    monitoringStore.handleUpdate(topic, payload)
  })
})
```

### Autenticacao do Socket

O socket Phoenix utiliza autenticacao JWT:

```elixir
# SettlementServiceWeb.UserSocket
defmodule SettlementServiceWeb.UserSocket do
  use Phoenix.Socket

  channel "transactions:*", SettlementServiceWeb.MonitoringChannel
  channel "system:*", SettlementServiceWeb.MonitoringChannel
  channel "settlement:*", SettlementServiceWeb.MonitoringChannel
  channel "dict:*", SettlementServiceWeb.MonitoringChannel
  channel "bacen:*", SettlementServiceWeb.MonitoringChannel
  channel "queues:*", SettlementServiceWeb.MonitoringChannel

  @impl true
  def connect(%{"token" => token}, socket, _connect_info) do
    case Shared.Auth.JwtAuth.verify_token(token) do
      {:ok, claims} -> {:ok, assign(socket, :user_id, claims["sub"])}
      {:error, _} -> :error
    end
  end
end
```

## HealthChecker

O `SettlementService.Monitoring.HealthChecker` executa verificacoes periodicas:

### Verificacoes a cada 10 segundos

| Servico | Verificacao | Criterio OK |
|---------|-------------|-------------|
| PostgreSQL | `Shared.Repo.query("SELECT 1")` | Retorna sem erro |
| Redis | `Shared.Redis.Connection.ping()` | Retorna `"PONG"` |
| NATS | `Process.alive?(nats_pid)` | Processo vivo |
| DICT Service | HTTP GET | Status 2xx |
| SPI Service | HTTP GET | Status 2xx |

::: info NATS HEALTH CHECK
A verificacao NATS usa `Process.alive?` para confirmar que o processo da conexao NATS esta ativo, nao apenas a variavel de ambiente. URLs dos servicos sao configuradas via variaveis de ambiente (nao hardcoded `localhost`).
:::

### Verificacoes a cada 30 segundos

| Servico | Verificacao | Criterio |
|---------|-------------|----------|
| BACEN CPM | ChannelRouter.status(:cpm) | `healthy`, `degraded` ou `down` |
| BACEN CSM | ChannelRouter.status(:csm) | `healthy`, `degraded` ou `down` |

### Transicoes de Estado

O HealthChecker registra transicoes de estado nos logs:

```
[warning] [HealthChecker] Service 'redis' changed from :healthy to :degraded
[warning] [HealthChecker] Service 'redis' changed from :degraded to :down
[info] [HealthChecker] Service 'redis' recovered to :healthy
```

### Broadcast de Saude

```elixir
# Formato do payload enviado via WebSocket
%{
  "services" => %{
    "database" => %{"status" => "healthy", "latency_ms" => 2},
    "redis" => %{"status" => "healthy", "latency_ms" => 1},
    "nats" => %{"status" => "healthy", "latency_ms" => 3},
    "dict_service" => %{"status" => "healthy", "latency_ms" => 15},
    "spi_service" => %{"status" => "healthy", "latency_ms" => 12}
  },
  "bacen" => %{
    "cpm" => %{"status" => "healthy", "failures" => 0},
    "csm" => %{"status" => "healthy", "failures" => 0}
  },
  "timestamp" => "2026-02-13T14:30:00Z"
}
```

## QueueMonitor

O `SettlementService.Monitoring.QueueMonitor` monitora o consumer lag a cada 15 segundos:

### Metricas por Consumer

| Consumer | Stream | Metrica |
|----------|--------|---------|
| `spi-inbound` | MONETARIE_SPI | Mensagens pendentes |
| `spi-outbound` | MONETARIE_SPI | Mensagens pendentes |
| `spi-status` | MONETARIE_SPI | Mensagens pendentes |
| `spi-return` | MONETARIE_SPI | Mensagens pendentes |
| `core-events` | MONETARIE_CORE | Mensagens pendentes |
| `settlement-sched` | MONETARIE_SETTLEMENT | Mensagens pendentes |

### Broadcast de Filas

```json
{
  "queues": [
    {"name": "spi-inbound", "pending": 0, "ack_pending": 0},
    {"name": "spi-outbound", "pending": 5, "ack_pending": 2},
    {"name": "core-events", "pending": 0, "ack_pending": 0}
  ],
  "timestamp": "2026-02-13T14:30:00Z"
}
```

## Metricas Prometheus

### Endpoint

```
GET /metrics
```

### Metricas Disponiveis

#### Requisicoes HTTP

| Metrica | Tipo | Labels |
|---------|------|--------|
| `phoenix_endpoint_duration_milliseconds` | Histogram | method, route, status |
| `phoenix_endpoint_count` | Counter | method, route, status |

#### Banco de Dados

| Metrica | Tipo | Labels |
|---------|------|--------|
| `ecto_query_duration_milliseconds` | Histogram | repo, source |
| `ecto_query_queue_time_milliseconds` | Histogram | repo |
| `ecto_pool_size` | Gauge | repo |
| `ecto_pool_idle` | Gauge | repo |

#### Workers NATS

| Metrica | Tipo | Labels |
|---------|------|--------|
| `pix_worker_message_processed_total` | Counter | worker, result |
| `pix_worker_batch_completed_total` | Counter | worker, size |
| `pix_worker_poll_duration_seconds` | Histogram | worker |

#### Circuit Breaker

| Metrica | Tipo | Labels |
|---------|------|--------|
| `pix_circuit_breaker_state_change_total` | Counter | name, from, to |
| `pix_circuit_breaker_request_total` | Counter | name, result |

### Configuracao Prometheus

```yaml
# prometheus.yml
scrape_configs:
  - job_name: 'monetarie-pix'
    scrape_interval: 15s
    kubernetes_sd_configs:
      - role: pod
        namespaces:
          names: ['pix']
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_label_app]
        regex: pix-backend
        action: keep
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port]
        target_label: __address__
        replacement: ${1}:4003
        action: replace
```

### NetworkPolicy para Prometheus

```yaml
# Permitir scraping do Google Managed Prometheus (GMP)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-prometheus-scrape
  namespace: pix
spec:
  podSelector:
    matchLabels:
      app: pix-backend
  ingress:
    - from:
        - podSelector:
            matchLabels:
              purpose: gmp-collector
      ports:
        - port: 4003
          protocol: TCP
```

## Conformidade ANS (Acordo de Nivel de Servico)

### Requisito BCB

O Banco Central exige que transacoes PIX sejam liquidadas em ate **1,6 segundos** (1.600ms).

### Tracking no Dashboard

A view de detalhe de transacao exibe o timing ANS:

```mermaid
flowchart LR
    OP["Operacao<br/>(operation_time)"] --> AC["Aceite<br/>(acceptance_time)"]
    AC --> LQ["Liquidacao<br/>(settlement_time)"]
    LQ --> DT["Delta<br/>(settlement - operation)"]

    DT -->|<= 1600ms| OK["OK"]
    DT -->|> 1600ms| EX["EXCEDIDO"]

    style OK fill:#2ecc71,stroke:#333,color:#fff
    style EX fill:#e74c3c,stroke:#333,color:#fff
```

| Campo | Descricao |
|-------|-----------|
| `operation_time` | Momento da criacao da transacao |
| `acceptance_time` | Momento do aceite (ACCC) |
| `settlement_time` | Momento da liquidacao (STLD) |
| Delta | `settlement_time - operation_time` |

### Badges ANS

| Condicao | Badge | Cor |
|----------|-------|-----|
| Delta <= 1.600ms | **OK** | Esmeralda (#2ecc71) |
| Delta > 1.600ms | **EXCEDIDO** | Vermelho (#e74c3c) |

### Dados de Seed

As 200 transacoes de seed possuem deltas entre 300ms e 1.500ms, garantindo conformidade ANS para demonstracao.

## Endpoints de Monitoramento

### Health Check

```bash
# Health check basico
curl -s https://pixapi-dev.fluxiq.com.br/health | jq
```

### Metricas via API

| Metodo | Path | Descricao |
|--------|------|-----------|
| GET | `/api/v1/monitoring/health` | Health check detalhado com todos os servicos |
| GET | `/api/v1/monitoring/metrics` | Metricas BEAM VM (processos, memoria, schedulers) |
| GET | `/api/v1/monitoring/infrastructure` | Alertas de infraestrutura |

### Metricas BEAM VM

```json
{
  "beam": {
    "process_count": 1247,
    "memory_total_mb": 512,
    "memory_processes_mb": 256,
    "memory_ets_mb": 48,
    "scheduler_count": 8,
    "scheduler_utilization": [0.45, 0.38, 0.52, 0.41, 0.33, 0.47, 0.39, 0.44],
    "run_queue": 0
  },
  "timestamp": "2026-02-13T14:30:00Z"
}
```

## Alertas Recomendados

| Metrica | Limiar | Severidade | Acao |
|---------|--------|------------|------|
| Health check falho | > 3 consecutivos | Critico | Investigar servico afetado |
| Consumer lag | > 1.000 msgs | Alto | Escalar pods ou aumentar concurrency |
| ANS delta medio | > 1.200ms | Alto | Investigar gargalo (DB, rede, BACEN) |
| Circuit breaker open | Qualquer | Alto | Verificar servico downstream |
| DB pool exausto | idle = 0 | Critico | Aumentar POOL_SIZE ou investigar queries lentas |
| Redis memoria | > 80% | Alto | Revisar TTLs, aumentar memoria |
| BACEN canal down | Qualquer | Critico | Verificar RSFN, acionar failover |

## Resultado Esperado

Apos configurar o monitoramento:

- O dashboard exibe 6 paineis com dados em tempo real via WebSocket
- O HealthChecker verifica servicos a cada 10s e canais BACEN a cada 30s
- O QueueMonitor reporta consumer lag a cada 15s
- O endpoint `/metrics` expoe metricas Prometheus para scraping
- Transicoes de estado de servicos sao logadas com `Logger.warning`
- O timing ANS e exibido em cada transacao com badge OK/EXCEDIDO
- Metricas BEAM VM (processos, memoria, schedulers) estao disponiveis via API
