Dashboard de Grafana (Fuente: https://grafana.com/blog/2023/10/10/how-to-embed-grafana-dashboards-into-web-applications/
===== Instalar Grafana y Prometheus =====
Lanzaremos [[https://es.wikipedia.org/wiki/Grafana|Grafana]] y [[https://en.wikipedia.org/wiki/Prometheus_(software)|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:
* ''Grafana'' quedará accesible en http://localhost:3000
* ''Prometheus'' quedará accesible en http://localhost:9090
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:
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:
'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.
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)
{{ metrics.png }}
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
{{ prometheus.png }}
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''
{{ grafana_add_connection.png }}
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
{{ my_dashboard.png }}