Logs en producción: estructura, niveles y alertas
Clase 19 de 21 • Curso Profesional de DevOps
Contenido del curso
Containers y ambientes de desarrollo
Pruebas
Integración Continua
Despliegue Continuo
Reliability
Cierre del curso
Domina los logs en producción con estructura, niveles correctos y alertas accionables. Aquí se explica cómo pasar de simples prints a un sistema fiable basado en structured logging, exception tracking y una cultura de responsabilidad on call que reduce caos y acelera la respuesta ante fallos.
¿Por qué los logs en producción requieren estructura y niveles claros?
Cuando producción falla, no puedes “reiniciar y probar” como en local. Los logs deben ser moderados, útiles y siempre parseables. Con miles de máquinas y un flujo inmenso, el texto libre no escala: necesitas structured logging en JSON para que cualquier sistema pueda agregar, filtrar y analizar sin fricción.
- Usa niveles de log: logger.info, logger.warn, logger.error, logger.fatal. Cada uno comunica severidad y urgencia.
- Estandariza el formato: structured logging en JSON permite parsear y agregar. Evita mezclar texto libre con objetos sin estándar.
- Priorización efectiva: busca fatal cuando el servicio cae. Trata como error lo que controlas internamente. Deja en info fallos de servicios externos que no controlas, si no impactan la disponibilidad.
- Ejemplo de herramientas: Pino en Node facilita structured logging en JSON.
Ideas clave: - “Ser moderado con los logs” porque cuestan y pueden saturar. Aun así, cuando “todo se rompe”, los logs son tu ancla. - Sin estructura, no podrás “meterlo en ningún sistema de logs para agregar”. La estandarización es no negociable.
¿Qué ventajas aporta el structured logging en JSON?
- Parseo confiable: cada entrada es un objeto con claves predecibles.
- Búsquedas precisas: filtra por nivel, servicio, request-id o error-id.
- Agregación y visualización: integra con tu pila de observabilidad sin hacks.
¿Cómo decidir el nivel correcto de cada evento?
- Evalúa impacto en usuario y estado del servicio.
- Define reglas claras por dominio: qué es info, warn, error, fatal en tu aplicación.
- Mantén consistencia para que los filtros funcionen cuando más importa.
¿Cómo organizar la responsabilidad y el on call para incidentes?
La persona o equipo que despliega es quien debe estar on call. No delegues en un operador ajeno: quien tiene más contexto soluciona más rápido y mejor.
- Recibe alertas de lo crítico y haz seguimiento de cada incidente.
- Evita buscar a ciegas en un “stream infinito”: usa un exception tracker para errores no manejados.
- Envía excepciones a un “bucket” especial: priorízalas y dales visibilidad.
Prácticas recomendadas: - Integraciones útiles: crear un issue en GitHub, enviar alerta a Slack, o ambas según severidad. - Usa reglas de severidad: si es crítico, que suene el teléfono; si es menor, que vaya a un backlog para revisión sin prisa. - Observa el life cycle por release: relaciona excepciones con despliegues para rastrear regresiones rápido.
¿Por qué un exception tracker cambia el juego?
- Centraliza errores no manejados con contexto suficiente para actuar.
- Permite reglas de alerta por severidad e impacto.
- Prioriza: lo que llega al exception tracker merece más atención que el ruido de logs generales.
¿Qué decisiones tomar sobre exception tracking y datos sensibles?
Hay soluciones abiertas como Sentry (puedes auto-hospedar) o usar el servicio del proveedor. Considera:
- Si lo corres en tu infraestructura y se cae, también caen las alertas: te quedas ciego.
- Prefiere no enviar datos personales en errores: minimiza riesgo y habilita proveedores externos con tranquilidad.
- Define una integración entre tu logger y el exception tracker para no duplicar código.
¿Cómo mapear niveles de log a Sentry sin esfuerzo extra?
Un patrón productivo: asociar niveles altos a envíos automáticos al exception tracker. Así, quien usa la librería no debe “pensarlo”.
// Ejemplo conceptual con Pino + Sentry (Node.js)
import pino from 'pino'
import * as Sentry from '@sentry/node'
Sentry.init({ dsn: process.env.SENTRY_DSN })
const logger = pino({ level: 'info' })
function log(level, msg, context = {}) {
logger[level]({ msg, ...context })
if (['error', 'fatal'].includes(level)) {
Sentry.captureMessage(msg, level.toUpperCase())
}
}
// Uso
log('info', 'servicio iniciado', { service: 'api' })
log('error', 'falló dependencia interna', { service: 'api', code: 'EDEP' })
log('fatal', 'servicio caído', { service: 'api' })
Beneficios prácticos reportados: - Menos llamadas a operaciones y más control del equipo dueño del servicio. - Alertas alineadas a quien puede arreglar el problema. - Flujo natural: logger.error y logger.fatal van a Sentry; el resto, solo a la pila de logs.
¿Tienes una práctica útil de structured logging o un flujo de on call que te funciona? Comparte tu enfoque y qué alertas realmente te ayudan a reaccionar a tiempo.