Entornos de desarrollo

1º DAM/DAW - Curso 2024-2025

User Tools

Site Tools


apuntes:monitorizacion

Monitorización de aplicaciones

Instalar Grafana y Prometheus

Lanzaremos Grafana y Prometheus como contenedores docker, configurados en una red para que puedan verse el uno al otro. Al mismo tiempo publicaremos los puertos sobre la máquina local para poder acceder a sus interfaces web:

version: "3"
services:
  prometheus:
    image: prom/prometheus
    ports:
      - 9090:9090
    volumes:
      - ./prometheus_data:/prometheus
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
    extra_hosts:
      - "host.docker.internal:192.168.1.120"  # coloca aqui la IP local de tu equipo
    networks:
      - localprom

  grafana:
    image: grafana/grafana-enterprise
    ports:
      - 3000:3000
    volumes:
      - ./grafana_data:/var/lib/grafana
    extra_hosts:
      - "host.docker.internal:192.168.1.120"  # coloca aqui la IP local de tu equipo
    networks:
      - localprom
    depends_on:
      - prometheus

networks:
  localprom:
    driver: bridge

Hay que tener en cuenta que:

A su vez dejaremos este fichero, prometheus.yml en la carpeta raíz de nuestro proyecto. Ahi configuramos donde escuchan prometheus y el servicio que estamos monitorizando:

prometheus.yml
global:
  scrape_interval: 5s

scrape_configs:
  - job_name: "prometheus_service"
    static_configs:
      - targets: ["host.docker.internal:9090"]

  - job_name: "nodejs_service"
    static_configs:
      - targets: ["host.docker.internal:8080"]

Integrar Grafana con Node.js

Ahora tendremos que facilitar un endpoint /metrics en nuestro servicio para que Prometheus pueda extraer las métricas de nuestro servicio haciendo peticiones al mismo.

Primero, añadimos la librería de Prometheus para nuestra aplicación:

"dependencies": {
    . . .
    "prom-client": "^15.1.3"
  },

Y definimos una serie de métricas en el fichero config/metrics.js. Más adelante las haremos accesible como respuesta en el endpoint /metrics que vamos a publicar:

config/metrics.js
'use strict';
const promClient = require('prom-client');
 
// Crea un histograma para registrar la duración de las peticiones HTTP en segundos
const httpRequestDurationSeconds = new promClient.Histogram({
    name: 'http_request_duration_seconds',
    help: 'Duration of HTTP requests in seconds',
    labelNames: ['method', 'path', 'code'],
});
 
// Crea un contador de peticiones HTTP totales
const httpRequestsTotal = new promClient.Counter({
    name: 'http_requests_total',
    help: 'How many HTTP requests processed, partitioned by status code, method, and HTTP path',
    labelNames: ['method', 'path', 'code'],
});
 
// Crea una medición de las peticiones HTTP en vuelo
const inFlightRequests = new promClient.Gauge({
    name: 'http_requests_in_flight',
    help: 'Current number of in-flight HTTP requests',
});
 
module.exports = {
    httpRequestDurationSeconds,
    httpRequestsTotal,
    inFlightRequests,
};

En nuestro fichero principal, app.js, configuraremos lo necesario para recoger las métricas que hemos configurado antes y publicaremos el nuevo endpoint /metrics que las dejará accesibles para Prometheus, que es quién las recoge y almacena.

También llamaremos a promClient.collectDefaultMetrics() que recoge algunas métricas ya establecidas por defecto que quizás nos pueda interesar también mostrar en los Dashboards que haremos con Grafana.

apps.js
const promClient = require('prom-client');
const { httpRequestDurationSeconds, httpRequestsTotal, inFlightRequests } = require('./config/metrics');
. . .
// Recoge métricas por defecto
promClient.collectDefaultMetrics();
. . .
// Recoger las métricas configuradas en config/metrics
app.use((req, res, next) => {
    // Anota la request en vuelo
    inFlightRequests.inc();
 
    // Inicia un timer para comenzar a calcular la duración de la request
    const end = httpRequestDurationSeconds.startTimer();
 
    const method = req.method;
    const path = req.route ? req.route.path : req.path; 
 
    // Cada vez que una request termina, se recogen las métricas configuradas
    res.on('finish', () => {
        const statusCode = res.statusCode;
 
        // Captura la duración de la petición
        end({ method, path, code: statusCode }); 
        // Incrementa el contador de peticiones HTTP
        httpRequestsTotal.inc({
            code: statusCode,
            method: method.toLowerCase(),
            path: path
        });
 
        // Decrementa el contador de peticiones en vuelo
        inFlightRequests.dec();
    });
 
    next();
});
 
// Define el endpoint que usará prometheus para recoger las métricas
app.get('/metrics', async(req, res) => {
    try {
        res.set('Content-Type', promClient.register.contentType);
        res.end(await promClient.register.metrics());
    } catch (error) {
        res.status(500).end(error);
    }
});
. . .
app.use('/', cities);
. . .

En http://localhost:8080/metrics ya podremos visualizar las métricas (como texto plano)

Figure 4: Métricas de nuestro servicio Node.js

Comprobar la configuración de Prometheus

Antes de seguir, para comprobar que todo está funcionando bien, podemos echar un vistazo en Prometheus y verificar que tiene acceso a las métricas que nuestro servicio publica a través del endpoint /metrics que acabamos de configurar:

Status → Targets

Figure 5: Configuración de Prometheus en http://localhost:9090

Configurar un dashboard en Grafana

Añadir Prometheus como connection

Ahora, accediendo al interfaz web de Grafana (http://localhost:3000), configuraremos a Prometheus como un nuevo conector ya que proporcionará datos para los Dashboards que queremos diseñar en Grafana.

Accedemos a Connection → Add new connection → Prometheus

Figure 6: Añadir una nueva connection en Grafana

Y pulsamos Save & test para darlo por configurado

Crear un dashboard y visualizaciones

El último paso será crear un nuevo Dashboard y añadir todas las visualizaciones (gráficos) que precisemos. Por ejemplo:

  • Peticiones por segundo
  • Tasa de fallos
  • Códigos de estado como respuestas
  • Tiempo de respuesta
Figure 7: Grafana dashboard

© 2025 Santiago Faci

apuntes/monitorizacion.txt · Last modified: 2025/03/25 00:30 by Santiago Faci