Tabla de Contenidos

Sistema de Log básico

PEDRO DELGADO YARZA 2014/03/06 13:44

Configuración

En cualquier aplicación Fudneweb 2.0, tenemos por defecto inicializado el sistema de Log ya que Seam crea un objeto Log según los parámetros indicados en el fichero de configuración de log4j (log4j.xml). Este fichero se carga automáticamente siempre que se encuentre dentro del classpath de la aplicación.

Un ejemplo del contenido de este fichero es el siguiente:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
 
    <!-- Definicion de appenders -->
    <appender name="consola" class="org.apache.log4j.ConsoleAppender"> 
        <param name="Target" value="System.out"/> 
        <layout class="org.apache.log4j.PatternLayout"> 
            <param name="ConversionPattern" value="%d{DATE} %5p %c{1}:%L - %m%n"/> 
        </layout> 
    </appender> 
 
	<appender name="fichero-local" class="org.apache.log4j.FileAppender">
        <param name="File" value="./log/prototipo_seam_deploy.log" />
        <param name="Append" value="true" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{DATE} %5p %c{1}:%L - %m%n"/>
        </layout>           
    </appender>
 
    <appender name="fichero-sistemas" class="org.apache.log4j.FileAppender">
        <param name="File" value="/var/httpd/oas10g/logs/prototipo_seam_deploy.log" />
        <param name="Append" value="true" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{DATE} %5p %c{1}:%L - %m%n"/>
        </layout>           
    </appender>
 
    <!-- Fin definicion de appenders -->
 
    <!-- Definicion de niveles de log -->
    <logger name="org.apache">
        <level value="WARN"/>
    </logger>
 
    <logger name="javax.faces">
        <level value="WARN"/>
    </logger>
 
    <logger name="org.ajax4jsf">
        <level value="WARN"/>
    </logger>
 
    <logger name="org.richfaces">
        <level value="WARN"/>
    </logger>
 
    <logger name="org.jboss">
        <level value="WARN"/> 
    </logger>
 
    <logger name="org.jboss.seam">
        <level value="WARN"/> 
    </logger>
 
	 <logger name="org.jboss.ejb3">
		<level value="WARN"/>
	</logger>
 
   <logger name="org.jboss.kernel">
      <level value="WARN"/>
   </logger>
 
	<logger name="org.hibernate">
        <level value="WARN"/> 
    </logger>
 
	<logger name="org.quartz.simpl">
		<level value="WARN"/> 
	</logger>
    <!-- Fin definicion de niveles de log -->
 
    <!-- Configuracion despliege -->
    <root> 
        <priority value="DEBUG" />
        <appender-ref ref="consola" />
        <appender-ref ref="fichero-local" />  
    </root>
    <!-- Fin configuracion despliege -->   
 
 
</log4j:configuration>

Como podemos ver en este ejemplo, el fichero está estructurado en varias secciones que comentamos a continuación:

Obtención del log en nuestra aplicación

Una vez que tenemos definido el mecanismo de log en nuestra aplicación debemos saber cómo recuperarlo e incluirlo para que podamos usarlo en nuestro códugo fuente.

Inyectar log con Seam

Seam proporciona una API de logging que simplifica mucho la manera de gestionar el log. Utilizando la anotación @Logger podemos inyectar una instancia del Log sin necesidad de configurar nada más.

Esta variable de log inyectada, tendrá un método disponible por cada nivel de log que queramos tener. Así pues si la variable es log, tendremos un método info, debug, warn, error, fatal.

public class ManejadorFundeweb {
  @Logger
  private Logger log;
  ....
  ....
 
  public boolean compruebaCantidad(User user, Product product, int quantity) {
    log.debug("Comprobando cantidad para el usuario: #0 producto: #1 cantidad: #2", user.username(), product.name(), quantity);
    ....
  }
}

Nota: Como podemos ver en la llamad anaterior al log, dentro del mensaje de log introducimos los parámetros con #0, #1, … #n. Posteriormente en el mismo método de log obtenemos el valor de cada uno.

Obtener log con Seam pero sin inyectarlo

Si en un componente Seam (lleva la anotación @Name), también lleva la anotación @BypassInterceptors, entonces la inyección de log por Seam no funcionará ya que la anotación @Logger, no inyectara un logger a la clase. Para solventar este problema, utilizaremos la clase Logging de Seam para obtener un logger de manera manual.

@Name("pruebaLog")
@BypassInterceptors
public class ClasePrueba {
   private static final Log LOG = Logging.getLog(ClasePrueba.class);
   ...	
}

Log en aplicaciones no Seam

Cuando estamos fuera de un aplicación Seam no tenemos disponible las clases del paquete org.jboss.seam. Pero sí tenemos unos wrappers hechos en ATICA que nos solventan el problema de incorporar el log, para ello añadir la siguiente dependencia Maven:

<dependency>
	<groupId>org.um.atica</groupId>
	<artifactId>fundeweb-commons-services</artifactId>
	<version>1.2.6-CR-2</version>
</dependency>

Nota: Antes de incluir la dependencia, revise las versiones de la misma. Ha de incluir la versión más actualizada de esta librería.

Una vez incluida la dependencia, la obtención del log se realiza de manera muy similar al apartado anterior

import org.umu.atica.log.Log;
import org.umu.atica.log.Logging;
public class ClasePrueba {
   private static final Log LOG = Logging.getLog(ClasePrueba.class);
   ...
}

Gestión de los mensajes de log

Es importante a la hora de gestionar el log, diferenciar el log que utilizaremos para la fase de desarrollo y el que pondremos finalmente en explotación. Esta diferenciación no es trivial ya que la cantidad de log que es necesario para el desarrollo es mayor que el que finalmente se necesita en explotación.

Así pues, cuando estemos desarrollando deberemos fijar el log en DEBUG, en este estado se nos generarán un mayor número de trazas de depuración. A su vez, nosotros en la aplicación anotaremos como DEBUG, aquellas trazas que serán útiles sólo para la fase de desarrollo.

En cuanto a explotación, el nivel adecuado de log será INFO, en este nivel la información que se genera deberá ser la imprescindible para realizar comprobaciones y trazabilidad del uso de la aplicación, pero deberá ser menor que la generada en estado DEBUG. En este punto, además del nivel de debug es imprescindible incofporar el usuario que realiza las diferentes acciones en cada traza (esto nos da la trazabilidad de usuario). Para ello debemos incluir un parámetro en nuestras trazas de log que recupere el usuario que está ejecutando la aplicación, este valor lo podemos obtener de la clase UmuIdentity, que se carga cuando el usuario se loguea en la aplicación.

Al mismo tiempo, en nuestro fichero de configuración de log, debemos asegurarnos, para los diferentes componentes que generan log, asegurar un nivel adecuado para cada entorno. A continuación mostramos un ejemplo de ello.

<logger name="org.apache">
	<level value="WARN"/>
</logger>
 
<logger name="javax.faces">
	<level value="WARN"/>
</logger>
 
<logger name="org.ajax4jsf">
	<level value="WARN"/>
</logger>
 
<logger name="org.richfaces">
	<level value="WARN"/>
</logger>
 
<logger name="org.quartz.simpl">
	<level value="WARN"/> 
</logger>