> For the complete documentation index, see [llms.txt](https://es-kb.topopool.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://es-kb.topopool.com/monitoreo/prometheus-grafana.md).

# Prometheus y Grafana

Vamos a levantar un stack de monitoreo completo que te da visibilidad en tiempo real sobre el estado de tus nodos: métricas de cardano-node, sistema (CPU, RAM, disco, red) y métricas de pool (stake, delegadores, bloques, ROA).

***

## Arquitectura del setup

```
cardano-node ──── puerto 12798 ─────┐
                                    ├──► Prometheus ──► Grafana ──► Dashboard TOPO⚡
node_exporter ─── puerto 9100 ──────┘
pool-exporter ─── (opcional) ───────┘
```

El servidor de monitoreo puede ser el mismo relay o una VM separada. Si lo ponés en el mismo relay, Prometheus scrapea localhost; si es una VM aparte, abrís los puertos de métricas solo hacia esa IP.

{% hint style="info" %}
En esta guía asumimos que el servidor de monitoreo corre en la misma máquina que el relay, o que tenés acceso a la IP privada del relay desde el servidor de monitoreo.
{% endhint %}

***

## 1. Verificar la configuración de cardano-node

El nodo ya expone métricas si el `config.json` tiene configurados estos campos:

```json
"hasPrometheus": ["127.0.0.1", 12798],
"hasEKG": 12789
```

Verificamos qué endpoint tiene las métricas:

```bash
# Puerto Prometheus (legacy tracing — lo más común)
curl -s http://127.0.0.1:12798 | head -5

# Puerto EKG (JSON — nuevo tracing backend o fallback)
curl -s http://127.0.0.1:12789 | jq '.cardano.node.metrics' 2>/dev/null | head -10
```

Si el puerto **12798** responde con líneas tipo `cardano_node_metrics_epoch_int 523`, usá ese como scrape target en Prometheus (es lo que hacemos en esta guía).

Si 12798 está vacío y todo está en **12789**, el nodo usa el nuevo tracing backend (`cardano-tracer`). En ese caso el scrape target en prometheus.yml debe apuntar al puerto que `cardano-tracer` exponga para Prometheus — típicamente también 12798 pero servido por el tracer, no por el nodo directamente. El resultado en Grafana es el mismo.

{% hint style="warning" %}
El bind de `hasPrometheus` está en `127.0.0.1` — solo accesible localmente. Si el servidor de monitoreo es una VM separada, cambia a `0.0.0.0` y agrega la IP del servidor de monitoreo al firewall.
{% endhint %}

***

## 2. Instalar Node Exporter

Node Exporter expone métricas del sistema operativo: CPU, RAM, disco, red y tiempo de sincronización NTP.

```bash
# Descargar la última versión
NODE_EXPORTER_VERSION="1.8.2"
wget https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz
tar xzf node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz
sudo cp node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64/node_exporter /usr/local/bin/
```

Crear el servicio systemd:

```bash
sudo tee /etc/systemd/system/node_exporter.service > /dev/null << 'EOF'
[Unit]
Description=Node Exporter
After=network.target

[Service]
Type=simple
User=TU_USUARIO
ExecStart=/usr/local/bin/node_exporter \
  --collector.systemd \
  --collector.processes \
  --web.listen-address=127.0.0.1:9100
StandardOutput=journal
StandardError=journal
SyslogIdentifier=node_exporter
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable node_exporter
sudo systemctl start node_exporter
```

Verificar:

```bash
curl -s http://127.0.0.1:9100/metrics | grep node_cpu | head -5
```

***

## 3. Instalar Prometheus

```bash
PROMETHEUS_VERSION="2.53.0"
wget https://github.com/prometheus/prometheus/releases/download/v${PROMETHEUS_VERSION}/prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz
tar xzf prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz
sudo cp prometheus-${PROMETHEUS_VERSION}.linux-amd64/{prometheus,promtool} /usr/local/bin/
sudo mkdir -p /etc/prometheus /var/lib/prometheus
```

### Configuración de Prometheus

```bash
sudo tee /etc/prometheus/prometheus.yml > /dev/null << 'EOF'
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'cardano'
    static_configs:
      - targets:
          - 'localhost:12798'
        labels:
          alias: 'RELAY'
      # Si tienes BP accesible:
      # - targets: ['IP-BP:12798']
      #   labels:
      #     alias: 'CORE'

  - job_name: 'node'
    static_configs:
      - targets:
          - 'localhost:9100'
        labels:
          alias: 'RELAY'
      # - targets: ['IP-BP:9100']
      #   labels:
      #     alias: 'CORE'
EOF
```

{% hint style="info" %}
El campo `alias` en los labels es el que usa el dashboard TOPO⚡ para distinguir entre nodos. Usa `RELAY` para el relay y `CORE` para el block producer.
{% endhint %}

Crear el servicio systemd:

```bash
sudo tee /etc/systemd/system/prometheus.service > /dev/null << 'EOF'
[Unit]
Description=Prometheus
After=network.target

[Service]
Type=simple
User=TU_USUARIO
ExecStart=/usr/local/bin/prometheus \
  --config.file=/etc/prometheus/prometheus.yml \
  --storage.tsdb.path=/var/lib/prometheus \
  --storage.tsdb.retention.time=90d \
  --web.listen-address=127.0.0.1:9090
StandardOutput=journal
StandardError=journal
SyslogIdentifier=prometheus
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

sudo chown -R TU_USUARIO:TU_USUARIO /var/lib/prometheus
sudo systemctl daemon-reload
sudo systemctl enable prometheus
sudo systemctl start prometheus
```

Verificar que Prometheus levantó y puede scrape los targets:

```bash
curl -s http://127.0.0.1:9090/api/v1/targets | jq '.data.activeTargets[] | {job: .labels.job, state: .health}'
```

***

## 4. Instalar Grafana

```bash
sudo apt-get install -y apt-transport-https software-properties-common
wget -q -O - https://apt.grafana.com/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/grafana.key
echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com stable main" \
  | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt-get update
sudo apt-get install -y grafana

sudo systemctl daemon-reload
sudo systemctl enable grafana-server
sudo systemctl start grafana-server
```

Grafana queda en el **puerto 3000**. Para acceder desde tu máquina local, abrí un túnel SSH:

```bash
ssh -L 3000:localhost:3000 tu_usuario@IP-DEL-SERVIDOR
```

Luego abrí `http://localhost:3000` en el browser. Login por defecto: `admin` / `admin`.

{% hint style="warning" %}
No expongas el puerto 3000 a internet. Usá siempre el túnel SSH o un proxy inverso con autenticación.
{% endhint %}

***

## 5. Configurar Prometheus como datasource en Grafana

1. En Grafana: **Configuration** → **Data sources** → **Add data source**
2. Selecciona **Prometheus**
3. URL: `http://localhost:9090`
4. Clic en **Save & test** — debe aparecer "Data source is working"

***

## 6. Importar el dashboard TOPO⚡

El dashboard incluye:

| Panel                      | Qué muestra                                            |
| -------------------------- | ------------------------------------------------------ |
| Epoch / Block Height / Tip | Estado actual de la cadena                             |
| KES Expiration             | Tiempo restante hasta vencimiento de KES               |
| Pool Performance           | % de bloques forjados vs asignados                     |
| Saturation                 | % de saturación del pool                               |
| CPU / RAM / Disk / Network | Recursos del sistema por nodo                          |
| Mempool                    | Transacciones y bytes en mempool                       |
| Block delay / Late blocks  | Salud de la red P2P                                    |
| P2P Connections            | Conexiones por tipo (duplex, unidirectional, incoming) |
| Stake Metrics / ROA        | Stake activo, delegadores, retorno                     |
| Time Sync                  | Sincronización NTP — crítico para la forja de bloques  |

### Cómo importar

1. En Grafana: **Dashboards** → **Import**
2. Clic en **Upload JSON file**
3. Selecciona el archivo `topo-dashboard.json` (disponible en este repositorio en `kb/monitoreo/`)
4. En **prometheus**, selecciona el datasource que acabás de crear
5. Clic en **Import**

***

## 7. Métricas custom del pool

Los paneles de **Stake Metrics**, **Delegators**, **Blocks Minted**, **Saturation**, **Rank** y **ROA** usan métricas que no vienen del nodo directamente — vienen de un script que consulta la API de Koios y expone los datos vía un exporter personalizado.

Las métricas son:

```
saturation        delegators        blocks_lifetime
blocks_epoch      blocks_est_epoch  roa / roa_short
stake             stake_active      pledged
position          tx_submit_count   tx_submit_fail_count
```

Si estos paneles aparecen vacíos, instalá el **pool-exporter**: un script bash que consulta Koios y escribe las métricas en un archivo `.prom` que node\_exporter ya sirve en `:9100`. Sin puerto extra ni cambios en `prometheus.yml`. Ver guía completa: [Pool Exporter (Koios → Prometheus)](/monitoreo/pool-exporter.md).

***

## 8. Alertas básicas recomendadas

El dashboard ya tiene condiciones de alerta pre-configuradas para:

* CPU > 75% sostenido por 5 minutos
* RAM > 16 GB
* Chain density < 4% (nodo fuera de sync)
* Time sync > 5 segundos (problema NTP grave)

Para recibir las alertas por email o Telegram, configurá un **Contact point** en Grafana: **Alerting** → **Contact points** → **Add contact point**.

***

## Checklist final

```
✅ cardano-node expone métricas en :12798
✅ node_exporter corriendo en :9100
✅ Prometheus scrapeando ambos (ver /targets)
✅ Grafana instalado y accesible via túnel SSH
✅ Datasource Prometheus configurado y funcionando
✅ Dashboard TOPO⚡ importado
✅ Verificar que KES Expiration muestra tiempo correcto
✅ Verificar que CPU/RAM/Disk muestran datos del relay
```
