Sentry Self-Hosted: Seguimiento de Errores e Instalación

Sentry es la plataforma de seguimiento de errores más utilizada del mundo, capaz de capturar excepciones, errores de JavaScript y eventos de rendimiento de aplicaciones en tiempo real. La versión self-hosted permite mantener todos los datos de errores en tu propia infraestructura, ideal para equipos con requisitos de privacidad o que prefieren no pagar por el servicio en la nube. Esta guía cubre la instalación de Sentry self-hosted con Docker, la configuración de proyectos, la integración con los SDKs y la gestión de alertas.

Requisitos Previos

  • Ubuntu 20.04/22.04 o CentOS 8+/Rocky Linux 8+
  • Docker 19.03.6+ y Docker Compose 2.0+
  • Mínimo 8 GB de RAM (Sentry es exigente en recursos)
  • 4 vCPUs mínimo
  • 40 GB de espacio en disco (los datos crecen rápidamente)
  • Docker configurado para usar hasta 4 GB de RAM por contenedor

Instalación de Sentry Self-Hosted

# Clonar el repositorio oficial de sentry self-hosted
git clone https://github.com/getsentry/self-hosted.git /opt/sentry
cd /opt/sentry

# Usar una versión estable (no latest)
git checkout 24.1.0

# Verificar los requisitos del sistema antes de instalar
./install.sh --help

# Ejecutar el script de instalación
# Este proceso puede tardar 15-30 minutos la primera vez
./install.sh

El script de instalación:

  1. Verifica los requisitos del sistema
  2. Genera las claves secretas de seguridad
  3. Construye o descarga las imágenes Docker
  4. Ejecuta las migraciones de base de datos
  5. Te pide crear el usuario administrador
# Si la instalación se interrumpe, puedes reanudarla
./install.sh --no-user-prompt

# Iniciar Sentry después de la instalación
docker compose up -d

# Ver el estado de los servicios
docker compose ps

# Ver los logs de inicio
docker compose logs -f web

Sentry estará disponible en http://tu-ip:9000.

Configuración Post-Instalación

Configurar el correo electrónico

Edita sentry/config.yml:

# /opt/sentry/sentry/config.yml

mail.backend: 'smtp'
mail.host: 'smtp.gmail.com'
mail.port: 587
mail.username: '[email protected]'
mail.password: 'tu-app-password'
mail.use-tls: true
mail.from: '[email protected]'

Configurar la URL pública

Edita sentry/config.yml:

system.url-prefix: 'https://sentry.tudominio.com'
system.admin-email: '[email protected]'

Edita sentry/sentry.conf.py:

CSRF_TRUSTED_ORIGINS = ["https://sentry.tudominio.com"]
# Aplicar los cambios
docker compose restart web worker

Proxy inverso con Nginx

# /etc/nginx/sites-available/sentry
server {
    listen 443 ssl;
    server_name sentry.tudominio.com;

    ssl_certificate /etc/letsencrypt/live/sentry.tudominio.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sentry.tudominio.com/privkey.pem;

    # Aumentar el tamaño máximo de payload (para subir source maps)
    client_max_body_size 100M;

    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
    }
}

Crear Proyectos y DSNs

  1. Accede a Sentry en http://tu-ip:9000
  2. Ve a Configuración → Proyectos → Crear proyecto
  3. Selecciona el framework/lenguaje de tu aplicación
  4. Sentry genera un DSN (Data Source Name) con este formato: https://[email protected]/PROJECT_ID
# Via API de Sentry
# Primero, obtener un token de API:
# Configuración → Cuenta → Tokens de API → Crear token (scope: project:write)

# Crear un proyecto via API
curl -X POST "https://sentry.tudominio.com/api/0/teams/mi-organizacion/mi-equipo/projects/" \
  -H "Authorization: Bearer TU_TOKEN_API" \
  -H "Content-Type: application/json" \
  -d '{"name": "Mi API de Producción", "platform": "python-django"}'

# Listar proyectos
curl "https://sentry.tudominio.com/api/0/projects/" \
  -H "Authorization: Bearer TU_TOKEN_API"

Integración del SDK en Python

# Instalar el SDK de Sentry para Python
pip install sentry-sdk

# Para frameworks específicos:
pip install sentry-sdk[fastapi]    # FastAPI
pip install sentry-sdk[django]     # Django
pip install sentry-sdk[flask]      # Flask
pip install sentry-sdk[celery]     # Celery
# Configuración básica en cualquier aplicación Python
import sentry_sdk

sentry_sdk.init(
    dsn="https://[email protected]/1",
    # Entorno para filtrar eventos
    environment="production",
    # Versión de la aplicación para rastrear regresiones
    release="[email protected]",
    # Porcentaje de transacciones a rastrear (para rendimiento)
    traces_sample_rate=0.1,    # 10% de las transacciones
    # Perfiles de CPU (0-1)
    profiles_sample_rate=0.1,
    # Capturar eventos adicionales
    attach_stacktrace=True,
    send_default_pii=False,    # No enviar datos personales identificables
)
# Integración con Django (settings.py)
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.redis import RedisIntegration
from sentry_sdk.integrations.celery import CeleryIntegration

sentry_sdk.init(
    dsn="https://[email protected]/1",
    integrations=[
        DjangoIntegration(),
        RedisIntegration(),
        CeleryIntegration(),
    ],
    environment="production",
    traces_sample_rate=0.05,  # 5% en producción
)
# Capturar errores y contexto adicional
from sentry_sdk import capture_exception, capture_message, set_user, set_tag

# Añadir contexto del usuario a todos los eventos
def vista_login(request):
    if request.user.is_authenticated:
        set_user({
            "id": str(request.user.id),
            "email": request.user.email,
            "username": request.user.username,
        })

# Capturar excepción manualmente
try:
    resultado = operacion_arriesgada()
except Exception as e:
    capture_exception(e)

# Capturar un mensaje personalizado
capture_message("Pago procesado correctamente", level="info")

# Añadir tags para filtrar en Sentry
set_tag("version_api", "v2")
set_tag("region", "eu-west-1")

Integración del SDK en JavaScript

# Instalar el SDK de Sentry
# Para aplicaciones de navegador:
npm install @sentry/browser

# Para React:
npm install @sentry/react

# Para Node.js:
npm install @sentry/node

# Para Next.js:
npm install @sentry/nextjs
// index.js o app.js (cargar lo antes posible)
import * as Sentry from '@sentry/browser';

Sentry.init({
  dsn: 'https://[email protected]/1',
  environment: process.env.NODE_ENV,
  release: process.env.VITE_APP_VERSION,
  
  // Integración para rastreo de rendimiento
  integrations: [
    Sentry.browserTracingIntegration(),
    Sentry.replayIntegration({
      // Grabación de sesiones con errores
      maskAllText: true,
      blockAllMedia: false,
    }),
  ],
  
  // Porcentaje de transacciones a rastrear
  tracesSampleRate: 0.1,
  // Porcentaje de replays de sesiones
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,  // 100% de sesiones con error
});
// Capturar errores manualmente
import * as Sentry from '@sentry/browser';

// Capturar una excepción
try {
  hacerAlgoArriesgado();
} catch (error) {
  Sentry.captureException(error);
}

// Añadir contexto adicional
Sentry.setUser({ id: '1234', email: '[email protected]' });
Sentry.setTag('version_ui', '3.4.0');
Sentry.setContext('pedido', { id: 'ORD-789', total: 99.99 });

// Breadcrumb manual para trazar el flujo del usuario
Sentry.addBreadcrumb({
  category: 'accion-usuario',
  message: 'Usuario hizo clic en "Finalizar compra"',
  level: 'info',
});

Monitoreo de Rendimiento

Sentry puede rastrear transacciones completas para identificar cuellos de botella:

# Python: crear una transacción personalizada
from sentry_sdk import start_transaction

with start_transaction(op="tarea", name="procesar-pedido"):
    with sentry_sdk.start_span(op="db.query", description="consultar inventario"):
        resultado = db.query("SELECT stock FROM productos WHERE id = %s", [id_producto])
    
    with sentry_sdk.start_span(op="http.request", description="llamar API de pagos"):
        respuesta_pago = api_pagos.procesar(importe)

Alertas y Notificaciones

En Proyecto → Alertas → Crear regla de alerta:

# Ejemplo: alertar cuando hay un pico de errores

Nombre: Pico de errores en producción
Condición: El número de eventos supera 100 en 1 hora
Filtro: environment = production AND level = error
Acciones:
  - Enviar notificación a Slack: #alertas-errores
  - Enviar email a: [email protected]
  - Crear issue en Jira (si está integrado)
# Alerta de regresión de rendimiento
Nombre: Latencia de API alta
Condición: P95 > 3000ms para transacción "POST /api/pedidos"
Acciones:
  - Enviar a Slack: #rendimiento
# Integrar Sentry con Slack desde la interfaz:
# Configuración de la organización → Integraciones → Slack → Conectar

Solución de Problemas

La instalación falla por falta de memoria:

# Verificar RAM disponible
free -h

# Sentry necesita al menos 8 GB de RAM total
# Si el sistema tiene menos, editar docker-compose.yml
# para limitar los contenedores que más consumen

# Aumentar el swap como medida temporal
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Los eventos no aparecen en Sentry:

# Verificar que el DSN es correcto
curl "https://sentry.tudominio.com/api/PROJECT_ID/store/" \
  -X POST \
  -H "X-Sentry-Auth: Sentry sentry_version=7, sentry_client=test, sentry_key=TU_PUBLIC_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message": "Test event", "level": "info"}'

# Revisar los logs del worker que procesa los eventos
docker compose logs worker --tail 100

Sentry consume demasiado disco:

# Ver el espacio usado por cada componente
docker exec sentry-self-hosted-postgres-1 du -sh /var/lib/postgresql/data/
docker exec sentry-self-hosted-redis-1 redis-cli dbsize

# Configurar la retención de datos en Sentry
# Configuración → Organización → Retención de datos
# Los planes self-hosted tienen 90 días por defecto

# Limpiar eventos antiguos manualmente
docker compose run --rm worker python manage.py cleanup --days=30

El servicio web no responde:

# Ver los logs del contenedor web
docker compose logs web --tail 100

# Reiniciar los servicios web
docker compose restart web worker

# Verificar que la base de datos está accesible
docker compose exec web sentry exec python -c "from django.db import connection; connection.ensure_connection()"

Conclusión

Sentry self-hosted es la solución definitiva para equipos que necesitan rastreo de errores profesional sin comprometer la privacidad de los datos de sus usuarios. Aunque los requisitos de hardware son elevados comparados con otras herramientas de observabilidad, la profundidad de información que proporciona en cada error, con contexto completo del stack trace, variables de entorno y datos del usuario, justifica la inversión. La integración con el SDK requiere pocas líneas de código y proporciona valor inmediato, especialmente en producción donde los errores son difíciles de reproducir localmente.