Creación de un Sistema de Logs en Go para Observabilidad
Clase 27 de 30 • Curso de Ciberseguridad para Desarrollo Web
Resumen
¿Cómo crear tu primer sistema de logs?
Los logs son cruciales para la observabilidad de sistemas, ayudando a identificar y analizar qué sucede en ellos. Herramientas como New Relic, Datadog, Kibana y CloudWatch facilitan esta tarea. Pero la verdadera magia comienza cuando creamos nuestro propio sistema de logs. Los logs deben ser consistentes, claros, encontrables y accionables.
¿Cómo deben ser los logs ideales?
- Consistentes: Uniformidad en todo el sistema para fácil comprensión.
- Claros: Mensajes precisos que no generen confusiones.
- Encontrables: Facilidad para su búsqueda y análisis.
- Accionables: Capaces de desencadenar acciones concretas.
Veamos cómo implementar un sistema de logs desde el código.
Implementación de un sistema de logs en Go
Para empezar, dentro de nuestro proyecto, crearemos una carpeta llamada Logger
con un archivo logger.go
, siguiendo estos pasos:
Estructura básica del Logger
- Definición de enum para niveles de log:
package logger
type LogLevel string
const (
Fatal LogLevel = "FATAL"
Error LogLevel = "ERROR"
Warning LogLevel = "WARNING"
Info LogLevel = "INFO"
)
- Creación de la estructura
Logger
:
type Logger struct {
ServiceName string
}
func NewLogger(serviceName string) Logger {
return Logger{ServiceName: serviceName}
}
Aquí, la estructura incluye el parámetro ServiceName
para identificar el origen del log.
Método básico para el logging
Implementamos un método que loguee en formato JSON, convirtiéndose en una base escalable y filtrable:
func (l Logger) Log(ctx context.Context, eventName string, logLevel LogLevel, attributes map[string]interface{}) {
logMap := map[string]interface{}{
"service": l.ServiceName,
"event": eventName,
"level": logLevel,
"attributes": attributes,
}
logJSON, _ := json.Marshal(logMap)
fmt.Println(string(logJSON))
}
Añade métodos para diferentes niveles de error
Crear métodos específicos para cada nivel de log usando el método Log
previamente definido:
func (l Logger) Info(ctx context.Context, eventName string, attributes map[string]interface{}) {
l.Log(ctx, eventName, Info, attributes)
}
func (l Logger) Warning(ctx context.Context, eventName string, attributes map[string]interface{}) {
l.Log(ctx, eventName, Warning, attributes)
}
func (l Logger) Error(ctx context.Context, eventName string, err error, attributes map[string]interface{}) {
attributes["error"] = err.Error()
l.Log(ctx, eventName, Error, attributes)
}
func (l Logger) Fatal(ctx context.Context, eventName string, attributes map[string]interface{}) {
l.Log(ctx, eventName, Fatal, attributes)
}
Refactoriza tu Lambda para usar el sistema de logs
En el archivo de nuestra lambda, handleGitHubNotifications
, inicializamos el objeto Logger
antes de ejecutar cualquier lógica:
logger := NewLogger("handleGitHubWebhook")
attributes := make(map[string]interface{})
Sustituimos los métodos fmt.Print
por el uso del Logger
:
attributes["webhook"] = "hitCommit"
logger.Info(context.Background(), "validGitHubWebhookReceived", attributes)
Así, implementamos el sistema de logging dentro de una Lambda usando el despliegue de Terraform para asegurarnos de que los cambios se reflejan correctamente.
Visualización de logs en AWS CloudWatch
Una vez realizada la implementación, podemos verificar los logs en AWS CloudWatch accediendo a monitor, donde nuestros logs se reflejan en formato JSON por cada evento. Esto facilita la lectura y gestión de la información.
Con este conocimiento, estás preparado para extender el sistema de logs y mejorar la observabilidad de tus servicios. Continúa explorando y aprendiendo sobre cómo optimizar tus sistemas para alcanzar el máximo potencial. ¡El mundo de la observabilidad te espera!