Saltar a contenido

Guía Detallada de Logging

Vamos a profundizar en nuestras prácticas de logging, utilizando el contexto de la funcionalidad de "Solicitud de Feedback" para que el aprendizaje sea más práctico y relevante. Esta guía tiene como objetivo detallar cómo aplicar las mejores prácticas de logging en cada etapa del flujo, desde la creación de la solicitud hasta la aprobación y el envío a los evaluadores.

¿Por Qué el Logging es Crucial? 🤔

En un sistema distribuido como el nuestro, el logging es esencial para:

  • Depuración y Solución de Problemas (Troubleshooting): Identificar y corregir errores rápidamente.
  • Monitoreo de la Aplicación: Seguir el rendimiento y la salud del sistema.
  • Análisis de Negocio: Extraer información valiosa sobre el comportamiento de los usuarios y el uso de las funcionalidades.
  • Auditoría: Rastrear eventos importantes para fines de seguridad y cumplimiento.

Estrategias Generales de Logging 📝

  1. Logging Estructurado: Utilice un formato consistente (preferiblemente JSON) para facilitar el análisis y el filtrado de los logs.
  2. Niveles de Log Apropiados: Utilice los niveles DEBUG, INFO, WARN y ERROR según la severidad del evento.
  3. Contexto Enriquecido: Incluya información relevante en el log, como:
    • transactionId: Para rastrear la solicitud de feedback en todo el flujo.
    • userId: ID del colaborador que creó la solicitud.
    • pdmId: ID del PDM que aprobó/rechazó la solicitud.
    • feedbackRequestId: ID de la solicitud de feedback.
  4. Logs de Eventos de Negocio: Registre eventos importantes desde el punto de vista del negocio para generar KPIs y métricas.
  5. Privacidad: Evite registrar información sensible (ej: contraseñas, datos de tarjetas de crédito).
  6. Rendimiento: Un exceso de logs puede afectar el rendimiento. Sea estratégico al elegir qué registrar y en qué nivel.

Logging en Acción: Solicitud de Feedback 🚀

Vamos a detallar cómo aplicar el logging en cada etapa del flujo de "Solicitud de Feedback".

1. Creación de la Solicitud (Colaborador)

  • Acción: El colaborador accede a la pantalla de listado de solicitudes de feedback.
    • INFO: "Usuario accedió a la pantalla de listado de solicitudes de feedback", userId, transactionId
  • Acción: El colaborador hace clic en el botón "Nueva Solicitud".
    • INFO: "Usuario inició la creación de una nueva solicitud de feedback", userId, transactionId
  • Acción: El colaborador llena el formulario.
    • DEBUG: (Si es necesario) Registrar las preguntas personalizadas ingresadas por el colaborador (con cuidado de no registrar información sensible).
  • Acción: El colaborador agrega evaluadores (nombre y correo electrónico).
    • DEBUG: (Si es necesario) Registrar los evaluadores agregados (con cuidado de no registrar información sensible).
    • WARN: Si el correo del evaluador es de CI&T, registrar: "Intento de agregar evaluador con correo de CI&T", userId, transactionId, emailEvaluador
  • Acción: El colaborador hace clic en el botón "Guardar Solicitud".
    • INFO: "Usuario guardó la solicitud de feedback", userId, feedbackRequestId, transactionId
    • ERROR: Si ocurre un error al guardar la solicitud (ej: fallo en la base de datos), registrar: "Fallo al guardar la solicitud de feedback", userId, transactionId, error, stackTrace

2. Notificación al PDM

  • Acción: El sistema envía un correo de notificación al PDM.
    • INFO: "Correo de notificación enviado al PDM", pdmId, feedbackRequestId, transactionId
    • ERROR: Si ocurre un error al enviar el correo, registrar: "Fallo al enviar correo de notificación al PDM", pdmId, feedbackRequestId, transactionId, error, stackTrace

3. Aprobación/Rechazo del PDM

  • Acción: El PDM accede a la pantalla de listado de feedbacks por aprobar.
    • INFO: "PDM accedió a la pantalla de listado de solicitudes de feedback por aprobar", pdmId, transactionId
  • Acción: El PDM aprueba o rechaza la solicitud.
    • INFO: "PDM aprobó la solicitud de feedback", pdmId, feedbackRequestId, transactionId
    • INFO: "PDM rechazó la solicitud de feedback", pdmId, feedbackRequestId, transactionId, comentarios (comentarios del PDM)
    • ERROR: Si ocurre un error al aprobar/rechazar la solicitud, registrar: "Fallo al aprobar/rechazar la solicitud de feedback", pdmId, feedbackRequestId, transactionId, error, stackTrace

4. Envío de Correo a los Evaluadores (Si se aprueba)

  • Acción: El sistema envía un correo a los evaluadores.
    • INFO: "Correo de solicitud de feedback enviado a los evaluadores", feedbackRequestId, numeroEvaluadores, transactionId
    • ERROR: Si ocurre un error al enviar el correo, registrar: "Fallo al enviar correo de solicitud de feedback a los evaluadores", feedbackRequestId, transactionId, error, stackTrace

5. Edición de la Solicitud (Si se rechaza)

  • Acción: El colaborador edita la solicitud rechazada.
    • INFO: "Colaborador inició la edición de la solicitud de feedback rechazada", userId, feedbackRequestId, transactionId
  • Acción: El colaborador guarda la solicitud editada.
    • INFO: "Colaborador guardó la solicitud de feedback editada", userId, feedbackRequestId, transactionId

Ejemplo de Logs Estructurados (JSON) 📊

Aquí hay algunos ejemplos de cómo se verían los logs estructurados en JSON:

{
  "timestamp": "2024-10-27T10:00:00.000Z",
  "level": "INFO",
  "message": "Usuario accedió a la pantalla de listado de solicitudes de feedback",
  "userId": "user123",
  "transactionId": "txn456"
}
{
  "timestamp": "2024-10-27T10:05:00.000Z",
  "level": "WARN",
  "message": "Intento de agregar evaluador con correo de CI&T",
  "userId": "user123",
  "transactionId": "txn456",
  "emailEvaluador": "email@ciandt.com"
}
{
  "timestamp": "2024-10-27T10:10:00.000Z",
  "level": "ERROR",
  "message": "Fallo al guardar la solicitud de feedback",
  "userId": "user123",
  "feedbackRequestId": "fbq789",
  "transactionId": "txn456",
  "error": "Error de conexión con la base de datos",
  "stackTrace": "..."
}

Ejemplo de Logs Estructurados con Lombok (Spring Boot) 🛠️

Para simplificar la creación de logs estructurados en Spring Boot, podemos usar Lombok para generar automáticamente el logger:

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.UUID;
import java.util.Map;

@Service
@Slf4j // Genera automáticamente el logger
public class FeedbackService {

    public void crearSolicitud(String userId) {
        UUID transactionId = UUID.randomUUID();
        log.info("Usuario inició la creación de una nueva solicitud de feedback", Map.of(
            "userId", userId,
            "transactionId", transactionId
        ));
        // ...
    }

    public void notificarPdm(String pdmId, String feedbackRequestId) {
        UUID transactionId = UUID.randomUUID();
        log.info("Correo de notificación enviado al PDM", Map.of(
            "pdmId", pdmId,
            "feedbackRequestId", feedbackRequestId,
            "transactionId", transactionId
        ));
        // ...
    }

    public void agregarEvaluador(String userId, String emailEvaluador) {
        if (emailEvaluador.contains("@ciandt.com")) {
            UUID transactionId = UUID.randomUUID();
            log.warn("Intento de agregar evaluador con correo de CI&T", Map.of(
                "userId", userId,
                "transactionId", transactionId,
                "emailEvaluador", emailEvaluador
            ));
            throw new IllegalArgumentException("No es posible agregar evaluadores con correo de CI&T");
        }
    }
}

Monitoreo y Métricas 📈

Con los logs estructurados, podemos monitorear la aplicación y extraer métricas importantes:

  • Número de solicitudes de feedback creadas por día/semana/mes.
  • Tiempo promedio para que el PDM apruebe/rechace una solicitud.
  • Número de correos enviados a los evaluadores.
  • Número de errores al guardar solicitudes.

Herramientas y Tecnologías 🛠️

  • Spring Boot: Utilice SLF4J y Logback para logging estructurado. Use Lombok para simplificar la creación del logger.
  • FastAPI: Utilice el módulo logging de Python y configure un handler para formatear los logs en JSON.
  • ELK Stack (Elasticsearch, Logstash, Kibana) o Grafana Loki: Para la recolección, almacenamiento y análisis de los logs.

Enviando Logs a Grafana Loki 📤

Grafana Loki es una excelente opción para centralizar y analizar sus logs. Para enviar sus logs a Loki, necesita configurar un "appender" (en el caso de Logback) o un "handler" (en el caso de Python) que formatee los logs en el formato esperado por Loki y los envíe al servidor.

  1. Formateando los Logs: Loki espera los logs en un formato específico, generalmente con una marca de tiempo (timestamp) y una etiqueta (label) que identifica la fuente del log.
  2. Configurando Appenders/Handlers:
    • Logback (Spring Boot): Puede usar un appender como Loki4jAppender para enviar los logs directamente a Loki.
    • Python: Puede crear un handler personalizado que formatee los logs y los envíe a la API de Loki.

Ejemplo de Configuración de Logback para Loki:

  1. Agregue la dependencia de Loki4jAppender a su proyecto:

    <dependency>
        <groupId>com.github.loki4j</groupId>
        <artifactId>loki4j-logback-appender</artifactId>
        <version>1.5</version>
    </dependency>
    
  2. Configure el logback.xml:

    <configuration>
        <appender name="Loki" class="com.github.loki4j.logback.Loki4jAppender">
            <url>http://localhost:3100/loki/api/v1/push</url> <!-- Reemplace con la URL de su Loki -->
            <format class="com.github.loki4j.logback.JsonFormatter">
                <jsonLayout>
                    <pattern>
                        {
                            "timestamp": "%date{yyyy-MM-dd'T'HH:mm:ss.SSSZ}",
                            "level": "%level",
                            "message": "%message",
                            "logger": "%logger",
                            "thread": "%thread",
                            "transactionId": "%mdc{transactionId}", <!-- Si usa MDC -->
                            "userId": "%mdc{userId}" <!-- Si usa MDC -->
                        }
                    </pattern>
                </jsonLayout>
            </format>
            <label class="com.github.loki4j.logback.StaticLabelProvider">
                <label>
                    <name>app</name>
                    <value>feedback-service</value> <!-- Nombre de su aplicación -->
                </label>
            </label>
        </appender>
    
        <root level="INFO">
            <appender-ref ref="Loki"/>
        </root>
    </configuration>
    

Creando Appenders/Handlers Personalizados:

Si las opciones existentes no satisfacen sus necesidades, puede crear sus propios appenders/handlers para formatear y enviar los logs a Loki o a cualquier otra herramienta de análisis.

Conclusión 🎉

Espero que esta guía detallada les ayude a implementar un sistema de logging robusto y eficiente en la funcionalidad de "Solicitud de Feedback". Recuerden que el logging es una habilidad esencial para cualquier desarrollador y que la práctica lleva a la perfección.

Si tienen dudas o sugerencias, ¡no duden en compartirlas! Estamos juntos en este viaje. 💪