Java: Logs de Aplicaciones – La senda del Guerrero

Lógica básica a la hora de poner trazas:

  • No des por hecho que tienes acceso al código/subversión:
    Si tu traza (INFO/WARN/ERROR) necesita de leer el código, es que no es una buena traza.
  • No des por hecho que tienes trazas de nivel DEBUG:
    Si tienes que tener las trazas en modo debug es que necesitas una traza bien definida en un nivel inferior, ya sea ERROR, WARN o INFO.
  • No des por hecho que solo accede 1 usuario a tu aplicación:
    Las trazas se mezclan, haz que sean identificables y se puedan correlacionar las diferentes líneas de log y así saber que líneas pertenecen a que petición o usuario.
  • Ni mucha, ni poca; pon información útil:
    No hace falta que pongas el quijote, tampoco pongas un dato que no se sepa que es.
  • No pongas acentos; si las pones en ingles, mejor:
    Los acentos no siempre son ASCII/ISO-8859-1, los ficheros de logs a veces se ven mal o los “greps” no funcionan bien.

Ejemplo de traza “mala” (que no aporta nada útil, ni tiene contexto de referencia) (y se repite 100 veces sin ninguna diferencia):

2012-02-07 14:04:30,471 [catalina-exec-35] INFO  com.acme.coyote.servlets.UploadServlet - Buscando caracteres no compatibles en: ESTA TARDE VA A SALIR EL SOL

Ejemplo de traza “buena” (que aporta información útil):

2012-02-16 14:42:10,504 ERROR com.acme.XXXX [10.242.1.8:ACME:PEDRO] [Login] Error en password company=ACME user=PEDRO pwd=<NULL>

Usando MDC/NDC (log4j) para mejorar la trazabilidad

Ejemplo de uso/implementación (si usas threads “extras” o workers hay q trabajar un poco más este ejemplo para heredar/pasar la información de contexto, ya que los datos de MDC/NDC son “ThreadLocal”):

import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
import org.apache.log4j.NDC;

// log4j.appender.XXXX.layout.ConversionPattern=%d{ISO8601} %p %c [%X{IP}:%X{SESSION}:%x] %m%n

public class MyClass extends HttpServlet {
    
    private final static Logger l = Logger.getLogger(MyClass.class);

    // [...blablabla...]

    public void doGet(final HttpServletRequest req, final HttpServletResponse resp) 
                throws IOException, ServletException {
        try {
            MDC.put("IP", req.getRemoteAddr()); // MDC IP=10.242.1.8
            MDC.put("SESSION", req.getRequestedSessionId()); // MDC SESSION=7A7B9C9D721EAAFFAA1BB7E43BDFD2F1
            //
            NDC.push("doGet"); // NDC (add entry point)
            //
            String p_user = req.getParameter("user"));

            // Check Params
            if (p_user == null) {
                l.error("Invalid parameters USER=<NULL>");
                // 2012-02-16 16:42:10,504 ERROR com.acme.MyClass [10.242.1.8:7A7B9C9D721EAAFFAA1BB7E43BDFD2F1:doGet] Invalid parameters USER=<NULL>
                // [...blablabla...]
                return;
            }
            
            // Remapping Parameters
            p_user = p_user.trim().toUpperCase();
            
            NDC.push("USER=" + p_user); // NDC (add user info)

            try {
                NDC.push("Test");
                l.info("blablabla");
                // 2012-02-16 16:42:10,801 ERROR com.acme.MyClass [10.242.1.8:7A7B9C9D721EAAFFAA1BB7E43BDFD2F1:doGet USER=PEPE Test] blablabla
                // [...blablabla...]
            }
            finally {
                NDC.pop();
            }

            // [...blablabla...]

            l.info("Request OK");
            // 2012-02-16 16:42:11,102 ERROR com.acme.MyClass [10.242.1.8:7A7B9C9D721EAAFFAA1BB7E43BDFD2F1:doGet USER=PEPE] Request OK
        }
        catch (Exception e) {
            l.error("Request ERROR (Exception=" + e.toString() + ")");
            // 2012-02-16 16:42:11,102 ERROR com.acme.MyClass [10.242.1.8:7A7B9C9D721EAAFFAA1BB7E43BDFD2F1:doGet USER=PEPE] Request ERROR (Exception=java.lang.NullPointerException)
        }
        finally {
            NDC.clear();
            MDC.clear();
        }
    }

    // [...blablabla...]
}

Referencias:
NDC vs MDC – Which one should I use?
Log4j MDC (Mapped Diagnostic Context) : Example code
Build Flexible Logs With log4j
Effective logging practices ease enterprise development

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: