Curso-lenguaje-python/catch-all/05_infra_test/05_prometheus_grafana/README.md

10 KiB

Configuración de Grafana con Prometheus para proyectos Python usando Docker

En este artículo, cubriremos cómo configurar el monitoreo de servicios para proyectos Python con Prometheus y Grafana utilizando contenedores Docker.

El monitoreo de servicios nos permite analizar eventos específicos en nuestros proyectos, tales como llamadas a bases de datos, interacción con API, seguimiento del rendimiento de recursos, etc. Puedes detectar fácilmente comportamientos inusuales o descubrir pistas útiles detrás de los problemas.

Escenario de Caso Real

Teníamos un servicio temporal que redirigía las solicitudes entrantes de sitios web específicos hasta que Google dejara de indexar estas páginas web. Utilizando el monitoreo de servicios, podemos ver fácilmente el conteo de redirecciones de forma regular. En un momento determinado en el futuro, el número de redirecciones disminuirá, lo que significa que el tráfico se ha migrado al sitio web objetivo, y ya no necesitaremos que este servicio esté en funcionamiento.

Configuración de contenedores Docker

Vamos a ejecutar todos nuestros servicios localmente en contenedores Docker. En las grandes empresas, existe un servicio global para Prometheus y Grafana que incluye todos los proyectos de monitoreo de microservicios. Probablemente ni siquiera necesites escribir ningún pipeline de despliegue para las herramientas de monitoreo de servicios.

Archivo docker-compose.yml

Comencemos creando un archivo docker-compose.yml con los servicios necesarios:

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ${PWD}/prometheus.yml:/etc/prometheus/prometheus.yml
    restart: unless-stopped
    networks:
      - monitoring-net
    healthcheck:
      test: ["CMD", "wget", "--spider", "http://localhost:9090/-/healthy"]
      interval: 1m30s
      timeout: 30s
      retries: 3
      start_period: 30s

  grafana:
    hostname: grafana
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - 3001:3000
    restart: unless-stopped
    networks:
      - monitoring-net
    healthcheck:
      test: ["CMD", "wget", "--spider", "http://localhost:3000/api/health"]
      interval: 1m30s
      timeout: 30s
      retries: 3
      start_period: 30s

  app:
    build:
      context: .
      dockerfile: Dockerfile
    depends_on:
      - prometheus
    ports:
      - "8080:8080"
    networks:
      - monitoring-net
    command: ["python3", "app/main.py"]

networks:
  monitoring-net:
    driver: bridge

El punto más importante de la configuración anterior es montar el archivo prometheus.yml desde nuestra máquina local al contenedor Docker. Este archivo incluye la configuración para obtener datos (métricas) de nuestro servicio de aplicación o proyecto Python. Sin el archivo, no podrás ver las métricas personalizadas que incluye tu proyecto.

Por lo tanto, crea un nuevo archivo llamado prometheus.yml en el nivel raíz de tu proyecto.

Archivo prometheus.yml

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'app'
    static_configs:
      - targets: ['app:8080']

Ahora, Prometheus obtendrá datos de nuestro proyecto.

Todas las demás configuraciones en el archivo de composición son autoexplicativas y no son muy críticas, como mencionamos para Prometheus.

Crear un nuevo proyecto Python

Ahora, vamos a crear una aplicación Python muy sencilla que creará una métrica para rastrear el tiempo empleado y las solicitudes realizadas. Crea una nueva carpeta llamada app en el nivel raíz del proyecto. También incluye __init__.py para marcarla como un paquete Python.

A continuación, crea otro archivo llamado main.py que contendrá la lógica principal del programa, como se muestra a continuación:

Archivo app/main.py

from prometheus_client import start_http_server, Summary, Counter, Gauge, Histogram
import random
import time

# Create metrics to track time spent, requests made, and other events.
REQUEST_TIME = Summary('request_processing_seconds', 'Time spent processing request')
UPDATE_COUNT = Counter('update_count', 'Number of updates')
ACTIVE_REQUESTS = Gauge('active_requests', 'Number of active requests')
REQUEST_LATENCY = Histogram('request_latency_seconds', 'Request latency in seconds')

# Decorate function with metrics.
@REQUEST_TIME.time()
@REQUEST_LATENCY.time()
def process_request(t):
    """A dummy function that takes some time."""
    ACTIVE_REQUESTS.inc()
    time.sleep(t)
    ACTIVE_REQUESTS.dec()

def main():
    # Start up the server to expose the metrics.
    start_http_server(8000)
    print("[*] Starting server on port 8000...")
    
    # Generate some requests.
    while True:
        msg = random.random()
        process_request(msg)
        update_increment = random.randint(1, 100)
        UPDATE_COUNT.inc(update_increment)
        print(f'[+] Processing request: {msg:.4f} | Updates: {update_increment}')
        time.sleep(random.uniform(0.5, 2.0))  # Random delay between requests

if __name__ == '__main__':
    main()

Aquí, estamos utilizando un paquete de Python llamado prometheus_client para interactuar con Prometheus. Permite fácilmente la creación de diferentes tipos de métricas que nuestro proyecto requiere.

El código anterior se copió de la documentación oficial de prometheus_client, que simplemente crea una nueva métrica llamada request_processing_seconds que mide el tiempo empleado en esa solicitud en particular. Cubriremos otros tipos de métricas más adelante en este artículo.

Ahora, vamos a crear un Dockerfile y un requirements.txt para construir nuestro proyecto.

Archivo Dockerfile

# Usa la imagen base oficial de Python
FROM python:3.9-slim

# Establece el directorio de trabajo
WORKDIR /app

# Copia los archivos de requerimientos
COPY requirements.txt .

# Instala las dependencias
RUN pip install --no-cache-dir -r requirements.txt

# Copia el código de la aplicación
COPY app/ /app

# Expone el puerto de la aplicación
EXPOSE 8000

# Comando por defecto para ejecutar la aplicación
CMD ["python", "main.py"]

Archivo requirements.txt

prometheus_client

Ahora estamos listos para construir y ejecutar los servicios.

Ejecución de los servicios

Para ver todo en acción, ejecuta los siguientes comandos:

docker-compose up -d --build

Esto levantará todos los servicios definidos en docker-compose.yml, compilando la imagen de la aplicación en el proceso.

Configuración de Grafana

En esta sección, usaremos Prometheus como fuente de datos para mostrar métricas en gráficos de Grafana.

  1. Navega a http://localhost:3001 para ver la página de inicio de sesión de Grafana y utiliza admin tanto para el nombre de usuario como para la contraseña. Luego, requerirá agregar una nueva contraseña, y puedes mantenerla igual ya que estamos probando localmente.

  2. Después de iniciar sesión correctamente, deberías ver el panel predeterminado de Grafana. Luego selecciona Data Sources en la página.

  3. A continuación, selecciona Prometheus como fuente de datos:

  4. Luego requerirá la URL en la que se está ejecutando el servicio de Prometheus, que será el nombre del servicio de Docker que creamos http://prometheus:9090.

  5. Finalmente, haz clic en el botón Save & Test para verificar la conexión de la fuente de datos.

    ![](https://res.cloudinary.com/practicaldev/image/fetch/s--i4CVmg76--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%

2Cw_800/https://www.thepylot.dev/content/images/size/w1000/2022/06/Screen-Shot-2022-06-11-at-16.56.55.png)

¡Genial! Ahora nuestro Grafana está listo para ilustrar las métricas que provienen de Prometheus.

Creación de un nuevo dashboard en Grafana

  1. Navega a http://localhost:3001/dashboards para crear un nuevo dashboard y agregar un nuevo panel. Haz clic en New Dashboard y luego en Add New Panel para la inicialización.

  2. A continuación, seleccionamos código dentro del panel de consultas y escribimos request_processing_seconds. Podrás ver 3 tipos diferentes de sufijos con los datos de tus métricas personalizadas. Prometheus simplemente aplica diferentes tipos de cálculos a tus datos de manera predeterminada.

  3. Selecciona una de las opciones y haz clic en Run Query para verla en el gráfico.

Finalmente, podemos ver las métricas de nuestro proyecto ilustradas muy bien por Grafana.

Otras métricas

Hay muchos tipos de métricas disponibles según lo que requiera el proyecto. Si queremos contar un evento específico, como actualizaciones de registros en la base de datos, podemos usar Counter().

Si tenemos una cola de mensajes como Kafka o RabbitMQ, podemos usar Gauge() para ilustrar el número de elementos que esperan en la cola.

Intenta agregar otra métrica en main.py como se muestra a continuación y aplica los mismos pasos para conectar Prometheus con Grafana:

Ejemplo de una nueva métrica con Counter

UPDATE_COUNT = Counter('update_count', 'Number of updates')

# Dentro de tu función de procesamiento
update_increment = random.randint(1, 100)
UPDATE_COUNT.inc(update_increment)

No olvides construir nuevamente la imagen de Docker para todos los servicios:

docker-compose up -d --build