Sei sulla pagina 1di 14

Sistemas de Trazas

Fecha de creacin: 12.01.2003 Revisin 1.0 (25.03.2003) Enrique Rodriguez Lasterra (lasterra AT javahispano DOT org)

http://www.javaHispano.org

Copyright (c) 2002, Enrique Rodriguez Lasterra. Este documento puede ser distribuido solo bajo los trminos y condiciones de la licencia de Documentacin de javaHispano v1.0 o posterior (la ltima versin se encuentra en http://www.javahispano.org/licencias/).

Sistemas de Trazas

Sistemas de Trazas
Quien no ha puesto un System.out.println para escribir en la consola el valor de una variable? Y el tpico mensaje ?llega aqu?????. Sin duda alguna, esta es la forma ms sencilla y ms utilizada de depurar nuestro cdigo. En base a esta idea se han ido creando sistemas de gestin de logs/trazas que han ido aadiendo diversas funcionalidades demandadas por los programadores. Este articulo intenta explicar como utilizar los mas conocidos, Jakarta-Log4j, el nuevo paquete de la JDK1.4 java.util.logging y Jakarta-Commons-Logging.

Jakarta-Log4j
Jakarta-Log4j es una de las ms antiguas, potentes y conocidas. Entre sus caractersticas principales se encuentran: Diferentes niveles de traza. (Error, informacin, depurar.) Filtros segn categora Redireccin de las trazas a diferentes destinos. (A un archivo, a consola, a BBDD.) Diferentes formatos de visualizacin. (Visualizar fecha, lnea, nombre de la clase..) Configuracin por ficheros

Vamos a ir descubriendo estas caractersticas paso a paso:

Niveles de Prioridad de Traza


Log4j provee al programador de 5 niveles de traza: OFF, no se muestra en ningn caso FATAL, para mostrar mensajes de situaciones que probablemente harn abortar la aplicacin ERROR, para mostrar mensajes de errores que no son deseados pero que no interrumpirn la aplicacin WARN, para mostrar mensajes de contextos peligros para la aplicacin, o ciertas operaciones de uso no recomendado INFO, para mostrar mensajes de informacin sobre la ejecucin de la aplicacin, o eventos importantes dentro de la misma
Pgina 2

Sistemas de Trazas

DEBUG, para mostrar mensajes interesantes para depurar la aplicacin. Muy orientado al tiempo de desarrollo ALL, se muestra en todos los casos

Cuando escribimos nuestras aplicaciones, las trazas se escriben en los diferentes niveles dependiendo de la operacin que se utilice. As para escribir en el nivel INFO se usa log.info("Nivel Info"); y para el nivel DEBUG log.debug("Nivel Debug"). Por lo general el nivel de prioridad esta fijado por defecto a INFO, por lo que los mensajes de nivel DEBUG no son visualizados. Este nivel genera un caudal elevado de trazas por lo que su uso suele estar restringido a entornos de desarrollo. Un apartado importante en el uso de las trazas es como utilizarlas cuando se producen errores/excepciones. No siempre hay que escribir las trazas de excepciones a nivel de error, ya que en algunos casos no interesa que se visualicen. En caso de escribir componentes que posteriormente utilicen otras personas, convendra relanzar la excepcin y escribir la traza a nivel de DEBUG o INFO dependiendo de si el programador sera el propio usuario de la clase o si un tercero sera quien la utilice.

Categoras ( como filtrar las trazas)


Para ver esta caracterstica es necesario adentrarse un poco ms en la configuracin y el cdigo necesario para trabajar con Log4j. En el siguiente ejemplo se muestra como tracear una clase.

import org.apache.log4j.* public class Pruebaslog4j { Logger log = Logger.getLogger(this.getClass()); /** Creates a new instance of Pruebaslog4j */ public Pruebaslog4j () { try { log.info("Constructor"); log.warn("nivel WARN"); if (log.isDebugEnabled()) { log.debug("Traza de nivel debug"); } } catch (IllegalStateException e) { log.error("Traza de nivel error", e); } } /** * @param args the command line arguments */ public static void main(String[] args) { Pruebaslog4j pl4j = new Pruebaslog4j (); } }

Pgina 3

Sistemas de Trazas

En la segunda lnea se obtiene el objeto con el cual se escriben las trazas, el objeto Logger. Se puede hacer referencia a este objeto bajo el nombre "escritor", ya que es el quien se encarga de escribir los mensajes a los diferentes soportes con los cuales Log4j trabaja. Para obtener este objeto se le pasa la clase, o el nombre completo de la clase, es decir, paquete.otropaquete.NombreClase, o cualquier otro nombre con el que se defina la categora de esta traza. Se puede jerarquizar las categoras, separando los niveles con "."(Puntos). Por tanto si se define la categora con el nombre componente.primario, primario es una categora hija de componente. Como veremos mas adelante, las configuraciones que se asocien a componente sern heredadas por primario. Estas configuraciones se realizan en el archivo de configuracin.

Archivo de configuracin
Log4j se puede configurar desde un archivo XML o desde un archivo de propiedades. Empecemos por la mas antigua y sencilla, el archivo de propiedades. Para configurar Log4j de esta forma es necesario que el archivo log4j.properties este en el CLASSPATH de nuestra aplicacin. Esto quiere decir que tiene que estar en la raz de nuestro cdigo, o dentro de algn archivo JAR que nuestra aplicacin cargue, o al lanzar el programa, fijando la propiedad del sistema con el argumento
java Clase -Dlog4j.configuration=log4j.properties

Este archivo comienza con la configuracin del nivel principal de la jerarqua, el ROOT. Bajo este nivel se encuentran todas las categoras de nuestra aplicacin. Para configurar el nivel ROOT hay que escribir en el fichero de propiedades la propiedad log4j.rootLogger e igualarla al nivel de prioridad que por defecto se desea fijar. Tras el nivel de prioridad, separados entre comas, los diferentes appenders a los que por defecto se desean redireccionar nuestras trazas. (Aprenders??? la explicacin un poco ms abajo, paciencia ;-)
log4j.rootLogger=DEBUG, Consola, Fichero

En el ejemplo fijamos el nivel por defecto a DEBUG (muy tpico cuando estamos desarrollando el cdigo) y redireccionamos a los appenders Consola y Fichero. Ya tenemos todo nuestro cdigo fijado con un nivel de trazas DEBUG. En muchos casos, no nos interesa ver todas las trazas de una aplicacin, por ejemplo, cuando se utiliza un componente cuyo funcionamiento ya ha sido probado. Para subir el nivel de traza a INFO o WARN en dicho componente escribimos la siguiente propiedad en el fichero de configuracin.
log4j.Logger.NombreCategoria=INFO

O si se utiliza como nombre de categora la ruta completa a las clases


Pgina 4

Sistemas de Trazas

log4j.Logger.com.empresa.componente=INFO

Cuando se realiza esta operacin, decimos que la categora tiene un nivel de traza fijado de forma explicita. Esto hace que el paquete "com.empresa.componente" tenga el nivel de traza fijado a INFO, o lo que es lo mismo, no se escribir ninguna traza de nivel DEBUG dentro de ese paquete. Si el componente tiene subpaquetes, y estos no tienen un nivel de traza fijado de forma explicita, heredan el nivel de traza del paquete que los contiene. Visto al revs, si un paquete no tiene asignado de forma explicita un nivel de prioridad de traza, el paquete obtiene el nivel del paquete en el que esta contenido. As de forma recursiva, hasta que se encuentre con un paquete con nivel de traza asignado de forma explicita o con el nivel principal de la jerarqua, con ROOT. A continuacin 3 ejemplos que visualizan el comportamiento de herencia anteriormente descrito. (Fijaros en la ltima columna) Nivel Jerarqua Clases CATEGORIA Nivel de traza asignado de forma explicita
.

Nivel de traza asignado

Nivel Jerarqua Clases CATEGORIA

Nivel de traza asignado de forma explicita


.

Nivel de traza asignado

Nivel Jerarqua Clases CATEGORIA

Nivel de traza asignado de forma explicita


.

Nivel de traza asignado

Appenders
Una vez establecido el nivel de trazas de nuestro cdigo hay que configurar donde queremos que nuestras trazas sean escritas o direccionadas. Las opciones ms utilizadas son a la consola y los archivos de texto, pero Log4j tambin puede escribir las trazas en base de datos, en una cola de mensajes JMS o en el visor de sucesos de Microsoft Windows. Veamos como se configuraran los appenders: Lo primero de todo es definir los nombre de los appenders que se van a utilizar en la propiedad log4j.rootLogger. Recordad que en esta propiedad se fijaba el nivel de traza por defecto y seguido y separados por coma, el nombre de los appenders que se van a usar. Al fijar estos appenders en la categora principal, todas las trazas de la aplicacin sern direccionadas a ellos
Pgina 5

Sistemas de Trazas

log4j.rootLogger=DEBUG, Consola, Fichero

Si se quiere que alguna categora en concreto sea direccionada a otro appender, definiremos para esa categora su appender
log4j.Logger.categoriaComponente=INFO, FicheroComponente

Si se realiza este tipo de configuracin hay que tener en cuenta que los appenders por defecto son heredados. Log4j utiliza para hablar de esta propiedad el termino "additivity" de appenders. Para el ejemplo anterior, las trazas escritas para la categora categoriaComponente, sern direccionadas al appender FicheroComponente, Fichero y Consola, ya que Fichero y Consola son heredados por defecto desde la categora ROOT. Si no se desea heredar los appenders, hay que definir la siguiente propiedad en el fichero de configuracin:
log4j.logger.append.categoriaComponente=false

Solo queda configurar cada uno de ellos.

Configurar el ConsoleAppender
Para configurar el aprender Consola, lo primero que hay que decirle es el tipo de aprender que es, en este caso de consola, por lo que hay que escribir la siguiente propiedad
log4j.appender.Consola=org.apache.log4j.ConsoleAppender

Lo siguiente ser configurar el nivel de traza, ya que cada aprender puede tener uno distinto. Por ejemplo, es bastante comn poner la salida a fichero con nivel DEBUG y la salida de consola con nivel INFO.
log4j.appender.Consola.Threshold=INFO

Para acabar con la configuracin de la salida, asignamos el appender a un stream. Ya que lo que se busca es escribir en consola, se fija la salida a System.out.
log4j.appender.Consola.Target=System.out

La configuracin de un appender para fichero sera muy parecida. Primero se le dice al appender que es de tipo fichero. Existen varios tipos de appender a fichero, los ms comunes son RollingFileAppender y DailyRollingFileAppender
Pgina 6

Sistemas de Trazas

El primero escribe las trazas en un fichero de tamao mximo configurable. Cuando se llega a ese tamao, el fichero se renombra a nombreFichero.ext.1, y se continan escribiendo las trazas en un nuevo fichero nombreFichero.ext. Cuando este llegue a su tamao mximo se renombrara a nombreFichero.ext.1 y el que era nombreFichero.ext.1 pasa a ser nombreFichero.ext.2. As continuamente, van "rotando" los ficheros, de hay su nombre de RollingFileAppender. En caso de que se llegue al nmero mximo de ficheros, se borrara el fichero ms antiguo. El segundo escribe las trazas en un fichero diario, al acabar el da, Log4j crea un nuevo fichero

Configurar un RollingFileAppender
Como siempre le decimos al appender de que tipo es
log4j.appender.Fichero= org.apache.log4j.RollingFileAppender

Le decimos la ruta donde se va a crear el fichero, tomando como raz el lugar donde se encuentre el fichero. Tambin se puede utilizar una ruta completa (c://log/trazas.log o en UNIX /usr/log/trazas.log)
log4j.appender.Fichero.File=./log/Trazas.log

* Me llevo bastante mal con esta propiedad, muchas veces me veo obligado a escribir la ruta completa para que las trazas se escriban en el fichero. Por ultimo configuramos el tamao mximo del fichero, y el nmero mximo de ficheros que van a rotar.
log4j.appender.Fichero.MaxFileSize=500KB

log4j.appender.Fichero.MaxBackupIndex=10

Con esta configuracin tendremos 5 megas de trazas.

Otros Appenders
Con los ejemplos anteriores se muestra la facilidad para configurar los appenders. Log4j tiene multiples appenders a los cuales redireccionar las trazas, ejemplo de configuracin bsicos serian los siguentes:

JDBCAppender
Pgina 7

Sistemas de Trazas

#Como siempre tipo de appender log4j.appender.appenderBD=org.apache.log4j.jdbc.JDBCAppender #url a la base de datos, en este caso ejemplo para mysql log4j.appender.appenderBD.URL=jdbc:mysql://javahispano/Log4j #usuario y password de la base de datos log4j.appender.appenderBD.user=java log4j.appender.appenderBD.password=hispano #isntruccin SQL a la que se va a llamar log4j.appender.appenderBD.sql=INSERT INTO Tabla (fecha,mensaje) VALUES ('%d','%c - %p - %m')

SMTPAppender

log4j.appender.appenderCorreo.To =drafts@javahispano.org log4j.appender.appenderCorreo.From =lasterra@javahispano.org log4j.appender.appenderCorreo.Subject =Error Enviado desde Log4j #Si el servidor requiere autentificacin no funcionara :-( log4j.appender.appenderCorreo.SMTPHost=smtp.javahispano.org //or ip-Adress log4j.appender.appenderCorreo.BufferSize=1

Layouts
Este es el ltimo de los elementos configurables, la forma y la informacin que se escribe en cada traza. A cada appender se le puede aadir un layout. El ms comn es el PatternLayout, en el cual se configuran una serie de variables, es decir, el patrn, que se cambiaran en el momento de escribir en el appender. Mas claro con un ejemplo
log4j.appender.Consola.layout =PatternLayout

log4j.appender.Consola.layout.ConversionPattern= %d [%p,%c] %m %n

Con ese patrn se visualizara


Hora [Prioridad de la traza, categoria] El mensaje de la traza de lnea Salto

Un ejemplo
11:55:48,755 [DEBUG,org.javahispano.articulo] Mensaje de nivel DEBUG

Otras opciones que admite el patrn son %F: Nombre del fichero. (Operacin muy costosa)
Pgina 8

Sistemas de Trazas

%l: Nmero de lnea. (Operacin muy costosa) %d{ISO8601}: Fecha en el estndar ISO 8601 (2003-01-12 17:26:30,234) %d{HH:mm:ss,SSS}: Fecha con la misma sintaxis del SimpleDateFormat %r: Milisegundos desde que comenz el programa %t: Hilo que llamo al Logger.

Ms informacin en: [PatternLayout]

Configurando en XML
Todo lo anteriormente explicado para la configuracin de Log4j con el archivo de propiedades log4j.propierties se puede aplicar a la configuracin en xml del archivo log4j.xml Como se ve a continuacin, primero se configuran los diferentes appenders, posteriormente se van configurando aquellas categoras a las cuales se les desea efectuar un tratamiento especial, y por ultimo la categora ROOT.

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="Fichero" class="org.apache.log4j.FileAppender"> <param name="File" value="A1.log" /> <param name="Append" value="false" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%t %-5p %c{2} - %m%n"/> </layout> </appender> <appender name="Consola" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> </layout> </appender> <category name="nombreCategoria"> <priority value="debug" /> <appender-ref ref="Fichero" /> </category> <root> <priority value ="debug" /> <appender-ref ref="Consola" /> </root> </log4j:configuration>

Pgina 9

Sistemas de Trazas

Rendimiento
Log 4j se ha construido intentando lograr el mayor rendimiento posible. El peso de aadir una traza dentro del programa ralentiza su ejecucin entre 5 y 50 nanosegundos cuando esta deshabilitada. Si esta habilitada depende del tipo de appender y del layout. La mayor parte de este tiempo se gasta en construir el String del mensaje. Para evitar este tiempo Log4j tiene las operaciones Logger.isDebugEnabled() Logger.isInfoEnabled, etc. Gracias a estas operaciones, y aadiendo una condicin en el cdigo, podemos ahorrar bastante tiempo a cambio de escribir la condicin. Si la velocidad es un aspecto crtico para la aplicacin hay que considerar la necesidad de introducir este recurso.

java.util.logging
El nuevo paquete introducido en la JDK1.4 es muy similar al anterior sistema descrito. El cdigo de las aplicaciones es muy similar, ya que tambin se utiliza en objeto Logger para escribir las trazas. La definicin de los niveles es la siguiente SEVERE (valor mas alto) WARNING INFO CONFIG FINE FINER FINEST (valor mas bajo)

En vez de appender, este sistema de logging habla de "handlers" (manejadores). La J2SE viene con 5 tipos de handlers: Stream Console File Socket Memory

De entre todos estos, es el ltimo el que no esta dentro de la distribucin de Log4j

Pgina 10

Sistemas de Trazas

A cada handler, al igual que a los appenders de Log4j, se le puede asociar un formato. O bien la traza es un simple String con el mensaje, SimpleFormatter. O bien esta definida en XML, XMLFormatter. Un ejemplo de este ltimo sera:

<record> <date>2000-08-23 19:21:05</date> <millis>967083665789</millis> <sequence>1256</sequence> <logger>kgh.test.fred</logger> <level>INFO</level> <class>kgh.test.XMLTest</class> <method>writeLog</method> <thread>10</thread> <message>Hello world!</message> </record>

El fichero de configuracin viene incluido dentro del JRE.< Directorio _ JRE >/lib/logging.properties. En el se configuran los handlers que se van a utilizar, asignando a la propiedad handlers los handlers separados por coma
handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

La configuracin de cada handler, primero el lugar donde se van a generar los Logs
java.util.logging.FileHandler.pattern = %h/java%u.log

"/" El separador del sistema "%t" El directorio temporal "%h" el directorio del usuario (Mis documentos o /usr/home) "%g" numero generado para distinguir la rotacion de ficheros "%u" numero unico para resolver posibles conflictos

Tamao maximo del fichero


java.util.logging.FileHandler.limit = 50000

Numero de archivos del ciclo de rotacin

Pgina 11

Sistemas de Trazas

java.util.logging.FileHandler.count = 1

Formato de escritura
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

Tambien se puede configurar un nivel de salida. Como ejemplo se muestra esta configuracin en el ConsoleHandler
java.util.logging.ConsoleHandler.level = INFO

java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

El nivel por defecto


.level=INFO

Se pueden definir diferentes niveles de salida para cada paquete, en java.util.logging no se puede hablar del concepto de categora.
com.xyz.foo.level = SEVERE

Si en vez de modificar este archivo, queremos configrar nuestra aplicacin con otro, al lanzar la aplicacin le debemos decir donde se encuentra dicho archivo de la siguiente forma:
java -Djava.util.logging.config.file=rutaAMiarchivo

Jakarta-Commons-Logging (JCL)
En vista de que son varios los sistemas de trazas que actualmente se pueden elegir, bajo el proyecto commons de Jakarta, se ha creado un pequeo subproyecto gracias a el cual se puede intercambiar de un sistema de trazas a otro sin tener que cambiar ni una lnea de cdigo. JCL provee de clases e interfaces que se encargan de llamar a las clases de los verdaderos sistemas de trazas. Por defecto, si las clases de log4j estn en el CLASSPATH de la aplicacin, sern a ellas a quien se direccione la llamada. Si estas no son localizadas, y se esta trabajando con la JDK1.4, se realizan llamadas a
Pgina 12

Sistemas de Trazas

las clases del paquete java.util.logging. Y si no el propio JCL las direcciona todas las trazas a System.err. Para usar JCL solo hay que hacer dos cosas Aadir JCL al CLASSPATH de tu aplicacin Escribir en tu codigo las sentencias de JCL en vez de las de otro sistema de trazas

Por lo tanto, una vez JCL esta en nuestro CLASSPATH, debemos importar las clases que necesitamos

import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;

Obtener el Log, conocido como Logger en Log4j y java.util.logging


Log log = LogFactory.getLog(this.getClass());

Escribir las trazas igual que en los sistemas anteriormente explicados

if (log.isDebugEnabled()) log.debug("mensaje");

Gracias a ese pequeo cambio, podemos usar Log4j, java.util.logging u otro sistema de trazas sin tener que cambiar el cdigo. Hacer uso de JCL es recomendable si: Estas programando clases que utilizara otro programador Utilizas diferentes sistemas de trazas segn el proyecto en el que trabajas Programas clases que se usaran en otros proyectos y/o entornos No tienes muy claro que sistemas de trazas usar

Conclusin
Este artculo muestra los sistemas de trazas mas conocidos. Se puede extraer de la
Pgina 13

Sistemas de Trazas

lectura que java.util.logging es una copia de Log4j, con algunas opciones menos pero con la garanta de que va incluido en la JDK. Para mi no hay dudas, Log4j y JCL es la mejor combinacin, pero el gusto y la confianza en los productos Open Source harn que cada uno elija la combinacin que mas le guste. En cualquier caso, cualquiera es mejor que utilizar System.out y me aventuro a decir que mejor que cualquier sistema propio que se haya podido crear.

Recursos y referencias
[1] Jakarta-Log4j, http://jakarta.apache.org/log4j/ [2] Ultima versin Log4j, http://jakarta.apache.org/log4j/docs/download.html [PatternLayout] API PatternLayout,

http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/PatternLayout.html [3] Java logging overview, http://java.sun.com/j2se/1.4.1/docs/guide/util/logging/overview.html [4] Jakarta-Commons-Logging, http://jakarta.apache.org/commons/logging/index.html [5] Versiones JCL, http://jakarta.apache.org/builds/jakarta-commons/release/commons-logging/ [6] JCL user guide, http://cvs.apache.org/viewcvs.cgi/*checkout*/jakarta-commons/logging/usersguide.html?rev=HEAD [7] The complete log4j manual, Ceki Gulcu, The complete log4j manual, el libro del padre de Log4j

Acerca del autor


Informtico de nacimiento y a un paso de licenciarse como ingeniero por la Universidad de Deusto.Trabaja en la empresa bilbana NHT-Norwick.com desde hace ya mas de dos aos donde programa, como no, en Java.

Copyright (c) 2002, Enrique Rodriguez Lasterra. Este documento puede ser distribuido solo bajo los trminos y condiciones de la licencia de Documentacin de javaHispano v1.0 o posterior (la ltima versin se encuentra en http://www.javahispano.org/licencias/).

Pgina 14

Potrebbero piacerti anche