Introducción
El logging no es simplemente registrar eventos en un archivo. Para aplicaciones Go que operan en entornos de producción de alta carga, los logs son la principal fuente de información de diagnóstico. Sin un logging de calidad, la búsqueda de errores se convierte en una adivinanza y el monitoreo del sistema se vuelve imposible.
Go ofrece al desarrollador herramientas flexibles: desde el paquete integrado log hasta potentes bibliotecas de terceros. En este artículo analizaremos las mejores prácticas de logging en Go, aprenderemos a estructurar registros, seleccionar niveles y evitar errores típicos. El material será útil tanto para principiantes como para desarrolladores experimentados que deseen ordenar su enfoque del logging.
La biblioteca estándar log: capacidades básicas y limitaciones
El paquete log de la biblioteca estándar de Go es la forma más sencilla de comenzar a hacer logging. Proporciona un logger listo que escribe en os.Stderr.
Ejemplo simple de uso
package main
import ( "log")
func main() { log.Println("Aplicación iniciada") log.Printf("Usuario %s ha iniciado sesión", "admin") log.Fatal("Error crítico: base de datos no disponible")}La salida se verá así:
2023/10/27 14:35:12 Aplicación iniciada2023/10/27 14:35:12 Usuario admin ha iniciado sesión2023/10/27 14:35:12 Error crítico: base de datos no disponibleLimitaciones del logger estándar
- Falta de niveles de logging — no hay división en Info, Warn, Error. Todos los mensajes se escriben en un solo flujo.
- Mala estructura — el registro es una cadena simple, difícil de parsear automáticamente.
- Falta de contexto — no se puede agregar fácilmente un identificador de solicitud o de usuario.
- Problemas de rendimiento — el logger estándar bloquea la goroutine al escribir, lo que puede convertirse en un cuello de botella.
Para utilidades pequeñas o prototipos, log es perfectamente adecuado. Pero para aplicaciones de producción, vale la pena considerar alternativas.
Logging estructurado: ¿por qué es importante?
El logging estructurado es un enfoque en el que cada mensaje representa un conjunto de pares "clave-valor" (generalmente en formato JSON). Esto permite:
- Parsear logs automáticamente en sistemas de recolección (ELK, Splunk, Grafana Loki).
- Filtrar registros por cualquier atributo (nivel, servicio, ID de solicitud).
- Construir dashboards y alertas basadas en campos numéricos.
Bibliotecas populares para logging estructurado
- logrus — una de las primeras y más populares bibliotecas. Proporciona niveles, formato (JSON, texto), hooks para enviar logs a sistemas externos. Sin embargo, tiene un alto consumo de memoria.
- zerolog — biblioteca enfocada en el rendimiento (zero allocation). Ideal para microservicios y sistemas de alta carga.
- zap — de Uber. Muy rápido, con dos modos: SugaredLogger (conveniente) y Logger (máxima velocidad).
- slog — paquete estándar, añadido en Go 1.21. Proporciona logging estructurado "de fábrica".
Ejemplo usando slog (Go 1.21+)
package main
import ( "log/slog" "os")
func main() { logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) logger.Info("Servidor iniciado", "port", 8080, "env", "production") logger.Error("Error de conexión a la BD", "db", "postgres", "timeout", 5)}Salida en JSON:
{"time":"2023-10-27T14:40:00.123Z","level":"INFO","msg":"Servidor iniciado","port":8080,"env":"production"}{"time":"2023-10-27T14:40:01.456Z","level":"ERROR","msg":"Error de conexión a la BD","db":"postgres","t