Como usar Log4j en aplicaciones Web

Cuando quieres usar log4j en una aplicación de escritorio lo normal es cargar el archivo de configuración (log4j.properies) en el main para tenerlo disponible para toda la aplicación pero en una aplicación web no hay ningún main, además que las aplicaciones se ejecutan sobre un servidor y hay que tener esto en cuenta para definir donde estará el log4j.properies y también donde almacenaremos nuestros ficheros de log.

La solución más sencilla es usar SLF4J (Simple Logging Facade for Java) y así con poner el archivo log4j.properies en la carpeta src este ya se carga sin de forma automática y lo más importante que nos permite abstraernos de la librería de logging utilizada lo que permite que puedas cambiar de una a otra sin tener que estar modificando todo el código. En este otro post puedes ver como usar log4j con SLF4J.

Pero si lo que quieres es hacer una aplicación sencillita con servlets y jsp es muy sencillo usar log4j. El primer paso para poder usarlo es cargar el archivo de configuración para lo que será necesario crear un servlet como este:


package es.com.blogspot.programandoointentandolo.log4j;

import java.io.File;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.PropertyConfigurator;

/**
 *
 * @author Ivan Salas Corrales
 * <http://programandoointentandolo.com>
 */
 
@WebServlet(name = "CargaLog4j", urlPatterns = {"/cargalog4j"}, 
        initParams = {@WebInitParam(name = "log4jPropertiesFile",
        value = "/WEB-INF/classes/log4j.properties")}, loadOnStartup = 1)
public class CargaLog4j extends HttpServlet {
    
    @Override
    public void init(ServletConfig config) throws ServletException{
        
        // Obtiene el parametro de inicio
        String log4jFile = config.getInitParameter("log4jPropertiesFile");
        
        // Obtiene la ruta real del archivo (ruta absoluta)
        ServletContext context = config.getServletContext();
        log4jFile = context.getRealPath(log4jFile);
        
        // Carga el log4j.properties si existe y sino carga BasicConfigurator
        if (new File(log4jFile).isFile()) {
            PropertyConfigurator.configure(log4jFile);
        } 
        else {
            BasicConfigurator.configure();
        }
 
        super.init(config);
    }
}

Para cargar el archivo hace falta indicar la ruta completa de donde se encuentra para lo que es necesario usar getRealPath y se podría comprobar si ciertamente existe el archivo log4j.properties aunque es de suponer que el archivo estará en su sitio y que la ruta será la correcta porque lo estaremos poniendo nosotros y no un usuario que podría poner lo que se le ocurriese.

Como el archivo solo se tiene que cargar una única vez lo adecuado es sobrescribir el método init. Aunque se puede escribir la ruta en la que se encuentra el archivo dentro del propio código java lo mejor es sería ponerlo como un parámetro de contexto de forma que el web.xml quedaría como el siguiente.


<servlet>
 <servlet-name>CargaLog4j</servlet-name>
  <servlet-class>es.com.blogspot.programandoointentandolo.log4j.CargaLog4j</servlet-class>
  <init-param>
    <param-name>log4jPropertiesFile</param-name>
    <param-value>/WEB-INF/classes/log4j.properties</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>

Y si prefieres usar anotaciones en lugar de escribir en el web.xml en el código anterior puedes ver como (línea 18), aunque es obvio si se usa una cosa no se usa la otra.

Para que el archivo este en /WEB-INF/classes hay que colocarlo en la carpeta src (src en eclipse o Source Packages en NetBeans) y el único punto que tiene algo que comentar es el load-on-startup que sirve para indicar cuando queremos que se cargué el servlet indicando 1 hacemos que se carge al desplegar la aplicación sino se pusiese este parámetro o si fuese menor que 0 el método init del servlet se ejecutaría cuando al contenedor web le pareciese, probablemente cuando se produjese la primera llamada al servlet, pero en este caso nos interesa que este listo antes que el resto de la aplicación por lo que lo ponemos a 1.

Y con esto ya podemos utilizar log4j en nuestra aplicación de igual forma que en una aplicación de escritorio.


package es.com.blogspot.programandoointentandolo.prueba;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;

/**
 *
 * @author Ivan Salas Corrales
 * <http://programandoointentandolo.com>
 */

 public class PruebaLog4j extends HttpServlet {
    
    private Logger log = Logger.getLogger(PruebaLog4j.class);
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        log.error("Un fallo");
        log.info("Un mensaje informativo");

    }
}

Y para terminar un ejemplo de log4j.properties:


# Se mostraran los mensajes desde el nivel debug en los appenders C (consola) y F (fichero)
log4j.rootLogger=DEBUG, C, F

# C is set to be a ConsoleAppender.
log4j.appender.C=org.apache.log4j.ConsoleAppender
log4j.appender.C.layout=org.apache.log4j.PatternLayout
log4j.appender.C.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

# F is set to be a RollingFileAppender
log4j.appender.F=org.apache.log4j.RollingFileAppender
log4j.appender.F.File=${catalina.home}/logs/MiAplicacion.log
log4j.appender.F.Append=true

log4j.appender.F.MaxFileSize=100KB
log4j.appender.F.MaxBackupIndex=1

log4j.appender.F.layout=org.apache.log4j.PatternLayout
log4j.appender.F.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

Si como fue mi caso estas usando el servidor Apache Tomcat 7.0.22.0 si para la ruta del archivo de log usas una ruta relativa como esta logs/MiAplicacion.log el archivo te aparecerá dentro de la carpeta bin del tomcat (C:\Program Files\Apache Software Foundation\Apache Tomcat 7.0.22\bin\logs\MiAplicacion.log) porque toma la ruta relativa al ejecutable del servidor en lugar de a la raíz del servidor como podría parecer mas lógico o incluso a la de la aplicación. Para poder guardar el archivo en una carpeta a partir de la raíz del tomcat en este caso hay que usar ${catalina.home} seguido de la ruta en la que se quiera guardar el log, en el ejemplo de log4j.properties se guarda en la carpeta logs que contiene los logs del propio servidor.
También se puede usar ${catalina.base} en lugar de ${catalina.home} y el resultado será el mismo si se ejecuta desde el propio servidor pero si por ejemplo estas usando un IDE como NetBeans y usas ${catalina.base} el archivo no te aparecerá en la carpeta del Tomcat sino en la ruta indicada en las propiedades del Tomcat para Catalina Base, que será algo similar a esto C:\Users\Ivan\.netbeans\7.1\apache-tomcat-7.0.22.0_base.

Puedes descargar el .war del ejemplo aquí.

One Response

  1. Anonymous 24 mayo, 2013 Reply

Leave a Reply